From 2b77ba8bc7a842829ad9193816dc1d7d5e9c5be6 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sat, 4 Apr 2009 20:47:02 +0000 Subject: [PATCH] Add some basic support for generating C++ member functions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68425 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenFunction.cpp | 21 +++++++++++++++++- lib/CodeGen/CodeGenFunction.h | 4 ++++ lib/CodeGen/CodeGenModule.cpp | 33 ++++++++++++++++++---------- test/CodeGenCXX/member-functions.cpp | 15 +++++++++++++ 4 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 test/CodeGenCXX/member-functions.cpp diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index dc00a76ff9..5b63e6594d 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -18,6 +18,7 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "llvm/Support/CFG.h" #include "llvm/Target/TargetData.h" using namespace clang; @@ -26,7 +27,8 @@ using namespace CodeGen; CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) : BlockFunction(cgm, *this, Builder), CGM(cgm), Target(CGM.getContext().Target), - DebugInfo(0), SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0) { + DebugInfo(0), SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0), + CXXThisDecl(0) { LLVMIntTy = ConvertType(getContext().IntTy); LLVMPointerWidth = Target.getPointerWidth(0); } @@ -201,6 +203,19 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD, DebugInfo = CGM.getDebugInfo(); FunctionArgList Args; + + if (const CXXMethodDecl *MD = dyn_cast(FD)) { + if (MD->isInstance()) { + // Create the implicit 'this' decl. + // FIXME: I'm not entirely sure I like using a fake decl just for code + // generation. Maybe we can come up with a better way? + CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), + &getContext().Idents.get("this"), + MD->getThisType(getContext())); + Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType())); + } + } + if (FD->getNumParams()) { const FunctionProtoType* FProto = FD->getType()->getAsFunctionProtoType(); assert(FProto && "Function def must have prototype!"); @@ -221,6 +236,10 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD, } else { FinishFunction(); } + + // Destroy the 'this' declaration. + if (CXXThisDecl) + CXXThisDecl->Destroy(getContext()); } /// ContainsLabel - Return true if the statement contains a label in it. If diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 13a0e85486..96db4a45c7 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -232,6 +232,10 @@ private: /// BlockScopes - Map of which "cleanup scope" scope basic blocks have. BlockScopeMap BlockScopes; + /// CXXThisDecl - When parsing an C++ function, this will hold the implicit + /// 'this' declaration. + ImplicitParamDecl *CXXThisDecl; + public: CodeGenFunction(CodeGenModule &cgm); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index b4cf533186..379ff9b424 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -820,18 +820,26 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) { - const llvm::FunctionType *Ty = - cast(getTypes().ConvertType(D->getType())); - - // As a special case, make sure that definitions of K&R function - // "type foo()" aren't declared as varargs (which forces the backend - // to do unnecessary work). - if (D->getType()->isFunctionNoProtoType()) { - assert(Ty->isVarArg() && "Didn't lower type as expected"); - // Due to stret, the lowered function could have arguments. Just create the - // same type as was lowered by ConvertType but strip off the varargs bit. - std::vector Args(Ty->param_begin(), Ty->param_end()); - Ty = llvm::FunctionType::get(Ty->getReturnType(), Args, false); + const llvm::FunctionType *Ty; + + if (const CXXMethodDecl *MD = dyn_cast(D)) { + bool isVariadic = D->getType()->getAsFunctionProtoType()->isVariadic(); + + Ty = getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), isVariadic); + } else { + Ty = cast(getTypes().ConvertType(D->getType())); + + // As a special case, make sure that definitions of K&R function + // "type foo()" aren't declared as varargs (which forces the backend + // to do unnecessary work). + if (D->getType()->isFunctionNoProtoType()) { + assert(Ty->isVarArg() && "Didn't lower type as expected"); + // Due to stret, the lowered function could have arguments. + // Just create the same type as was lowered by ConvertType + // but strip off the varargs bit. + std::vector Args(Ty->param_begin(), Ty->param_end()); + Ty = llvm::FunctionType::get(Ty->getReturnType(), Args, false); + } } // Get or create the prototype for teh function. @@ -1305,6 +1313,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { return; switch (D->getKind()) { + case Decl::CXXMethod: case Decl::Function: case Decl::Var: EmitGlobal(cast(D)); diff --git a/test/CodeGenCXX/member-functions.cpp b/test/CodeGenCXX/member-functions.cpp new file mode 100644 index 0000000000..a6fa000319 --- /dev/null +++ b/test/CodeGenCXX/member-functions.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -emit-llvm %s -o %t && +struct C { + void f(); +}; + +// RUN: grep "define void @_ZN1C1fEv" %t | count 1 && +void C::f() { +} + +// RUN: grep "call void @_ZN1C1fEv" %t | count 1 +void f() { + C c; + + c.f(); +} \ No newline at end of file -- 2.40.0