diff options
Diffstat (limited to 'lib/CodeGen/CGExprConstant.cpp')
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 202 |
1 files changed, 65 insertions, 137 deletions
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index b508dcb..54f7eee 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -104,16 +104,7 @@ AppendBytes(CharUnits FieldOffsetInChars, llvm::Constant *InitCst) { // Round up the field offset to the alignment of the field type. CharUnits AlignedNextFieldOffsetInChars = - NextFieldOffsetInChars.RoundUpToAlignment(FieldAlignment); - - if (AlignedNextFieldOffsetInChars > FieldOffsetInChars) { - assert(!Packed && "Alignment is wrong even with a packed struct!"); - - // Convert the struct to a packed struct. - ConvertStructToPacked(); - - AlignedNextFieldOffsetInChars = NextFieldOffsetInChars; - } + NextFieldOffsetInChars.RoundUpToAlignment(FieldAlignment); if (AlignedNextFieldOffsetInChars < FieldOffsetInChars) { // We need to append padding. @@ -122,6 +113,24 @@ AppendBytes(CharUnits FieldOffsetInChars, llvm::Constant *InitCst) { assert(NextFieldOffsetInChars == FieldOffsetInChars && "Did not add enough padding!"); + AlignedNextFieldOffsetInChars = + NextFieldOffsetInChars.RoundUpToAlignment(FieldAlignment); + } + + if (AlignedNextFieldOffsetInChars > FieldOffsetInChars) { + assert(!Packed && "Alignment is wrong even with a packed struct!"); + + // Convert the struct to a packed struct. + ConvertStructToPacked(); + + // After we pack the struct, we may need to insert padding. + if (NextFieldOffsetInChars < FieldOffsetInChars) { + // We need to append padding. + AppendPadding(FieldOffsetInChars - NextFieldOffsetInChars); + + assert(NextFieldOffsetInChars == FieldOffsetInChars && + "Did not add enough padding!"); + } AlignedNextFieldOffsetInChars = NextFieldOffsetInChars; } @@ -486,10 +495,14 @@ llvm::Constant *ConstStructBuilder::Finalize(QualType Ty) { // No tail padding is necessary. } else { // Append tail padding if necessary. - AppendTailPadding(LayoutSizeInChars); - CharUnits LLVMSizeInChars = - NextFieldOffsetInChars.RoundUpToAlignment(LLVMStructAlignment); + NextFieldOffsetInChars.RoundUpToAlignment(LLVMStructAlignment); + + if (LLVMSizeInChars != LayoutSizeInChars) + AppendTailPadding(LayoutSizeInChars); + + LLVMSizeInChars = + NextFieldOffsetInChars.RoundUpToAlignment(LLVMStructAlignment); // Check if we need to convert the struct to a packed struct. if (NextFieldOffsetInChars <= LayoutSizeInChars && @@ -501,7 +514,10 @@ llvm::Constant *ConstStructBuilder::Finalize(QualType Ty) { "Converting to packed did not help!"); } - assert(LayoutSizeInChars == NextFieldOffsetInChars && + LLVMSizeInChars = + NextFieldOffsetInChars.RoundUpToAlignment(LLVMStructAlignment); + + assert(LayoutSizeInChars == LLVMSizeInChars && "Tail padding mismatch!"); } @@ -734,6 +750,20 @@ public: // initialise any elements that have not been initialised explicitly unsigned NumInitableElts = std::min(NumInitElements, NumElements); + // Initialize remaining array elements. + // FIXME: This doesn't handle member pointers correctly! + llvm::Constant *fillC; + if (Expr *filler = ILE->getArrayFiller()) + fillC = CGM.EmitConstantExpr(filler, filler->getType(), CGF); + else + fillC = llvm::Constant::getNullValue(ElemTy); + if (!fillC) + return nullptr; + + // Try to use a ConstantAggregateZero if we can. + if (fillC->isNullValue() && !NumInitableElts) + return llvm::ConstantAggregateZero::get(AType); + // Copy initializer elements. std::vector<llvm::Constant*> Elts; Elts.reserve(NumInitableElts + NumElements); @@ -748,15 +778,6 @@ public: Elts.push_back(C); } - // Initialize remaining array elements. - // FIXME: This doesn't handle member pointers correctly! - llvm::Constant *fillC; - if (Expr *filler = ILE->getArrayFiller()) - fillC = CGM.EmitConstantExpr(filler, filler->getType(), CGF); - else - fillC = llvm::Constant::getNullValue(ElemTy); - if (!fillC) - return nullptr; RewriteType |= (fillC->getType() != ElemTy); Elts.resize(NumElements, fillC); @@ -869,7 +890,8 @@ public: if (VD->isFileVarDecl() || VD->hasExternalStorage()) return CGM.GetAddrOfGlobalVar(VD); else if (VD->isLocalVarDecl()) - return CGM.getStaticLocalDeclAddress(VD); + return CGM.getOrCreateStaticVarDecl( + *VD, CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false)); } } return nullptr; @@ -1126,13 +1148,14 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, // FIXME: the target may want to specify that this is packed. llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(), Complex[1]->getType(), - NULL); + nullptr); return llvm::ConstantStruct::get(STy, Complex); } case APValue::Float: { const llvm::APFloat &Init = Value.getFloat(); if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf && - !Context.getLangOpts().NativeHalfType) + !Context.getLangOpts().NativeHalfType && + !Context.getLangOpts().HalfArgsAndReturns) return llvm::ConstantInt::get(VMContext, Init.bitcastToAPInt()); else return llvm::ConstantFP::get(VMContext, Init); @@ -1148,7 +1171,7 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, // FIXME: the target may want to specify that this is packed. llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(), Complex[1]->getType(), - NULL); + nullptr); return llvm::ConstantStruct::get(STy, Complex); } case APValue::Vector: { @@ -1189,9 +1212,6 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, unsigned NumElements = Value.getArraySize(); unsigned NumInitElts = Value.getArrayInitializedElts(); - std::vector<llvm::Constant*> Elts; - Elts.reserve(NumElements); - // Emit array filler, if there is one. llvm::Constant *Filler = nullptr; if (Value.hasArrayFiller()) @@ -1199,7 +1219,18 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, CAT->getElementType(), CGF); // Emit initializer elements. - llvm::Type *CommonElementType = nullptr; + llvm::Type *CommonElementType = + getTypes().ConvertType(CAT->getElementType()); + + // Try to use a ConstantAggregateZero if we can. + if (Filler && Filler->isNullValue() && !NumInitElts) { + llvm::ArrayType *AType = + llvm::ArrayType::get(CommonElementType, NumElements); + return llvm::ConstantAggregateZero::get(AType); + } + + std::vector<llvm::Constant*> Elts; + Elts.reserve(NumElements); for (unsigned I = 0; I < NumElements; ++I) { llvm::Constant *C = Filler; if (I < NumInitElts) @@ -1268,83 +1299,6 @@ CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) { return getCXXABI().EmitMemberDataPointer(type, chars); } -static void -FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, - SmallVectorImpl<llvm::Constant *> &Elements, - uint64_t StartOffset) { - assert(StartOffset % CGM.getContext().getCharWidth() == 0 && - "StartOffset not byte aligned!"); - - if (CGM.getTypes().isZeroInitializable(T)) - return; - - if (const ConstantArrayType *CAT = - CGM.getContext().getAsConstantArrayType(T)) { - QualType ElementTy = CAT->getElementType(); - uint64_t ElementSize = CGM.getContext().getTypeSize(ElementTy); - - for (uint64_t I = 0, E = CAT->getSize().getZExtValue(); I != E; ++I) { - FillInNullDataMemberPointers(CGM, ElementTy, Elements, - StartOffset + I * ElementSize); - } - } else if (const RecordType *RT = T->getAs<RecordType>()) { - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - - // Go through all bases and fill in any null pointer to data members. - for (const auto &I : RD->bases()) { - if (I.isVirtual()) { - // Ignore virtual bases. - continue; - } - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl()); - - // Ignore empty bases. - if (BaseDecl->isEmpty()) - continue; - - // Ignore bases that don't have any pointer to data members. - if (CGM.getTypes().isZeroInitializable(BaseDecl)) - continue; - - uint64_t BaseOffset = - CGM.getContext().toBits(Layout.getBaseClassOffset(BaseDecl)); - FillInNullDataMemberPointers(CGM, I.getType(), - Elements, StartOffset + BaseOffset); - } - - // Visit all fields. - unsigned FieldNo = 0; - for (RecordDecl::field_iterator I = RD->field_begin(), - E = RD->field_end(); I != E; ++I, ++FieldNo) { - QualType FieldType = I->getType(); - - if (CGM.getTypes().isZeroInitializable(FieldType)) - continue; - - uint64_t FieldOffset = StartOffset + Layout.getFieldOffset(FieldNo); - FillInNullDataMemberPointers(CGM, FieldType, Elements, FieldOffset); - } - } else { - assert(T->isMemberPointerType() && "Should only see member pointers here!"); - assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() && - "Should only see pointers to data members here!"); - - CharUnits StartIndex = CGM.getContext().toCharUnitsFromBits(StartOffset); - CharUnits EndIndex = StartIndex + CGM.getContext().getTypeSizeInChars(T); - - // FIXME: hardcodes Itanium member pointer representation! - llvm::Constant *NegativeOne = - llvm::ConstantInt::get(CGM.Int8Ty, -1ULL, /*isSigned*/true); - - // Fill in the null data member pointer. - for (CharUnits I = StartIndex; I != EndIndex; ++I) - Elements[I.getQuantity()] = NegativeOne; - } -} - static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM, llvm::Type *baseType, const CXXRecordDecl *base); @@ -1433,32 +1387,8 @@ static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM, if (baseLayout.isZeroInitializableAsBase()) return llvm::Constant::getNullValue(baseType); - // If the base type is a struct, we can just use its null constant. - if (isa<llvm::StructType>(baseType)) { - return EmitNullConstant(CGM, base, /*complete*/ false); - } - - // Otherwise, some bases are represented as arrays of i8 if the size - // of the base is smaller than its corresponding LLVM type. Figure - // out how many elements this base array has. - llvm::ArrayType *baseArrayType = cast<llvm::ArrayType>(baseType); - unsigned numBaseElements = baseArrayType->getNumElements(); - - // Fill in null data member pointers. - SmallVector<llvm::Constant *, 16> baseElements(numBaseElements); - FillInNullDataMemberPointers(CGM, CGM.getContext().getTypeDeclType(base), - baseElements, 0); - - // Now go through all other elements and zero them out. - if (numBaseElements) { - llvm::Constant *i8_zero = llvm::Constant::getNullValue(CGM.Int8Ty); - for (unsigned i = 0; i != numBaseElements; ++i) { - if (!baseElements[i]) - baseElements[i] = i8_zero; - } - } - - return llvm::ConstantArray::get(baseArrayType, baseElements); + // Otherwise, we can just use its null constant. + return EmitNullConstant(CGM, base, /*asCompleteObject=*/false); } llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { @@ -1489,9 +1419,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { assert(T->isMemberPointerType() && "Should only see member pointers here!"); assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() && "Should only see pointers to data members here!"); - - // Itanium C++ ABI 2.3: - // A NULL pointer is represented as -1. + return getCXXABI().EmitNullMemberPointer(T->castAs<MemberPointerType>()); } |