aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp121
1 files changed, 100 insertions, 21 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 7e522f2..e4ae5bb 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -274,20 +274,21 @@ void CodeGenModule::applyGlobalValReplacements() {
// This is only used in aliases that we created and we know they have a
// linear structure.
-static const llvm::GlobalObject *getAliasedGlobal(const llvm::GlobalAlias &GA) {
- llvm::SmallPtrSet<const llvm::GlobalAlias*, 4> Visited;
- const llvm::Constant *C = &GA;
+static const llvm::GlobalObject *getAliasedGlobal(
+ const llvm::GlobalIndirectSymbol &GIS) {
+ llvm::SmallPtrSet<const llvm::GlobalIndirectSymbol*, 4> Visited;
+ const llvm::Constant *C = &GIS;
for (;;) {
C = C->stripPointerCasts();
if (auto *GO = dyn_cast<llvm::GlobalObject>(C))
return GO;
// stripPointerCasts will not walk over weak aliases.
- auto *GA2 = dyn_cast<llvm::GlobalAlias>(C);
- if (!GA2)
+ auto *GIS2 = dyn_cast<llvm::GlobalIndirectSymbol>(C);
+ if (!GIS2)
return nullptr;
- if (!Visited.insert(GA2).second)
+ if (!Visited.insert(GIS2).second)
return nullptr;
- C = GA2->getAliasee();
+ C = GIS2->getIndirectSymbol();
}
}
@@ -299,20 +300,35 @@ void CodeGenModule::checkAliases() {
DiagnosticsEngine &Diags = getDiags();
for (const GlobalDecl &GD : Aliases) {
const auto *D = cast<ValueDecl>(GD.getDecl());
- const AliasAttr *AA = D->getAttr<AliasAttr>();
+ SourceLocation Location;
+ bool IsIFunc = D->hasAttr<IFuncAttr>();
+ if (const Attr *A = D->getDefiningAttr())
+ Location = A->getLocation();
+ else
+ llvm_unreachable("Not an alias or ifunc?");
StringRef MangledName = getMangledName(GD);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
- auto *Alias = cast<llvm::GlobalAlias>(Entry);
+ auto *Alias = cast<llvm::GlobalIndirectSymbol>(Entry);
const llvm::GlobalValue *GV = getAliasedGlobal(*Alias);
if (!GV) {
Error = true;
- Diags.Report(AA->getLocation(), diag::err_cyclic_alias);
+ Diags.Report(Location, diag::err_cyclic_alias) << IsIFunc;
} else if (GV->isDeclaration()) {
Error = true;
- Diags.Report(AA->getLocation(), diag::err_alias_to_undefined);
+ Diags.Report(Location, diag::err_alias_to_undefined)
+ << IsIFunc << IsIFunc;
+ } else if (IsIFunc) {
+ // Check resolver function type.
+ llvm::FunctionType *FTy = dyn_cast<llvm::FunctionType>(
+ GV->getType()->getPointerElementType());
+ assert(FTy);
+ if (!FTy->getReturnType()->isPointerTy())
+ Diags.Report(Location, diag::err_ifunc_resolver_return);
+ if (FTy->getNumParams())
+ Diags.Report(Location, diag::err_ifunc_resolver_params);
}
- llvm::Constant *Aliasee = Alias->getAliasee();
+ llvm::Constant *Aliasee = Alias->getIndirectSymbol();
llvm::GlobalValue *AliaseeGV;
if (auto CE = dyn_cast<llvm::ConstantExpr>(Aliasee))
AliaseeGV = cast<llvm::GlobalValue>(CE->getOperand(0));
@@ -323,7 +339,7 @@ void CodeGenModule::checkAliases() {
StringRef AliasSection = SA->getName();
if (AliasSection != AliaseeGV->getSection())
Diags.Report(SA->getLocation(), diag::warn_alias_with_section)
- << AliasSection;
+ << AliasSection << IsIFunc << IsIFunc;
}
// We have to handle alias to weak aliases in here. LLVM itself disallows
@@ -331,13 +347,13 @@ void CodeGenModule::checkAliases() {
// compatibility with gcc we implement it by just pointing the alias
// to its aliasee's aliasee. We also warn, since the user is probably
// expecting the link to be weak.
- if (auto GA = dyn_cast<llvm::GlobalAlias>(AliaseeGV)) {
+ if (auto GA = dyn_cast<llvm::GlobalIndirectSymbol>(AliaseeGV)) {
if (GA->isInterposable()) {
- Diags.Report(AA->getLocation(), diag::warn_alias_to_weak_alias)
- << GV->getName() << GA->getName();
+ Diags.Report(Location, diag::warn_alias_to_weak_alias)
+ << GV->getName() << GA->getName() << IsIFunc;
Aliasee = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
- GA->getAliasee(), Alias->getType());
- Alias->setAliasee(Aliasee);
+ GA->getIndirectSymbol(), Alias->getType());
+ Alias->setIndirectSymbol(Aliasee);
}
}
}
@@ -347,7 +363,7 @@ void CodeGenModule::checkAliases() {
for (const GlobalDecl &GD : Aliases) {
StringRef MangledName = getMangledName(GD);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
- auto *Alias = cast<llvm::GlobalAlias>(Entry);
+ auto *Alias = dyn_cast<llvm::GlobalIndirectSymbol>(Entry);
Alias->replaceAllUsesWith(llvm::UndefValue::get(Alias->getType()));
Alias->eraseFromParent();
}
@@ -1538,6 +1554,10 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
if (Global->hasAttr<AliasAttr>())
return EmitAliasDefinition(GD);
+ // IFunc like an alias whose value is resolved at runtime by calling resolver.
+ if (Global->hasAttr<IFuncAttr>())
+ return emitIFuncDefinition(GD);
+
// If this is CUDA, be selective about which declarations we emit.
if (LangOpts.CUDA) {
if (LangOpts.CUDAIsDevice) {
@@ -2901,7 +2921,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
StringRef MangledName = getMangledName(GD);
if (AA->getAliasee() == MangledName) {
- Diags.Report(AA->getLocation(), diag::err_cyclic_alias);
+ Diags.Report(AA->getLocation(), diag::err_cyclic_alias) << 0;
return;
}
@@ -2932,7 +2952,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
if (Entry) {
if (GA->getAliasee() == Entry) {
- Diags.Report(AA->getLocation(), diag::err_cyclic_alias);
+ Diags.Report(AA->getLocation(), diag::err_cyclic_alias) << 0;
return;
}
@@ -2969,6 +2989,65 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
setAliasAttributes(D, GA);
}
+void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
+ const auto *D = cast<ValueDecl>(GD.getDecl());
+ const IFuncAttr *IFA = D->getAttr<IFuncAttr>();
+ assert(IFA && "Not an ifunc?");
+
+ StringRef MangledName = getMangledName(GD);
+
+ if (IFA->getResolver() == MangledName) {
+ Diags.Report(IFA->getLocation(), diag::err_cyclic_alias) << 1;
+ return;
+ }
+
+ // Report an error if some definition overrides ifunc.
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ if (Entry && !Entry->isDeclaration()) {
+ GlobalDecl OtherGD;
+ if (lookupRepresentativeDecl(MangledName, OtherGD) &&
+ DiagnosedConflictingDefinitions.insert(GD).second) {
+ Diags.Report(D->getLocation(), diag::err_duplicate_mangled_name);
+ Diags.Report(OtherGD.getDecl()->getLocation(),
+ diag::note_previous_definition);
+ }
+ return;
+ }
+
+ Aliases.push_back(GD);
+
+ llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
+ llvm::Constant *Resolver =
+ GetOrCreateLLVMFunction(IFA->getResolver(), DeclTy, GD,
+ /*ForVTable=*/false);
+ llvm::GlobalIFunc *GIF =
+ llvm::GlobalIFunc::create(DeclTy, 0, llvm::Function::ExternalLinkage,
+ "", Resolver, &getModule());
+ if (Entry) {
+ if (GIF->getResolver() == Entry) {
+ Diags.Report(IFA->getLocation(), diag::err_cyclic_alias) << 1;
+ return;
+ }
+ assert(Entry->isDeclaration());
+
+ // If there is a declaration in the module, then we had an extern followed
+ // by the ifunc, as in:
+ // extern int test();
+ // ...
+ // int test() __attribute__((ifunc("resolver")));
+ //
+ // Remove it and replace uses of it with the ifunc.
+ GIF->takeName(Entry);
+
+ Entry->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GIF,
+ Entry->getType()));
+ Entry->eraseFromParent();
+ } else
+ GIF->setName(MangledName);
+
+ SetCommonAttributes(D, GIF);
+}
+
llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,
ArrayRef<llvm::Type*> Tys) {
return llvm::Intrinsic::getDeclaration(&getModule(), (llvm::Intrinsic::ID)IID,