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