class DIE;
class DIEAbbrev;
class GCMetadataPrinter;
+class GlobalIndirectSymbol;
class GlobalValue;
class GlobalVariable;
class MachineBasicBlock;
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);
};
}
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:
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() {
(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))
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
}
// Okay, create the alias but do not insert it into the module yet.
- std::unique_ptr<GlobalAlias> GA(
- GlobalAlias::create(Ty, AddrSpace, (GlobalValue::LinkageTypes)Linkage,
- Name, Aliasee, /*Parent*/ nullptr));
+ std::unique_ptr<GlobalIndirectSymbol> 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);
}
// 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<GlobalAlias>(GA.get()));
+ else
+ llvm_unreachable("Not an alias!");
assert(GA->getName() == Name && "Should not be a name conflict!");
// The module owns this now
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();
SmallVector<Instruction *, 64> InstructionList;
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
- std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
+ std::vector<std::pair<GlobalIndirectSymbol*, unsigned> > IndirectSymbolInits;
std::vector<std::pair<Function*, unsigned> > FunctionPrefixes;
std::vector<std::pair<Function*, unsigned> > FunctionPrologues;
std::vector<std::pair<Function*, unsigned> > FunctionPersonalityFns;
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<uint64_t> Record,
StringRef Blob,
}
/// 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<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
- std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
+ std::vector<std::pair<GlobalIndirectSymbol*, unsigned> >
+ IndirectSymbolInitWorklist;
std::vector<std::pair<Function*, unsigned> > FunctionPrefixWorklist;
std::vector<std::pair<Function*, unsigned> > FunctionPrologueWorklist;
std::vector<std::pair<Function*, unsigned> > FunctionPersonalityFnWorklist;
GlobalInitWorklist.swap(GlobalInits);
- AliasInitWorklist.swap(AliasInits);
+ IndirectSymbolInitWorklist.swap(IndirectSymbolInits);
FunctionPrefixWorklist.swap(FunctionPrefixes);
FunctionPrologueWorklist.swap(FunctionPrologues);
FunctionPersonalityFnWorklist.swap(FunctionPersonalityFns);
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<Constant>(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<GlobalAlias>(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()) {
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
// Force deallocation of memory for these vectors to favor the client that
// want lazy deserialization.
std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits);
- std::vector<std::pair<GlobalAlias*, unsigned> >().swap(AliasInits);
+ std::vector<std::pair<GlobalIndirectSymbol*, unsigned> >().swap(
+ IndirectSymbolInits);
return std::error_code();
}
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:
// 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;
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()) {
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]
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<GlobalAlias>(&GIS) && MAI->hasAltEntry() && isa<MCBinaryExpr>(Expr))
+ OutStreamer->EmitSymbolAttribute(Name, MCSA_AltEntry);
+
+ // Emit the directives as assignments aka .set:
+ OutStreamer->EmitAssignment(Name, Expr);
+
+ if (auto *GA = dyn_cast<GlobalAlias>(&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<MCSymbolELF>(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
}
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<MCBinaryExpr>(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<MCSymbolELF>(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
AliasStack.push_back(Cur);
}
for (const GlobalAlias *AncestorAlias : reverse(AliasStack))
- printAlias(*AncestorAlias);
+ emitGlobalIndirectSymbol(M, *AncestorAlias);
AliasStack.clear();
}
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);
// 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);
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<GlobalAlias>(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 << " <<NULL ALIASEE>>";
} else {
- writeOperand(Aliasee, !isa<ConstantExpr>(Aliasee));
+ writeOperand(IS, !isa<ConstantExpr>(IS));
}
- printInfoComment(*GA);
+ printInfoComment(*GIS);
Out << '\n';
}
else if (const Function *F = dyn_cast<Function>(GV))
W.printFunction(F);
else
- W.printAlias(cast<GlobalAlias>(GV));
+ W.printIndirectSymbol(cast<GlobalIndirectSymbol>(GV));
} else if (const MetadataAsValue *V = dyn_cast<MetadataAsValue>(this)) {
V->getMetadata()->print(ROS, MST, getModuleFromVal(V));
} else if (const Constant *C = dyn_cast<Constant>(this)) {
if (const Function *F = dyn_cast<Function>(this))
return F->empty() && !F->isMaterializable();
- // Aliases are always definitions.
- assert(isa<GlobalAlias>(this));
+ // Aliases and ifuncs are always definitions.
+ assert(isa<GlobalIndirectSymbol>(this));
return false;
}
// referenced by the initializer to the alive set.
if (GV->hasInitializer())
MarkUsedGlobalsAsNeeded(GV->getInitializer());
- } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(G)) {
- // The target of a global alias is needed.
- MarkUsedGlobalsAsNeeded(GA->getAliasee());
+ } else if (GlobalIndirectSymbol *GIS = dyn_cast<GlobalIndirectSymbol>(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