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