summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGExprConstant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGExprConstant.cpp')
-rw-r--r--lib/CodeGen/CGExprConstant.cpp579
1 files changed, 304 insertions, 275 deletions
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 172a77d..2595ff0 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -27,359 +27,387 @@
using namespace clang;
using namespace CodeGen;
-namespace {
+//===----------------------------------------------------------------------===//
+// ConstStructBuilder
+//===----------------------------------------------------------------------===//
+
+namespace {
class ConstStructBuilder {
CodeGenModule &CGM;
CodeGenFunction *CGF;
bool Packed;
-
unsigned NextFieldOffsetInBytes;
-
unsigned LLVMStructAlignment;
-
std::vector<llvm::Constant *> Elements;
-
+public:
+ static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
+ InitListExpr *ILE);
+
+private:
ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF)
: CGM(CGM), CGF(CGF), Packed(false), NextFieldOffsetInBytes(0),
LLVMStructAlignment(1) { }
bool AppendField(const FieldDecl *Field, uint64_t FieldOffset,
- const Expr *InitExpr) {
- uint64_t FieldOffsetInBytes = FieldOffset / 8;
+ llvm::Constant *InitExpr);
- assert(NextFieldOffsetInBytes <= FieldOffsetInBytes
- && "Field offset mismatch!");
+ bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
+ llvm::Constant *InitExpr);
- // Emit the field.
- llvm::Constant *C = CGM.EmitConstantExpr(InitExpr, Field->getType(), CGF);
- if (!C)
- return false;
+ void AppendPadding(uint64_t NumBytes);
- unsigned FieldAlignment = getAlignment(C);
+ void AppendTailPadding(uint64_t RecordSize);
- // Round up the field offset to the alignment of the field type.
- uint64_t AlignedNextFieldOffsetInBytes =
- llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment);
+ void ConvertStructToPacked();
+
+ bool Build(InitListExpr *ILE);
- if (AlignedNextFieldOffsetInBytes > FieldOffsetInBytes) {
- assert(!Packed && "Alignment is wrong even with a packed struct!");
+ unsigned getAlignment(const llvm::Constant *C) const {
+ if (Packed) return 1;
+ return CGM.getTargetData().getABITypeAlignment(C->getType());
+ }
- // Convert the struct to a packed struct.
- ConvertStructToPacked();
-
- AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
- }
+ uint64_t getSizeInBytes(const llvm::Constant *C) const {
+ return CGM.getTargetData().getTypeAllocSize(C->getType());
+ }
+};
- if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) {
- // We need to append padding.
- AppendPadding(FieldOffsetInBytes - NextFieldOffsetInBytes);
+bool ConstStructBuilder::
+AppendField(const FieldDecl *Field, uint64_t FieldOffset,
+ llvm::Constant *InitCst) {
+ uint64_t FieldOffsetInBytes = FieldOffset / 8;
- assert(NextFieldOffsetInBytes == FieldOffsetInBytes &&
- "Did not add enough padding!");
+ assert(NextFieldOffsetInBytes <= FieldOffsetInBytes
+ && "Field offset mismatch!");
- AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
- }
+ // Emit the field.
+ if (!InitCst)
+ return false;
- // Add the field.
- Elements.push_back(C);
- NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes + getSizeInBytes(C);
-
- if (Packed)
- assert(LLVMStructAlignment == 1 && "Packed struct not byte-aligned!");
- else
- LLVMStructAlignment = std::max(LLVMStructAlignment, FieldAlignment);
+ unsigned FieldAlignment = getAlignment(InitCst);
- return true;
- }
+ // Round up the field offset to the alignment of the field type.
+ uint64_t AlignedNextFieldOffsetInBytes =
+ llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment);
- bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
- const Expr *InitExpr) {
- llvm::ConstantInt *CI =
- cast_or_null<llvm::ConstantInt>(CGM.EmitConstantExpr(InitExpr,
- Field->getType(),
- CGF));
- // FIXME: Can this ever happen?
- if (!CI)
- return false;
-
- if (FieldOffset > NextFieldOffsetInBytes * 8) {
- // We need to add padding.
- uint64_t NumBytes =
- llvm::RoundUpToAlignment(FieldOffset -
- NextFieldOffsetInBytes * 8, 8) / 8;
+ if (AlignedNextFieldOffsetInBytes > FieldOffsetInBytes) {
+ assert(!Packed && "Alignment is wrong even with a packed struct!");
- AppendPadding(NumBytes);
- }
+ // Convert the struct to a packed struct.
+ ConvertStructToPacked();
+
+ AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
+ }
- uint64_t FieldSize =
- Field->getBitWidth()->EvaluateAsInt(CGM.getContext()).getZExtValue();
+ if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) {
+ // We need to append padding.
+ AppendPadding(FieldOffsetInBytes - NextFieldOffsetInBytes);
- llvm::APInt FieldValue = CI->getValue();
+ assert(NextFieldOffsetInBytes == FieldOffsetInBytes &&
+ "Did not add enough padding!");
- // Promote the size of FieldValue if necessary
- // FIXME: This should never occur, but currently it can because initializer
- // constants are cast to bool, and because clang is not enforcing bitfield
- // width limits.
- if (FieldSize > FieldValue.getBitWidth())
- FieldValue.zext(FieldSize);
+ AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
+ }
- // Truncate the size of FieldValue to the bit field size.
- if (FieldSize < FieldValue.getBitWidth())
- FieldValue.trunc(FieldSize);
+ // Add the field.
+ Elements.push_back(InitCst);
+ NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes +
+ getSizeInBytes(InitCst);
+
+ if (Packed)
+ assert(LLVMStructAlignment == 1 && "Packed struct not byte-aligned!");
+ else
+ LLVMStructAlignment = std::max(LLVMStructAlignment, FieldAlignment);
- if (FieldOffset < NextFieldOffsetInBytes * 8) {
- // Either part of the field or the entire field can go into the previous
- // byte.
- assert(!Elements.empty() && "Elements can't be empty!");
+ return true;
+}
- unsigned BitsInPreviousByte =
- NextFieldOffsetInBytes * 8 - FieldOffset;
+bool ConstStructBuilder::
+ AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
+ llvm::Constant *InitCst) {
+ llvm::ConstantInt *CI = cast_or_null<llvm::ConstantInt>(InitCst);
+ // FIXME: Can this ever happen?
+ if (!CI)
+ return false;
- bool FitsCompletelyInPreviousByte =
- BitsInPreviousByte >= FieldValue.getBitWidth();
+ if (FieldOffset > NextFieldOffsetInBytes * 8) {
+ // We need to add padding.
+ uint64_t NumBytes =
+ llvm::RoundUpToAlignment(FieldOffset -
+ NextFieldOffsetInBytes * 8, 8) / 8;
- llvm::APInt Tmp = FieldValue;
+ AppendPadding(NumBytes);
+ }
- if (!FitsCompletelyInPreviousByte) {
- unsigned NewFieldWidth = FieldSize - BitsInPreviousByte;
+ uint64_t FieldSize =
+ Field->getBitWidth()->EvaluateAsInt(CGM.getContext()).getZExtValue();
- if (CGM.getTargetData().isBigEndian()) {
- Tmp = Tmp.lshr(NewFieldWidth);
- Tmp.trunc(BitsInPreviousByte);
+ llvm::APInt FieldValue = CI->getValue();
- // We want the remaining high bits.
- FieldValue.trunc(NewFieldWidth);
- } else {
- Tmp.trunc(BitsInPreviousByte);
+ // Promote the size of FieldValue if necessary
+ // FIXME: This should never occur, but currently it can because initializer
+ // constants are cast to bool, and because clang is not enforcing bitfield
+ // width limits.
+ if (FieldSize > FieldValue.getBitWidth())
+ FieldValue.zext(FieldSize);
- // We want the remaining low bits.
- FieldValue = FieldValue.lshr(BitsInPreviousByte);
- FieldValue.trunc(NewFieldWidth);
- }
- }
+ // Truncate the size of FieldValue to the bit field size.
+ if (FieldSize < FieldValue.getBitWidth())
+ FieldValue.trunc(FieldSize);
- Tmp.zext(8);
- if (CGM.getTargetData().isBigEndian()) {
- if (FitsCompletelyInPreviousByte)
- Tmp = Tmp.shl(BitsInPreviousByte - FieldValue.getBitWidth());
- } else {
- Tmp = Tmp.shl(8 - BitsInPreviousByte);
- }
+ if (FieldOffset < NextFieldOffsetInBytes * 8) {
+ // Either part of the field or the entire field can go into the previous
+ // byte.
+ assert(!Elements.empty() && "Elements can't be empty!");
- // Or in the bits that go into the previous byte.
- if (llvm::ConstantInt *Val = dyn_cast<llvm::ConstantInt>(Elements.back()))
- Tmp |= Val->getValue();
- else
- assert(isa<llvm::UndefValue>(Elements.back()));
+ unsigned BitsInPreviousByte =
+ NextFieldOffsetInBytes * 8 - FieldOffset;
- Elements.back() = llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp);
+ bool FitsCompletelyInPreviousByte =
+ BitsInPreviousByte >= FieldValue.getBitWidth();
- if (FitsCompletelyInPreviousByte)
- return true;
- }
+ llvm::APInt Tmp = FieldValue;
- while (FieldValue.getBitWidth() > 8) {
- llvm::APInt Tmp;
+ if (!FitsCompletelyInPreviousByte) {
+ unsigned NewFieldWidth = FieldSize - BitsInPreviousByte;
if (CGM.getTargetData().isBigEndian()) {
- // We want the high bits.
- Tmp = FieldValue;
- Tmp = Tmp.lshr(Tmp.getBitWidth() - 8);
- Tmp.trunc(8);
+ Tmp = Tmp.lshr(NewFieldWidth);
+ Tmp.trunc(BitsInPreviousByte);
+
+ // We want the remaining high bits.
+ FieldValue.trunc(NewFieldWidth);
} else {
- // We want the low bits.
- Tmp = FieldValue;
- Tmp.trunc(8);
+ Tmp.trunc(BitsInPreviousByte);
- FieldValue = FieldValue.lshr(8);
+ // We want the remaining low bits.
+ FieldValue = FieldValue.lshr(BitsInPreviousByte);
+ FieldValue.trunc(NewFieldWidth);
}
-
- Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp));
- NextFieldOffsetInBytes++;
-
- FieldValue.trunc(FieldValue.getBitWidth() - 8);
}
- assert(FieldValue.getBitWidth() > 0 &&
- "Should have at least one bit left!");
- assert(FieldValue.getBitWidth() <= 8 &&
- "Should not have more than a byte left!");
+ Tmp.zext(8);
+ if (CGM.getTargetData().isBigEndian()) {
+ if (FitsCompletelyInPreviousByte)
+ Tmp = Tmp.shl(BitsInPreviousByte - FieldValue.getBitWidth());
+ } else {
+ Tmp = Tmp.shl(8 - BitsInPreviousByte);
+ }
- if (FieldValue.getBitWidth() < 8) {
- if (CGM.getTargetData().isBigEndian()) {
- unsigned BitWidth = FieldValue.getBitWidth();
+ // Or in the bits that go into the previous byte.
+ if (llvm::ConstantInt *Val = dyn_cast<llvm::ConstantInt>(Elements.back()))
+ Tmp |= Val->getValue();
+ else
+ assert(isa<llvm::UndefValue>(Elements.back()));
- FieldValue.zext(8);
- FieldValue = FieldValue << (8 - BitWidth);
- } else
- FieldValue.zext(8);
- }
+ Elements.back() = llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp);
- // Append the last element.
- Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(),
- FieldValue));
- NextFieldOffsetInBytes++;
- return true;
+ if (FitsCompletelyInPreviousByte)
+ return true;
}
- void AppendPadding(uint64_t NumBytes) {
- if (!NumBytes)
- return;
+ while (FieldValue.getBitWidth() > 8) {
+ llvm::APInt Tmp;
+
+ if (CGM.getTargetData().isBigEndian()) {
+ // We want the high bits.
+ Tmp = FieldValue;
+ Tmp = Tmp.lshr(Tmp.getBitWidth() - 8);
+ Tmp.trunc(8);
+ } else {
+ // We want the low bits.
+ Tmp = FieldValue;
+ Tmp.trunc(8);
- const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
- if (NumBytes > 1)
- Ty = llvm::ArrayType::get(Ty, NumBytes);
+ FieldValue = FieldValue.lshr(8);
+ }
- llvm::Constant *C = llvm::UndefValue::get(Ty);
- Elements.push_back(C);
- assert(getAlignment(C) == 1 && "Padding must have 1 byte alignment!");
+ Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp));
+ NextFieldOffsetInBytes++;
- NextFieldOffsetInBytes += getSizeInBytes(C);
+ FieldValue.trunc(FieldValue.getBitWidth() - 8);
}
- void AppendTailPadding(uint64_t RecordSize) {
- assert(RecordSize % 8 == 0 && "Invalid record size!");
+ assert(FieldValue.getBitWidth() > 0 &&
+ "Should have at least one bit left!");
+ assert(FieldValue.getBitWidth() <= 8 &&
+ "Should not have more than a byte left!");
- uint64_t RecordSizeInBytes = RecordSize / 8;
- assert(NextFieldOffsetInBytes <= RecordSizeInBytes && "Size mismatch!");
+ if (FieldValue.getBitWidth() < 8) {
+ if (CGM.getTargetData().isBigEndian()) {
+ unsigned BitWidth = FieldValue.getBitWidth();
- unsigned NumPadBytes = RecordSizeInBytes - NextFieldOffsetInBytes;
- AppendPadding(NumPadBytes);
+ FieldValue.zext(8);
+ FieldValue = FieldValue << (8 - BitWidth);
+ } else
+ FieldValue.zext(8);
}
- void ConvertStructToPacked() {
- std::vector<llvm::Constant *> PackedElements;
- uint64_t ElementOffsetInBytes = 0;
+ // Append the last element.
+ Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(),
+ FieldValue));
+ NextFieldOffsetInBytes++;
+ return true;
+}
- for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
- llvm::Constant *C = Elements[i];
+void ConstStructBuilder::AppendPadding(uint64_t NumBytes) {
+ if (!NumBytes)
+ return;
- unsigned ElementAlign =
- CGM.getTargetData().getABITypeAlignment(C->getType());
- uint64_t AlignedElementOffsetInBytes =
- llvm::RoundUpToAlignment(ElementOffsetInBytes, ElementAlign);
+ const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
+ if (NumBytes > 1)
+ Ty = llvm::ArrayType::get(Ty, NumBytes);
- if (AlignedElementOffsetInBytes > ElementOffsetInBytes) {
- // We need some padding.
- uint64_t NumBytes =
- AlignedElementOffsetInBytes - ElementOffsetInBytes;
+ llvm::Constant *C = llvm::UndefValue::get(Ty);
+ Elements.push_back(C);
+ assert(getAlignment(C) == 1 && "Padding must have 1 byte alignment!");
- const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
- if (NumBytes > 1)
- Ty = llvm::ArrayType::get(Ty, NumBytes);
+ NextFieldOffsetInBytes += getSizeInBytes(C);
+}
- llvm::Constant *Padding = llvm::UndefValue::get(Ty);
- PackedElements.push_back(Padding);
- ElementOffsetInBytes += getSizeInBytes(Padding);
- }
+void ConstStructBuilder::AppendTailPadding(uint64_t RecordSize) {
+ assert(RecordSize % 8 == 0 && "Invalid record size!");
- PackedElements.push_back(C);
- ElementOffsetInBytes += getSizeInBytes(C);
- }
+ uint64_t RecordSizeInBytes = RecordSize / 8;
+ assert(NextFieldOffsetInBytes <= RecordSizeInBytes && "Size mismatch!");
- assert(ElementOffsetInBytes == NextFieldOffsetInBytes &&
- "Packing the struct changed its size!");
+ unsigned NumPadBytes = RecordSizeInBytes - NextFieldOffsetInBytes;
+ AppendPadding(NumPadBytes);
+}
- Elements = PackedElements;
- LLVMStructAlignment = 1;
- Packed = true;
- }
-
- bool Build(InitListExpr *ILE) {
- RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
- const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
-
- unsigned FieldNo = 0;
- unsigned ElementNo = 0;
- for (RecordDecl::field_iterator Field = RD->field_begin(),
- FieldEnd = RD->field_end();
- ElementNo < ILE->getNumInits() && Field != FieldEnd;
- ++Field, ++FieldNo) {
- if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field)
- continue;
-
- if (Field->isBitField()) {
- if (!Field->getIdentifier())
- continue;
-
- if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
- ILE->getInit(ElementNo)))
- return false;
- } else {
- if (!AppendField(*Field, Layout.getFieldOffset(FieldNo),
- ILE->getInit(ElementNo)))
- return false;
- }
+void ConstStructBuilder::ConvertStructToPacked() {
+ std::vector<llvm::Constant *> PackedElements;
+ uint64_t ElementOffsetInBytes = 0;
- ElementNo++;
- }
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
+ llvm::Constant *C = Elements[i];
- uint64_t LayoutSizeInBytes = Layout.getSize() / 8;
+ unsigned ElementAlign =
+ CGM.getTargetData().getABITypeAlignment(C->getType());
+ uint64_t AlignedElementOffsetInBytes =
+ llvm::RoundUpToAlignment(ElementOffsetInBytes, ElementAlign);
- if (NextFieldOffsetInBytes > LayoutSizeInBytes) {
- // If the struct is bigger than the size of the record type,
- // we must have a flexible array member at the end.
- assert(RD->hasFlexibleArrayMember() &&
- "Must have flexible array member if struct is bigger than type!");
-
- // No tail padding is necessary.
- return true;
- }
+ if (AlignedElementOffsetInBytes > ElementOffsetInBytes) {
+ // We need some padding.
+ uint64_t NumBytes =
+ AlignedElementOffsetInBytes - ElementOffsetInBytes;
- uint64_t LLVMSizeInBytes = llvm::RoundUpToAlignment(NextFieldOffsetInBytes,
- LLVMStructAlignment);
+ const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
+ if (NumBytes > 1)
+ Ty = llvm::ArrayType::get(Ty, NumBytes);
- // Check if we need to convert the struct to a packed struct.
- if (NextFieldOffsetInBytes <= LayoutSizeInBytes &&
- LLVMSizeInBytes > LayoutSizeInBytes) {
- assert(!Packed && "Size mismatch!");
-
- ConvertStructToPacked();
- assert(NextFieldOffsetInBytes == LayoutSizeInBytes &&
- "Converting to packed did not help!");
+ llvm::Constant *Padding = llvm::UndefValue::get(Ty);
+ PackedElements.push_back(Padding);
+ ElementOffsetInBytes += getSizeInBytes(Padding);
}
- // Append tail padding if necessary.
- AppendTailPadding(Layout.getSize());
-
- assert(Layout.getSize() / 8 == NextFieldOffsetInBytes &&
- "Tail padding mismatch!");
-
- return true;
+ PackedElements.push_back(C);
+ ElementOffsetInBytes += getSizeInBytes(C);
}
- unsigned getAlignment(const llvm::Constant *C) const {
- if (Packed)
- return 1;
+ assert(ElementOffsetInBytes == NextFieldOffsetInBytes &&
+ "Packing the struct changed its size!");
- return CGM.getTargetData().getABITypeAlignment(C->getType());
+ Elements = PackedElements;
+ LLVMStructAlignment = 1;
+ Packed = true;
+}
+
+bool ConstStructBuilder::Build(InitListExpr *ILE) {
+ RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+
+ unsigned FieldNo = 0;
+ unsigned ElementNo = 0;
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
+
+ // If this is a union, skip all the fields that aren't being initialized.
+ if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field)
+ continue;
+
+ // Don't emit anonymous bitfields, they just affect layout.
+ if (Field->isBitField() && !Field->getIdentifier())
+ continue;
+
+ // Get the initializer. A struct can include fields without initializers,
+ // we just use explicit null values for them.
+ llvm::Constant *EltInit;
+ if (ElementNo < ILE->getNumInits())
+ EltInit = CGM.EmitConstantExpr(ILE->getInit(ElementNo++),
+ Field->getType(), CGF);
+ else
+ EltInit = CGM.EmitNullConstant(Field->getType());
+
+ if (!Field->isBitField()) {
+ // Handle non-bitfield members.
+ if (!AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit))
+ return false;
+ } else {
+ // Otherwise we have a bitfield.
+ if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo), EltInit))
+ return false;
+ }
}
- uint64_t getSizeInBytes(const llvm::Constant *C) const {
- return CGM.getTargetData().getTypeAllocSize(C->getType());
+ uint64_t LayoutSizeInBytes = Layout.getSize() / 8;
+
+ if (NextFieldOffsetInBytes > LayoutSizeInBytes) {
+ // If the struct is bigger than the size of the record type,
+ // we must have a flexible array member at the end.
+ assert(RD->hasFlexibleArrayMember() &&
+ "Must have flexible array member if struct is bigger than type!");
+
+ // No tail padding is necessary.
+ return true;
}
-public:
- static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
- InitListExpr *ILE) {
- ConstStructBuilder Builder(CGM, CGF);
+ uint64_t LLVMSizeInBytes = llvm::RoundUpToAlignment(NextFieldOffsetInBytes,
+ LLVMStructAlignment);
- if (!Builder.Build(ILE))
- return 0;
+ // Check if we need to convert the struct to a packed struct.
+ if (NextFieldOffsetInBytes <= LayoutSizeInBytes &&
+ LLVMSizeInBytes > LayoutSizeInBytes) {
+ assert(!Packed && "Size mismatch!");
+
+ ConvertStructToPacked();
+ assert(NextFieldOffsetInBytes <= LayoutSizeInBytes &&
+ "Converting to packed did not help!");
+ }
- llvm::Constant *Result =
- llvm::ConstantStruct::get(CGM.getLLVMContext(),
- Builder.Elements, Builder.Packed);
+ // Append tail padding if necessary.
+ AppendTailPadding(Layout.getSize());
- assert(llvm::RoundUpToAlignment(Builder.NextFieldOffsetInBytes,
- Builder.getAlignment(Result)) ==
- Builder.getSizeInBytes(Result) && "Size mismatch!");
+ assert(Layout.getSize() / 8 == NextFieldOffsetInBytes &&
+ "Tail padding mismatch!");
- return Result;
- }
-};
+ return true;
+}
+
+llvm::Constant *ConstStructBuilder::
+ BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF, InitListExpr *ILE) {
+ ConstStructBuilder Builder(CGM, CGF);
+
+ if (!Builder.Build(ILE))
+ return 0;
+
+ llvm::Constant *Result =
+ llvm::ConstantStruct::get(CGM.getLLVMContext(),
+ Builder.Elements, Builder.Packed);
+
+ assert(llvm::RoundUpToAlignment(Builder.NextFieldOffsetInBytes,
+ Builder.getAlignment(Result)) ==
+ Builder.getSizeInBytes(Result) && "Size mismatch!");
+
+ return Result;
+}
+
+//===----------------------------------------------------------------------===//
+// ConstExprEmitter
+//===----------------------------------------------------------------------===//
+
class ConstExprEmitter :
public StmtVisitor<ConstExprEmitter, llvm::Constant*> {
CodeGenModule &CGM;
@@ -418,13 +446,18 @@ public:
// Get the function pointer (or index if this is a virtual function).
if (MD->isVirtual()) {
- uint64_t Index = CGM.getVTables().getMethodVtableIndex(MD);
+ uint64_t Index = CGM.getVTables().getMethodVTableIndex(MD);
+ // FIXME: We shouldn't use / 8 here.
+ uint64_t PointerWidthInBytes =
+ CGM.getContext().Target.getPointerWidth(0) / 8;
+
// Itanium C++ ABI 2.3:
// For a non-virtual function, this field is a simple function pointer.
// For a virtual function, it is 1 plus the virtual table offset
// (in bytes) of the function, represented as a ptrdiff_t.
- Values[0] = llvm::ConstantInt::get(PtrDiffTy, (Index * 8) + 1);
+ Values[0] = llvm::ConstantInt::get(PtrDiffTy,
+ (Index * PointerWidthInBytes) + 1);
} else {
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
const llvm::Type *Ty =
@@ -528,8 +561,6 @@ public:
const MemberPointerType *DestTy =
E->getType()->getAs<MemberPointerType>();
- const CXXRecordDecl *BaseClass =
- cast<CXXRecordDecl>(cast<RecordType>(SrcTy->getClass())->getDecl());
const CXXRecordDecl *DerivedClass =
cast<CXXRecordDecl>(cast<RecordType>(DestTy->getClass())->getDecl());
@@ -543,7 +574,7 @@ public:
// Check if we need to update the adjustment.
if (llvm::Constant *Offset =
- CGM.GetNonVirtualBaseClassOffset(DerivedClass, BaseClass)) {
+ CGM.GetNonVirtualBaseClassOffset(DerivedClass, E->getBasePath())) {
llvm::Constant *Values[2];
Values[0] = CS->getOperand(0);
@@ -587,17 +618,15 @@ public:
}
llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) {
- std::vector<llvm::Constant*> Elts;
- const llvm::ArrayType *AType =
- cast<llvm::ArrayType>(ConvertType(ILE->getType()));
unsigned NumInitElements = ILE->getNumInits();
- // FIXME: Check for wide strings
- // FIXME: Check for NumInitElements exactly equal to 1??
- if (NumInitElements > 0 &&
+ if (NumInitElements == 1 &&
(isa<StringLiteral>(ILE->getInit(0)) ||
- isa<ObjCEncodeExpr>(ILE->getInit(0))) &&
- ILE->getType()->getArrayElementTypeNoTypeQual()->isCharType())
+ isa<ObjCEncodeExpr>(ILE->getInit(0))))
return Visit(ILE->getInit(0));
+
+ std::vector<llvm::Constant*> Elts;
+ const llvm::ArrayType *AType =
+ cast<llvm::ArrayType>(ConvertType(ILE->getType()));
const llvm::Type *ElemTy = AType->getElementType();
unsigned NumElements = AType->getNumElements();
OpenPOWER on IntegriCloud