From 41071debe9b8887449c3f2ee0dd7124ed47bdda8 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Fri, 15 Aug 2008 23:26:23 +0000 Subject: [PATCH] Clean up CodeGenModule interface. - Add CodeGenModule::EmitTopLevelDecl which uses switch on kind instead of ugly & slow dyn_cast chains. - Drop some simple forwarding methods into the ObjC runtime. - Privatize appropriate methods. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54827 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 115 +++++++++++++++++++++++++++------- lib/CodeGen/CodeGenModule.h | 37 +++++------ lib/CodeGen/ModuleBuilder.cpp | 60 ++---------------- 3 files changed, 112 insertions(+), 100 deletions(-) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 3340cdff56..99390c1135 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -86,10 +86,10 @@ void CodeGenModule::WarnUnsupported(const Decl *D, const char *Type) { &Msg, 1); } -/// setVisibility - Set the visibility for the given LLVM GlobalValue -/// according to the given clang AST visibility value. -void CodeGenModule::setVisibility(llvm::GlobalValue *GV, - VisibilityAttr::VisibilityTypes Vis) { +/// setGlobalVisibility - Set the visibility for the given LLVM +/// GlobalValue according to the given clang AST visibility value. +static void setGlobalVisibility(llvm::GlobalValue *GV, + VisibilityAttr::VisibilityTypes Vis) { switch (Vis) { default: assert(0 && "Unknown visibility!"); case VisibilityAttr::DefaultVisibility: @@ -185,7 +185,7 @@ void CodeGenModule::SetGlobalValueAttributes(const FunctionDecl *FD, GV->setLinkage(llvm::Function::WeakLinkage); if (const VisibilityAttr *attr = FD->getAttr()) - CodeGenModule::setVisibility(GV, attr->getVisibility()); + setGlobalVisibility(GV, attr->getVisibility()); // FIXME: else handle -fvisibility if (const AsmLabelAttr *ALA = FD->getAttr()) { @@ -242,24 +242,6 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD, SetGlobalValueAttributes(FD, F); } -void CodeGenModule::EmitObjCMethod(const ObjCMethodDecl *OMD) { - // If this is not a prototype, emit the body. - if (OMD->getBody()) - CodeGenFunction(*this).GenerateObjCMethod(OMD); -} -void CodeGenModule::EmitObjCProtocolImplementation(const ObjCProtocolDecl *PD){ - Runtime->GenerateProtocol(PD); -} - -void CodeGenModule::EmitObjCCategoryImpl(const ObjCCategoryImplDecl *OCD) { - Runtime->GenerateCategory(OCD); -} - -void -CodeGenModule::EmitObjCClassImplementation(const ObjCImplementationDecl *OID) { - Runtime->GenerateClass(OID); -} - void CodeGenModule::EmitStatics() { // Emit code for each used static decl encountered. Since a previously unused // static decl may become used during the generation of code for a static @@ -486,7 +468,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { GV->setAlignment(Align / 8); if (const VisibilityAttr *attr = D->getAttr()) - setVisibility(GV, attr->getVisibility()); + setGlobalVisibility(GV, attr->getVisibility()); // FIXME: else handle -fvisibility if (const AsmLabelAttr *ALA = D->getAttr()) { @@ -849,3 +831,88 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str) { llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &str) { return GetAddrOfConstantString(str + "\0"); } + +/// EmitTopLevelDecl - Emit code for a single top level declaration. +void CodeGenModule::EmitTopLevelDecl(Decl *D) { + // If an error has occurred, stop code generation, but continue + // parsing and semantic analysis (to ensure all warnings and errors + // are emitted). + if (Diags.hasErrorOccurred()) + return; + + switch (D->getKind()) { + case Decl::Function: + case Decl::Var: + EmitGlobal(cast(D)); + break; + + case Decl::Namespace: + assert(0 && "FIXME: Namespace unsupported"); + break; + + // Objective-C Decls + + // Forward declarations, no (immediate) code generation. + case Decl::ObjCClass: + case Decl::ObjCCategory: + case Decl::ObjCForwardProtocol: + case Decl::ObjCInterface: + break; + + case Decl::ObjCProtocol: + Runtime->GenerateProtocol(cast(D)); + break; + + case Decl::ObjCCategoryImpl: + Runtime->GenerateCategory(cast(D)); + break; + + case Decl::ObjCImplementation: + Runtime->GenerateClass(cast(D)); + break; + + case Decl::ObjCMethod: { + ObjCMethodDecl *OMD = cast(D); + // If this is not a prototype, emit the body. + if (OMD->getBody()) + CodeGenFunction(*this).GenerateObjCMethod(OMD); + break; + } + case Decl::ObjCPropertyImpl: + assert(0 && "FIXME: ObjCPropertyImpl unsupported"); + break; + case Decl::ObjCCompatibleAlias: + assert(0 && "FIXME: ObjCCompatibleAlias unsupported"); + break; + + case Decl::LinkageSpec: { + LinkageSpecDecl *LSD = cast(D); + if (LSD->getLanguage() == LinkageSpecDecl::lang_cxx) + WarnUnsupported(LSD, "linkage spec"); + // FIXME: implement C++ linkage, C linkage works mostly by C + // language reuse already. + break; + } + + case Decl::FileScopeAsm: { + FileScopeAsmDecl *AD = cast(D); + std::string AsmString(AD->getAsmString()->getStrData(), + AD->getAsmString()->getByteLength()); + + const std::string &S = getModule().getModuleInlineAsm(); + if (S.empty()) + getModule().setModuleInlineAsm(AsmString); + else + getModule().setModuleInlineAsm(S + '\n' + AsmString); + break; + } + + default: + // Make sure we handled everything we should, every other kind is + // a non-top-level decl. FIXME: Would be nice to have an + // isTopLevelDeclKind function. Need to recode Decl::Kind to do + // that easily. + assert(isa(D) && "Unsupported decl kind"); + } +} + diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index dd8ac1739f..5f3714cb28 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -52,8 +52,8 @@ namespace CodeGen { class CGDebugInfo; class CGObjCRuntime; -/// CodeGenModule - This class organizes the cross-module state that is used -/// while generating LLVM code. +/// CodeGenModule - This class organizes the cross-function state that +/// is used while generating LLVM code. class CodeGenModule { typedef std::vector< std::pair > CtorList; @@ -138,11 +138,6 @@ public: /// GetAddrOfFunction - Return the llvm::Constant for the address /// of the given function. llvm::Constant *GetAddrOfFunction(const FunctionDecl *D); - - /// getBuiltinLibFunction - Given a builtin id for a function like - /// "__builtin_fabsf", return a Function* for "fabsf". - /// - llvm::Function *getBuiltinLibFunction(unsigned BuiltinID); /// GetStringForStringLiteral - Return the appropriate bytes for a /// string literal, properly padded to match the literal type. If @@ -150,6 +145,8 @@ public: /// GetAddrOfConstantStringLiteral. std::string GetStringForStringLiteral(const StringLiteral *E); + /// GetAddrOfConstantCFString - Return a pointer to a + /// constant CFString object for the given string. llvm::Constant *GetAddrOfConstantCFString(const std::string& str); /// GetAddrOfConstantStringFromLiteral - Return a pointer to a @@ -170,21 +167,19 @@ public: /// array containing the literal and a terminating '\-' /// character. The result has pointer to array type. llvm::Constant *GetAddrOfConstantCString(const std::string &str); + + /// getBuiltinLibFunction - Given a builtin id for a function like + /// "__builtin_fabsf", return a Function* for "fabsf". + llvm::Function *getBuiltinLibFunction(unsigned BuiltinID); llvm::Function *getMemCpyFn(); llvm::Function *getMemMoveFn(); llvm::Function *getMemSetFn(); llvm::Function *getIntrinsic(unsigned IID, const llvm::Type **Tys = 0, unsigned NumTys = 0); - - void EmitObjCMethod(const ObjCMethodDecl *OMD); - void EmitObjCCategoryImpl(const ObjCCategoryImplDecl *OCD); - void EmitObjCClassImplementation(const ObjCImplementationDecl *OID); - void EmitObjCProtocolImplementation(const ObjCProtocolDecl *PD); - /// EmitGlobal - Emit code for a singal global function or var - /// decl. Forward declarations are emitted lazily. - void EmitGlobal(const ValueDecl *D); + /// EmitTopLevelDecl - Emit code for a single top level declaration. + void EmitTopLevelDecl(Decl *D); void AddAnnotation(llvm::Constant *C) { Annotations.push_back(C); } @@ -194,18 +189,12 @@ public: const AnnotateAttr *AA, unsigned LineNo); /// WarnUnsupported - Print out a warning that codegen doesn't support the - /// specified stmt yet. - + /// specified stmt yet. void WarnUnsupported(const Stmt *S, const char *Type); /// WarnUnsupported - Print out a warning that codegen doesn't support the /// specified decl yet. void WarnUnsupported(const Decl *D, const char *Type); - - /// setVisibility - Set the visibility for the given LLVM GlobalValue - /// according to the given clang AST visibility value. - static void setVisibility(llvm::GlobalValue *GV, - VisibilityAttr::VisibilityTypes); private: void SetFunctionAttributes(const FunctionDecl *FD, @@ -215,6 +204,10 @@ private: void SetGlobalValueAttributes(const FunctionDecl *FD, llvm::GlobalValue *GV); + /// EmitGlobal - Emit code for a singal global function or var + /// decl. Forward declarations are emitted lazily. + void EmitGlobal(const ValueDecl *D); + void EmitGlobalDefinition(const ValueDecl *D); llvm::GlobalValue *EmitForwardFunctionDefinition(const FunctionDecl *D); void EmitGlobalFunctionDefinition(const FunctionDecl *D); diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index 17ac0023f8..dafc0f5e25 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -63,63 +63,15 @@ namespace { } virtual void HandleTopLevelDecl(Decl *D) { - // If an error occurred, stop code generation, but continue parsing and - // semantic analysis (to ensure all warnings and errors are emitted). - if (Diags.hasErrorOccurred()) - return; - - if (FunctionDecl *FD = dyn_cast(D)) { - Builder->EmitGlobal(FD); - } else if (VarDecl *VD = dyn_cast(D)) { - Builder->EmitGlobal(VD); - } else if (isa(D) || isa(D)) { - //Forward declaration. Only used for type checking. - } else if (ObjCProtocolDecl *PD = dyn_cast(D)){ - // Generate Protocol object. - Builder->EmitObjCProtocolImplementation(PD); - } else if (isa(D)){ - //Only used for typechecking. - } else if (ObjCCategoryImplDecl *OCD = dyn_cast(D)){ - // Generate methods, attach to category structure - Builder->EmitObjCCategoryImpl(OCD); - } else if (ObjCImplementationDecl * OID = - dyn_cast(D)){ - // Generate methods, attach to class structure - Builder->EmitObjCClassImplementation(OID); - } else if (isa(D)){ - // Ignore - generated when the implementation decl is CodeGen'd - } else if (ObjCMethodDecl *OMD = dyn_cast(D)){ - Builder->EmitObjCMethod(OMD); - } else if (isa(D) || isa(D)) { - // Forward declaration. Only used for type checking. - } else if (ObjCMethodDecl *OMD = dyn_cast(D)){ - Builder->EmitObjCMethod(OMD); - } else if (LinkageSpecDecl *LSD = dyn_cast(D)) { - if (LSD->getLanguage() == LinkageSpecDecl::lang_cxx) - Builder->WarnUnsupported(LSD, "linkage spec"); - // FIXME: implement C++ linkage, C linkage works mostly by C - // language reuse already. - } else if (FileScopeAsmDecl *AD = dyn_cast(D)) { - std::string AsmString(AD->getAsmString()->getStrData(), - AD->getAsmString()->getByteLength()); - - const std::string &S = Builder->getModule().getModuleInlineAsm(); - if (S.empty()) - Builder->getModule().setModuleInlineAsm(AsmString); - else - Builder->getModule().setModuleInlineAsm(S + '\n' + AsmString); - } else { - assert(isa(D) && "Unknown top level decl"); - // TODO: handle debug info? - } - + // Make sure to emit all elements of a ScopedDecl. if (ScopedDecl *SD = dyn_cast(D)) { - SD = SD->getNextDeclarator(); - if (SD) - HandleTopLevelDecl(SD); + for (; SD; SD = SD->getNextDeclarator()) + Builder->EmitTopLevelDecl(SD); + } else { + Builder->EmitTopLevelDecl(D); } } - + /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl /// (e.g. struct, union, enum, class) is completed. This allows the client to /// hack on the type, which can occur at any point in the file (because these -- 2.40.0