summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2008-05-17 20:03:47 +0000
committerEli Friedman <eli.friedman@gmail.com>2008-05-17 20:03:47 +0000
commitf2442dcc8d653d3dcb37104df35357d2ed31a31a (patch)
treea6d786f30735ee3799676e63881ef908dbd649f4 /clang/lib/CodeGen
parenteb185ca5e95aad1e3f61971bf1e39b1035b409d1 (diff)
downloadbcm5719-llvm-f2442dcc8d653d3dcb37104df35357d2ed31a31a.tar.gz
bcm5719-llvm-f2442dcc8d653d3dcb37104df35357d2ed31a31a.zip
Fix support for _Bool bitfields. The issue is that the bitfield width
used for _Bool is not the same as the primitive width (which for _Bool is 1 bit). The load and store changes add some casts to make the types consistent. The EmitLValue changes make sure that the pointer is of an appropriate type for loading the bitfield. This isn't perfect, but it's an improvement, and getting everything right depends on actually laying out structs in an ABI-compliant way. llvm-svn: 51224
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp24
1 files changed, 20 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index d6791074c7d..840ed4314f6 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -14,11 +14,13 @@
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/AST.h"
+#include "clang/Basic/TargetInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
@@ -175,6 +177,11 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV,
V = LV.isBitfieldSigned() ?
Builder.CreateAShr(V, ShAmt, "tmp") :
Builder.CreateLShr(V, ShAmt, "tmp");
+
+ // The bitfield type and the normal type differ when the storage sizes
+ // differ (currently just _Bool).
+ V = Builder.CreateIntCast(V, ConvertType(ExprType), false, "tmp");
+
return RValue::get(V);
}
@@ -280,13 +287,18 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
unsigned short StartBit = Dst.getBitfieldStartBit();
unsigned short BitfieldSize = Dst.getBitfieldSize();
llvm::Value *Ptr = Dst.getBitfieldAddr();
- const llvm::Type *EltTy =
- cast<llvm::PointerType>(Ptr->getType())->getElementType();
- unsigned EltTySize = EltTy->getPrimitiveSizeInBits();
llvm::Value *NewVal = Src.getScalarVal();
llvm::Value *OldVal = Builder.CreateLoad(Ptr, "tmp");
+ // The bitfield type and the normal type differ when the storage sizes
+ // differ (currently just _Bool).
+ const llvm::Type *EltTy = OldVal->getType();
+ unsigned EltTySize = CGM.getTargetData().getABITypeSizeInBits(EltTy);
+
+ NewVal = Builder.CreateIntCast(NewVal, EltTy, false, "tmp");
+
+ // Move the bits into the appropriate location
llvm::Value *ShAmt = llvm::ConstantInt::get(EltTy, StartBit);
NewVal = Builder.CreateShl(NewVal, ShAmt, "tmp");
@@ -531,7 +543,11 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue,
if (!Field->isBitField()) {
V = Builder.CreateStructGEP(BaseValue, idx, "tmp");
} else {
- const llvm::Type *FieldTy = ConvertType(Field->getType());
+ // FIXME: CodeGenTypes should expose a method to get the appropriate
+ // type for FieldTy (the appropriate type is ABI-dependent).
+ unsigned EltTySize =
+ CGM.getTargetData().getABITypeSizeInBits(ConvertType(Field->getType()));
+ const llvm::Type *FieldTy = llvm::IntegerType::get(EltTySize);
const llvm::PointerType *BaseTy =
cast<llvm::PointerType>(BaseValue->getType());
unsigned AS = BaseTy->getAddressSpace();
OpenPOWER on IntegriCloud