From b7ec246872b412f0e7bb9e93eacfd78cfa6adfb3 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Sat, 16 Aug 2008 03:19:19 +0000 Subject: [PATCH] Add NeXT runtime support for generating methods. Change CodeGenFunction::EmitParmDecl to take either a ParmVarDecl or an ImplicitParamDecl. Drop hasAggregateLLVMType from CodeGenModule.cpp (use version in CodeGenFunction). Change the Objective-C method generation to use EmitParmDecl for implicit parameters. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54838 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDecl.cpp | 5 ++- lib/CodeGen/CGObjC.cpp | 38 ++++++----------- lib/CodeGen/CGObjCGNU.cpp | 10 ----- lib/CodeGen/CGObjCMac.cpp | 77 ++++++++++++++++++++++++++++++++--- lib/CodeGen/CodeGenFunction.h | 6 ++- lib/CodeGen/CodeGenModule.cpp | 7 +--- 6 files changed, 93 insertions(+), 50 deletions(-) diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 5f0f7a987f..1d1721011b 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -191,7 +191,10 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { /// Emit an alloca (or GlobalValue depending on target) /// for the specified parameter and set up LocalDeclMap. -void CodeGenFunction::EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg) { +void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { + // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl? + assert(isa(D) || isa(D) && + "Invalid argument to EmitParmDecl"); QualType Ty = D.getType(); llvm::Value *DeclPtr; diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 54b4e19c57..2b4eb5b528 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -124,45 +124,31 @@ void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { // Emit allocs for param decls. Give the LLVM Argument nodes names. llvm::Function::arg_iterator AI = CurFn->arg_begin(); + // Name the struct return argument. if (hasAggregateLLVMType(OMD->getResultType())) { + AI->setName("agg.result"); ++AI; } + // Add implicit parameters to the decl map. - // TODO: Add something to AST to let the runtime specify the names and types - // of these. - - llvm::Value *&SelfEntry = LocalDeclMap[OMD->getSelfDecl()]; - const llvm::Type *IPTy = AI->getType(); - llvm::Value *DeclPtr = new llvm::AllocaInst(IPTy, 0, AI->getName() + - ".addr", AllocaInsertPt); - // Store the initial value into the alloca. - Builder.CreateStore(AI, DeclPtr); - SelfEntry = DeclPtr; + EmitParmDecl(*OMD->getSelfDecl(), AI); + ++AI; + + EmitParmDecl(*OMD->getCmdDecl(), AI); ++AI; - llvm::Value *&CmdEntry = LocalDeclMap[OMD->getCmdDecl()]; - IPTy = AI->getType(); - DeclPtr = new llvm::AllocaInst(IPTy, 0, AI->getName() + - ".addr", AllocaInsertPt); - // Store the initial value into the alloca. - Builder.CreateStore(AI, DeclPtr); - CmdEntry = DeclPtr; for (unsigned i = 0, e = OMD->getNumParams(); i != e; ++i, ++AI) { assert(AI != CurFn->arg_end() && "Argument mismatch!"); EmitParmDecl(*OMD->getParamDecl(i), AI); } - + assert(AI == CurFn->arg_end() && "Argument mismatch"); + GenerateFunction(OMD->getBody()); } -llvm::Value *CodeGenFunction::LoadObjCSelf(void) -{ - if (const ObjCMethodDecl *OMD = dyn_cast(CurFuncDecl)) { - ValueDecl *Decl = OMD->getSelfDecl(); - llvm::Value *SelfPtr = LocalDeclMap[&(*(Decl))]; - return Builder.CreateLoad(SelfPtr, "self"); - } - return NULL; +llvm::Value *CodeGenFunction::LoadObjCSelf(void) { + const ObjCMethodDecl *OMD = cast(CurFuncDecl); + return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self"); } CGObjCRuntime::~CGObjCRuntime() {} diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 7257f8d569..48c82c12f5 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -951,16 +951,6 @@ llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD) { llvm::GlobalValue::InternalLinkage, FunctionName, &TheModule); - llvm::Function::arg_iterator AI = Method->arg_begin(); - // Name the struct return argument. - // FIXME: This is probably the wrong test. - if (!ReturnTy->isFirstClassType() && ReturnTy != llvm::Type::VoidTy) { - AI->setName("agg.result"); - ++AI; - } - AI->setName("self"); - ++AI; - AI->setName("_cmd"); return Method; } diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 61b9534759..8cb1536b14 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -14,6 +14,7 @@ #include "CGObjCRuntime.h" #include "CodeGenModule.h" +#include "CodeGenFunction.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" @@ -22,6 +23,7 @@ #include "llvm/Module.h" #include "llvm/Support/IRBuilder.h" #include "llvm/Target/TargetData.h" +#include using namespace clang; @@ -194,6 +196,11 @@ private: /// the name. llvm::Constant *GetMethodVarType(ObjCMethodDecl *D); + /// GetNameForMethod - Return a name for the given method. + /// \param[out] NameOut - The return value. + void GetNameForMethod(const ObjCMethodDecl *OMD, + std::string &NameOut); + public: CGObjCMac(CodeGen::CodeGenModule &cgm); virtual llvm::Constant *GenerateConstantString(const std::string &String); @@ -606,7 +613,57 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { } void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ClassDecl) { - assert(0 && "Cannot generate class for Mac runtime."); + //assert(0 && "Cannot generate class for Mac runtime."); +} + +llvm::Function *CGObjCMac::GenerateMethod(const ObjCMethodDecl *OMD) { + const llvm::Type *ReturnTy = + CGM.getTypes().ConvertReturnType(OMD->getResultType()); + const llvm::Type *SelfTy = + CGM.getTypes().ConvertType(OMD->getSelfDecl()->getType()); + + std::vector ArgTys; + ArgTys.reserve(1 + 2 + OMD->param_size()); + + // FIXME: This is not something we should have to be dealing with + // here. + bool useStructRet = + CodeGen::CodeGenFunction::hasAggregateLLVMType(OMD->getResultType()); + if (useStructRet) { + ArgTys.push_back(llvm::PointerType::getUnqual(ReturnTy)); + ReturnTy = llvm::Type::VoidTy; + } + + // Implicit arguments + ArgTys.push_back(SelfTy); + ArgTys.push_back(ObjCTypes.SelectorPtrTy); + + for (ObjCMethodDecl::param_const_iterator + i = OMD->param_begin(), e = OMD->param_end(); + i != e; ++i) { + const llvm::Type *Ty = CGM.getTypes().ConvertType((*i)->getType()); + if (Ty->isFirstClassType()) { + ArgTys.push_back(Ty); + } else { + ArgTys.push_back(llvm::PointerType::getUnqual(Ty)); + } + } + + std::string Name; + GetNameForMethod(OMD, Name); + + llvm::Function *Method = + llvm::Function::Create(llvm::FunctionType::get(ReturnTy, + ArgTys, + OMD->isVariadic()), + llvm::GlobalValue::InternalLinkage, + Name, + &CGM.getModule()); + + if (useStructRet) + Method->addParamAttr(1, llvm::ParamAttr::StructRet); + + return Method; } llvm::Function *CGObjCMac::ModuleInitFunction() { @@ -616,11 +673,6 @@ llvm::Function *CGObjCMac::ModuleInitFunction() { return NULL; } -llvm::Function *CGObjCMac::GenerateMethod(const ObjCMethodDecl *OMD) { - assert(0 && "Cannot generate method preamble for Mac runtime."); - return 0; -} - /* *** Private Interface *** */ /// EmitImageInfo - Emit the image info marker used to encode some module @@ -786,6 +838,19 @@ llvm::Constant *CGObjCMac::GetMethodVarType(ObjCMethodDecl *D) { return getConstantGEP(Entry, 0, 0); } +void CGObjCMac::GetNameForMethod(const ObjCMethodDecl *D, + std::string &NameOut) { + // FIXME: Find the mangling GCC uses. + std::stringstream s; + s << (D->isInstance() ? "-" : "+"); + s << "["; + s << D->getClassInterface()->getName(); + s << " "; + s << D->getSelector().getName(); + s << "]"; + NameOut = s.str(); +} + void CGObjCMac::FinishModule() { EmitModuleInfo(); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index b595363ff0..e4061ec4f2 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -298,6 +298,8 @@ public: const llvm::Type *ConvertType(QualType T); + /// LoadObjCSelf - Load the value of self. This function is only + /// valid while generating code for an Objective-C method. llvm::Value *LoadObjCSelf(); /// isObjCPointerType - Return true if the specificed AST type will map onto @@ -368,7 +370,9 @@ public: void EmitBlockVarDecl(const VarDecl &D); void EmitLocalBlockVarDecl(const VarDecl &D); void EmitStaticBlockVarDecl(const VarDecl &D); - void EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg); + + /// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl. + void EmitParmDecl(const VarDecl &D, llvm::Value *Arg); //===--------------------------------------------------------------------===// // Statement Emission diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 1867207248..bbd7ab4bc9 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -166,11 +166,6 @@ void CodeGenModule::EmitAnnotations() { gv->setSection("llvm.metadata"); } -bool hasAggregateLLVMType(QualType T) { - return !T->isRealType() && !T->isPointerLikeType() && - !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 @@ -208,7 +203,7 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD, if (FuncAttrs) ParamAttrList.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs)); // Note that there is parallel code in CodeGenFunction::EmitCallExpr - bool AggregateReturn = hasAggregateLLVMType(FD->getResultType()); + bool AggregateReturn = CodeGenFunction::hasAggregateLLVMType(FD->getResultType()); if (AggregateReturn) ParamAttrList.push_back( llvm::ParamAttrsWithIndex::get(1, llvm::ParamAttr::StructRet)); -- 2.40.0