diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 34 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.cpp | 8 |
3 files changed, 41 insertions, 4 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 1dcc4f84650..e78b3156754 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/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/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 724364f5e23..dd32cad21b8 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/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<CXXRecordDecl>(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/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 0869b2d11c0..21c7c38eee1 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/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<const llvm::Type*> 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<CXXRecordDecl>(&RD)) + curField += CXXRD->getNumBases(); + for (RecordDecl::field_iterator Field = RD.field_begin(), FieldEnd = RD.field_end(); Field != FieldEnd; ++Field) { |