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 |