Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -907,7 +907,7 @@ Syntax:: - @ = [Linkage] [Visibility] ifunc , * @ + @ = [Linkage] [PreemptionSpecifier] [Visibility] ifunc , * @ .. _langref_comdats: Index: llvm/include/llvm-c/Core.h =================================================================== --- llvm/include/llvm-c/Core.h +++ llvm/include/llvm-c/Core.h @@ -1580,10 +1580,10 @@ macro(ConstantVector) \ macro(GlobalValue) \ macro(GlobalAlias) \ - macro(GlobalIFunc) \ macro(GlobalObject) \ macro(Function) \ macro(GlobalVariable) \ + macro(GlobalIFunc) \ macro(UndefValue) \ macro(PoisonValue) \ macro(Instruction) \ Index: llvm/include/llvm/AsmParser/LLParser.h =================================================================== --- llvm/include/llvm/AsmParser/LLParser.h +++ llvm/include/llvm/AsmParser/LLParser.h @@ -304,11 +304,10 @@ unsigned DLLStorageClass, bool DSOLocal, GlobalVariable::ThreadLocalMode TLM, GlobalVariable::UnnamedAddr UnnamedAddr); - bool parseIndirectSymbol(const std::string &Name, LocTy NameLoc, - unsigned L, unsigned Visibility, - unsigned DLLStorageClass, bool DSOLocal, - GlobalVariable::ThreadLocalMode TLM, - GlobalVariable::UnnamedAddr UnnamedAddr); + bool parseAliasOrIFunc(const std::string &Name, LocTy NameLoc, unsigned L, + unsigned Visibility, unsigned DLLStorageClass, + bool DSOLocal, GlobalVariable::ThreadLocalMode TLM, + GlobalVariable::UnnamedAddr UnnamedAddr); bool parseComdat(); bool parseStandaloneMetadata(); bool parseNamedMetadata(); Index: llvm/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/include/llvm/CodeGen/AsmPrinter.h +++ llvm/include/llvm/CodeGen/AsmPrinter.h @@ -41,7 +41,6 @@ class DwarfDebug; class GCMetadataPrinter; class GCStrategy; -class GlobalIndirectSymbol; class GlobalObject; class GlobalValue; class GlobalVariable; @@ -795,8 +794,8 @@ void emitModuleCommandLines(Module &M); GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &S); - /// Emit GlobalAlias or GlobalIFunc. - void emitGlobalIndirectSymbol(Module &M, const GlobalIndirectSymbol &GIS); + void emitGlobalAlias(Module &M, const GlobalAlias &GA); + void emitGlobalIFunc(Module &M, const GlobalIFunc &GI); /// This method decides whether the specified basic block requires a label. bool shouldEmitLabelForBasicBlock(const MachineBasicBlock &MBB) const; Index: llvm/include/llvm/IR/GlobalAlias.h =================================================================== --- llvm/include/llvm/IR/GlobalAlias.h +++ llvm/include/llvm/IR/GlobalAlias.h @@ -15,7 +15,8 @@ #define LLVM_IR_GLOBALALIAS_H #include "llvm/ADT/ilist_node.h" -#include "llvm/IR/GlobalIndirectSymbol.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/OperandTraits.h" #include "llvm/IR/Value.h" namespace llvm { @@ -24,8 +25,7 @@ class Module; template class SymbolTableListTraits; -class GlobalAlias : public GlobalIndirectSymbol, - public ilist_node { +class GlobalAlias : public GlobalValue, public ilist_node { friend class SymbolTableListTraits; GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, @@ -58,6 +58,17 @@ // Linkage, Type, Parent and AddressSpace taken from the Aliasee. static GlobalAlias *create(const Twine &Name, GlobalValue *Aliasee); + // allocate space for exactly one operand + void *operator new(size_t S) { return User::operator new(S, 1); } + void operator delete(void *Ptr) { User::operator delete(Ptr); } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + void copyAttributesFrom(const GlobalAlias *Src) { + GlobalValue::copyAttributesFrom(Src); + } + /// removeFromParent - This method unlinks 'this' from the containing module, /// but does not delete it. /// @@ -71,11 +82,9 @@ /// These methods retrieve and set alias target. void setAliasee(Constant *Aliasee); const Constant *getAliasee() const { - return getIndirectSymbol(); - } - Constant *getAliasee() { - return getIndirectSymbol(); + return static_cast(Op<0>().get()); } + Constant *getAliasee() { return static_cast(Op<0>().get()); } const GlobalObject *getAliaseeObject() const; GlobalObject *getAliaseeObject() { @@ -94,6 +103,12 @@ } }; +template <> +struct OperandTraits + : public FixedNumOperandTraits {}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Constant) + } // end namespace llvm #endif // LLVM_IR_GLOBALALIAS_H Index: llvm/include/llvm/IR/GlobalIFunc.h =================================================================== --- llvm/include/llvm/IR/GlobalIFunc.h +++ llvm/include/llvm/IR/GlobalIFunc.h @@ -18,7 +18,9 @@ #define LLVM_IR_GLOBALIFUNC_H #include "llvm/ADT/ilist_node.h" -#include "llvm/IR/GlobalIndirectSymbol.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/GlobalObject.h" +#include "llvm/IR/OperandTraits.h" #include "llvm/IR/Value.h" namespace llvm { @@ -29,8 +31,7 @@ // Traits class for using GlobalIFunc in symbol table in Module. template class SymbolTableListTraits; -class GlobalIFunc final : public GlobalIndirectSymbol, - public ilist_node { +class GlobalIFunc final : public GlobalObject, public ilist_node { friend class SymbolTableListTraits; GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, @@ -46,6 +47,17 @@ LinkageTypes Linkage, const Twine &Name, Constant *Resolver, Module *Parent); + // allocate space for exactly one operand + void *operator new(size_t S) { return User::operator new(S, 1); } + void operator delete(void *Ptr) { User::operator delete(Ptr); } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + void copyAttributesFrom(const GlobalIFunc *Src) { + GlobalObject::copyAttributesFrom(Src); + } + /// This method unlinks 'this' from the containing module, but does not /// delete it. void removeFromParent(); @@ -54,11 +66,11 @@ void eraseFromParent(); /// These methods retrieve and set ifunc resolver function. - void setResolver(Constant *Resolver) { - setIndirectSymbol(Resolver); + void setResolver(Constant *Resolver) { Op<0>().set(Resolver); } + const Constant *getResolver() const { + return static_cast(Op<0>().get()); } - const Constant *getResolver() const { return getIndirectSymbol(); } - Constant *getResolver() { return getIndirectSymbol(); } + Constant *getResolver() { return static_cast(Op<0>().get()); } // Return the resolver function after peeling off potential ConstantExpr // indirection. @@ -74,6 +86,12 @@ } }; +template <> +struct OperandTraits + : public FixedNumOperandTraits {}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalIFunc, Constant) + } // end namespace llvm #endif // LLVM_IR_GLOBALIFUNC_H Index: llvm/include/llvm/IR/GlobalIndirectSymbol.h =================================================================== --- llvm/include/llvm/IR/GlobalIndirectSymbol.h +++ /dev/null @@ -1,82 +0,0 @@ -//===- llvm/GlobalIndirectSymbol.h - GlobalIndirectSymbol class -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the GlobalIndirectSymbol class, which -// is a base class for GlobalAlias and GlobalIFunc. It contains all common code -// for aliases and ifuncs. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_GLOBALINDIRECTSYMBOL_H -#define LLVM_IR_GLOBALINDIRECTSYMBOL_H - -#include "llvm/IR/GlobalObject.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/OperandTraits.h" -#include "llvm/IR/User.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include - -namespace llvm { - -class GlobalIndirectSymbol : public GlobalValue { -protected: - GlobalIndirectSymbol(Type *Ty, ValueTy VTy, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, Constant *Symbol); - -public: - GlobalIndirectSymbol(const GlobalIndirectSymbol &) = delete; - GlobalIndirectSymbol &operator=(const GlobalIndirectSymbol &) = delete; - - // allocate space for exactly one operand - void *operator new(size_t S) { return User::operator new(S, 1); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); - - void copyAttributesFrom(const GlobalValue *Src) { - GlobalValue::copyAttributesFrom(Src); - } - - /// These methods set and retrieve indirect symbol. - void setIndirectSymbol(Constant *Symbol) { - setOperand(0, Symbol); - } - const Constant *getIndirectSymbol() const { - return getOperand(0); - } - Constant *getIndirectSymbol() { - return const_cast( - static_cast(this)->getIndirectSymbol()); - } - - const GlobalObject *getAliaseeObject() const; - GlobalObject *getAliaseeObject() { - return const_cast( - static_cast(this)->getAliaseeObject()); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == Value::GlobalAliasVal || - V->getValueID() == Value::GlobalIFuncVal; - } -}; - -template <> -struct OperandTraits : - public FixedNumOperandTraits { -}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalIndirectSymbol, Constant) - -} // end namespace llvm - -#endif // LLVM_IR_GLOBALINDIRECTSYMBOL_H Index: llvm/include/llvm/IR/GlobalObject.h =================================================================== --- llvm/include/llvm/IR/GlobalObject.h +++ llvm/include/llvm/IR/GlobalObject.h @@ -153,7 +153,8 @@ // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal || - V->getValueID() == Value::GlobalVariableVal; + V->getValueID() == Value::GlobalVariableVal || + V->getValueID() == Value::GlobalIFuncVal; } private: Index: llvm/include/llvm/IR/Value.h =================================================================== --- llvm/include/llvm/IR/Value.h +++ llvm/include/llvm/IR/Value.h @@ -37,7 +37,6 @@ class Function; class GlobalAlias; class GlobalIFunc; -class GlobalIndirectSymbol; class GlobalObject; class GlobalValue; class GlobalVariable; @@ -1016,21 +1015,16 @@ } }; -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return isa(Val) || isa(Val); - } -}; - template <> struct isa_impl { static inline bool doit(const Value &Val) { - return isa(Val) || isa(Val); + return isa(Val) || isa(Val); } }; template <> struct isa_impl { static inline bool doit(const Value &Val) { - return isa(Val) || isa(Val); + return isa(Val) || isa(Val) || + isa(Val); } }; Index: llvm/include/llvm/Transforms/Utils/ValueMapper.h =================================================================== --- llvm/include/llvm/Transforms/Utils/ValueMapper.h +++ llvm/include/llvm/Transforms/Utils/ValueMapper.h @@ -22,7 +22,6 @@ class Constant; class Function; -class GlobalIndirectSymbol; class GlobalVariable; class Instruction; class MDNode; @@ -122,7 +121,8 @@ /// instance: /// - \a scheduleMapGlobalInitializer() /// - \a scheduleMapAppendingVariable() -/// - \a scheduleMapGlobalIndirectSymbol() +/// - \a scheduleMapGlobalAlias() +/// - \a scheduleMapGlobalIFunc() /// - \a scheduleRemapFunction() /// /// Sometimes a callback needs a different mapping context. Such a context can @@ -182,9 +182,10 @@ bool IsOldCtorDtor, ArrayRef NewMembers, unsigned MappingContextID = 0); - void scheduleMapGlobalIndirectSymbol(GlobalIndirectSymbol &GIS, - Constant &Target, - unsigned MappingContextID = 0); + void scheduleMapGlobalAlias(GlobalAlias &GA, Constant &Aliasee, + unsigned MappingContextID = 0); + void scheduleMapGlobalIFunc(GlobalIFunc &GI, Constant &Resolver, + unsigned MappingContextID = 0); void scheduleRemapFunction(Function &F, unsigned MappingContextID = 0); }; Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -601,12 +601,15 @@ parseOptionalThreadLocal(TLM) || parseOptionalUnnamedAddr(UnnamedAddr)) return true; - if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc) + switch (Lex.getKind()) { + default: return parseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, DLLStorageClass, DSOLocal, TLM, UnnamedAddr); - - return parseIndirectSymbol(Name, NameLoc, Linkage, Visibility, + case lltok::kw_alias: + case lltok::kw_ifunc: + return parseAliasOrIFunc(Name, NameLoc, Linkage, Visibility, DLLStorageClass, DSOLocal, TLM, UnnamedAddr); + } } /// parseNamedGlobal: @@ -631,12 +634,15 @@ parseOptionalThreadLocal(TLM) || parseOptionalUnnamedAddr(UnnamedAddr)) return true; - if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc) + switch (Lex.getKind()) { + default: return parseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, DLLStorageClass, DSOLocal, TLM, UnnamedAddr); - - return parseIndirectSymbol(Name, NameLoc, Linkage, Visibility, + case lltok::kw_alias: + case lltok::kw_ifunc: + return parseAliasOrIFunc(Name, NameLoc, Linkage, Visibility, DLLStorageClass, DSOLocal, TLM, UnnamedAddr); + } } bool LLParser::parseComdat() { @@ -909,25 +915,25 @@ return ErrOS.str(); } -/// parseIndirectSymbol: +/// parseAliasOrIFunc: /// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier /// OptionalVisibility OptionalDLLStorageClass /// OptionalThreadLocal OptionalUnnamedAddr -/// 'alias|ifunc' IndirectSymbol IndirectSymbolAttr* +/// 'alias|ifunc' AliaseeOrResolver SymbolAttrs* /// -/// IndirectSymbol +/// AliaseeOrResolver /// ::= TypeAndValue /// -/// IndirectSymbolAttr +/// SymbolAttrs /// ::= ',' 'partition' StringConstant /// /// Everything through OptionalUnnamedAddr has already been parsed. /// -bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc, - unsigned L, unsigned Visibility, - unsigned DLLStorageClass, bool DSOLocal, - GlobalVariable::ThreadLocalMode TLM, - GlobalVariable::UnnamedAddr UnnamedAddr) { +bool LLParser::parseAliasOrIFunc(const std::string &Name, LocTy NameLoc, + unsigned L, unsigned Visibility, + unsigned DLLStorageClass, bool DSOLocal, + GlobalVariable::ThreadLocalMode TLM, + GlobalVariable::UnnamedAddr UnnamedAddr) { bool IsAlias; if (Lex.getKind() == lltok::kw_alias) IsAlias = true; @@ -1009,21 +1015,26 @@ } } - // Okay, create the alias but do not insert it into the module yet. - std::unique_ptr GA; - if (IsAlias) + // Okay, create the alias/ifunc but do not insert it into the module yet. + std::unique_ptr GA; + std::unique_ptr GI; + GlobalValue *GV; + if (IsAlias) { GA.reset(GlobalAlias::create(Ty, AddrSpace, (GlobalValue::LinkageTypes)Linkage, Name, Aliasee, /*Parent*/ nullptr)); - else - GA.reset(GlobalIFunc::create(Ty, AddrSpace, + GV = GA.get(); + } else { + GI.reset(GlobalIFunc::create(Ty, AddrSpace, (GlobalValue::LinkageTypes)Linkage, Name, Aliasee, /*Parent*/ nullptr)); - GA->setThreadLocalMode(TLM); - GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); - GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); - GA->setUnnamedAddr(UnnamedAddr); - maybeSetDSOLocal(DSOLocal, *GA); + GV = GI.get(); + } + GV->setThreadLocalMode(TLM); + GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); + GV->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); + GV->setUnnamedAddr(UnnamedAddr); + maybeSetDSOLocal(DSOLocal, *GV); // At this point we've parsed everything except for the IndirectSymbolAttrs. // Now parse them if there are any. @@ -1032,7 +1043,7 @@ if (Lex.getKind() == lltok::kw_partition) { Lex.Lex(); - GA->setPartition(Lex.getStrVal()); + GV->setPartition(Lex.getStrVal()); if (parseToken(lltok::StringConstant, "expected partition string")) return true; } else { @@ -1041,30 +1052,27 @@ } if (Name.empty()) - NumberedVals.push_back(GA.get()); + NumberedVals.push_back(GV); if (GVal) { // Verify that types agree. - if (GVal->getType() != GA->getType()) + if (GVal->getType() != GV->getType()) return error( ExplicitTypeLoc, "forward reference and definition of alias have different types"); // If they agree, just RAUW the old value with the alias and remove the // forward ref info. - GVal->replaceAllUsesWith(GA.get()); + GVal->replaceAllUsesWith(GV); GVal->eraseFromParent(); } // Insert into the module, we know its name won't collide now. if (IsAlias) - M->getAliasList().push_back(cast(GA.get())); + M->getAliasList().push_back(GA.release()); else - M->getIFuncList().push_back(cast(GA.get())); - assert(GA->getName() == Name && "Should not be a name conflict!"); - - // The module owns this now - GA.release(); + M->getIFuncList().push_back(GI.release()); + assert(GV->getName() == Name && "Should not be a name conflict!"); return false; } Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -41,7 +41,6 @@ #include "llvm/IR/GVMaterializer.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalIFunc.h" -#include "llvm/IR/GlobalIndirectSymbol.h" #include "llvm/IR/GlobalObject.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" @@ -500,7 +499,7 @@ SmallVector InstructionList; std::vector> GlobalInits; - std::vector> IndirectSymbolInits; + std::vector> IndirectSymbolInits; struct FunctionOperandInfo { Function *F; @@ -2253,8 +2252,7 @@ /// Resolve all of the initializers for global values and aliases that we can. Error BitcodeReader::resolveGlobalAndIndirectSymbolInits() { std::vector> GlobalInitWorklist; - std::vector> - IndirectSymbolInitWorklist; + std::vector> IndirectSymbolInitWorklist; std::vector FunctionOperandWorklist; GlobalInitWorklist.swap(GlobalInits); @@ -2283,10 +2281,16 @@ Constant *C = dyn_cast_or_null(ValueList[ValID]); if (!C) return error("Expected a constant"); - GlobalIndirectSymbol *GIS = IndirectSymbolInitWorklist.back().first; - if (isa(GIS) && C->getType() != GIS->getType()) - return error("Alias and aliasee types don't match"); - GIS->setIndirectSymbol(C); + GlobalValue *GV = IndirectSymbolInitWorklist.back().first; + if (auto *GA = dyn_cast(GV)) { + if (C->getType() != GV->getType()) + return error("Alias and aliasee types don't match"); + GA->setAliasee(C); + } else if (auto *GI = dyn_cast(GV)) { + GI->setResolver(C); + } else { + return error("Expected an alias or an ifunc"); + } } IndirectSymbolInitWorklist.pop_back(); } @@ -3118,8 +3122,7 @@ // Force deallocation of memory for these vectors to favor the client that // want lazy deserialization. std::vector>().swap(GlobalInits); - std::vector>().swap( - IndirectSymbolInits); + std::vector>().swap(IndirectSymbolInits); return Error::success(); } @@ -3499,7 +3502,7 @@ auto Val = Record[OpNum++]; auto Linkage = Record[OpNum++]; - GlobalIndirectSymbol *NewGA; + GlobalValue *NewGA; if (BitCode == bitc::MODULE_CODE_ALIAS || BitCode == bitc::MODULE_CODE_ALIAS_OLD) NewGA = GlobalAlias::create(Ty, AddrSpace, getDecodedLinkage(Linkage), Name, Index: llvm/lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -40,7 +40,6 @@ #include "llvm/IR/GVMaterializer.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalIFunc.h" -#include "llvm/IR/GlobalIndirectSymbol.h" #include "llvm/IR/GlobalObject.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -71,7 +71,6 @@ #include "llvm/IR/GCStrategy.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalIFunc.h" -#include "llvm/IR/GlobalIndirectSymbol.h" #include "llvm/IR/GlobalObject.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" @@ -1604,14 +1603,13 @@ emitGlobalVariable(GV); } -void AsmPrinter::emitGlobalIndirectSymbol(Module &M, - const GlobalIndirectSymbol& GIS) { - MCSymbol *Name = getSymbol(&GIS); - bool IsFunction = GIS.getValueType()->isFunctionTy(); +void AsmPrinter::emitGlobalAlias(Module &M, const GlobalAlias &GA) { + MCSymbol *Name = getSymbol(&GA); + bool IsFunction = GA.getValueType()->isFunctionTy(); // Treat bitcasts of functions as functions also. This is important at least // on WebAssembly where object and function addresses can't alias each other. if (!IsFunction) - if (auto *CE = dyn_cast(GIS.getIndirectSymbol())) + if (auto *CE = dyn_cast(GA.getAliasee())) if (CE->getOpcode() == Instruction::BitCast) IsFunction = CE->getOperand(0)->getType()->getPointerElementType()->isFunctionTy(); @@ -1621,61 +1619,80 @@ // point, all the extra label is emitted, we just have to emit linkage for // those labels. if (TM.getTargetTriple().isOSBinFormatXCOFF()) { - assert(!isa(GIS) && "IFunc is not supported on AIX."); assert(MAI->hasVisibilityOnlyWithLinkage() && "Visibility should be handled with emitLinkage() on AIX."); - emitLinkage(&GIS, Name); + emitLinkage(&GA, Name); // If it's a function, also emit linkage for aliases of function entry // point. if (IsFunction) - emitLinkage(&GIS, - getObjFileLowering().getFunctionEntryPointSymbol(&GIS, TM)); + emitLinkage(&GA, + getObjFileLowering().getFunctionEntryPointSymbol(&GA, TM)); return; } - if (GIS.hasExternalLinkage() || !MAI->getWeakRefDirective()) + if (GA.hasExternalLinkage() || !MAI->getWeakRefDirective()) OutStreamer->emitSymbolAttribute(Name, MCSA_Global); - else if (GIS.hasWeakLinkage() || GIS.hasLinkOnceLinkage()) + else if (GA.hasWeakLinkage() || GA.hasLinkOnceLinkage()) OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference); else - assert(GIS.hasLocalLinkage() && "Invalid alias or ifunc linkage"); + assert(GA.hasLocalLinkage() && "Invalid alias linkage"); // Set the symbol type to function if the alias has a function type. // This affects codegen when the aliasee is not a function. if (IsFunction) - OutStreamer->emitSymbolAttribute(Name, isa(GIS) - ? MCSA_ELF_TypeIndFunction - : MCSA_ELF_TypeFunction); + OutStreamer->emitSymbolAttribute(Name, MCSA_ELF_TypeFunction); - emitVisibility(Name, GIS.getVisibility()); + emitVisibility(Name, GA.getVisibility()); - const MCExpr *Expr = lowerConstant(GIS.getIndirectSymbol()); + const MCExpr *Expr = lowerConstant(GA.getAliasee()); - if (isa(&GIS) && MAI->hasAltEntry() && isa(Expr)) + if (MAI->hasAltEntry() && isa(Expr)) OutStreamer->emitSymbolAttribute(Name, MCSA_AltEntry); // Emit the directives as assignments aka .set: OutStreamer->emitAssignment(Name, Expr); - MCSymbol *LocalAlias = getSymbolPreferLocal(GIS); + MCSymbol *LocalAlias = getSymbolPreferLocal(GA); if (LocalAlias != Name) OutStreamer->emitAssignment(LocalAlias, Expr); - if (auto *GA = dyn_cast(&GIS)) { - // If the aliasee does not correspond to a symbol in the output, i.e. the - // alias is not of an object or the aliased object is private, then set the - // size of the alias symbol from the type of the alias. We don't do this in - // other situations as the alias and aliasee having differing types but same - // size may be intentional. - const GlobalObject *Aliasee = GA->getAliaseeObject(); - if (MAI->hasDotTypeDotSizeDirective() && GA->getValueType()->isSized() && - (!Aliasee || Aliasee->hasPrivateLinkage())) { - const DataLayout &DL = M.getDataLayout(); - uint64_t Size = DL.getTypeAllocSize(GA->getValueType()); - OutStreamer->emitELFSize(Name, MCConstantExpr::create(Size, OutContext)); - } + // If the aliasee does not correspond to a symbol in the output, i.e. the + // alias is not of an object or the aliased object is private, then set the + // size of the alias symbol from the type of the alias. We don't do this in + // other situations as the alias and aliasee having differing types but same + // size may be intentional. + const GlobalObject *BaseObject = GA.getAliaseeObject(); + if (MAI->hasDotTypeDotSizeDirective() && GA.getValueType()->isSized() && + (!BaseObject || BaseObject->hasPrivateLinkage())) { + const DataLayout &DL = M.getDataLayout(); + uint64_t Size = DL.getTypeAllocSize(GA.getValueType()); + OutStreamer->emitELFSize(Name, MCConstantExpr::create(Size, OutContext)); } } +void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) { + assert(!TM.getTargetTriple().isOSBinFormatXCOFF() && + "IFunc is not supported on AIX."); + + MCSymbol *Name = getSymbol(&GI); + + if (GI.hasExternalLinkage() || !MAI->getWeakRefDirective()) + OutStreamer->emitSymbolAttribute(Name, MCSA_Global); + else if (GI.hasWeakLinkage() || GI.hasLinkOnceLinkage()) + OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference); + else + assert(GI.hasLocalLinkage() && "Invalid ifunc linkage"); + + OutStreamer->emitSymbolAttribute(Name, MCSA_ELF_TypeIndFunction); + emitVisibility(Name, GI.getVisibility()); + + // Emit the directives as assignments aka .set: + const MCExpr *Expr = lowerConstant(GI.getResolver()); + OutStreamer->emitAssignment(Name, Expr); + MCSymbol *LocalAlias = getSymbolPreferLocal(GI); + if (LocalAlias != Name) + OutStreamer->emitAssignment(LocalAlias, Expr); +} + void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) { if (!RS.needsSection()) return; @@ -1856,11 +1873,11 @@ AliasStack.push_back(Cur); } for (const GlobalAlias *AncestorAlias : llvm::reverse(AliasStack)) - emitGlobalIndirectSymbol(M, *AncestorAlias); + emitGlobalAlias(M, *AncestorAlias); AliasStack.clear(); } for (const auto &IFunc : M.ifuncs()) - emitGlobalIndirectSymbol(M, IFunc); + emitGlobalIFunc(M, IFunc); GCModuleInfo *MI = getAnalysisIfAvailable(); assert(MI && "AsmPrinter didn't require GCModuleInfo?"); Index: llvm/lib/IR/AsmWriter.cpp =================================================================== --- llvm/lib/IR/AsmWriter.cpp +++ llvm/lib/IR/AsmWriter.cpp @@ -45,7 +45,6 @@ #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalIFunc.h" -#include "llvm/IR/GlobalIndirectSymbol.h" #include "llvm/IR/GlobalObject.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" @@ -2594,7 +2593,8 @@ void printTypeIdentities(); void printGlobal(const GlobalVariable *GV); - void printIndirectSymbol(const GlobalIndirectSymbol *GIS); + void printAlias(const GlobalAlias *GA); + void printIFunc(const GlobalIFunc *GI); void printComdat(const Comdat *C); void printFunction(const Function *F); void printArgument(const Argument *FA, AttributeSet Attrs); @@ -2832,12 +2832,12 @@ // Output all aliases. if (!M->alias_empty()) Out << "\n"; for (const GlobalAlias &GA : M->aliases()) - printIndirectSymbol(&GA); + printAlias(&GA); // Output all ifuncs. if (!M->ifunc_empty()) Out << "\n"; for (const GlobalIFunc &GI : M->ifuncs()) - printIndirectSymbol(&GI); + printIFunc(&GI); // Output all of the functions. for (const Function &F : *M) { @@ -3566,50 +3566,76 @@ printInfoComment(*GV); } -void AssemblyWriter::printIndirectSymbol(const GlobalIndirectSymbol *GIS) { - if (GIS->isMaterializable()) +void AssemblyWriter::printAlias(const GlobalAlias *GA) { + if (GA->isMaterializable()) Out << "; Materializable\n"; - AsmWriterContext WriterCtx(&TypePrinter, &Machine, GIS->getParent()); - WriteAsOperandInternal(Out, GIS, WriterCtx); + AsmWriterContext WriterCtx(&TypePrinter, &Machine, GA->getParent()); + WriteAsOperandInternal(Out, GA, WriterCtx); Out << " = "; - Out << getLinkageNameWithSpace(GIS->getLinkage()); - PrintDSOLocation(*GIS, Out); - PrintVisibility(GIS->getVisibility(), Out); - PrintDLLStorageClass(GIS->getDLLStorageClass(), Out); - PrintThreadLocalModel(GIS->getThreadLocalMode(), Out); - StringRef UA = getUnnamedAddrEncoding(GIS->getUnnamedAddr()); + Out << getLinkageNameWithSpace(GA->getLinkage()); + PrintDSOLocation(*GA, Out); + PrintVisibility(GA->getVisibility(), Out); + PrintDLLStorageClass(GA->getDLLStorageClass(), Out); + PrintThreadLocalModel(GA->getThreadLocalMode(), Out); + StringRef UA = getUnnamedAddrEncoding(GA->getUnnamedAddr()); if (!UA.empty()) Out << UA << ' '; - if (isa(GIS)) - Out << "alias "; - else if (isa(GIS)) - Out << "ifunc "; - else - llvm_unreachable("Not an alias or ifunc!"); - - TypePrinter.print(GIS->getValueType(), Out); + Out << "alias "; + TypePrinter.print(GA->getValueType(), Out); Out << ", "; - const Constant *IS = GIS->getIndirectSymbol(); - - if (!IS) { - TypePrinter.print(GIS->getType(), Out); + if (const Constant *Aliasee = GA->getAliasee()) { + writeOperand(Aliasee, !isa(Aliasee)); + } else { + TypePrinter.print(GA->getType(), Out); Out << " <>"; + } + + if (GA->hasPartition()) { + Out << ", partition \""; + printEscapedString(GA->getPartition(), Out); + Out << '"'; + } + + printInfoComment(*GA); + Out << '\n'; +} + +void AssemblyWriter::printIFunc(const GlobalIFunc *GI) { + if (GI->isMaterializable()) + Out << "; Materializable\n"; + + AsmWriterContext WriterCtx(&TypePrinter, &Machine, GI->getParent()); + WriteAsOperandInternal(Out, GI, WriterCtx); + Out << " = "; + + Out << getLinkageNameWithSpace(GI->getLinkage()); + PrintDSOLocation(*GI, Out); + PrintVisibility(GI->getVisibility(), Out); + + Out << "ifunc "; + + TypePrinter.print(GI->getValueType(), Out); + Out << ", "; + + if (const Constant *Resolver = GI->getResolver()) { + writeOperand(Resolver, !isa(Resolver)); } else { - writeOperand(IS, !isa(IS)); + TypePrinter.print(GI->getType(), Out); + Out << " <>"; } - if (GIS->hasPartition()) { + if (GI->hasPartition()) { Out << ", partition \""; - printEscapedString(GIS->getPartition(), Out); + printEscapedString(GI->getPartition(), Out); Out << '"'; } - printInfoComment(*GIS); + printInfoComment(*GI); Out << '\n'; } @@ -4600,8 +4626,12 @@ W.printGlobal(V); else if (const Function *F = dyn_cast(GV)) W.printFunction(F); + else if (const GlobalAlias *A = dyn_cast(GV)) + W.printAlias(A); + else if (const GlobalIFunc *I = dyn_cast(GV)) + W.printIFunc(I); else - W.printIndirectSymbol(cast(GV)); + llvm_unreachable("Unknown GlobalValue to print out!"); } else if (const MetadataAsValue *V = dyn_cast(this)) { V->getMetadata()->print(ROS, MST, getModuleFromVal(V)); } else if (const Constant *C = dyn_cast(this)) { Index: llvm/lib/IR/Globals.cpp =================================================================== --- llvm/lib/IR/Globals.cpp +++ llvm/lib/IR/Globals.cpp @@ -235,7 +235,7 @@ return F->empty() && !F->isMaterializable(); // Aliases and ifuncs are always definitions. - assert(isa(this)); + assert(isa(this) || isa(this)); return false; } @@ -280,14 +280,44 @@ return true; } -const GlobalObject *GlobalValue::getAliaseeObject() const { - if (auto *GO = dyn_cast(this)) +static const GlobalObject * +findBaseObject(const Constant *C, DenseSet &Aliases) { + if (auto *GO = dyn_cast(C)) return GO; - if (auto *GA = dyn_cast(this)) - return GA->getAliaseeObject(); + if (auto *GA = dyn_cast(C)) + if (Aliases.insert(GA).second) + return findBaseObject(GA->getOperand(0), Aliases); + if (auto *CE = dyn_cast(C)) { + switch (CE->getOpcode()) { + case Instruction::Add: { + auto *LHS = findBaseObject(CE->getOperand(0), Aliases); + auto *RHS = findBaseObject(CE->getOperand(1), Aliases); + if (LHS && RHS) + return nullptr; + return LHS ? LHS : RHS; + } + case Instruction::Sub: { + if (findBaseObject(CE->getOperand(1), Aliases)) + return nullptr; + return findBaseObject(CE->getOperand(0), Aliases); + } + case Instruction::IntToPtr: + case Instruction::PtrToInt: + case Instruction::BitCast: + case Instruction::GetElementPtr: + return findBaseObject(CE->getOperand(0), Aliases); + default: + break; + } + } return nullptr; } +const GlobalObject *GlobalValue::getAliaseeObject() const { + DenseSet Aliases; + return findBaseObject(this, Aliases); +} + bool GlobalValue::isAbsoluteSymbolRef() const { auto *GO = dyn_cast(this); if (!GO) @@ -420,50 +450,6 @@ clearMetadata(); } -//===----------------------------------------------------------------------===// -// GlobalIndirectSymbol Implementation -//===----------------------------------------------------------------------===// - -GlobalIndirectSymbol::GlobalIndirectSymbol(Type *Ty, ValueTy VTy, - unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, - Constant *Symbol) - : GlobalValue(Ty, VTy, &Op<0>(), 1, Linkage, Name, AddressSpace) { - Op<0>() = Symbol; -} - -static const GlobalObject * -findBaseObject(const Constant *C, DenseSet &Aliases) { - if (auto *GO = dyn_cast(C)) - return GO; - if (auto *GA = dyn_cast(C)) - if (Aliases.insert(GA).second) - return findBaseObject(GA->getOperand(0), Aliases); - if (auto *CE = dyn_cast(C)) { - switch (CE->getOpcode()) { - case Instruction::Add: { - auto *LHS = findBaseObject(CE->getOperand(0), Aliases); - auto *RHS = findBaseObject(CE->getOperand(1), Aliases); - if (LHS && RHS) - return nullptr; - return LHS ? LHS : RHS; - } - case Instruction::Sub: { - if (findBaseObject(CE->getOperand(1), Aliases)) - return nullptr; - return findBaseObject(CE->getOperand(0), Aliases); - } - case Instruction::IntToPtr: - case Instruction::PtrToInt: - case Instruction::BitCast: - case Instruction::GetElementPtr: - return findBaseObject(CE->getOperand(0), Aliases); - default: - break; - } - } - return nullptr; -} - //===----------------------------------------------------------------------===// // GlobalAlias Implementation //===----------------------------------------------------------------------===// @@ -471,8 +457,9 @@ GlobalAlias::GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Link, const Twine &Name, Constant *Aliasee, Module *ParentModule) - : GlobalIndirectSymbol(Ty, Value::GlobalAliasVal, AddressSpace, Link, Name, - Aliasee) { + : GlobalValue(Ty, Value::GlobalAliasVal, &Op<0>(), 1, Link, Name, + AddressSpace) { + setAliasee(Aliasee); if (ParentModule) ParentModule->getAliasList().push_back(this); } @@ -516,7 +503,7 @@ void GlobalAlias::setAliasee(Constant *Aliasee) { assert((!Aliasee || Aliasee->getType() == getType()) && "Alias and aliasee types should match!"); - setIndirectSymbol(Aliasee); + Op<0>().set(Aliasee); } const GlobalObject *GlobalAlias::getAliaseeObject() const { @@ -531,8 +518,9 @@ GlobalIFunc::GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Link, const Twine &Name, Constant *Resolver, Module *ParentModule) - : GlobalIndirectSymbol(Ty, Value::GlobalIFuncVal, AddressSpace, Link, Name, - Resolver) { + : GlobalObject(Ty, Value::GlobalIFuncVal, &Op<0>(), 1, Link, Name, + AddressSpace) { + setResolver(Resolver); if (ParentModule) ParentModule->getIFuncList().push_back(this); } @@ -553,5 +541,5 @@ const Function *GlobalIFunc::getResolverFunction() const { DenseSet Aliases; - return cast(findBaseObject(getIndirectSymbol(), Aliases)); + return cast(findBaseObject(getResolver(), Aliases)); } Index: llvm/lib/Linker/IRMover.cpp =================================================================== --- llvm/lib/Linker/IRMover.cpp +++ llvm/lib/Linker/IRMover.cpp @@ -492,8 +492,8 @@ void linkGlobalVariable(GlobalVariable &Dst, GlobalVariable &Src); Error linkFunctionBody(Function &Dst, Function &Src); - void linkIndirectSymbolBody(GlobalIndirectSymbol &Dst, - GlobalIndirectSymbol &Src); + void linkAliasAliasee(GlobalAlias &Dst, GlobalAlias &Src); + void linkIFuncResolver(GlobalIFunc &Dst, GlobalIFunc &Src); Error linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src); /// Replace all types in the source AttributeList with the @@ -504,7 +504,7 @@ /// into the destination module. GlobalVariable *copyGlobalVariableProto(const GlobalVariable *SGVar); Function *copyFunctionProto(const Function *SF); - GlobalValue *copyGlobalIndirectSymbolProto(const GlobalIndirectSymbol *SGIS); + GlobalValue *copyIndirectSymbolProto(const GlobalValue *SGV); /// Perform "replace all uses with" operations. These work items need to be /// performed as part of materialization, but we postpone them to happen after @@ -606,10 +606,14 @@ } else if (auto *V = dyn_cast(New)) { if (V->hasInitializer() || V->hasAppendingLinkage()) return New; - } else { - auto *IS = cast(New); - if (IS->getIndirectSymbol()) + } else if (auto *GA = dyn_cast(New)) { + if (GA->getAliasee()) + return New; + } else if (auto *GI = dyn_cast(New)) { + if (GI->getResolver()) return New; + } else { + llvm_unreachable("Invalid GlobalValue type"); } // If the global is being linked for an indirect symbol, it may have already @@ -680,22 +684,28 @@ /// Set up prototypes for any indirect symbols that come over from the source /// module. -GlobalValue * -IRLinker::copyGlobalIndirectSymbolProto(const GlobalIndirectSymbol *SGIS) { +GlobalValue *IRLinker::copyIndirectSymbolProto(const GlobalValue *SGV) { // If there is no linkage to be performed or we're linking from the source, // bring over SGA. - auto *Ty = TypeMap.get(SGIS->getValueType()); - GlobalIndirectSymbol *GIS; - if (isa(SGIS)) - GIS = GlobalAlias::create(Ty, SGIS->getAddressSpace(), - GlobalValue::ExternalLinkage, SGIS->getName(), - &DstM); - else - GIS = GlobalIFunc::create(Ty, SGIS->getAddressSpace(), - GlobalValue::ExternalLinkage, SGIS->getName(), - nullptr, &DstM); - GIS->copyAttributesFrom(SGIS); - return GIS; + auto *Ty = TypeMap.get(SGV->getValueType()); + + if (auto *GA = dyn_cast(SGV)) { + auto *DGA = GlobalAlias::create(Ty, SGV->getAddressSpace(), + GlobalValue::ExternalLinkage, + SGV->getName(), &DstM); + DGA->copyAttributesFrom(GA); + return DGA; + } + + if (auto *GI = dyn_cast(SGV)) { + auto *DGI = GlobalIFunc::create(Ty, SGV->getAddressSpace(), + GlobalValue::ExternalLinkage, + SGV->getName(), nullptr, &DstM); + DGI->copyAttributesFrom(GI); + return DGI; + } + + llvm_unreachable("Invalid source global value type"); } GlobalValue *IRLinker::copyGlobalValueProto(const GlobalValue *SGV, @@ -707,7 +717,7 @@ NewGV = copyFunctionProto(SF); } else { if (ForDefinition) - NewGV = copyGlobalIndirectSymbolProto(cast(SGV)); + NewGV = copyIndirectSymbolProto(SGV); else if (SGV->getValueType()->isFunctionTy()) NewGV = Function::Create(cast(TypeMap.get(SGV->getValueType())), @@ -1111,10 +1121,12 @@ return Error::success(); } -void IRLinker::linkIndirectSymbolBody(GlobalIndirectSymbol &Dst, - GlobalIndirectSymbol &Src) { - Mapper.scheduleMapGlobalIndirectSymbol(Dst, *Src.getIndirectSymbol(), - IndirectSymbolMCID); +void IRLinker::linkAliasAliasee(GlobalAlias &Dst, GlobalAlias &Src) { + Mapper.scheduleMapGlobalAlias(Dst, *Src.getAliasee(), IndirectSymbolMCID); +} + +void IRLinker::linkIFuncResolver(GlobalIFunc &Dst, GlobalIFunc &Src) { + Mapper.scheduleMapGlobalIFunc(Dst, *Src.getResolver(), IndirectSymbolMCID); } Error IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) { @@ -1124,7 +1136,11 @@ linkGlobalVariable(cast(Dst), *GVar); return Error::success(); } - linkIndirectSymbolBody(cast(Dst), cast(Src)); + if (auto *GA = dyn_cast(&Src)) { + linkAliasAliasee(cast(Dst), *GA); + return Error::success(); + } + linkIFuncResolver(cast(Dst), cast(Src)); return Error::success(); } Index: llvm/lib/Object/ModuleSymbolTable.cpp =================================================================== --- llvm/lib/Object/ModuleSymbolTable.cpp +++ llvm/lib/Object/ModuleSymbolTable.cpp @@ -204,8 +204,9 @@ if (GVar->isConstant()) Res |= BasicSymbolRef::SF_Const; } - if (isa_and_nonnull(GV->getAliaseeObject()) || isa(GV)) - Res |= BasicSymbolRef::SF_Executable; + if (const GlobalObject *GO = GV->getAliaseeObject()) + if (isa(GO) || isa(GO)) + Res |= BasicSymbolRef::SF_Executable; if (isa(GV)) Res |= BasicSymbolRef::SF_Indirect; if (GV->hasPrivateLinkage()) Index: llvm/lib/Transforms/IPO/LowerTypeTests.cpp =================================================================== --- llvm/lib/Transforms/IPO/LowerTypeTests.cpp +++ llvm/lib/Transforms/IPO/LowerTypeTests.cpp @@ -342,7 +342,8 @@ struct ScopedSaveAliaseesAndUsed { Module &M; SmallVector Used, CompilerUsed; - std::vector> FunctionAliases; + std::vector> FunctionAliases; + std::vector> ResolverIFuncs; ScopedSaveAliaseesAndUsed(Module &M) : M(M) { // The users of this class want to replace all function references except @@ -362,12 +363,16 @@ if (GlobalVariable *GV = collectUsedGlobalVariables(M, CompilerUsed, true)) GV->eraseFromParent(); - for (auto &GIS : concat(M.aliases(), M.ifuncs())) { + for (auto &GA : M.aliases()) { // FIXME: This should look past all aliases not just interposable ones, // see discussion on D65118. - if (auto *F = - dyn_cast(GIS.getIndirectSymbol()->stripPointerCasts())) - FunctionAliases.push_back({&GIS, F}); + if (auto *F = dyn_cast(GA.getAliasee()->stripPointerCasts())) + FunctionAliases.push_back({&GA, F}); + } + + for (auto &GI : M.ifuncs()) { + if (auto *F = dyn_cast(GI.getResolver()->stripPointerCasts())) + ResolverIFuncs.push_back({&GI, F}); } } @@ -376,8 +381,15 @@ appendToCompilerUsed(M, CompilerUsed); for (auto P : FunctionAliases) - P.first->setIndirectSymbol( + P.first->setAliasee( ConstantExpr::getBitCast(P.second, P.first->getType())); + + for (auto P : ResolverIFuncs) { + // This does not preserve pointer casts that may have been stripped by the + // constructor, but the resolver's type is different from that of the + // ifunc anyway. + P.first->setResolver(P.second); + } } }; Index: llvm/lib/Transforms/Utils/SplitModule.cpp =================================================================== --- llvm/lib/Transforms/Utils/SplitModule.cpp +++ llvm/lib/Transforms/Utils/SplitModule.cpp @@ -24,7 +24,6 @@ #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalObject.h" -#include "llvm/IR/GlobalIndirectSymbol.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instruction.h" @@ -65,9 +64,8 @@ if (const Instruction *I = dyn_cast(U)) { const GlobalValue *F = I->getParent()->getParent(); GVtoClusterMap.unionSets(GV, F); - } else if (isa(U) || isa(U) || - isa(U)) { - GVtoClusterMap.unionSets(GV, cast(U)); + } else if (const GlobalValue *GVU = dyn_cast(U)) { + GVtoClusterMap.unionSets(GV, GVU); } else { llvm_unreachable("Underimplemented use case"); } @@ -91,6 +89,14 @@ } } +static const GlobalObject *getGVPartitioningRoot(const GlobalValue *GV) +{ + const GlobalObject *GO = GV->getAliaseeObject(); + if (const auto *GI = dyn_cast_or_null(GO)) + GO = GI->getResolverFunction(); + return GO; +} + // Find partitions for module in the way that no locals need to be // globalized. // Try to balance pack those partitions into N files since this roughly equals @@ -123,14 +129,11 @@ Member = &GV; } - // For aliases we should not separate them from their aliasees regardless - // of linkage. - if (auto *GIS = dyn_cast(&GV)) { - if (const GlobalObject *Aliasee = GIS->getAliaseeObject()) - GVtoClusterMap.unionSets(&GV, Aliasee); - } else if (auto *GIS = dyn_cast(&GV)) { - GVtoClusterMap.unionSets(&GV, GIS->getResolverFunction()); - } + // Aliases should not be separated from their aliasees and ifuncs should + // not be separated from their resolvers regardless of linkage. + if (const GlobalObject *Root = getGVPartitioningRoot(&GV)) + if (&GV != Root) + GVtoClusterMap.unionSets(&GV, Root); if (const Function *F = dyn_cast(&GV)) { for (const BasicBlock &BB : *F) { @@ -227,12 +230,8 @@ // Returns whether GV should be in partition (0-based) I of N. static bool isInPartition(const GlobalValue *GV, unsigned I, unsigned N) { - if (auto *GIS = dyn_cast(GV)) { - if (const GlobalObject *Base = GIS->getAliaseeObject()) - GV = Base; - } else if (auto *GIS = dyn_cast(GV)) { - GV = GIS->getResolverFunction(); - } + if (const GlobalObject *Root = getGVPartitioningRoot(GV)) + GV = Root; StringRef Name; if (const Comdat *C = GV->getComdat()) Index: llvm/lib/Transforms/Utils/ValueMapper.cpp =================================================================== --- llvm/lib/Transforms/Utils/ValueMapper.cpp +++ llvm/lib/Transforms/Utils/ValueMapper.cpp @@ -26,7 +26,8 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" -#include "llvm/IR/GlobalIndirectSymbol.h" +#include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/GlobalIFunc.h" #include "llvm/IR/GlobalObject.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/InlineAsm.h" @@ -68,7 +69,7 @@ enum EntryKind { MapGlobalInit, MapAppendingVar, - MapGlobalIndirectSymbol, + MapAliasOrIFunc, RemapFunction }; struct GVInitTy { @@ -79,8 +80,8 @@ GlobalVariable *GV; Constant *InitPrefix; }; - struct GlobalIndirectSymbolTy { - GlobalIndirectSymbol *GIS; + struct AliasOrIFuncTy { + GlobalValue *GV; Constant *Target; }; @@ -91,7 +92,7 @@ union { GVInitTy GVInit; AppendingGVTy AppendingGV; - GlobalIndirectSymbolTy GlobalIndirectSymbol; + AliasOrIFuncTy AliasOrIFunc; Function *RemapF; } Data; }; @@ -163,8 +164,8 @@ bool IsOldCtorDtor, ArrayRef NewMembers, unsigned MCID); - void scheduleMapGlobalIndirectSymbol(GlobalIndirectSymbol &GIS, Constant &Target, - unsigned MCID); + void scheduleMapAliasOrIFunc(GlobalValue &GV, Constant &Target, + unsigned MCID); void scheduleRemapFunction(Function &F, unsigned MCID); void flush(); @@ -873,10 +874,17 @@ E.AppendingGVIsOldCtorDtor, makeArrayRef(NewInits)); break; } - case WorklistEntry::MapGlobalIndirectSymbol: - E.Data.GlobalIndirectSymbol.GIS->setIndirectSymbol( - mapConstant(E.Data.GlobalIndirectSymbol.Target)); + case WorklistEntry::MapAliasOrIFunc: { + GlobalValue *GV = E.Data.AliasOrIFunc.GV; + Constant *Target = mapConstant(E.Data.AliasOrIFunc.Target); + if (auto *GA = dyn_cast(GV)) + GA->setAliasee(Target); + else if (auto *GI = dyn_cast(GV)) + GI->setResolver(Target); + else + llvm_unreachable("Not alias or ifunc"); break; + } case WorklistEntry::RemapFunction: remapFunction(*E.Data.RemapF); break; @@ -1069,16 +1077,18 @@ AppendingInits.append(NewMembers.begin(), NewMembers.end()); } -void Mapper::scheduleMapGlobalIndirectSymbol(GlobalIndirectSymbol &GIS, - Constant &Target, unsigned MCID) { - assert(AlreadyScheduled.insert(&GIS).second && "Should not reschedule"); +void Mapper::scheduleMapAliasOrIFunc(GlobalValue &GV, Constant &Target, + unsigned MCID) { + assert(AlreadyScheduled.insert(&GV).second && "Should not reschedule"); + assert((isa(GV) || isa(GV)) && + "Should be alias or ifunc"); assert(MCID < MCs.size() && "Invalid mapping context"); WorklistEntry WE; - WE.Kind = WorklistEntry::MapGlobalIndirectSymbol; + WE.Kind = WorklistEntry::MapAliasOrIFunc; WE.MCID = MCID; - WE.Data.GlobalIndirectSymbol.GIS = &GIS; - WE.Data.GlobalIndirectSymbol.Target = &Target; + WE.Data.AliasOrIFunc.GV = &GV; + WE.Data.AliasOrIFunc.Target = &Target; Worklist.push_back(WE); } @@ -1175,10 +1185,14 @@ GV, InitPrefix, IsOldCtorDtor, NewMembers, MCID); } -void ValueMapper::scheduleMapGlobalIndirectSymbol(GlobalIndirectSymbol &GIS, - Constant &Target, - unsigned MCID) { - getAsMapper(pImpl)->scheduleMapGlobalIndirectSymbol(GIS, Target, MCID); +void ValueMapper::scheduleMapGlobalAlias(GlobalAlias &GA, Constant &Aliasee, + unsigned MCID) { + getAsMapper(pImpl)->scheduleMapAliasOrIFunc(GA, Aliasee, MCID); +} + +void ValueMapper::scheduleMapGlobalIFunc(GlobalIFunc &GI, Constant &Resolver, + unsigned MCID) { + getAsMapper(pImpl)->scheduleMapAliasOrIFunc(GI, Resolver, MCID); } void ValueMapper::scheduleRemapFunction(Function &F, unsigned MCID) { Index: llvm/unittests/IR/ConstantsTest.cpp =================================================================== --- llvm/unittests/IR/ConstantsTest.cpp +++ llvm/unittests/IR/ConstantsTest.cpp @@ -385,7 +385,7 @@ new GlobalVariable(*M, PtrTy, false, GlobalValue::ExternalLinkage, GEP); ASSERT_EQ(GEP, Ref->getInitializer()); - auto *Global = new GlobalVariable(*M, PtrTy, false, + auto *Global = new GlobalVariable(*M, IntTy, false, GlobalValue::ExternalLinkage, nullptr); auto *Alias = GlobalAlias::create(IntTy, 0, GlobalValue::ExternalLinkage, "alias", Global, M.get());