Path: blob/main/contrib/llvm-project/llvm/lib/IR/Globals.cpp
35233 views
//===-- Globals.cpp - Implement the GlobalValue & GlobalVariable class ----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the GlobalValue & GlobalVariable classes for the IR9// library.10//11//===----------------------------------------------------------------------===//1213#include "LLVMContextImpl.h"14#include "llvm/IR/ConstantRange.h"15#include "llvm/IR/Constants.h"16#include "llvm/IR/DerivedTypes.h"17#include "llvm/IR/GlobalAlias.h"18#include "llvm/IR/GlobalValue.h"19#include "llvm/IR/GlobalVariable.h"20#include "llvm/IR/Module.h"21#include "llvm/Support/Error.h"22#include "llvm/Support/ErrorHandling.h"23#include "llvm/Support/MD5.h"24#include "llvm/TargetParser/Triple.h"25using namespace llvm;2627//===----------------------------------------------------------------------===//28// GlobalValue Class29//===----------------------------------------------------------------------===//3031// GlobalValue should be a Constant, plus a type, a module, some flags, and an32// intrinsic ID. Add an assert to prevent people from accidentally growing33// GlobalValue while adding flags.34static_assert(sizeof(GlobalValue) ==35sizeof(Constant) + 2 * sizeof(void *) + 2 * sizeof(unsigned),36"unexpected GlobalValue size growth");3738// GlobalObject adds a comdat.39static_assert(sizeof(GlobalObject) == sizeof(GlobalValue) + sizeof(void *),40"unexpected GlobalObject size growth");4142bool GlobalValue::isMaterializable() const {43if (const Function *F = dyn_cast<Function>(this))44return F->isMaterializable();45return false;46}47Error GlobalValue::materialize() { return getParent()->materialize(this); }4849/// Override destroyConstantImpl to make sure it doesn't get called on50/// GlobalValue's because they shouldn't be treated like other constants.51void GlobalValue::destroyConstantImpl() {52llvm_unreachable("You can't GV->destroyConstantImpl()!");53}5455Value *GlobalValue::handleOperandChangeImpl(Value *From, Value *To) {56llvm_unreachable("Unsupported class for handleOperandChange()!");57}5859/// copyAttributesFrom - copy all additional attributes (those not needed to60/// create a GlobalValue) from the GlobalValue Src to this one.61void GlobalValue::copyAttributesFrom(const GlobalValue *Src) {62setVisibility(Src->getVisibility());63setUnnamedAddr(Src->getUnnamedAddr());64setThreadLocalMode(Src->getThreadLocalMode());65setDLLStorageClass(Src->getDLLStorageClass());66setDSOLocal(Src->isDSOLocal());67setPartition(Src->getPartition());68if (Src->hasSanitizerMetadata())69setSanitizerMetadata(Src->getSanitizerMetadata());70else71removeSanitizerMetadata();72}7374GlobalValue::GUID GlobalValue::getGUID(StringRef GlobalName) {75return MD5Hash(GlobalName);76}7778void GlobalValue::removeFromParent() {79switch (getValueID()) {80#define HANDLE_GLOBAL_VALUE(NAME) \81case Value::NAME##Val: \82return static_cast<NAME *>(this)->removeFromParent();83#include "llvm/IR/Value.def"84default:85break;86}87llvm_unreachable("not a global");88}8990void GlobalValue::eraseFromParent() {91switch (getValueID()) {92#define HANDLE_GLOBAL_VALUE(NAME) \93case Value::NAME##Val: \94return static_cast<NAME *>(this)->eraseFromParent();95#include "llvm/IR/Value.def"96default:97break;98}99llvm_unreachable("not a global");100}101102GlobalObject::~GlobalObject() { setComdat(nullptr); }103104bool GlobalValue::isInterposable() const {105if (isInterposableLinkage(getLinkage()))106return true;107return getParent() && getParent()->getSemanticInterposition() &&108!isDSOLocal();109}110111bool GlobalValue::canBenefitFromLocalAlias() const {112// See AsmPrinter::getSymbolPreferLocal(). For a deduplicate comdat kind,113// references to a discarded local symbol from outside the group are not114// allowed, so avoid the local alias.115auto isDeduplicateComdat = [](const Comdat *C) {116return C && C->getSelectionKind() != Comdat::NoDeduplicate;117};118return hasDefaultVisibility() &&119GlobalObject::isExternalLinkage(getLinkage()) && !isDeclaration() &&120!isa<GlobalIFunc>(this) && !isDeduplicateComdat(getComdat());121}122123const DataLayout &GlobalValue::getDataLayout() const {124return getParent()->getDataLayout();125}126127void GlobalObject::setAlignment(MaybeAlign Align) {128assert((!Align || *Align <= MaximumAlignment) &&129"Alignment is greater than MaximumAlignment!");130unsigned AlignmentData = encode(Align);131unsigned OldData = getGlobalValueSubClassData();132setGlobalValueSubClassData((OldData & ~AlignmentMask) | AlignmentData);133assert(getAlign() == Align && "Alignment representation error!");134}135136void GlobalObject::setAlignment(Align Align) {137assert(Align <= MaximumAlignment &&138"Alignment is greater than MaximumAlignment!");139unsigned AlignmentData = encode(Align);140unsigned OldData = getGlobalValueSubClassData();141setGlobalValueSubClassData((OldData & ~AlignmentMask) | AlignmentData);142assert(getAlign() && *getAlign() == Align &&143"Alignment representation error!");144}145146void GlobalObject::copyAttributesFrom(const GlobalObject *Src) {147GlobalValue::copyAttributesFrom(Src);148setAlignment(Src->getAlign());149setSection(Src->getSection());150}151152std::string GlobalValue::getGlobalIdentifier(StringRef Name,153GlobalValue::LinkageTypes Linkage,154StringRef FileName) {155// Value names may be prefixed with a binary '1' to indicate156// that the backend should not modify the symbols due to any platform157// naming convention. Do not include that '1' in the PGO profile name.158Name.consume_front("\1");159160std::string GlobalName;161if (llvm::GlobalValue::isLocalLinkage(Linkage)) {162// For local symbols, prepend the main file name to distinguish them.163// Do not include the full path in the file name since there's no guarantee164// that it will stay the same, e.g., if the files are checked out from165// version control in different locations.166if (FileName.empty())167GlobalName += "<unknown>";168else169GlobalName += FileName;170171GlobalName += GlobalIdentifierDelimiter;172}173GlobalName += Name;174return GlobalName;175}176177std::string GlobalValue::getGlobalIdentifier() const {178return getGlobalIdentifier(getName(), getLinkage(),179getParent()->getSourceFileName());180}181182StringRef GlobalValue::getSection() const {183if (auto *GA = dyn_cast<GlobalAlias>(this)) {184// In general we cannot compute this at the IR level, but we try.185if (const GlobalObject *GO = GA->getAliaseeObject())186return GO->getSection();187return "";188}189return cast<GlobalObject>(this)->getSection();190}191192const Comdat *GlobalValue::getComdat() const {193if (auto *GA = dyn_cast<GlobalAlias>(this)) {194// In general we cannot compute this at the IR level, but we try.195if (const GlobalObject *GO = GA->getAliaseeObject())196return const_cast<GlobalObject *>(GO)->getComdat();197return nullptr;198}199// ifunc and its resolver are separate things so don't use resolver comdat.200if (isa<GlobalIFunc>(this))201return nullptr;202return cast<GlobalObject>(this)->getComdat();203}204205void GlobalObject::setComdat(Comdat *C) {206if (ObjComdat)207ObjComdat->removeUser(this);208ObjComdat = C;209if (C)210C->addUser(this);211}212213StringRef GlobalValue::getPartition() const {214if (!hasPartition())215return "";216return getContext().pImpl->GlobalValuePartitions[this];217}218219void GlobalValue::setPartition(StringRef S) {220// Do nothing if we're clearing the partition and it is already empty.221if (!hasPartition() && S.empty())222return;223224// Get or create a stable partition name string and put it in the table in the225// context.226if (!S.empty())227S = getContext().pImpl->Saver.save(S);228getContext().pImpl->GlobalValuePartitions[this] = S;229230// Update the HasPartition field. Setting the partition to the empty string231// means this global no longer has a partition.232HasPartition = !S.empty();233}234235using SanitizerMetadata = GlobalValue::SanitizerMetadata;236const SanitizerMetadata &GlobalValue::getSanitizerMetadata() const {237assert(hasSanitizerMetadata());238assert(getContext().pImpl->GlobalValueSanitizerMetadata.count(this));239return getContext().pImpl->GlobalValueSanitizerMetadata[this];240}241242void GlobalValue::setSanitizerMetadata(SanitizerMetadata Meta) {243getContext().pImpl->GlobalValueSanitizerMetadata[this] = Meta;244HasSanitizerMetadata = true;245}246247void GlobalValue::removeSanitizerMetadata() {248DenseMap<const GlobalValue *, SanitizerMetadata> &MetadataMap =249getContext().pImpl->GlobalValueSanitizerMetadata;250MetadataMap.erase(this);251HasSanitizerMetadata = false;252}253254void GlobalValue::setNoSanitizeMetadata() {255SanitizerMetadata Meta;256Meta.NoAddress = true;257Meta.NoHWAddress = true;258setSanitizerMetadata(Meta);259}260261StringRef GlobalObject::getSectionImpl() const {262assert(hasSection());263return getContext().pImpl->GlobalObjectSections[this];264}265266void GlobalObject::setSection(StringRef S) {267// Do nothing if we're clearing the section and it is already empty.268if (!hasSection() && S.empty())269return;270271// Get or create a stable section name string and put it in the table in the272// context.273if (!S.empty())274S = getContext().pImpl->Saver.save(S);275getContext().pImpl->GlobalObjectSections[this] = S;276277// Update the HasSectionHashEntryBit. Setting the section to the empty string278// means this global no longer has a section.279setGlobalObjectFlag(HasSectionHashEntryBit, !S.empty());280}281282bool GlobalValue::isNobuiltinFnDef() const {283const Function *F = dyn_cast<Function>(this);284if (!F || F->empty())285return false;286return F->hasFnAttribute(Attribute::NoBuiltin);287}288289bool GlobalValue::isDeclaration() const {290// Globals are definitions if they have an initializer.291if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(this))292return GV->getNumOperands() == 0;293294// Functions are definitions if they have a body.295if (const Function *F = dyn_cast<Function>(this))296return F->empty() && !F->isMaterializable();297298// Aliases and ifuncs are always definitions.299assert(isa<GlobalAlias>(this) || isa<GlobalIFunc>(this));300return false;301}302303bool GlobalObject::canIncreaseAlignment() const {304// Firstly, can only increase the alignment of a global if it305// is a strong definition.306if (!isStrongDefinitionForLinker())307return false;308309// It also has to either not have a section defined, or, not have310// alignment specified. (If it is assigned a section, the global311// could be densely packed with other objects in the section, and312// increasing the alignment could cause padding issues.)313if (hasSection() && getAlign())314return false;315316// On ELF platforms, we're further restricted in that we can't317// increase the alignment of any variable which might be emitted318// into a shared library, and which is exported. If the main319// executable accesses a variable found in a shared-lib, the main320// exe actually allocates memory for and exports the symbol ITSELF,321// overriding the symbol found in the library. That is, at link322// time, the observed alignment of the variable is copied into the323// executable binary. (A COPY relocation is also generated, to copy324// the initial data from the shadowed variable in the shared-lib325// into the location in the main binary, before running code.)326//327// And thus, even though you might think you are defining the328// global, and allocating the memory for the global in your object329// file, and thus should be able to set the alignment arbitrarily,330// that's not actually true. Doing so can cause an ABI breakage; an331// executable might have already been built with the previous332// alignment of the variable, and then assuming an increased333// alignment will be incorrect.334335// Conservatively assume ELF if there's no parent pointer.336bool isELF =337(!Parent || Triple(Parent->getTargetTriple()).isOSBinFormatELF());338if (isELF && !isDSOLocal())339return false;340341// GV with toc-data attribute is defined in a TOC entry. To mitigate TOC342// overflow, the alignment of such symbol should not be increased. Otherwise,343// padding is needed thus more TOC entries are wasted.344bool isXCOFF =345(!Parent || Triple(Parent->getTargetTriple()).isOSBinFormatXCOFF());346if (isXCOFF)347if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(this))348if (GV->hasAttribute("toc-data"))349return false;350351return true;352}353354template <typename Operation>355static const GlobalObject *356findBaseObject(const Constant *C, DenseSet<const GlobalAlias *> &Aliases,357const Operation &Op) {358if (auto *GO = dyn_cast<GlobalObject>(C)) {359Op(*GO);360return GO;361}362if (auto *GA = dyn_cast<GlobalAlias>(C)) {363Op(*GA);364if (Aliases.insert(GA).second)365return findBaseObject(GA->getOperand(0), Aliases, Op);366}367if (auto *CE = dyn_cast<ConstantExpr>(C)) {368switch (CE->getOpcode()) {369case Instruction::Add: {370auto *LHS = findBaseObject(CE->getOperand(0), Aliases, Op);371auto *RHS = findBaseObject(CE->getOperand(1), Aliases, Op);372if (LHS && RHS)373return nullptr;374return LHS ? LHS : RHS;375}376case Instruction::Sub: {377if (findBaseObject(CE->getOperand(1), Aliases, Op))378return nullptr;379return findBaseObject(CE->getOperand(0), Aliases, Op);380}381case Instruction::IntToPtr:382case Instruction::PtrToInt:383case Instruction::BitCast:384case Instruction::GetElementPtr:385return findBaseObject(CE->getOperand(0), Aliases, Op);386default:387break;388}389}390return nullptr;391}392393const GlobalObject *GlobalValue::getAliaseeObject() const {394DenseSet<const GlobalAlias *> Aliases;395return findBaseObject(this, Aliases, [](const GlobalValue &) {});396}397398bool GlobalValue::isAbsoluteSymbolRef() const {399auto *GO = dyn_cast<GlobalObject>(this);400if (!GO)401return false;402403return GO->getMetadata(LLVMContext::MD_absolute_symbol);404}405406std::optional<ConstantRange> GlobalValue::getAbsoluteSymbolRange() const {407auto *GO = dyn_cast<GlobalObject>(this);408if (!GO)409return std::nullopt;410411MDNode *MD = GO->getMetadata(LLVMContext::MD_absolute_symbol);412if (!MD)413return std::nullopt;414415return getConstantRangeFromMetadata(*MD);416}417418bool GlobalValue::canBeOmittedFromSymbolTable() const {419if (!hasLinkOnceODRLinkage())420return false;421422// We assume that anyone who sets global unnamed_addr on a non-constant423// knows what they're doing.424if (hasGlobalUnnamedAddr())425return true;426427// If it is a non constant variable, it needs to be uniqued across shared428// objects.429if (auto *Var = dyn_cast<GlobalVariable>(this))430if (!Var->isConstant())431return false;432433return hasAtLeastLocalUnnamedAddr();434}435436//===----------------------------------------------------------------------===//437// GlobalVariable Implementation438//===----------------------------------------------------------------------===//439440GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link,441Constant *InitVal, const Twine &Name,442ThreadLocalMode TLMode, unsigned AddressSpace,443bool isExternallyInitialized)444: GlobalObject(Ty, Value::GlobalVariableVal,445OperandTraits<GlobalVariable>::op_begin(this),446InitVal != nullptr, Link, Name, AddressSpace),447isConstantGlobal(constant),448isExternallyInitializedConstant(isExternallyInitialized) {449assert(!Ty->isFunctionTy() && PointerType::isValidElementType(Ty) &&450"invalid type for global variable");451setThreadLocalMode(TLMode);452if (InitVal) {453assert(InitVal->getType() == Ty &&454"Initializer should be the same type as the GlobalVariable!");455Op<0>() = InitVal;456}457}458459GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant,460LinkageTypes Link, Constant *InitVal,461const Twine &Name, GlobalVariable *Before,462ThreadLocalMode TLMode,463std::optional<unsigned> AddressSpace,464bool isExternallyInitialized)465: GlobalVariable(Ty, constant, Link, InitVal, Name, TLMode,466AddressSpace467? *AddressSpace468: M.getDataLayout().getDefaultGlobalsAddressSpace(),469isExternallyInitialized) {470if (Before)471Before->getParent()->insertGlobalVariable(Before->getIterator(), this);472else473M.insertGlobalVariable(this);474}475476void GlobalVariable::removeFromParent() {477getParent()->removeGlobalVariable(this);478}479480void GlobalVariable::eraseFromParent() {481getParent()->eraseGlobalVariable(this);482}483484void GlobalVariable::setInitializer(Constant *InitVal) {485if (!InitVal) {486if (hasInitializer()) {487// Note, the num operands is used to compute the offset of the operand, so488// the order here matters. Clearing the operand then clearing the num489// operands ensures we have the correct offset to the operand.490Op<0>().set(nullptr);491setGlobalVariableNumOperands(0);492}493} else {494assert(InitVal->getType() == getValueType() &&495"Initializer type must match GlobalVariable type");496// Note, the num operands is used to compute the offset of the operand, so497// the order here matters. We need to set num operands to 1 first so that498// we get the correct offset to the first operand when we set it.499if (!hasInitializer())500setGlobalVariableNumOperands(1);501Op<0>().set(InitVal);502}503}504505/// Copy all additional attributes (those not needed to create a GlobalVariable)506/// from the GlobalVariable Src to this one.507void GlobalVariable::copyAttributesFrom(const GlobalVariable *Src) {508GlobalObject::copyAttributesFrom(Src);509setExternallyInitialized(Src->isExternallyInitialized());510setAttributes(Src->getAttributes());511if (auto CM = Src->getCodeModel())512setCodeModel(*CM);513}514515void GlobalVariable::dropAllReferences() {516User::dropAllReferences();517clearMetadata();518}519520void GlobalVariable::setCodeModel(CodeModel::Model CM) {521unsigned CodeModelData = static_cast<unsigned>(CM) + 1;522unsigned OldData = getGlobalValueSubClassData();523unsigned NewData = (OldData & ~(CodeModelMask << CodeModelShift)) |524(CodeModelData << CodeModelShift);525setGlobalValueSubClassData(NewData);526assert(getCodeModel() == CM && "Code model representation error!");527}528529//===----------------------------------------------------------------------===//530// GlobalAlias Implementation531//===----------------------------------------------------------------------===//532533GlobalAlias::GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Link,534const Twine &Name, Constant *Aliasee,535Module *ParentModule)536: GlobalValue(Ty, Value::GlobalAliasVal, &Op<0>(), 1, Link, Name,537AddressSpace) {538setAliasee(Aliasee);539if (ParentModule)540ParentModule->insertAlias(this);541}542543GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace,544LinkageTypes Link, const Twine &Name,545Constant *Aliasee, Module *ParentModule) {546return new GlobalAlias(Ty, AddressSpace, Link, Name, Aliasee, ParentModule);547}548549GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace,550LinkageTypes Linkage, const Twine &Name,551Module *Parent) {552return create(Ty, AddressSpace, Linkage, Name, nullptr, Parent);553}554555GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace,556LinkageTypes Linkage, const Twine &Name,557GlobalValue *Aliasee) {558return create(Ty, AddressSpace, Linkage, Name, Aliasee, Aliasee->getParent());559}560561GlobalAlias *GlobalAlias::create(LinkageTypes Link, const Twine &Name,562GlobalValue *Aliasee) {563return create(Aliasee->getValueType(), Aliasee->getAddressSpace(), Link, Name,564Aliasee);565}566567GlobalAlias *GlobalAlias::create(const Twine &Name, GlobalValue *Aliasee) {568return create(Aliasee->getLinkage(), Name, Aliasee);569}570571void GlobalAlias::removeFromParent() { getParent()->removeAlias(this); }572573void GlobalAlias::eraseFromParent() { getParent()->eraseAlias(this); }574575void GlobalAlias::setAliasee(Constant *Aliasee) {576assert((!Aliasee || Aliasee->getType() == getType()) &&577"Alias and aliasee types should match!");578Op<0>().set(Aliasee);579}580581const GlobalObject *GlobalAlias::getAliaseeObject() const {582DenseSet<const GlobalAlias *> Aliases;583return findBaseObject(getOperand(0), Aliases, [](const GlobalValue &) {});584}585586//===----------------------------------------------------------------------===//587// GlobalIFunc Implementation588//===----------------------------------------------------------------------===//589590GlobalIFunc::GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Link,591const Twine &Name, Constant *Resolver,592Module *ParentModule)593: GlobalObject(Ty, Value::GlobalIFuncVal, &Op<0>(), 1, Link, Name,594AddressSpace) {595setResolver(Resolver);596if (ParentModule)597ParentModule->insertIFunc(this);598}599600GlobalIFunc *GlobalIFunc::create(Type *Ty, unsigned AddressSpace,601LinkageTypes Link, const Twine &Name,602Constant *Resolver, Module *ParentModule) {603return new GlobalIFunc(Ty, AddressSpace, Link, Name, Resolver, ParentModule);604}605606void GlobalIFunc::removeFromParent() { getParent()->removeIFunc(this); }607608void GlobalIFunc::eraseFromParent() { getParent()->eraseIFunc(this); }609610const Function *GlobalIFunc::getResolverFunction() const {611return dyn_cast<Function>(getResolver()->stripPointerCastsAndAliases());612}613614void GlobalIFunc::applyAlongResolverPath(615function_ref<void(const GlobalValue &)> Op) const {616DenseSet<const GlobalAlias *> Aliases;617findBaseObject(getResolver(), Aliases, Op);618}619620621