Index: llvm/trunk/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/AsmPrinter.h +++ llvm/trunk/include/llvm/CodeGen/AsmPrinter.h @@ -34,6 +34,7 @@ class DIE; class DIEAbbrev; class GCMetadataPrinter; +class GlobalIndirectSymbol; class GlobalValue; class GlobalVariable; class MachineBasicBlock; @@ -546,6 +547,9 @@ void EmitXXStructorList(const DataLayout &DL, const Constant *List, bool isCtor); GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &C); + /// Emit GlobalAlias or GlobalIFunc. + void emitGlobalIndirectSymbol(Module &M, + const GlobalIndirectSymbol& GIS); }; } Index: llvm/trunk/lib/AsmParser/LLParser.h =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.h +++ llvm/trunk/lib/AsmParser/LLParser.h @@ -275,9 +275,11 @@ bool HasLinkage, unsigned Visibility, unsigned DLLStorageClass, GlobalVariable::ThreadLocalMode TLM, bool UnnamedAddr); - bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Linkage, - unsigned Visibility, unsigned DLLStorageClass, - GlobalVariable::ThreadLocalMode TLM, bool UnnamedAddr); + bool parseIndirectSymbol(const std::string &Name, LocTy Loc, + unsigned Linkage, unsigned Visibility, + unsigned DLLStorageClass, + GlobalVariable::ThreadLocalMode TLM, + bool UnnamedAddr); bool parseComdat(); bool ParseStandaloneMetadata(); bool ParseNamedMetadata(); Index: llvm/trunk/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.cpp +++ llvm/trunk/lib/AsmParser/LLParser.cpp @@ -503,8 +503,9 @@ if (Lex.getKind() != lltok::kw_alias) return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, DLLStorageClass, TLM, UnnamedAddr); - return ParseAlias(Name, NameLoc, Linkage, Visibility, DLLStorageClass, TLM, - UnnamedAddr); + + return parseIndirectSymbol(Name, NameLoc, Linkage, Visibility, + DLLStorageClass, TLM, UnnamedAddr); } /// ParseNamedGlobal: @@ -533,8 +534,8 @@ return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, DLLStorageClass, TLM, UnnamedAddr); - return ParseAlias(Name, NameLoc, Linkage, Visibility, DLLStorageClass, TLM, - UnnamedAddr); + return parseIndirectSymbol(Name, NameLoc, Linkage, Visibility, + DLLStorageClass, TLM, UnnamedAddr); } bool LLParser::parseComdat() { @@ -690,26 +691,31 @@ (GlobalValue::VisibilityTypes)V == GlobalValue::DefaultVisibility; } -/// ParseAlias: +/// parseIndirectSymbol: /// ::= GlobalVar '=' OptionalLinkage OptionalVisibility /// OptionalDLLStorageClass OptionalThreadLocal -/// OptionalUnnamedAddr 'alias' Aliasee +/// OptionalUnnamedAddr 'alias' IndirectSymbol /// -/// Aliasee +/// IndirectSymbol /// ::= TypeAndValue /// /// Everything through OptionalUnnamedAddr has already been parsed. /// -bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, unsigned L, - unsigned Visibility, unsigned DLLStorageClass, - GlobalVariable::ThreadLocalMode TLM, - bool UnnamedAddr) { - assert(Lex.getKind() == lltok::kw_alias); +bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc, + unsigned L, unsigned Visibility, + unsigned DLLStorageClass, + GlobalVariable::ThreadLocalMode TLM, + bool UnnamedAddr) { + bool IsAlias; + if (Lex.getKind() == lltok::kw_alias) + IsAlias = true; + else + llvm_unreachable("Not an alias!"); Lex.Lex(); GlobalValue::LinkageTypes Linkage = (GlobalValue::LinkageTypes) L; - if(!GlobalAlias::isValidLinkage(Linkage)) + if(IsAlias && !GlobalAlias::isValidLinkage(Linkage)) return Error(NameLoc, "invalid linkage type for alias"); if (!isValidVisibilityForLinkage(Visibility, L)) @@ -746,11 +752,16 @@ return Error(AliaseeLoc, "An alias must have pointer type"); unsigned AddrSpace = PTy->getAddressSpace(); - if (Ty != PTy->getElementType()) + if (IsAlias && Ty != PTy->getElementType()) return Error( ExplicitTypeLoc, "explicit pointee type doesn't match operand's pointee type"); + if (!IsAlias && !PTy->getElementType()->isFunctionTy()) + return Error( + ExplicitTypeLoc, + "explicit pointee type should be a function type"); + GlobalValue *GVal = nullptr; // See if the alias was forward referenced, if so, prepare to replace the @@ -770,9 +781,13 @@ } // Okay, create the alias but do not insert it into the module yet. - std::unique_ptr GA( - GlobalAlias::create(Ty, AddrSpace, (GlobalValue::LinkageTypes)Linkage, - Name, Aliasee, /*Parent*/ nullptr)); + std::unique_ptr GA; + if (IsAlias) + GA.reset(GlobalAlias::create(Ty, AddrSpace, + (GlobalValue::LinkageTypes)Linkage, Name, + Aliasee, /*Parent*/ nullptr)); + else + llvm_unreachable("Not an alias!"); GA->setThreadLocalMode(TLM); GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); @@ -795,7 +810,10 @@ } // Insert into the module, we know its name won't collide now. - M->getAliasList().push_back(GA.get()); + if (IsAlias) + M->getAliasList().push_back(cast(GA.get())); + else + llvm_unreachable("Not an alias!"); assert(GA->getName() == Name && "Should not be a name conflict!"); // The module owns this now Index: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp @@ -163,7 +163,7 @@ SmallVector InstructionList; std::vector > GlobalInits; - std::vector > AliasInits; + std::vector > IndirectSymbolInits; std::vector > FunctionPrefixes; std::vector > FunctionPrologues; std::vector > FunctionPersonalityFns; @@ -395,7 +395,7 @@ std::error_code rememberAndSkipMetadata(); std::error_code parseFunctionBody(Function *F); std::error_code globalCleanup(); - std::error_code resolveGlobalAndAliasInits(); + std::error_code resolveGlobalAndIndirectSymbolInits(); std::error_code parseMetadata(bool ModuleLevel = false); std::error_code parseMetadataStrings(ArrayRef Record, StringRef Blob, @@ -2492,15 +2492,16 @@ } /// Resolve all of the initializers for global values and aliases that we can. -std::error_code BitcodeReader::resolveGlobalAndAliasInits() { +std::error_code BitcodeReader::resolveGlobalAndIndirectSymbolInits() { std::vector > GlobalInitWorklist; - std::vector > AliasInitWorklist; + std::vector > + IndirectSymbolInitWorklist; std::vector > FunctionPrefixWorklist; std::vector > FunctionPrologueWorklist; std::vector > FunctionPersonalityFnWorklist; GlobalInitWorklist.swap(GlobalInits); - AliasInitWorklist.swap(AliasInits); + IndirectSymbolInitWorklist.swap(IndirectSymbolInits); FunctionPrefixWorklist.swap(FunctionPrefixes); FunctionPrologueWorklist.swap(FunctionPrologues); FunctionPersonalityFnWorklist.swap(FunctionPersonalityFns); @@ -2519,20 +2520,20 @@ GlobalInitWorklist.pop_back(); } - while (!AliasInitWorklist.empty()) { - unsigned ValID = AliasInitWorklist.back().second; + while (!IndirectSymbolInitWorklist.empty()) { + unsigned ValID = IndirectSymbolInitWorklist.back().second; if (ValID >= ValueList.size()) { - AliasInits.push_back(AliasInitWorklist.back()); + IndirectSymbolInits.push_back(IndirectSymbolInitWorklist.back()); } else { Constant *C = dyn_cast_or_null(ValueList[ValID]); if (!C) return error("Expected a constant"); - GlobalAlias *Alias = AliasInitWorklist.back().first; - if (C->getType() != Alias->getType()) + GlobalIndirectSymbol *GIS = IndirectSymbolInitWorklist.back().first; + if (isa(GIS) && C->getType() != GIS->getType()) return error("Alias and aliasee types don't match"); - Alias->setAliasee(C); + GIS->setIndirectSymbol(C); } - AliasInitWorklist.pop_back(); + IndirectSymbolInitWorklist.pop_back(); } while (!FunctionPrefixWorklist.empty()) { @@ -3157,8 +3158,8 @@ std::error_code BitcodeReader::globalCleanup() { // Patch the initializers for globals and aliases up. - resolveGlobalAndAliasInits(); - if (!GlobalInits.empty() || !AliasInits.empty()) + resolveGlobalAndIndirectSymbolInits(); + if (!GlobalInits.empty() || !IndirectSymbolInits.empty()) return error("Malformed global initializer set"); // Look for intrinsic functions which need to be upgraded at some point @@ -3175,7 +3176,8 @@ // Force deallocation of memory for these vectors to favor the client that // want lazy deserialization. std::vector >().swap(GlobalInits); - std::vector >().swap(AliasInits); + std::vector >().swap( + IndirectSymbolInits); return std::error_code(); } @@ -3325,7 +3327,7 @@ case bitc::CONSTANTS_BLOCK_ID: if (std::error_code EC = parseConstants()) return EC; - if (std::error_code EC = resolveGlobalAndAliasInits()) + if (std::error_code EC = resolveGlobalAndIndirectSymbolInits()) return EC; break; case bitc::METADATA_BLOCK_ID: @@ -3658,7 +3660,7 @@ // ALIAS: [alias type, addrspace, aliasee val#, linkage, visibility, dllstorageclass] case bitc::MODULE_CODE_ALIAS: case bitc::MODULE_CODE_ALIAS_OLD: { - bool NewRecord = BitCode == bitc::MODULE_CODE_ALIAS; + bool NewRecord = BitCode != bitc::MODULE_CODE_ALIAS_OLD; if (Record.size() < (3 + (unsigned)NewRecord)) return error("Invalid record"); unsigned OpNum = 0; @@ -3679,8 +3681,13 @@ auto Val = Record[OpNum++]; auto Linkage = Record[OpNum++]; - auto *NewGA = GlobalAlias::create( + GlobalIndirectSymbol *NewGA; + if (BitCode == bitc::MODULE_CODE_ALIAS || + BitCode == bitc::MODULE_CODE_ALIAS_OLD) + NewGA = GlobalAlias::create( Ty, AddrSpace, getDecodedLinkage(Linkage), "", TheModule); + else + llvm_unreachable("Not an alias!"); // Old bitcode files didn't have visibility field. // Local linkage must have default visibility. if (OpNum != Record.size()) { @@ -3698,7 +3705,7 @@ if (OpNum != Record.size()) NewGA->setUnnamedAddr(Record[OpNum++]); ValueList.push_back(NewGA); - AliasInits.push_back(std::make_pair(NewGA, Val)); + IndirectSymbolInits.push_back(std::make_pair(NewGA, Val)); break; } /// MODULE_CODE_PURGEVALS: [numvals] Index: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1060,6 +1060,49 @@ EmitGlobalVariable(GV); } +void AsmPrinter::emitGlobalIndirectSymbol(Module &M, + const GlobalIndirectSymbol& GIS) { + MCSymbol *Name = getSymbol(&GIS); + + if (GIS.hasExternalLinkage() || !MAI->getWeakRefDirective()) + OutStreamer->EmitSymbolAttribute(Name, MCSA_Global); + else if (GIS.hasWeakLinkage() || GIS.hasLinkOnceLinkage()) + OutStreamer->EmitSymbolAttribute(Name, MCSA_WeakReference); + else + assert(GIS.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 (GIS.getType()->getPointerElementType()->isFunctionTy()) + OutStreamer->EmitSymbolAttribute(Name, MCSA_ELF_TypeFunction); + + EmitVisibility(Name, GIS.getVisibility()); + + const MCExpr *Expr = lowerConstant(GIS.getIndirectSymbol()); + + if (isa(&GIS) && MAI->hasAltEntry() && isa(Expr)) + OutStreamer->EmitSymbolAttribute(Name, MCSA_AltEntry); + + // Emit the directives as assignments aka .set: + OutStreamer->EmitAssignment(Name, 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 *BaseObject = GA->getBaseObject(); + if (MAI->hasDotTypeDotSizeDirective() && GA->getValueType()->isSized() && + (!BaseObject || BaseObject->hasPrivateLinkage())) { + const DataLayout &DL = M.getDataLayout(); + uint64_t Size = DL.getTypeAllocSize(GA->getValueType()); + OutStreamer->emitELFSize(cast(Name), + MCConstantExpr::create(Size, OutContext)); + } + } +} + bool AsmPrinter::doFinalization(Module &M) { // Set the MachineFunction to nullptr so that we can catch attempted // accesses to MF specific features at the module level and so that @@ -1148,45 +1191,7 @@ } OutStreamer->AddBlankLine(); - const auto printAlias = [this, &M](const GlobalAlias &Alias) { - MCSymbol *Name = getSymbol(&Alias); - - if (Alias.hasExternalLinkage() || !MAI->getWeakRefDirective()) - OutStreamer->EmitSymbolAttribute(Name, MCSA_Global); - else if (Alias.hasWeakLinkage() || Alias.hasLinkOnceLinkage()) - OutStreamer->EmitSymbolAttribute(Name, MCSA_WeakReference); - else - assert(Alias.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 (Alias.getType()->getPointerElementType()->isFunctionTy()) - OutStreamer->EmitSymbolAttribute(Name, MCSA_ELF_TypeFunction); - - EmitVisibility(Name, Alias.getVisibility()); - const MCExpr *Expr = lowerConstant(Alias.getAliasee()); - - if (MAI->hasAltEntry() && isa(Expr)) - OutStreamer->EmitSymbolAttribute(Name, MCSA_AltEntry); - - // Emit the directives as assignments aka .set: - OutStreamer->EmitAssignment(Name, Expr); - - // 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 = Alias.getBaseObject(); - if (MAI->hasDotTypeDotSizeDirective() && Alias.getValueType()->isSized() && - (!BaseObject || BaseObject->hasPrivateLinkage())) { - const DataLayout &DL = M.getDataLayout(); - uint64_t Size = DL.getTypeAllocSize(Alias.getValueType()); - OutStreamer->emitELFSize(cast(Name), - MCConstantExpr::create(Size, OutContext)); - } - }; // Print aliases in topological order, that is, for each alias a = b, // b must be printed before a. // This is because on some targets (e.g. PowerPC) linker expects aliases in @@ -1201,7 +1206,7 @@ AliasStack.push_back(Cur); } for (const GlobalAlias *AncestorAlias : reverse(AliasStack)) - printAlias(*AncestorAlias); + emitGlobalIndirectSymbol(M, *AncestorAlias); AliasStack.clear(); } Index: llvm/trunk/lib/IR/AsmWriter.cpp =================================================================== --- llvm/trunk/lib/IR/AsmWriter.cpp +++ llvm/trunk/lib/IR/AsmWriter.cpp @@ -2047,7 +2047,7 @@ void printTypeIdentities(); void printGlobal(const GlobalVariable *GV); - void printAlias(const GlobalAlias *GV); + void printIndirectSymbol(const GlobalIndirectSymbol *GIS); void printComdat(const Comdat *C); void printFunction(const Function *F); void printArgument(const Argument *FA, AttributeSet Attrs, unsigned Idx); @@ -2270,7 +2270,7 @@ // Output all aliases. if (!M->alias_empty()) Out << "\n"; for (const GlobalAlias &GA : M->aliases()) - printAlias(&GA); + printIndirectSymbol(&GA); // Output global use-lists. printUseLists(nullptr); @@ -2451,36 +2451,39 @@ printInfoComment(*GV); } -void AssemblyWriter::printAlias(const GlobalAlias *GA) { - if (GA->isMaterializable()) +void AssemblyWriter::printIndirectSymbol(const GlobalIndirectSymbol *GIS) { + if (GIS->isMaterializable()) Out << "; Materializable\n"; - WriteAsOperandInternal(Out, GA, &TypePrinter, &Machine, GA->getParent()); + WriteAsOperandInternal(Out, GIS, &TypePrinter, &Machine, GIS->getParent()); Out << " = "; - PrintLinkage(GA->getLinkage(), Out); - PrintVisibility(GA->getVisibility(), Out); - PrintDLLStorageClass(GA->getDLLStorageClass(), Out); - PrintThreadLocalModel(GA->getThreadLocalMode(), Out); - if (GA->hasUnnamedAddr()) + PrintLinkage(GIS->getLinkage(), Out); + PrintVisibility(GIS->getVisibility(), Out); + PrintDLLStorageClass(GIS->getDLLStorageClass(), Out); + PrintThreadLocalModel(GIS->getThreadLocalMode(), Out); + if (GIS->hasUnnamedAddr()) Out << "unnamed_addr "; - Out << "alias "; + if (isa(GIS)) + Out << "alias "; + else + llvm_unreachable("Not an alias!"); - TypePrinter.print(GA->getValueType(), Out); + TypePrinter.print(GIS->getValueType(), Out); Out << ", "; - const Constant *Aliasee = GA->getAliasee(); + const Constant *IS = GIS->getIndirectSymbol(); - if (!Aliasee) { - TypePrinter.print(GA->getType(), Out); + if (!IS) { + TypePrinter.print(GIS->getType(), Out); Out << " <>"; } else { - writeOperand(Aliasee, !isa(Aliasee)); + writeOperand(IS, !isa(IS)); } - printInfoComment(*GA); + printInfoComment(*GIS); Out << '\n'; } @@ -3348,7 +3351,7 @@ else if (const Function *F = dyn_cast(GV)) W.printFunction(F); else - W.printAlias(cast(GV)); + W.printIndirectSymbol(cast(GV)); } 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/trunk/lib/IR/Globals.cpp =================================================================== --- llvm/trunk/lib/IR/Globals.cpp +++ llvm/trunk/lib/IR/Globals.cpp @@ -159,8 +159,8 @@ if (const Function *F = dyn_cast(this)) return F->empty() && !F->isMaterializable(); - // Aliases are always definitions. - assert(isa(this)); + // Aliases and ifuncs are always definitions. + assert(isa(this)); return false; } Index: llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp +++ llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp @@ -205,9 +205,9 @@ // referenced by the initializer to the alive set. if (GV->hasInitializer()) MarkUsedGlobalsAsNeeded(GV->getInitializer()); - } else if (GlobalAlias *GA = dyn_cast(G)) { - // The target of a global alias is needed. - MarkUsedGlobalsAsNeeded(GA->getAliasee()); + } else if (GlobalIndirectSymbol *GIS = dyn_cast(G)) { + // The target of a global alias or ifunc is needed. + MarkUsedGlobalsAsNeeded(GIS->getIndirectSymbol()); } else { // Otherwise this must be a function object. We have to scan the body of // the function looking for constants and global values which are used as