From: Fariborz Jahanian Date: Sat, 25 Jul 2009 21:12:28 +0000 (+0000) Subject: ir-gen for non-virtual base class initialization X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=742cd1b7bb86b52b23b335d47abbd842dac0e1bf;p=clang ir-gen for non-virtual base class initialization in constructors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77087 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 1dcc4f8465..e78b315675 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -53,6 +53,9 @@ void ASTRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *RD) { // Round up the current record size to the base's alignment boundary. Size = (Size + (BaseAlign-1)) & ~(BaseAlign-1); + // Non-virtual base class has offset too. + FieldOffsets.push_back(Size); + // Reserve space for this base. Size += BaseSize; diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 724364f5e2..dd32cad21b 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -17,6 +17,7 @@ #include "CodeGenModule.h" #include "Mangle.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -418,13 +419,40 @@ const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D, /// EmitCtorPrologue - This routine generates necessary code to initialize /// base classes and non-static data members belonging to this constructor. void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) { - for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(), + const CXXRecordDecl *ClassDecl = cast(CD->getDeclContext()); + assert(ClassDecl->vbases_begin() == ClassDecl->vbases_end() + && "FIXME. virtual base initialization unsupported"); + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl); + llvm::Type *I8Ptr = VMContext.getPointerTypeUnqual(llvm::Type::Int8Ty); + unsigned FieldNo = 0; + for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(), E = CD->init_end(); B != E; ++B) { CXXBaseOrMemberInitializer *Member = (*B); if (Member->isBaseInitializer()) { - // FIXME. Added base initialilzers here. - assert(false && "FIXME. base initialization unsupported"); + uint64_t Offset = Layout.getFieldOffset(FieldNo++) / 8; + assert(Member->getConstructor() && + "EmitCtorPrologue - no constructor to initialize base class"); + llvm::Value *LoadOfThis = LoadCXXThis(); + llvm::LLVMContext &VMContext = getLLVMContext(); + llvm::Value *V; + if (Offset > 0) { + llvm::Value *OffsetVal = llvm::ConstantInt::get(llvm::Type::Int32Ty, + Offset); + V = Builder.CreateBitCast(LoadOfThis, I8Ptr); + V = Builder.CreateGEP(V, OffsetVal, "add.ptr"); + } + else + V = Builder.CreateBitCast(LoadOfThis, I8Ptr); + + const llvm::Type *BasePtr = + ConvertType(QualType(Member->getBaseClass(), 0)); + BasePtr = VMContext.getPointerTypeUnqual(BasePtr); + V = Builder.CreateBitCast(V, BasePtr); + EmitCXXConstructorCall(Member->getConstructor(), + Ctor_Complete, V, + Member->const_arg_begin(), + Member->const_arg_end()); } else { // non-static data member initilaizers. diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index 0869b2d11c..21c7c38eee 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -14,6 +14,7 @@ #include "CodeGenTypes.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "llvm/DerivedTypes.h" @@ -545,8 +546,13 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) { uint64_t llvmSize = 0; // FIXME: Make this a SmallVector std::vector LLVMFields; - + unsigned curField = 0; + // Adjust by number of bases. + // FIXME. This will probably change when virtual bases are supported. + if (const CXXRecordDecl *CXXRD = dyn_cast(&RD)) + curField += CXXRD->getNumBases(); + for (RecordDecl::field_iterator Field = RD.field_begin(), FieldEnd = RD.field_end(); Field != FieldEnd; ++Field) { diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp new file mode 100644 index 0000000000..d2c33aef54 --- /dev/null +++ b/test/CodeGenCXX/constructor-init.cpp @@ -0,0 +1,49 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +extern "C" int printf(...); + +struct M { + M() { printf("M()\n"); } + M(int i) { iM = i; printf("M(%d)\n", i); } + int iM; + void MPR() {printf("iM = %d\n", iM); }; +}; + +struct P { + P() { printf("P()\n"); } + P(int i) { iP = i; printf("P(%d)\n", i); } + int iP; + void PPR() {printf("iP = %d\n", iP); }; +}; + +struct Q { + Q() { printf("Q()\n"); } + Q(int i) { iQ = i; printf("Q(%d)\n", i); } + int iQ; + void QPR() {printf("iQ = %d\n", iQ); }; +}; + +struct N : M , P, Q { + N() : f1(1.314), P(2000), ld(00.1234+f1), M(1000), Q(3000), + d1(3.4567), i1(1234), m1(100) { printf("N()\n"); } + M m1; + M m2; + float f1; + int i1; + float d1; + void PR() { printf("f1 = %f d1 = %f i1 = %d ld = %f \n", f1,d1,i1, ld); + MPR(); + PPR(); + QPR(); + } + float ld; + float ff; +}; + +int main() { + M m1; + + N n1; + n1.PR(); +} +