//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_GLOBAL_VARIABLE_H
-#define LLVM_GLOBAL_VARIABLE_H
+#ifndef LLVM_IR_GLOBALVARIABLE_H
+#define LLVM_IR_GLOBALVARIABLE_H
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/ilist_node.h"
-#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/OperandTraits.h"
namespace llvm {
class Module;
class Constant;
-template<typename ValueSubClass, typename ItemParentClass>
- class SymbolTableListTraits;
+template <typename ValueSubClass> class SymbolTableListTraits;
-class GlobalVariable : public GlobalValue, public ilist_node<GlobalVariable> {
- friend class SymbolTableListTraits<GlobalVariable, Module>;
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- void operator=(const GlobalVariable &) LLVM_DELETED_FUNCTION;
- GlobalVariable(const GlobalVariable &) LLVM_DELETED_FUNCTION;
+class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
+ friend class SymbolTableListTraits<GlobalVariable>;
+ void *operator new(size_t, unsigned) = delete;
+ void operator=(const GlobalVariable &) = delete;
+ GlobalVariable(const GlobalVariable &) = delete;
void setParent(Module *parent);
- bool isConstantGlobal : 1; // Is this a global constant?
- unsigned threadLocalMode : 3; // Is this symbol "Thread Local",
- // if so, what is the desired model?
-
+ bool isConstantGlobal : 1; // Is this a global constant?
+ bool isExternallyInitializedConstant : 1; // Is this a global whose value
+ // can change from its initial
+ // value before global
+ // initializers are run?
public:
// allocate space for exactly one operand
void *operator new(size_t s) {
return User::operator new(s, 1);
}
- enum ThreadLocalMode {
- NotThreadLocal = 0,
- GeneralDynamicTLSModel,
- LocalDynamicTLSModel,
- InitialExecTLSModel,
- LocalExecTLSModel
- };
-
/// GlobalVariable ctor - If a parent module is specified, the global is
/// automatically inserted into the end of the specified modules global list.
GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage,
- Constant *Initializer = 0, const Twine &Name = "",
- ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0);
+ Constant *Initializer = nullptr, const Twine &Name = "",
+ ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0,
+ bool isExternallyInitialized = false);
/// GlobalVariable ctor - This creates a global and inserts it before the
/// specified other global.
GlobalVariable(Module &M, Type *Ty, bool isConstant,
LinkageTypes Linkage, Constant *Initializer,
- const Twine &Name = "",
- GlobalVariable *InsertBefore = 0,
- ThreadLocalMode = NotThreadLocal,
- unsigned AddressSpace = 0);
+ const Twine &Name = "", GlobalVariable *InsertBefore = nullptr,
+ ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0,
+ bool isExternallyInitialized = false);
- ~GlobalVariable() {
- NumOperands = 1; // FIXME: needed by operator delete
+ ~GlobalVariable() override {
+ // FIXME: needed by operator delete
+ setGlobalVariableNumOperands(1);
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- /// hasInitializer - Unless a global variable isExternal(), it has an
- /// initializer. The initializer for the global variable/constant is held by
- /// Initializer if an initializer is specified.
+ /// Definitions have initializers, declarations don't.
///
inline bool hasInitializer() const { return !isDeclaration(); }
return hasInitializer() &&
// The initializer of a global variable with weak linkage may change at
// link time.
- !mayBeOverridden();
+ !mayBeOverridden() &&
+ // The initializer of a global variable with the externally_initialized
+ // marker may change at runtime before C++ initializers are evaluated.
+ !isExternallyInitialized();
}
/// hasUniqueInitializer - Whether the global variable has an initializer, and
// instead. It is wrong to modify the initializer of a global variable
// with *_odr linkage because then different instances of the global may
// have different initializers, breaking the One Definition Rule.
- !isWeakForLinker();
+ !isWeakForLinker() &&
+ // It is not safe to modify initializers of global variables with the
+ // external_initializer marker since the value may be changed at runtime
+ // before C++ initializers are evaluated.
+ !isExternallyInitialized();
}
/// getInitializer - Return the initializer for this global variable. It is
bool isConstant() const { return isConstantGlobal; }
void setConstant(bool Val) { isConstantGlobal = Val; }
- /// If the value is "Thread Local", its value isn't shared by the threads.
- bool isThreadLocal() const { return threadLocalMode != NotThreadLocal; }
- void setThreadLocal(bool Val) {
- threadLocalMode = Val ? GeneralDynamicTLSModel : NotThreadLocal;
+ bool isExternallyInitialized() const {
+ return isExternallyInitializedConstant;
}
- void setThreadLocalMode(ThreadLocalMode Val) { threadLocalMode = Val; }
- ThreadLocalMode getThreadLocalMode() const {
- return static_cast<ThreadLocalMode>(threadLocalMode);
+ void setExternallyInitialized(bool Val) {
+ isExternallyInitializedConstant = Val;
}
/// copyAttributesFrom - copy all additional attributes (those not needed to
/// create a GlobalVariable) from the GlobalVariable Src to this one.
- void copyAttributesFrom(const GlobalValue *Src);
+ void copyAttributesFrom(const GlobalValue *Src) override;
/// removeFromParent - This method unlinks 'this' from the containing module,
/// but does not delete it.
///
- virtual void removeFromParent();
+ void removeFromParent() override;
/// eraseFromParent - This method unlinks 'this' from the containing module
/// and deletes it.
///
- virtual void eraseFromParent();
-
- /// Override Constant's implementation of this method so we can
- /// replace constant initializers.
- virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
+ void eraseFromParent() override;
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Value *V) {