From d4cbda6292b321c2e7dce7f039d92918fee99b3a Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Sun, 8 Jun 2008 15:45:52 +0000 Subject: [PATCH] implement the alias attirbute (in both Sema and Codegen) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52092 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Attr.h | 16 ++++++++- include/clang/Parse/AttributeList.h | 1 + lib/CodeGen/CodeGenModule.cpp | 56 ++++++++++++++++++++--------- lib/CodeGen/CodeGenModule.h | 3 ++ lib/Parse/AttributeList.cpp | 3 ++ lib/Sema/Sema.h | 1 + lib/Sema/SemaDecl.cpp | 29 +++++++++++++++ test/CodeGen/attributes.c | 4 +++ 8 files changed, 95 insertions(+), 18 deletions(-) diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 7840d59c3a..c7da6d924b 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -23,6 +23,7 @@ namespace clang { class Attr { public: enum Kind { + Alias, Aligned, Packed, Annotate, @@ -106,7 +107,20 @@ public: } static bool classof(const AnnotateAttr *A) { return true; } }; - + +class AliasAttr : public Attr { + std::string Aliasee; +public: + AliasAttr(const std::string &aliasee) : Attr(Alias), Aliasee(aliasee) {} + + const std::string& getAliasee() const { return Aliasee; } + + // Implement isa/cast/dyncast/etc. + + static bool classof(const Attr *A) { return A->getKind() == Alias; } + static bool classof(const AliasAttr *A) { return true; } +}; + class NoReturnAttr : public Attr { public: NoReturnAttr() : Attr(NoReturn) {} diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 63318dbcb4..112a495e6e 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -43,6 +43,7 @@ public: enum Kind { // Please keep this list alphabetized. AT_address_space, + AT_alias, AT_aligned, AT_annotate, AT_deprecated, diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index b802ce7d97..1d0001c607 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -188,6 +188,24 @@ bool hasAggregateLLVMType(QualType T) { !T->isVoidType() && !T->isVectorType() && !T->isFunctionType(); } +void CodeGenModule::SetGlobalValueAttributes(const FunctionDecl *FD, + llvm::GlobalValue *GV) { + // TODO: Set up linkage and many other things. Note, this is a simple + // approximation of what we really want. + if (FD->getStorageClass() == FunctionDecl::Static) + GV->setLinkage(llvm::Function::InternalLinkage); + else if (FD->getAttr()) + GV->setLinkage(llvm::Function::DLLImportLinkage); + else if (FD->getAttr()) + GV->setLinkage(llvm::Function::DLLExportLinkage); + else if (FD->getAttr() || FD->isInline()) + GV->setLinkage(llvm::Function::WeakLinkage); + + if (const VisibilityAttr *attr = FD->getAttr()) + CodeGenModule::setVisibility(GV, attr->getVisibility()); + // FIXME: else handle -fvisibility +} + void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD, llvm::Function *F, const llvm::FunctionType *FTy) { @@ -230,20 +248,7 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD, if (FD->getAttr()) F->setCallingConv(llvm::CallingConv::Fast); - // TODO: Set up linkage and many other things. Note, this is a simple - // approximation of what we really want. - if (FD->getStorageClass() == FunctionDecl::Static) - F->setLinkage(llvm::Function::InternalLinkage); - else if (FD->getAttr()) - F->setLinkage(llvm::Function::DLLImportLinkage); - else if (FD->getAttr()) - F->setLinkage(llvm::Function::DLLExportLinkage); - else if (FD->getAttr() || FD->isInline()) - F->setLinkage(llvm::Function::WeakLinkage); - - if (const VisibilityAttr *attr = FD->getAttr()) - CodeGenModule::setVisibility(F, attr->getVisibility()); - // FIXME: else handle -fvisibility + SetGlobalValueAttributes(FD, F); } @@ -263,8 +268,20 @@ llvm::Constant *CodeGenModule::GetAddrOfFunctionDecl(const FunctionDecl *D, // If it doesn't already exist, just create and return an entry. if (F == 0) { // FIXME: param attributes for sext/zext etc. - F = llvm::Function::Create(FTy, llvm::Function::ExternalLinkage, - D->getName(), &getModule()); + if (D->getBody() || !D->getAttr()) + F = llvm::Function::Create(FTy, llvm::Function::ExternalLinkage, + D->getName(), &getModule()); + else { + const std::string& aliaseeName = D->getAttr()->getAliasee(); + llvm::Function *aliasee = getModule().getFunction(aliaseeName); + llvm::GlobalValue *alias = new llvm::GlobalAlias(aliasee->getType(), + llvm::Function::ExternalLinkage, + D->getName(), + aliasee, + &getModule()); + SetGlobalValueAttributes(D, alias); + return Entry = alias; + } SetFunctionAttributes(D, F, FTy); return Entry = F; @@ -494,8 +511,11 @@ void CodeGenModule::EmitObjCClassImplementation( void CodeGenModule::EmitFunction(const FunctionDecl *FD) { // If this is not a prototype, emit the body. - if (!FD->isThisDeclarationADefinition()) + if (!FD->isThisDeclarationADefinition()) { + if (FD->getAttr()) + GetAddrOfFunctionDecl(FD, true); return; + } // If the function is a static, defer code generation until later so we can // easily omit unused statics. @@ -534,6 +554,8 @@ void CodeGenModule::EmitStatics() { if (const FunctionDecl *FD = dyn_cast(D)) { if (FD->getBody()) CodeGenFunction(*this).GenerateCode(FD); + else if (FD->getAttr()) + GetAddrOfFunctionDecl(FD, true); } else { EmitGlobalVarInit(cast(D)); } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index de2995f6a8..d69b87f12f 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -154,6 +154,9 @@ private: void SetFunctionAttributes(const FunctionDecl *FD, llvm::Function *F, const llvm::FunctionType *FTy); + + void SetGlobalValueAttributes(const FunctionDecl *FD, + llvm::GlobalValue *GV); }; } // end namespace CodeGen diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index c99722c54a..8697d4ece8 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -56,6 +56,9 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { if (!memcmp(Str, "pure", 4)) return AT_pure; if (!memcmp(Str, "mode", 4)) return AT_mode; break; + case 5: + if (!memcmp(Str, "alias", 5)) return AT_alias; + break; case 6: if (!memcmp(Str, "packed", 6)) return AT_packed; if (!memcmp(Str, "malloc", 6)) return AT_malloc; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index f91cbf4a20..a86bc6b62b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -319,6 +319,7 @@ private: void HandleExtVectorTypeAttribute(TypedefDecl *d, AttributeList *rawAttr); void HandleAlignedAttribute(Decl *d, AttributeList *rawAttr); + void HandleAliasAttribute(Decl *d, AttributeList *rawAttr); void HandlePackedAttribute(Decl *d, AttributeList *rawAttr); void HandleAnnotateAttribute(Decl *d, AttributeList *rawAttr); void HandleNoReturnAttribute(Decl *d, AttributeList *rawAttr); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b56622ceb9..ed34f9fe00 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2250,6 +2250,9 @@ void Sema::HandleDeclAttribute(Decl *New, AttributeList *Attr) { } // FIXME: Diagnostic? break; + case AttributeList::AT_alias: + HandleAliasAttribute(New, Attr); + break; case AttributeList::AT_deprecated: HandleDeprecatedAttribute(New, Attr); break; @@ -2438,6 +2441,32 @@ void Sema::HandlePackedAttribute(Decl *d, AttributeList *rawAttr) { rawAttr->getName()->getName()); } +void Sema::HandleAliasAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() != 1) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("1")); + return; + } + + Expr *Arg = static_cast(rawAttr->getArg(0)); + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Str = dyn_cast(Arg); + + if (Str == 0 || Str->isWide()) { + Diag(rawAttr->getLoc(), diag::err_attribute_argument_n_not_string, + "alias", std::string("1")); + return; + } + + const char *Alias = Str->getStrData(); + unsigned AliasLen = Str->getByteLength(); + + // FIXME: check if target symbol exists in current file + + d->addAttr(new AliasAttr(std::string(Alias, AliasLen))); +} + void Sema::HandleNoReturnAttribute(Decl *d, AttributeList *rawAttr) { // check the attribute arguments. if (rawAttr->getNumArgs() != 0) { diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c index a310a3ab64..95273f84a6 100644 --- a/test/CodeGen/attributes.c +++ b/test/CodeGen/attributes.c @@ -24,3 +24,7 @@ int t6 __attribute__((visibility("protected"))); // RUN: clang -emit-llvm < %s | grep 't7.*nounwind' void t7() __attribute__((noreturn, nothrow)); void t7() {} + +// RUN: clang -emit-llvm < %s | grep 't9.*alias.*weak.*t8' +void __t8() {} +void t9() __attribute__((weak, alias("__t8"))); -- 2.40.0