summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGExprConstant.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2009-07-27 01:23:51 +0000
committerAnders Carlsson <andersca@mac.com>2009-07-27 01:23:51 +0000
commitba4c6d1c91afc1d7dd83f3b3add69d9551f60123 (patch)
treed55fd2ce2d8d879382df35ad166b9082ab2e681f /clang/lib/CodeGen/CGExprConstant.cpp
parent21e0f895a123a68bab49291a656e078bb75e9502 (diff)
downloadbcm5719-llvm-ba4c6d1c91afc1d7dd83f3b3add69d9551f60123.tar.gz
bcm5719-llvm-ba4c6d1c91afc1d7dd83f3b3add69d9551f60123.zip
More work on bitfield support in the new constant struct builder.
llvm-svn: 77177
Diffstat (limited to 'clang/lib/CodeGen/CGExprConstant.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprConstant.cpp81
1 files changed, 79 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index db34fdee0c3..97e420b70da 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -119,6 +119,82 @@ class VISIBILITY_HIDDEN ConstStructBuilder {
return true;
}
+ 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) {
+ // FIXME: Add padding.
+ return false;
+ }
+
+ uint64_t FieldSize =
+ Field->getBitWidth()->EvaluateAsInt(CGM.getContext()).getZExtValue();
+
+ llvm::APInt FieldValue = CI->getValue();
+
+ // 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);
+
+ // Truncate the size of FieldValue to the bit field size.
+ if (FieldSize < FieldValue.getBitWidth())
+ FieldValue.trunc(FieldSize);
+
+ if (FieldOffset < NextFieldOffsetInBytes * 8) {
+ // FIXME: Part of the bitfield should go into the previous byte.
+ return false;
+ }
+
+ while (FieldValue.getBitWidth() > 8) {
+ llvm::APInt Tmp;
+
+ if (CGM.getTargetData().isBigEndian()) {
+ // We want the low bits.
+ Tmp = FieldValue.getLoBits(8);
+ } else {
+ // We want the high bits.
+ Tmp = FieldValue.getHiBits(8);
+ }
+
+ Tmp.trunc(8);
+ 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!");
+
+ if (FieldValue.getBitWidth() < 8) {
+ if (CGM.getTargetData().isBigEndian()) {
+ unsigned BitWidth = FieldValue.getBitWidth();
+
+ FieldValue.zext(8);
+ FieldValue = FieldValue << (8 - BitWidth);
+ } else
+ FieldValue.zext(8);
+ }
+
+ // Append the last element.
+ Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(),
+ FieldValue));
+ NextFieldOffsetInBytes++;
+ return true;
+ }
+
void AppendPadding(uint64_t NumBytes) {
if (!NumBytes)
return;
@@ -158,8 +234,9 @@ class VISIBILITY_HIDDEN ConstStructBuilder {
if (!Field->getIdentifier())
continue;
- // FIXME: Bitfield support.
- return false;
+ if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
+ ILE->getInit(ElementNo)))
+ return false;
} else {
if (!AppendField(*Field, Layout.getFieldOffset(FieldNo),
ILE->getInit(ElementNo)))
OpenPOWER on IntegriCloud