1 | //===-- Globals.cpp - Implement the GlobalValue & GlobalVariable class ----===// |
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 implements the GlobalValue & GlobalVariable classes for the IR |
10 | // library. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "LLVMContextImpl.h" |
15 | #include "llvm/IR/ConstantRange.h" |
16 | #include "llvm/IR/Constants.h" |
17 | #include "llvm/IR/DerivedTypes.h" |
18 | #include "llvm/IR/GlobalAlias.h" |
19 | #include "llvm/IR/GlobalValue.h" |
20 | #include "llvm/IR/GlobalVariable.h" |
21 | #include "llvm/IR/MDBuilder.h" |
22 | #include "llvm/IR/Module.h" |
23 | #include "llvm/Support/Error.h" |
24 | #include "llvm/Support/ErrorHandling.h" |
25 | #include "llvm/Support/MD5.h" |
26 | #include "llvm/TargetParser/Triple.h" |
27 | using namespace llvm; |
28 | |
29 | //===----------------------------------------------------------------------===// |
30 | // GlobalValue Class |
31 | //===----------------------------------------------------------------------===// |
32 | |
33 | // GlobalValue should be a Constant, plus a type, a module, some flags, and an |
34 | // intrinsic ID. Add an assert to prevent people from accidentally growing |
35 | // GlobalValue while adding flags. |
36 | static_assert(sizeof(GlobalValue) == |
37 | sizeof(Constant) + 2 * sizeof(void *) + 2 * sizeof(unsigned), |
38 | "unexpected GlobalValue size growth" ); |
39 | |
40 | // GlobalObject adds a comdat. |
41 | static_assert(sizeof(GlobalObject) == sizeof(GlobalValue) + sizeof(void *), |
42 | "unexpected GlobalObject size growth" ); |
43 | |
44 | bool GlobalValue::isMaterializable() const { |
45 | if (const Function *F = dyn_cast<Function>(Val: this)) |
46 | return F->isMaterializable(); |
47 | return false; |
48 | } |
49 | Error GlobalValue::materialize() { return getParent()->materialize(GV: this); } |
50 | |
51 | /// Override destroyConstantImpl to make sure it doesn't get called on |
52 | /// GlobalValue's because they shouldn't be treated like other constants. |
53 | void GlobalValue::destroyConstantImpl() { |
54 | llvm_unreachable("You can't GV->destroyConstantImpl()!" ); |
55 | } |
56 | |
57 | Value *GlobalValue::handleOperandChangeImpl(Value *From, Value *To) { |
58 | llvm_unreachable("Unsupported class for handleOperandChange()!" ); |
59 | } |
60 | |
61 | /// copyAttributesFrom - copy all additional attributes (those not needed to |
62 | /// create a GlobalValue) from the GlobalValue Src to this one. |
63 | void GlobalValue::copyAttributesFrom(const GlobalValue *Src) { |
64 | setVisibility(Src->getVisibility()); |
65 | setUnnamedAddr(Src->getUnnamedAddr()); |
66 | setThreadLocalMode(Src->getThreadLocalMode()); |
67 | setDLLStorageClass(Src->getDLLStorageClass()); |
68 | setDSOLocal(Src->isDSOLocal()); |
69 | setPartition(Src->getPartition()); |
70 | if (Src->hasSanitizerMetadata()) |
71 | setSanitizerMetadata(Src->getSanitizerMetadata()); |
72 | else |
73 | removeSanitizerMetadata(); |
74 | } |
75 | |
76 | GlobalValue::GUID |
77 | GlobalValue::getGUIDAssumingExternalLinkage(StringRef GlobalIdentifier) { |
78 | return MD5Hash(Str: GlobalIdentifier); |
79 | } |
80 | |
81 | void GlobalValue::removeFromParent() { |
82 | switch (getValueID()) { |
83 | #define HANDLE_GLOBAL_VALUE(NAME) \ |
84 | case Value::NAME##Val: \ |
85 | return static_cast<NAME *>(this)->removeFromParent(); |
86 | #include "llvm/IR/Value.def" |
87 | default: |
88 | break; |
89 | } |
90 | llvm_unreachable("not a global" ); |
91 | } |
92 | |
93 | void GlobalValue::eraseFromParent() { |
94 | switch (getValueID()) { |
95 | #define HANDLE_GLOBAL_VALUE(NAME) \ |
96 | case Value::NAME##Val: \ |
97 | return static_cast<NAME *>(this)->eraseFromParent(); |
98 | #include "llvm/IR/Value.def" |
99 | default: |
100 | break; |
101 | } |
102 | llvm_unreachable("not a global" ); |
103 | } |
104 | |
105 | GlobalObject::~GlobalObject() { setComdat(nullptr); } |
106 | |
107 | bool GlobalValue::isInterposable() const { |
108 | if (isInterposableLinkage(Linkage: getLinkage())) |
109 | return true; |
110 | return getParent() && getParent()->getSemanticInterposition() && |
111 | !isDSOLocal(); |
112 | } |
113 | |
114 | bool GlobalValue::canBenefitFromLocalAlias() const { |
115 | if (isTagged()) { |
116 | // Cannot create local aliases to MTE tagged globals. The address of a |
117 | // tagged global includes a tag that is assigned by the loader in the |
118 | // GOT. |
119 | return false; |
120 | } |
121 | // See AsmPrinter::getSymbolPreferLocal(). For a deduplicate comdat kind, |
122 | // references to a discarded local symbol from outside the group are not |
123 | // allowed, so avoid the local alias. |
124 | auto isDeduplicateComdat = [](const Comdat *C) { |
125 | return C && C->getSelectionKind() != Comdat::NoDeduplicate; |
126 | }; |
127 | return hasDefaultVisibility() && |
128 | GlobalObject::isExternalLinkage(Linkage: getLinkage()) && !isDeclaration() && |
129 | !isa<GlobalIFunc>(Val: this) && !isDeduplicateComdat(getComdat()); |
130 | } |
131 | |
132 | const DataLayout &GlobalValue::getDataLayout() const { |
133 | return getParent()->getDataLayout(); |
134 | } |
135 | |
136 | void GlobalObject::setAlignment(MaybeAlign Align) { |
137 | assert((!Align || *Align <= MaximumAlignment) && |
138 | "Alignment is greater than MaximumAlignment!" ); |
139 | unsigned AlignmentData = encode(A: Align); |
140 | unsigned OldData = getGlobalValueSubClassData(); |
141 | setGlobalValueSubClassData((OldData & ~AlignmentMask) | AlignmentData); |
142 | assert(getAlign() == Align && "Alignment representation error!" ); |
143 | } |
144 | |
145 | void GlobalObject::setAlignment(Align Align) { |
146 | assert(Align <= MaximumAlignment && |
147 | "Alignment is greater than MaximumAlignment!" ); |
148 | unsigned AlignmentData = encode(A: Align); |
149 | unsigned OldData = getGlobalValueSubClassData(); |
150 | setGlobalValueSubClassData((OldData & ~AlignmentMask) | AlignmentData); |
151 | assert(getAlign() && *getAlign() == Align && |
152 | "Alignment representation error!" ); |
153 | } |
154 | |
155 | void GlobalObject::copyAttributesFrom(const GlobalObject *Src) { |
156 | GlobalValue::copyAttributesFrom(Src); |
157 | setAlignment(Src->getAlign()); |
158 | setSection(Src->getSection()); |
159 | } |
160 | |
161 | std::string GlobalValue::getGlobalIdentifier(StringRef Name, |
162 | GlobalValue::LinkageTypes Linkage, |
163 | StringRef FileName) { |
164 | // Value names may be prefixed with a binary '1' to indicate |
165 | // that the backend should not modify the symbols due to any platform |
166 | // naming convention. Do not include that '1' in the PGO profile name. |
167 | Name.consume_front(Prefix: "\1" ); |
168 | |
169 | std::string GlobalName; |
170 | if (llvm::GlobalValue::isLocalLinkage(Linkage)) { |
171 | // For local symbols, prepend the main file name to distinguish them. |
172 | // Do not include the full path in the file name since there's no guarantee |
173 | // that it will stay the same, e.g., if the files are checked out from |
174 | // version control in different locations. |
175 | if (FileName.empty()) |
176 | GlobalName += "<unknown>" ; |
177 | else |
178 | GlobalName += FileName; |
179 | |
180 | GlobalName += GlobalIdentifierDelimiter; |
181 | } |
182 | GlobalName += Name; |
183 | return GlobalName; |
184 | } |
185 | |
186 | std::string GlobalValue::getGlobalIdentifier() const { |
187 | return getGlobalIdentifier(Name: getName(), Linkage: getLinkage(), |
188 | FileName: getParent()->getSourceFileName()); |
189 | } |
190 | |
191 | StringRef GlobalValue::getSection() const { |
192 | if (auto *GA = dyn_cast<GlobalAlias>(Val: this)) { |
193 | // In general we cannot compute this at the IR level, but we try. |
194 | if (const GlobalObject *GO = GA->getAliaseeObject()) |
195 | return GO->getSection(); |
196 | return "" ; |
197 | } |
198 | return cast<GlobalObject>(Val: this)->getSection(); |
199 | } |
200 | |
201 | const Comdat *GlobalValue::getComdat() const { |
202 | if (auto *GA = dyn_cast<GlobalAlias>(Val: this)) { |
203 | // In general we cannot compute this at the IR level, but we try. |
204 | if (const GlobalObject *GO = GA->getAliaseeObject()) |
205 | return const_cast<GlobalObject *>(GO)->getComdat(); |
206 | return nullptr; |
207 | } |
208 | // ifunc and its resolver are separate things so don't use resolver comdat. |
209 | if (isa<GlobalIFunc>(Val: this)) |
210 | return nullptr; |
211 | return cast<GlobalObject>(Val: this)->getComdat(); |
212 | } |
213 | |
214 | void GlobalObject::setComdat(Comdat *C) { |
215 | if (ObjComdat) |
216 | ObjComdat->removeUser(GO: this); |
217 | ObjComdat = C; |
218 | if (C) |
219 | C->addUser(GO: this); |
220 | } |
221 | |
222 | StringRef GlobalValue::getPartition() const { |
223 | if (!hasPartition()) |
224 | return "" ; |
225 | return getContext().pImpl->GlobalValuePartitions[this]; |
226 | } |
227 | |
228 | void GlobalValue::setPartition(StringRef S) { |
229 | // Do nothing if we're clearing the partition and it is already empty. |
230 | if (!hasPartition() && S.empty()) |
231 | return; |
232 | |
233 | // Get or create a stable partition name string and put it in the table in the |
234 | // context. |
235 | if (!S.empty()) |
236 | S = getContext().pImpl->Saver.save(S); |
237 | getContext().pImpl->GlobalValuePartitions[this] = S; |
238 | |
239 | // Update the HasPartition field. Setting the partition to the empty string |
240 | // means this global no longer has a partition. |
241 | HasPartition = !S.empty(); |
242 | } |
243 | |
244 | using SanitizerMetadata = GlobalValue::SanitizerMetadata; |
245 | const SanitizerMetadata &GlobalValue::getSanitizerMetadata() const { |
246 | assert(hasSanitizerMetadata()); |
247 | assert(getContext().pImpl->GlobalValueSanitizerMetadata.count(this)); |
248 | return getContext().pImpl->GlobalValueSanitizerMetadata[this]; |
249 | } |
250 | |
251 | void GlobalValue::setSanitizerMetadata(SanitizerMetadata Meta) { |
252 | getContext().pImpl->GlobalValueSanitizerMetadata[this] = Meta; |
253 | HasSanitizerMetadata = true; |
254 | } |
255 | |
256 | void GlobalValue::removeSanitizerMetadata() { |
257 | DenseMap<const GlobalValue *, SanitizerMetadata> &MetadataMap = |
258 | getContext().pImpl->GlobalValueSanitizerMetadata; |
259 | MetadataMap.erase(Val: this); |
260 | HasSanitizerMetadata = false; |
261 | } |
262 | |
263 | void GlobalValue::setNoSanitizeMetadata() { |
264 | SanitizerMetadata Meta; |
265 | Meta.NoAddress = true; |
266 | Meta.NoHWAddress = true; |
267 | setSanitizerMetadata(Meta); |
268 | } |
269 | |
270 | StringRef GlobalObject::getSectionImpl() const { |
271 | assert(hasSection()); |
272 | return getContext().pImpl->GlobalObjectSections[this]; |
273 | } |
274 | |
275 | void GlobalObject::setSection(StringRef S) { |
276 | // Do nothing if we're clearing the section and it is already empty. |
277 | if (!hasSection() && S.empty()) |
278 | return; |
279 | |
280 | // Get or create a stable section name string and put it in the table in the |
281 | // context. |
282 | if (!S.empty()) |
283 | S = getContext().pImpl->Saver.save(S); |
284 | getContext().pImpl->GlobalObjectSections[this] = S; |
285 | |
286 | // Update the HasSectionHashEntryBit. Setting the section to the empty string |
287 | // means this global no longer has a section. |
288 | setGlobalObjectFlag(Bit: HasSectionHashEntryBit, Val: !S.empty()); |
289 | } |
290 | |
291 | void GlobalObject::setSectionPrefix(StringRef Prefix) { |
292 | MDBuilder MDB(getContext()); |
293 | setMetadata(KindID: LLVMContext::MD_section_prefix, |
294 | Node: MDB.createGlobalObjectSectionPrefix(Prefix)); |
295 | } |
296 | |
297 | std::optional<StringRef> GlobalObject::getSectionPrefix() const { |
298 | if (MDNode *MD = getMetadata(KindID: LLVMContext::MD_section_prefix)) { |
299 | [[maybe_unused]] StringRef MDName = |
300 | cast<MDString>(Val: MD->getOperand(I: 0))->getString(); |
301 | assert((MDName == "section_prefix" || |
302 | (isa<Function>(this) && MDName == "function_section_prefix" )) && |
303 | "Metadata not match" ); |
304 | return cast<MDString>(Val: MD->getOperand(I: 1))->getString(); |
305 | } |
306 | return std::nullopt; |
307 | } |
308 | |
309 | bool GlobalValue::isNobuiltinFnDef() const { |
310 | const Function *F = dyn_cast<Function>(Val: this); |
311 | if (!F || F->empty()) |
312 | return false; |
313 | return F->hasFnAttribute(Kind: Attribute::NoBuiltin); |
314 | } |
315 | |
316 | bool GlobalValue::isDeclaration() const { |
317 | // Globals are definitions if they have an initializer. |
318 | if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Val: this)) |
319 | return GV->getNumOperands() == 0; |
320 | |
321 | // Functions are definitions if they have a body. |
322 | if (const Function *F = dyn_cast<Function>(Val: this)) |
323 | return F->empty() && !F->isMaterializable(); |
324 | |
325 | // Aliases and ifuncs are always definitions. |
326 | assert(isa<GlobalAlias>(this) || isa<GlobalIFunc>(this)); |
327 | return false; |
328 | } |
329 | |
330 | bool GlobalObject::canIncreaseAlignment() const { |
331 | // Firstly, can only increase the alignment of a global if it |
332 | // is a strong definition. |
333 | if (!isStrongDefinitionForLinker()) |
334 | return false; |
335 | |
336 | // It also has to either not have a section defined, or, not have |
337 | // alignment specified. (If it is assigned a section, the global |
338 | // could be densely packed with other objects in the section, and |
339 | // increasing the alignment could cause padding issues.) |
340 | if (hasSection() && getAlign()) |
341 | return false; |
342 | |
343 | // On ELF platforms, we're further restricted in that we can't |
344 | // increase the alignment of any variable which might be emitted |
345 | // into a shared library, and which is exported. If the main |
346 | // executable accesses a variable found in a shared-lib, the main |
347 | // exe actually allocates memory for and exports the symbol ITSELF, |
348 | // overriding the symbol found in the library. That is, at link |
349 | // time, the observed alignment of the variable is copied into the |
350 | // executable binary. (A COPY relocation is also generated, to copy |
351 | // the initial data from the shadowed variable in the shared-lib |
352 | // into the location in the main binary, before running code.) |
353 | // |
354 | // And thus, even though you might think you are defining the |
355 | // global, and allocating the memory for the global in your object |
356 | // file, and thus should be able to set the alignment arbitrarily, |
357 | // that's not actually true. Doing so can cause an ABI breakage; an |
358 | // executable might have already been built with the previous |
359 | // alignment of the variable, and then assuming an increased |
360 | // alignment will be incorrect. |
361 | |
362 | // Conservatively assume ELF if there's no parent pointer. |
363 | bool isELF = (!Parent || Parent->getTargetTriple().isOSBinFormatELF()); |
364 | if (isELF && !isDSOLocal()) |
365 | return false; |
366 | |
367 | // GV with toc-data attribute is defined in a TOC entry. To mitigate TOC |
368 | // overflow, the alignment of such symbol should not be increased. Otherwise, |
369 | // padding is needed thus more TOC entries are wasted. |
370 | bool isXCOFF = (!Parent || Parent->getTargetTriple().isOSBinFormatXCOFF()); |
371 | if (isXCOFF) |
372 | if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Val: this)) |
373 | if (GV->hasAttribute(Kind: "toc-data" )) |
374 | return false; |
375 | |
376 | return true; |
377 | } |
378 | |
379 | template <typename Operation> |
380 | static const GlobalObject * |
381 | findBaseObject(const Constant *C, DenseSet<const GlobalAlias *> &Aliases, |
382 | const Operation &Op) { |
383 | if (auto *GO = dyn_cast<GlobalObject>(Val: C)) { |
384 | Op(*GO); |
385 | return GO; |
386 | } |
387 | if (auto *GA = dyn_cast<GlobalAlias>(Val: C)) { |
388 | Op(*GA); |
389 | if (Aliases.insert(V: GA).second) |
390 | return findBaseObject(GA->getOperand(i_nocapture: 0), Aliases, Op); |
391 | } |
392 | if (auto *CE = dyn_cast<ConstantExpr>(Val: C)) { |
393 | switch (CE->getOpcode()) { |
394 | case Instruction::Add: { |
395 | auto *LHS = findBaseObject(CE->getOperand(i_nocapture: 0), Aliases, Op); |
396 | auto *RHS = findBaseObject(CE->getOperand(i_nocapture: 1), Aliases, Op); |
397 | if (LHS && RHS) |
398 | return nullptr; |
399 | return LHS ? LHS : RHS; |
400 | } |
401 | case Instruction::Sub: { |
402 | if (findBaseObject(CE->getOperand(i_nocapture: 1), Aliases, Op)) |
403 | return nullptr; |
404 | return findBaseObject(CE->getOperand(i_nocapture: 0), Aliases, Op); |
405 | } |
406 | case Instruction::IntToPtr: |
407 | case Instruction::PtrToInt: |
408 | case Instruction::BitCast: |
409 | case Instruction::GetElementPtr: |
410 | return findBaseObject(CE->getOperand(i_nocapture: 0), Aliases, Op); |
411 | default: |
412 | break; |
413 | } |
414 | } |
415 | return nullptr; |
416 | } |
417 | |
418 | const GlobalObject *GlobalValue::getAliaseeObject() const { |
419 | DenseSet<const GlobalAlias *> Aliases; |
420 | return findBaseObject(C: this, Aliases, Op: [](const GlobalValue &) {}); |
421 | } |
422 | |
423 | bool GlobalValue::isAbsoluteSymbolRef() const { |
424 | auto *GO = dyn_cast<GlobalObject>(Val: this); |
425 | if (!GO) |
426 | return false; |
427 | |
428 | return GO->getMetadata(KindID: LLVMContext::MD_absolute_symbol); |
429 | } |
430 | |
431 | std::optional<ConstantRange> GlobalValue::getAbsoluteSymbolRange() const { |
432 | auto *GO = dyn_cast<GlobalObject>(Val: this); |
433 | if (!GO) |
434 | return std::nullopt; |
435 | |
436 | MDNode *MD = GO->getMetadata(KindID: LLVMContext::MD_absolute_symbol); |
437 | if (!MD) |
438 | return std::nullopt; |
439 | |
440 | return getConstantRangeFromMetadata(RangeMD: *MD); |
441 | } |
442 | |
443 | bool GlobalValue::canBeOmittedFromSymbolTable() const { |
444 | if (!hasLinkOnceODRLinkage()) |
445 | return false; |
446 | |
447 | // We assume that anyone who sets global unnamed_addr on a non-constant |
448 | // knows what they're doing. |
449 | if (hasGlobalUnnamedAddr()) |
450 | return true; |
451 | |
452 | // If it is a non constant variable, it needs to be uniqued across shared |
453 | // objects. |
454 | if (auto *Var = dyn_cast<GlobalVariable>(Val: this)) |
455 | if (!Var->isConstant()) |
456 | return false; |
457 | |
458 | return hasAtLeastLocalUnnamedAddr(); |
459 | } |
460 | |
461 | //===----------------------------------------------------------------------===// |
462 | // GlobalVariable Implementation |
463 | //===----------------------------------------------------------------------===// |
464 | |
465 | GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link, |
466 | Constant *InitVal, const Twine &Name, |
467 | ThreadLocalMode TLMode, unsigned AddressSpace, |
468 | bool isExternallyInitialized) |
469 | : GlobalObject(Ty, Value::GlobalVariableVal, AllocMarker, Link, Name, |
470 | AddressSpace), |
471 | isConstantGlobal(constant), |
472 | isExternallyInitializedConstant(isExternallyInitialized) { |
473 | assert(!Ty->isFunctionTy() && PointerType::isValidElementType(Ty) && |
474 | "invalid type for global variable" ); |
475 | setThreadLocalMode(TLMode); |
476 | if (InitVal) { |
477 | assert(InitVal->getType() == Ty && |
478 | "Initializer should be the same type as the GlobalVariable!" ); |
479 | Op<0>() = InitVal; |
480 | } else { |
481 | setGlobalVariableNumOperands(0); |
482 | } |
483 | } |
484 | |
485 | GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, |
486 | LinkageTypes Link, Constant *InitVal, |
487 | const Twine &Name, GlobalVariable *Before, |
488 | ThreadLocalMode TLMode, |
489 | std::optional<unsigned> AddressSpace, |
490 | bool isExternallyInitialized) |
491 | : GlobalVariable(Ty, constant, Link, InitVal, Name, TLMode, |
492 | AddressSpace |
493 | ? *AddressSpace |
494 | : M.getDataLayout().getDefaultGlobalsAddressSpace(), |
495 | isExternallyInitialized) { |
496 | if (Before) |
497 | Before->getParent()->insertGlobalVariable(Where: Before->getIterator(), GV: this); |
498 | else |
499 | M.insertGlobalVariable(GV: this); |
500 | } |
501 | |
502 | void GlobalVariable::removeFromParent() { |
503 | getParent()->removeGlobalVariable(GV: this); |
504 | } |
505 | |
506 | void GlobalVariable::eraseFromParent() { |
507 | getParent()->eraseGlobalVariable(GV: this); |
508 | } |
509 | |
510 | void GlobalVariable::setInitializer(Constant *InitVal) { |
511 | if (!InitVal) { |
512 | if (hasInitializer()) { |
513 | // Note, the num operands is used to compute the offset of the operand, so |
514 | // the order here matters. Clearing the operand then clearing the num |
515 | // operands ensures we have the correct offset to the operand. |
516 | Op<0>().set(nullptr); |
517 | setGlobalVariableNumOperands(0); |
518 | } |
519 | } else { |
520 | assert(InitVal->getType() == getValueType() && |
521 | "Initializer type must match GlobalVariable type" ); |
522 | // Note, the num operands is used to compute the offset of the operand, so |
523 | // the order here matters. We need to set num operands to 1 first so that |
524 | // we get the correct offset to the first operand when we set it. |
525 | if (!hasInitializer()) |
526 | setGlobalVariableNumOperands(1); |
527 | Op<0>().set(InitVal); |
528 | } |
529 | } |
530 | |
531 | void GlobalVariable::replaceInitializer(Constant *InitVal) { |
532 | assert(InitVal && "Can't compute type of null initializer" ); |
533 | ValueType = InitVal->getType(); |
534 | setInitializer(InitVal); |
535 | } |
536 | |
537 | /// Copy all additional attributes (those not needed to create a GlobalVariable) |
538 | /// from the GlobalVariable Src to this one. |
539 | void GlobalVariable::copyAttributesFrom(const GlobalVariable *Src) { |
540 | GlobalObject::copyAttributesFrom(Src); |
541 | setExternallyInitialized(Src->isExternallyInitialized()); |
542 | setAttributes(Src->getAttributes()); |
543 | if (auto CM = Src->getCodeModel()) |
544 | setCodeModel(*CM); |
545 | } |
546 | |
547 | void GlobalVariable::dropAllReferences() { |
548 | User::dropAllReferences(); |
549 | clearMetadata(); |
550 | } |
551 | |
552 | void GlobalVariable::setCodeModel(CodeModel::Model CM) { |
553 | unsigned CodeModelData = static_cast<unsigned>(CM) + 1; |
554 | unsigned OldData = getGlobalValueSubClassData(); |
555 | unsigned NewData = (OldData & ~(CodeModelMask << CodeModelShift)) | |
556 | (CodeModelData << CodeModelShift); |
557 | setGlobalValueSubClassData(NewData); |
558 | assert(getCodeModel() == CM && "Code model representation error!" ); |
559 | } |
560 | |
561 | void GlobalVariable::clearCodeModel() { |
562 | unsigned CodeModelData = 0; |
563 | unsigned OldData = getGlobalValueSubClassData(); |
564 | unsigned NewData = (OldData & ~(CodeModelMask << CodeModelShift)) | |
565 | (CodeModelData << CodeModelShift); |
566 | setGlobalValueSubClassData(NewData); |
567 | assert(getCodeModel() == std::nullopt && "Code model representation error!" ); |
568 | } |
569 | |
570 | //===----------------------------------------------------------------------===// |
571 | // GlobalAlias Implementation |
572 | //===----------------------------------------------------------------------===// |
573 | |
574 | GlobalAlias::GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Link, |
575 | const Twine &Name, Constant *Aliasee, |
576 | Module *ParentModule) |
577 | : GlobalValue(Ty, Value::GlobalAliasVal, AllocMarker, Link, Name, |
578 | AddressSpace) { |
579 | setAliasee(Aliasee); |
580 | if (ParentModule) |
581 | ParentModule->insertAlias(Alias: this); |
582 | } |
583 | |
584 | GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, |
585 | LinkageTypes Link, const Twine &Name, |
586 | Constant *Aliasee, Module *ParentModule) { |
587 | return new GlobalAlias(Ty, AddressSpace, Link, Name, Aliasee, ParentModule); |
588 | } |
589 | |
590 | GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, |
591 | LinkageTypes Linkage, const Twine &Name, |
592 | Module *Parent) { |
593 | return create(Ty, AddressSpace, Link: Linkage, Name, Aliasee: nullptr, ParentModule: Parent); |
594 | } |
595 | |
596 | GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, |
597 | LinkageTypes Linkage, const Twine &Name, |
598 | GlobalValue *Aliasee) { |
599 | return create(Ty, AddressSpace, Link: Linkage, Name, Aliasee, ParentModule: Aliasee->getParent()); |
600 | } |
601 | |
602 | GlobalAlias *GlobalAlias::create(LinkageTypes Link, const Twine &Name, |
603 | GlobalValue *Aliasee) { |
604 | return create(Ty: Aliasee->getValueType(), AddressSpace: Aliasee->getAddressSpace(), Linkage: Link, Name, |
605 | Aliasee); |
606 | } |
607 | |
608 | GlobalAlias *GlobalAlias::create(const Twine &Name, GlobalValue *Aliasee) { |
609 | return create(Link: Aliasee->getLinkage(), Name, Aliasee); |
610 | } |
611 | |
612 | void GlobalAlias::removeFromParent() { getParent()->removeAlias(Alias: this); } |
613 | |
614 | void GlobalAlias::eraseFromParent() { getParent()->eraseAlias(Alias: this); } |
615 | |
616 | void GlobalAlias::setAliasee(Constant *Aliasee) { |
617 | assert((!Aliasee || Aliasee->getType() == getType()) && |
618 | "Alias and aliasee types should match!" ); |
619 | Op<0>().set(Aliasee); |
620 | } |
621 | |
622 | const GlobalObject *GlobalAlias::getAliaseeObject() const { |
623 | DenseSet<const GlobalAlias *> Aliases; |
624 | return findBaseObject(C: getOperand(i_nocapture: 0), Aliases, Op: [](const GlobalValue &) {}); |
625 | } |
626 | |
627 | //===----------------------------------------------------------------------===// |
628 | // GlobalIFunc Implementation |
629 | //===----------------------------------------------------------------------===// |
630 | |
631 | GlobalIFunc::GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Link, |
632 | const Twine &Name, Constant *Resolver, |
633 | Module *ParentModule) |
634 | : GlobalObject(Ty, Value::GlobalIFuncVal, AllocMarker, Link, Name, |
635 | AddressSpace) { |
636 | setResolver(Resolver); |
637 | if (ParentModule) |
638 | ParentModule->insertIFunc(IFunc: this); |
639 | } |
640 | |
641 | GlobalIFunc *GlobalIFunc::create(Type *Ty, unsigned AddressSpace, |
642 | LinkageTypes Link, const Twine &Name, |
643 | Constant *Resolver, Module *ParentModule) { |
644 | return new GlobalIFunc(Ty, AddressSpace, Link, Name, Resolver, ParentModule); |
645 | } |
646 | |
647 | void GlobalIFunc::removeFromParent() { getParent()->removeIFunc(IFunc: this); } |
648 | |
649 | void GlobalIFunc::eraseFromParent() { getParent()->eraseIFunc(IFunc: this); } |
650 | |
651 | const Function *GlobalIFunc::getResolverFunction() const { |
652 | return dyn_cast<Function>(Val: getResolver()->stripPointerCastsAndAliases()); |
653 | } |
654 | |
655 | void GlobalIFunc::applyAlongResolverPath( |
656 | function_ref<void(const GlobalValue &)> Op) const { |
657 | DenseSet<const GlobalAlias *> Aliases; |
658 | findBaseObject(C: getResolver(), Aliases, Op); |
659 | } |
660 | |