diff options
Diffstat (limited to 'CodeGen')
-rw-r--r-- | CodeGen/CGExprConstant.cpp | 153 | ||||
-rw-r--r-- | CodeGen/CodeGenTypes.cpp | 12 | ||||
-rw-r--r-- | CodeGen/CodeGenTypes.h | 13 |
3 files changed, 126 insertions, 52 deletions
diff --git a/CodeGen/CGExprConstant.cpp b/CodeGen/CGExprConstant.cpp index d996fd8af4..fbf65aa59b 100644 --- a/CodeGen/CGExprConstant.cpp +++ b/CodeGen/CGExprConstant.cpp @@ -66,74 +66,135 @@ public: return EmitConversion(C, E->getSubExpr()->getType(), E->getType()); } - - llvm::Constant *VisitInitListExpr(InitListExpr *ILE) { - const llvm::CompositeType *CType = - dyn_cast<llvm::CompositeType>(ConvertType(ILE->getType())); - if (!CType) { - // We have a scalar in braces. Just use the first element. - return Visit(ILE->getInit(0)); + llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, + const llvm::ArrayType *AType) { + + std::vector<llvm::Constant*> Elts; + unsigned NumInitElements = ILE->getNumInits(); + const llvm::Type *ElemTy = AType->getElementType(); + unsigned NumElements = AType->getNumElements(); + + // Initialising an array requires us to automatically + // initialise any elements that have not been initialised explicitly + unsigned NumInitableElts = std::min(NumInitElements, NumElements); + + // Copy initializer elements. + unsigned i = 0; + for (; i < NumInitableElts; ++i) { + + llvm::Constant *C = Visit(ILE->getInit(i)); + // FIXME: Remove this when sema of initializers is finished (and the code + // above). + if (C == 0 && ILE->getInit(i)->getType()->isVoidType()) { + if (ILE->getType()->isVoidType()) return 0; + return llvm::UndefValue::get(AType); + } + assert (C && "Failed to create initializer expression"); + Elts.push_back(C); } - + + // Initialize remaining array elements. + for (; i < NumElements; ++i) + Elts.push_back(llvm::Constant::getNullValue(ElemTy)); + + return llvm::ConstantArray::get(AType, Elts); + } + + llvm::Constant *EmitStructInitialization(InitListExpr *ILE, + const llvm::StructType *SType) { + + std::vector<llvm::Constant*> Elts; + const CGRecordLayout *CGR = CGM.getTypes().getCGRecordLayout(SType); unsigned NumInitElements = ILE->getNumInits(); - unsigned NumInitableElts = NumInitElements; - std::vector<llvm::Constant*> Elts; + unsigned NumElements = SType->getNumElements(); - // Initialising an array or structure requires us to automatically + // Initialising an structure requires us to automatically // initialise any elements that have not been initialised explicitly - const llvm::ArrayType *AType = 0; - const llvm::StructType *SType = 0; - const llvm::Type *ElemTy = 0; - unsigned NumElements = 0; - - // If this is an array, we may have to truncate the initializer - if ((AType = dyn_cast<llvm::ArrayType>(CType))) { - NumElements = AType->getNumElements(); - ElemTy = AType->getElementType(); - NumInitableElts = std::min(NumInitableElts, NumElements); - } + unsigned NumInitableElts = std::min(NumInitElements, NumElements); - // If this is a structure, we may have to truncate the initializer - if ((SType = dyn_cast<llvm::StructType>(CType))) { - NumElements = SType->getNumElements(); - NumInitableElts = std::min(NumInitableElts, NumElements); + // Copy initializer elements. Skip padding fields. + unsigned EltNo = 0; // Element no in ILE + unsigned FieldNo = 0; // Field no in SType + while (EltNo < NumInitableElts) { + + // Zero initialize padding field. + if (CGR->isPaddingField(FieldNo)) { + const llvm::Type *FieldTy = SType->getElementType(FieldNo); + Elts.push_back(llvm::Constant::getNullValue(FieldTy)); + FieldNo++; + continue; + } + + llvm::Constant *C = Visit(ILE->getInit(EltNo)); + // FIXME: Remove this when sema of initializers is finished (and the code + // above). + if (C == 0 && ILE->getInit(EltNo)->getType()->isVoidType()) { + if (ILE->getType()->isVoidType()) return 0; + return llvm::UndefValue::get(SType); + } + assert (C && "Failed to create initializer expression"); + Elts.push_back(C); + EltNo++; + FieldNo++; + } + + // Initialize remaining structure elements. + for (unsigned i = Elts.size(); i < NumElements; ++i) { + const llvm::Type *FieldTy = SType->getElementType(i); + Elts.push_back(llvm::Constant::getNullValue(FieldTy)); } + + return llvm::ConstantStruct::get(SType, Elts); + } + + llvm::Constant *EmitVectorInitialization(InitListExpr *ILE, + const llvm::VectorType *VType) { + + std::vector<llvm::Constant*> Elts; + unsigned NumInitElements = ILE->getNumInits(); + unsigned NumElements = VType->getNumElements(); + assert (NumInitElements == NumElements + && "Unsufficient vector init elelments"); // Copy initializer elements. unsigned i = 0; - for (i = 0; i < NumInitableElts; ++i) { + for (; i < NumElements; ++i) { + llvm::Constant *C = Visit(ILE->getInit(i)); // FIXME: Remove this when sema of initializers is finished (and the code // above). if (C == 0 && ILE->getInit(i)->getType()->isVoidType()) { if (ILE->getType()->isVoidType()) return 0; - return llvm::UndefValue::get(CType); + return llvm::UndefValue::get(VType); } assert (C && "Failed to create initializer expression"); Elts.push_back(C); } - - if (SType) { - // Initialize remaining structure elements. - for (; i < NumElements; ++i) { - ElemTy = SType->getElementType(i); - Elts.push_back(llvm::Constant::getNullValue(ElemTy)); - } - return llvm::ConstantStruct::get(SType, Elts); + + return llvm::ConstantVector::get(VType, Elts); + } + + llvm::Constant *VisitInitListExpr(InitListExpr *ILE) { + const llvm::CompositeType *CType = + dyn_cast<llvm::CompositeType>(ConvertType(ILE->getType())); + + if (!CType) { + // We have a scalar in braces. Just use the first element. + return Visit(ILE->getInit(0)); } - - if (ILE->getType()->isVectorType()) - return llvm::ConstantVector::get(cast<llvm::VectorType>(CType), Elts); - - // Make sure we have an array at this point - assert(AType); + + if (const llvm::ArrayType *AType = dyn_cast<llvm::ArrayType>(CType)) + return EmitArrayInitialization(ILE, AType); - // Initialize remaining array elements. - for (; i < NumElements; ++i) - Elts.push_back(llvm::Constant::getNullValue(ElemTy)); + if (const llvm::StructType *SType = dyn_cast<llvm::StructType>(CType)) + return EmitStructInitialization(ILE, SType); - return llvm::ConstantArray::get(AType, Elts); + if (const llvm::VectorType *VType = dyn_cast<llvm::VectorType>(CType)) + return EmitVectorInitialization(ILE, VType); + + // Make sure we have an array at this point + assert(0 && "Unable to handle InitListExpr"); } llvm::Constant *VisitImplicitCastExpr(ImplicitCastExpr *ICExpr) { diff --git a/CodeGen/CodeGenTypes.cpp b/CodeGen/CodeGenTypes.cpp index f3510d4595..678733e6fa 100644 --- a/CodeGen/CodeGenTypes.cpp +++ b/CodeGen/CodeGenTypes.cpp @@ -66,7 +66,7 @@ namespace { /// placeBitField - Find a place for FD, which is a bit-field. void placeBitField(const FieldDecl *FD); - llvm::SmallVector<unsigned, 8> &getPaddingFields() { + llvm::SmallSet<unsigned, 8> &getPaddingFields() { return PaddingFields; } @@ -79,7 +79,7 @@ namespace { llvm::SmallVector<const FieldDecl *, 8> FieldDecls; std::vector<const llvm::Type*> LLVMFields; llvm::SmallVector<uint64_t, 8> Offsets; - llvm::SmallVector<unsigned, 8> PaddingFields; + llvm::SmallSet<unsigned, 8> PaddingFields; }; } @@ -334,7 +334,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { RO.layoutStructFields(RL); // Get llvm::StructType. - CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType()); + CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType(), + RO.getPaddingFields()); ResultType = TagDeclTypes[TD] = RLI->getLLVMType(); CGRecordLayouts[ResultType] = RLI; @@ -357,7 +358,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { RO.layoutUnionFields(); // Get llvm::StructType. - CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType()); + CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType(), + RO.getPaddingFields()); ResultType = TagDeclTypes[TD] = RLI->getLLVMType(); CGRecordLayouts[ResultType] = RLI; } else { @@ -520,7 +522,7 @@ void RecordOrganizer::addLLVMField(const llvm::Type *Ty, bool isPaddingField) { Offsets.push_back(llvmSize); llvmSize += TySize; if (isPaddingField) - PaddingFields.push_back(llvmFieldNo); + PaddingFields.insert(llvmFieldNo); LLVMFields.push_back(Ty); ++llvmFieldNo; } diff --git a/CodeGen/CodeGenTypes.h b/CodeGen/CodeGenTypes.h index 5ae49553ab..2ca3d3478c 100644 --- a/CodeGen/CodeGenTypes.h +++ b/CodeGen/CodeGenTypes.h @@ -15,6 +15,7 @@ #define CODEGEN_CODEGENTYPES_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" #include <vector> namespace llvm { @@ -42,7 +43,8 @@ namespace CodeGen { class CGRecordLayout { CGRecordLayout(); // DO NOT IMPLEMENT public: - CGRecordLayout(llvm::Type *T) : STy(T) { + CGRecordLayout(llvm::Type *T, llvm::SmallSet<unsigned, 8> &PF) + : STy(T), PaddingFields(PF) { // FIXME : Collect info about fields that requires adjustments // (i.e. fields that do not directly map to llvm struct fields.) } @@ -52,8 +54,17 @@ namespace CodeGen { return STy; } + bool isPaddingField(unsigned No) const { + return PaddingFields.count(No) != 0; + } + + unsigned getNumPaddingFields() { + return PaddingFields.size(); + } + private: llvm::Type *STy; + llvm::SmallSet<unsigned, 8> PaddingFields; }; /// CodeGenTypes - This class organizes the cross-module state that is used |