diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2008-05-17 20:03:47 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2008-05-17 20:03:47 +0000 |
commit | 316bb1b9eb9dc3da60e930f50c9b7578411d4966 (patch) | |
tree | 42ea2358ffb8a4546b5e7aa0e9b08f02113099df /lib/CodeGen/CGExpr.cpp | |
parent | 489ecd59eff2602744cbd5089c48ad0d77963dfa (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51224 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExpr.cpp')
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index d6791074c7..840ed4314f 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/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(); |