Fix a number of issues w.r.t. emission of global for functions and

aliases.
 - Attributes specific to a definition are only set when the
   definition is seen.
 - Alias generation is delayed until the end of the module; necessary
   since the alias may reference forward.
 - Fixes: PR2743, <rdr://6140807&6094512>
 - Improves: <rdr://6095112> (added XFAIL)

Also, print module on verification failures.

llvm-svn: 55966
This commit is contained in:
Daniel Dunbar
2008-09-08 23:44:31 +00:00
parent 3d56051f70
commit 0beedc1684
5 changed files with 159 additions and 70 deletions

View File

@@ -56,6 +56,7 @@ CodeGenModule::~CodeGenModule() {
void CodeGenModule::Release() {
EmitStatics();
EmitAliases();
if (Runtime)
if (llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction())
AddGlobalCtor(ObjCInitFunction);
@@ -63,7 +64,10 @@ void CodeGenModule::Release() {
EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitAnnotations();
// Run the verifier to check that the generated code is consistent.
assert(!verifyModule(TheModule));
if (verifyModule(TheModule, llvm::PrintMessageAction)) {
TheModule.dump();
assert(0 && "Module failed verification!");
}
}
/// ErrorUnsupported - Print out an error that codegen doesn't support the
@@ -176,18 +180,25 @@ void CodeGenModule::EmitAnnotations() {
static void SetGlobalValueAttributes(const Decl *D,
bool IsInternal,
bool IsInline,
llvm::GlobalValue *GV) {
llvm::GlobalValue *GV,
bool ForDefinition) {
// TODO: Set up linkage and many other things. Note, this is a simple
// approximation of what we really want.
if (IsInternal) {
GV->setLinkage(llvm::Function::InternalLinkage);
} else {
if (!ForDefinition) {
// Only a few attributes are set on declarations.
if (D->getAttr<DLLImportAttr>())
GV->setLinkage(llvm::Function::DLLImportLinkage);
else if (D->getAttr<DLLExportAttr>())
GV->setLinkage(llvm::Function::DLLExportLinkage);
else if (D->getAttr<WeakAttr>() || IsInline)
GV->setLinkage(llvm::Function::WeakLinkage);
} else {
if (IsInternal) {
GV->setLinkage(llvm::Function::InternalLinkage);
} else {
if (D->getAttr<DLLImportAttr>())
GV->setLinkage(llvm::Function::DLLImportLinkage);
else if (D->getAttr<DLLExportAttr>())
GV->setLinkage(llvm::Function::DLLExportLinkage);
else if (D->getAttr<WeakAttr>() || IsInline)
GV->setLinkage(llvm::Function::WeakLinkage);
}
}
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>())
@@ -201,7 +212,7 @@ static void SetGlobalValueAttributes(const Decl *D,
}
}
static void SetFunctionAttrs(const CGFunctionInfo &Info, llvm::Function *F) {
static void SetFunctionParamAttrs(const CGFunctionInfo &Info, llvm::Function *F) {
ParamAttrListType ParamAttrList;
Info.constructParamAttrList(ParamAttrList);
@@ -215,26 +226,79 @@ static void SetFunctionAttrs(const CGFunctionInfo &Info, llvm::Function *F) {
/// SetFunctionAttributesForDefinition - Set function attributes
/// specific to a function definition.
void CodeGenModule::SetFunctionAttributesForDefinition(llvm::Function *F) {
void CodeGenModule::SetFunctionAttributesForDefinition(const Decl *D,
llvm::Function *F) {
if (isa<ObjCMethodDecl>(D)) {
SetGlobalValueAttributes(D, true, false, F, true);
} else {
const FunctionDecl *FD = cast<FunctionDecl>(D);
SetGlobalValueAttributes(FD, FD->getStorageClass() == FunctionDecl::Static,
FD->isInline(), F, true);
}
if (!Features.Exceptions)
F->addParamAttr(0, llvm::ParamAttr::NoUnwind);
}
void CodeGenModule::SetMethodAttributes(const ObjCMethodDecl *MD,
llvm::Function *F) {
SetFunctionAttrs(CGFunctionInfo(MD, Context), F);
SetFunctionParamAttrs(CGFunctionInfo(MD, Context), F);
SetFunctionAttributesForDefinition(F);
SetGlobalValueAttributes(MD, true, false, F);
SetFunctionAttributesForDefinition(MD, F);
}
void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
llvm::Function *F) {
SetFunctionAttrs(CGFunctionInfo(FD), F);
SetFunctionParamAttrs(CGFunctionInfo(FD), F);
SetGlobalValueAttributes(FD, FD->getStorageClass() == FunctionDecl::Static,
FD->isInline(), F);
SetGlobalValueAttributes(FD, FD->getStorageClass() == FunctionDecl::Static,
FD->isInline(), F, false);
}
void CodeGenModule::EmitAliases() {
for (unsigned i = 0, e = Aliases.size(); i != e; ++i) {
const FunctionDecl *D = Aliases[i];
const AliasAttr *AA = D->getAttr<AliasAttr>();
// This is something of a hack, if the FunctionDecl got overridden
// then its attributes will be moved to the new declaration. In
// this case the current decl has no alias attribute, but we will
// eventually see it.
if (!AA)
continue;
const std::string& aliaseeName = AA->getAliasee();
llvm::Function *aliasee = getModule().getFunction(aliaseeName);
if (!aliasee) {
// FIXME: This isn't unsupported, this is just an error, which
// sema should catch, but...
ErrorUnsupported(D, "alias referencing a missing function");
continue;
}
llvm::GlobalValue *GA =
new llvm::GlobalAlias(aliasee->getType(),
llvm::Function::ExternalLinkage,
D->getName(),
aliasee,
&getModule());
llvm::GlobalValue *&Entry = GlobalDeclMap[D->getIdentifier()];
if (Entry) {
// If we created a dummy function for this then replace it.
GA->takeName(Entry);
llvm::Value *Casted =
llvm::ConstantExpr::getBitCast(GA, Entry->getType());
Entry->replaceAllUsesWith(Casted);
Entry->eraseFromParent();
Entry = GA;
}
// Alias should never be internal or inline.
SetGlobalValueAttributes(D, false, false, GA, true);
}
}
void CodeGenModule::EmitStatics() {
@@ -250,6 +314,8 @@ void CodeGenModule::EmitStatics() {
// Check if we have used a decl with the same name
// FIXME: The AST should have some sort of aggregate decls or
// global symbol map.
// FIXME: This is missing some important cases. For example, we
// need to check for uses in an alias and in a constructor.
if (!GlobalDeclMap.count(D->getIdentifier()))
continue;
@@ -316,8 +382,16 @@ void CodeGenModule::EmitGlobal(const ValueDecl *Global) {
bool isDef, isStatic;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
isDef = (FD->isThisDeclarationADefinition() ||
FD->getAttr<AliasAttr>());
// Aliases are deferred until code for everything else has been
// emitted.
if (FD->getAttr<AliasAttr>()) {
assert(!FD->isThisDeclarationADefinition() &&
"Function alias cannot have a definition!");
Aliases.push_back(FD);
return;
}
isDef = FD->isThisDeclarationADefinition();
isStatic = FD->getStorageClass() == FunctionDecl::Static;
} else if (const VarDecl *VD = cast<VarDecl>(Global)) {
assert(VD->isFileVarDecl() && "Cannot emit local var decl as global.");
@@ -512,29 +586,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
llvm::GlobalValue *
CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D) {
// FIXME: param attributes for sext/zext etc.
if (const AliasAttr *AA = D->getAttr<AliasAttr>()) {
assert(!D->getBody() && "Unexpected alias attr on function with body.");
const std::string& aliaseeName = AA->getAliasee();
llvm::Function *aliasee = getModule().getFunction(aliaseeName);
llvm::GlobalValue *alias = new llvm::GlobalAlias(aliasee->getType(),
llvm::Function::ExternalLinkage,
D->getName(),
aliasee,
&getModule());
// Alias should never be internal
SetGlobalValueAttributes(D, false, false, alias);
return alias;
} else {
const llvm::Type *Ty = getTypes().ConvertType(D->getType());
llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty),
llvm::Function::ExternalLinkage,
D->getName(), &getModule());
SetFunctionAttributes(D, F);
return F;
}
const llvm::Type *Ty = getTypes().ConvertType(D->getType());
llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty),
llvm::Function::ExternalLinkage,
D->getName(), &getModule());
SetFunctionAttributes(D, F);
return F;
}
llvm::Constant *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D) {
@@ -575,33 +632,22 @@ void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
Entry->replaceAllUsesWith(NewPtrForOldDecl);
// Ok, delete the old function now, which is dead.
// FIXME: Add GlobalValue->eraseFromParent().
assert(Entry->isDeclaration() && "Shouldn't replace non-declaration");
if (llvm::Function *F = dyn_cast<llvm::Function>(Entry)) {
F->eraseFromParent();
} else if (llvm::GlobalAlias *GA = dyn_cast<llvm::GlobalAlias>(Entry)) {
GA->eraseFromParent();
} else {
assert(0 && "Invalid global variable type.");
}
Entry->eraseFromParent();
Entry = NewFn;
}
}
if (D->getAttr<AliasAttr>()) {
;
} else {
llvm::Function *Fn = cast<llvm::Function>(Entry);
CodeGenFunction(*this).GenerateCode(D, Fn);
llvm::Function *Fn = cast<llvm::Function>(Entry);
CodeGenFunction(*this).GenerateCode(D, Fn);
SetFunctionAttributesForDefinition(Fn);
if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) {
AddGlobalCtor(Fn, CA->getPriority());
} else if (const DestructorAttr *DA = D->getAttr<DestructorAttr>()) {
AddGlobalDtor(Fn, DA->getPriority());
}
SetFunctionAttributesForDefinition(D, Fn);
if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) {
AddGlobalCtor(Fn, CA->getPriority());
} else if (const DestructorAttr *DA = D->getAttr<DestructorAttr>()) {
AddGlobalDtor(Fn, DA->getPriority());
}
}

View File

@@ -79,11 +79,16 @@ class CodeGenModule {
/// (which may change with attributes such as asm-labels).
llvm::DenseMap<IdentifierInfo*, llvm::GlobalValue*> GlobalDeclMap;
/// List of static global for which code generation is delayed. When
/// the translation unit has been fully processed we will lazily
/// emit definitions for only the decls that were actually used.
/// This should contain only Function and Var decls, and only those
/// which actually define something.
/// Aliases - List of aliases in module. These cannot be emitted
/// until all the code has been seen, as they reference things by
/// name instead of directly and may reference forward.
std::vector<const FunctionDecl*> Aliases;
/// StaticDecls - List of static global for which code generation is
/// delayed. When the translation unit has been fully processed we
/// will lazily emit definitions for only the decls that were
/// actually used. This should contain only Function and Var decls,
/// and only those which actually define something.
std::vector<const ValueDecl*> StaticDecls;
/// GlobalCtors - Store the list of global constructors and their
@@ -213,7 +218,9 @@ public:
private:
/// SetFunctionAttributesForDefinition - Set function attributes
/// specific to a function definition.
void SetFunctionAttributesForDefinition(llvm::Function *F);
/// \param D - The ObjCMethodDecl or FunctionDecl defining \arg F.
void SetFunctionAttributesForDefinition(const Decl *D,
llvm::Function *F);
void SetFunctionAttributes(const FunctionDecl *FD,
llvm::Function *F);
@@ -238,9 +245,9 @@ private:
/// or destructor array.
void EmitCtorList(const CtorList &Fns, const char *GlobalName);
void EmitAliases(void);
void EmitAnnotations(void);
void EmitStatics(void);
};
} // end namespace CodeGen
} // end namespace clang

View File

@@ -0,0 +1,16 @@
// RUN: clang -emit-llvm -o %t %s
// PR2743
// <rdr://6094512>
/* CodeGen should handle this even if it makes it past
sema. Unfortunately this test will become useless once sema starts
rejecting this. */
static void e0();
void f0() { e0(); }
inline void e1();
void f1() { e1(); }
void e2() __attribute__((weak));
void f2() { e2(); }

View File

@@ -0,0 +1,6 @@
// RUN: clang --emit-llvm -o %t %s &&
// RUN: grep -e "alias" %t
// XFAIL
static inline int foo () { return 0; }
int bar () __attribute__ ((alias ("foo")));

View File

@@ -0,0 +1,14 @@
// RUN: clang -emit-llvm -o %t %s &&
// RUN: grep -e "@f = alias" %t | count 1 &&
// RUN: grep -e "bitcast (i32 (i32)\\* @f to i32 (float)\\*)" %t | count 1
// <rdar://problem/6140807>
int f(float) __attribute__((weak, alias("x")));
// Make sure we replace uses properly...
int y() {
return f(1.);
}
int x(int) {
}