Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 1 | //===-- llvm/GlobalVariable.h - GlobalVariable class ------------*- C++ -*-===// | 
| 2 | // | ||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | ||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| 6 | // | ||
| 7 | //===----------------------------------------------------------------------===// | ||
| 8 | // | ||
| 9 | // This file contains the declaration of the GlobalVariable class, which | ||
| 10 | // represents a single global variable (or constant) in the VM. | ||
| 11 | // | ||
| 12 | // Global variables are constant pointers that refer to hunks of space that are | ||
| 13 | // allocated by either the VM, or by the linker in a static compiler.  A global | ||
| 14 | // variable may have an initial value, which is copied into the executables .data | ||
| 15 | // area.  Global Constants are required to have initializers. | ||
| 16 | // | ||
| 17 | //===----------------------------------------------------------------------===// | ||
| 18 | |||
| 19 | #ifndef LLVM_IR_GLOBALVARIABLE_H | ||
| 20 | #define LLVM_IR_GLOBALVARIABLE_H | ||
| 21 | |||
| 22 | #include "llvm/ADT/Twine.h" | ||
| 23 | #include "llvm/ADT/ilist_node.h" | ||
| 24 | #include "llvm/IR/Attributes.h" | ||
| 25 | #include "llvm/IR/GlobalObject.h" | ||
| 26 | #include "llvm/IR/OperandTraits.h" | ||
| 27 | #include "llvm/IR/Value.h" | ||
| 28 | #include <cassert> | ||
| 29 | #include <cstddef> | ||
| 30 | |||
| 31 | namespace llvm { | ||
| 32 | |||
| 33 | class Constant; | ||
| 34 | class Module; | ||
| 35 | |||
| 36 | template <typename ValueSubClass> class SymbolTableListTraits; | ||
| 37 | class DIGlobalVariableExpression; | ||
| 38 | |||
| 39 | class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> { | ||
| 40 | friend class SymbolTableListTraits<GlobalVariable>; | ||
| 41 | |||
| 42 |   AttributeSet Attrs; | ||
| 43 | bool isConstantGlobal : 1; // Is this a global constant? | ||
| 44 | bool isExternallyInitializedConstant : 1; // Is this a global whose value | ||
| 45 |                                                // can change from its initial | ||
| 46 |                                                // value before global | ||
| 47 |                                                // initializers are run? | ||
| 48 | |||
| 49 | public: | ||
| 50 |   /// GlobalVariable ctor - If a parent module is specified, the global is | ||
| 51 |   /// automatically inserted into the end of the specified modules global list. | ||
| 52 | GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage, | ||
| 53 | Constant *Initializer = nullptr, const Twine &Name = "", | ||
| 54 | ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, | ||
| 55 | bool isExternallyInitialized = false); | ||
| 56 |   /// GlobalVariable ctor - This creates a global and inserts it before the | ||
| 57 |   /// specified other global. | ||
| 58 | GlobalVariable(Module &M, Type *Ty, bool isConstant, LinkageTypes Linkage, | ||
| 59 | Constant *Initializer, const Twine &Name = "", | ||
| 60 | GlobalVariable *InsertBefore = nullptr, | ||
| 61 |                  ThreadLocalMode = NotThreadLocal, | ||
| 62 | std::optional<unsigned> AddressSpace = std::nullopt, | ||
| 63 | bool isExternallyInitialized = false); | ||
| 64 | GlobalVariable(const GlobalVariable &) = delete; | ||
| 65 | GlobalVariable &operator=(const GlobalVariable &) = delete; | ||
| 66 | |||
| 67 | ~GlobalVariable() { | ||
| 68 | dropAllReferences(); | ||
| 69 |   } | ||
| 70 | |||
| 71 |   // allocate space for exactly one operand | ||
| 72 | void *operator new(size_t s) { | ||
| 73 | return User::operator new(s, 1); | ||
| 74 |   } | ||
| 75 | |||
| 76 |   // delete space for exactly one operand as created in the corresponding new operator | ||
| 77 | void operator delete(void *ptr){ | ||
| 78 | assert(ptr != nullptr && "must not be nullptr"); | ||
| 79 | User *Obj = static_cast<User *>(ptr); | ||
| 80 |     // Number of operands can be set to 0 after construction and initialization. Make sure | ||
| 81 |     // that number of operands is reset to 1, as this is needed in User::operator delete | ||
| 82 | Obj->setGlobalVariableNumOperands(1); | ||
| 83 | User::operator delete(Obj); | ||
| 84 |   } | ||
| 85 | |||
| 86 |   /// Provide fast operand accessors | ||
| 87 | DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); | ||
| 88 | |||
| 89 |   /// Definitions have initializers, declarations don't. | ||
| 90 |   /// | ||
| 91 | inline bool hasInitializer() const { return !isDeclaration(); } | ||
| 92 | |||
| 93 |   /// hasDefinitiveInitializer - Whether the global variable has an initializer, | ||
| 94 |   /// and any other instances of the global (this can happen due to weak | ||
| 95 |   /// linkage) are guaranteed to have the same initializer. | ||
| 96 |   /// | ||
| 97 |   /// Note that if you want to transform a global, you must use | ||
| 98 |   /// hasUniqueInitializer() instead, because of the *_odr linkage type. | ||
| 99 |   /// | ||
| 100 |   /// Example: | ||
| 101 |   /// | ||
| 102 |   /// @a = global SomeType* null - Initializer is both definitive and unique. | ||
| 103 |   /// | ||
| 104 |   /// @b = global weak SomeType* null - Initializer is neither definitive nor | ||
| 105 |   /// unique. | ||
| 106 |   /// | ||
| 107 |   /// @c = global weak_odr SomeType* null - Initializer is definitive, but not | ||
| 108 |   /// unique. | ||
| 109 | inline bool hasDefinitiveInitializer() const { | ||
| 110 | return hasInitializer() && | ||
| 111 |       // The initializer of a global variable may change to something arbitrary | ||
| 112 |       // at link time. | ||
| 113 | !isInterposable() && | ||
| 114 |       // The initializer of a global variable with the externally_initialized | ||
| 115 |       // marker may change at runtime before C++ initializers are evaluated. | ||
| 116 | !isExternallyInitialized(); | ||
| 117 |   } | ||
| 118 | |||
| 119 |   /// hasUniqueInitializer - Whether the global variable has an initializer, and | ||
| 120 |   /// any changes made to the initializer will turn up in the final executable. | ||
| 121 | inline bool hasUniqueInitializer() const { | ||
| 122 |     return | ||
| 123 |         // We need to be sure this is the definition that will actually be used | ||
| 124 | isStrongDefinitionForLinker() && | ||
| 125 |         // It is not safe to modify initializers of global variables with the | ||
| 126 |         // external_initializer marker since the value may be changed at runtime | ||
| 127 |         // before C++ initializers are evaluated. | ||
| 128 | !isExternallyInitialized(); | ||
| 129 |   } | ||
| 130 | |||
| 131 |   /// getInitializer - Return the initializer for this global variable.  It is | ||
| 132 |   /// illegal to call this method if the global is external, because we cannot | ||
| 133 |   /// tell what the value is initialized to! | ||
| 134 |   /// | ||
| 135 | inline const Constant *getInitializer() const { | ||
| 136 | assert(hasInitializer() && "GV doesn't have initializer!"); | ||
| 137 | return static_cast<Constant*>(Op<0>().get()); | ||
| 138 |   } | ||
| 139 | inline Constant *getInitializer() { | ||
| 140 | assert(hasInitializer() && "GV doesn't have initializer!"); | ||
| 141 | return static_cast<Constant*>(Op<0>().get()); | ||
| 142 |   } | ||
| 143 |   /// setInitializer - Sets the initializer for this global variable, removing | ||
| 144 |   /// any existing initializer if InitVal==NULL.  If this GV has type T*, the | ||
| 145 |   /// initializer must have type T. | ||
| 146 | void setInitializer(Constant *InitVal); | ||
| 147 | |||
| 148 |   /// If the value is a global constant, its value is immutable throughout the | ||
| 149 |   /// runtime execution of the program.  Assigning a value into the constant | ||
| 150 |   /// leads to undefined behavior. | ||
| 151 |   /// | ||
| 152 | bool isConstant() const { return isConstantGlobal; } | ||
| 153 | void setConstant(bool Val) { isConstantGlobal = Val; } | ||
| 154 | |||
| 155 | bool isExternallyInitialized() const { | ||
| 156 | return isExternallyInitializedConstant; | ||
| 157 |   } | ||
| 158 | void setExternallyInitialized(bool Val) { | ||
| 159 | isExternallyInitializedConstant = Val; | ||
| 160 |   } | ||
| 161 | |||
| 162 |   /// copyAttributesFrom - copy all additional attributes (those not needed to | ||
| 163 |   /// create a GlobalVariable) from the GlobalVariable Src to this one. | ||
| 164 | void copyAttributesFrom(const GlobalVariable *Src); | ||
| 165 | |||
| 166 |   /// removeFromParent - This method unlinks 'this' from the containing module, | ||
| 167 |   /// but does not delete it. | ||
| 168 |   /// | ||
| 169 | void removeFromParent(); | ||
| 170 | |||
| 171 |   /// eraseFromParent - This method unlinks 'this' from the containing module | ||
| 172 |   /// and deletes it. | ||
| 173 |   /// | ||
| 174 | void eraseFromParent(); | ||
| 175 | |||
| 176 |   /// Drop all references in preparation to destroy the GlobalVariable. This | ||
| 177 |   /// drops not only the reference to the initializer but also to any metadata. | ||
| 178 | void dropAllReferences(); | ||
| 179 | |||
| 180 |   /// Attach a DIGlobalVariableExpression. | ||
| 181 | void addDebugInfo(DIGlobalVariableExpression *GV); | ||
| 182 | |||
| 183 |   /// Fill the vector with all debug info attachements. | ||
| 184 | void getDebugInfo(SmallVectorImpl<DIGlobalVariableExpression *> &GVs) const; | ||
| 185 | |||
| 186 |   /// Add attribute to this global. | ||
| 187 | void addAttribute(Attribute::AttrKind Kind) { | ||
| 188 | Attrs = Attrs.addAttribute(getContext(), Kind); | ||
| 189 |   } | ||
| 190 | |||
| 191 |   /// Add attribute to this global. | ||
| 192 | void addAttribute(StringRef Kind, StringRef Val = StringRef()) { | ||
| 193 | Attrs = Attrs.addAttribute(getContext(), Kind, Val); | ||
| 194 |   } | ||
| 195 | |||
| 196 |   /// Return true if the attribute exists. | ||
| 197 | bool hasAttribute(Attribute::AttrKind Kind) const { | ||
| 198 | return Attrs.hasAttribute(Kind); | ||
| 199 |   } | ||
| 200 | |||
| 201 |   /// Return true if the attribute exists. | ||
| 202 | bool hasAttribute(StringRef Kind) const { | ||
| 203 | return Attrs.hasAttribute(Kind); | ||
| 204 |   } | ||
| 205 | |||
| 206 |   /// Return true if any attributes exist. | ||
| 207 | bool hasAttributes() const { | ||
| 208 | return Attrs.hasAttributes(); | ||
| 209 |   } | ||
| 210 | |||
| 211 |   /// Return the attribute object. | ||
| 212 | Attribute getAttribute(Attribute::AttrKind Kind) const { | ||
| 213 | return Attrs.getAttribute(Kind); | ||
| 214 |   } | ||
| 215 | |||
| 216 |   /// Return the attribute object. | ||
| 217 | Attribute getAttribute(StringRef Kind) const { | ||
| 218 | return Attrs.getAttribute(Kind); | ||
| 219 |   } | ||
| 220 | |||
| 221 |   /// Return the attribute set for this global | ||
| 222 | AttributeSet getAttributes() const { | ||
| 223 | return Attrs; | ||
| 224 |   } | ||
| 225 | |||
| 226 |   /// Return attribute set as list with index. | ||
| 227 |   /// FIXME: This may not be required once ValueEnumerators | ||
| 228 |   /// in bitcode-writer can enumerate attribute-set. | ||
| 229 | AttributeList getAttributesAsList(unsigned index) const { | ||
| 230 | if (!hasAttributes()) | ||
| 231 | return AttributeList(); | ||
| 232 | std::pair<unsigned, AttributeSet> AS[1] = {{index, Attrs}}; | ||
| 233 | return AttributeList::get(getContext(), AS); | ||
| 234 |   } | ||
| 235 | |||
| 236 |   /// Set attribute list for this global | ||
| 237 | void setAttributes(AttributeSet A) { | ||
| 238 | Attrs = A; | ||
| 239 |   } | ||
| 240 | |||
| 241 |   /// Check if section name is present | ||
| 242 | bool hasImplicitSection() const { | ||
| 243 | return getAttributes().hasAttribute("bss-section") || | ||
| 244 | getAttributes().hasAttribute("data-section") || | ||
| 245 | getAttributes().hasAttribute("relro-section") || | ||
| 246 | getAttributes().hasAttribute("rodata-section"); | ||
| 247 |   } | ||
| 248 | |||
| 249 |   // Methods for support type inquiry through isa, cast, and dyn_cast: | ||
| 250 | static bool classof(const Value *V) { | ||
| 251 | return V->getValueID() == Value::GlobalVariableVal; | ||
| 252 |   } | ||
| 253 | }; | ||
| 254 | |||
| 255 | template <> | ||
| 256 | struct OperandTraits<GlobalVariable> : | ||
| 257 | public OptionalOperandTraits<GlobalVariable> { | ||
| 258 | }; | ||
| 259 | |||
| 260 | DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalVariable, Value) | ||
| 261 | |||
| 262 | } // end namespace llvm | ||
| 263 | |||
| 264 | #endif // LLVM_IR_GLOBALVARIABLE_H |