Implement bitfield read.

llvm-svn: 46257
This commit is contained in:
Lauro Ramos Venancio 2008-01-22 20:17:04 +00:00
parent 97ff7763dc
commit 2ddcb25a3b
4 changed files with 86 additions and 14 deletions

View File

@ -132,13 +132,37 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) {
// shuffle the input or extract/insert them as appropriate.
if (LV.isOCUVectorElt())
return EmitLoadOfOCUElementLValue(LV, ExprType);
assert(0 && "Bitfield ref not impl!");
if (LV.isBitfield())
return EmitLoadOfBitfieldLValue(LV, ExprType);
assert(0 && "Unknown LValue type!");
//an invalid RValue, but the assert will
//ensure that this point is never reached
return RValue();
}
RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV,
QualType ExprType) {
llvm::Value *Ptr = LV.getBitfieldAddr();
const llvm::Type *EltTy =
cast<llvm::PointerType>(Ptr->getType())->getElementType();
unsigned EltTySize = EltTy->getPrimitiveSizeInBits();
unsigned short BitfieldSize = LV.getBitfieldSize();
unsigned short EndBit = LV.getBitfieldStartBit() + BitfieldSize;
llvm::Value *V = Builder.CreateLoad(Ptr, "tmp");
llvm::Value *ShAmt = llvm::ConstantInt::get(EltTy, EltTySize - EndBit);
V = Builder.CreateShl(V, ShAmt, "tmp");
ShAmt = llvm::ConstantInt::get(EltTy, EltTySize - BitfieldSize);
V = LV.isBitfieldSigned() ?
Builder.CreateAShr(V, ShAmt, "tmp") :
Builder.CreateLShr(V, ShAmt, "tmp");
return RValue::get(V);
}
// If this is a reference to a subset of the elements of a vector, either
// shuffle the input or extract/insert them as appropriate.
RValue CodeGenFunction::EmitLoadOfOCUElementLValue(LValue LV,
@ -409,15 +433,13 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
FieldDecl *Field = E->getMemberDecl();
assert (!Field->isBitField() && "Bit-field access is not yet implmented");
unsigned idx = CGM.getTypes().getLLVMFieldNo(Field);
llvm::Value *Idxs[2] = { llvm::Constant::getNullValue(llvm::Type::Int32Ty),
llvm::ConstantInt::get(llvm::Type::Int32Ty, idx) };
llvm::Value *V = Builder.CreateGEP(BaseValue,Idxs, Idxs + 2, "tmp");
// Match union field type.
if (isUnion) {
if (isUnion || Field->isBitField()) {
const llvm::Type * FieldTy = ConvertType(Field->getType());
const llvm::PointerType * BaseTy =
cast<llvm::PointerType>(BaseValue->getType());
@ -428,10 +450,14 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
"tmp");
}
}
return LValue::MakeAddr(V);
// FIXME: If record field does not have one to one match with llvm::StructType
// field then apply appropriate masks to select only member field bits.
if (Field->isBitField()) {
CodeGenTypes::BitFieldInfo bitFieldInfo =
CGM.getTypes().getBitFieldInfo(Field);
return LValue::MakeBitfield(V, bitFieldInfo.Begin, bitFieldInfo.Size,
Field->getType()->isSignedIntegerType());
} else
return LValue::MakeAddr(V);
}
//===--------------------------------------------------------------------===//

View File

@ -159,6 +159,11 @@ class LValue {
union {
llvm::Value *VectorIdx; // Index into a vector subscript: V[i]
unsigned VectorElts; // Encoded OCUVector element subset: V.xyx
struct {
unsigned short StartBit;
unsigned short Size;
bool IsSigned;
} BitfieldData; // BitField start bit and size
};
public:
bool isSimple() const { return LVType == Simple; }
@ -177,8 +182,21 @@ public:
assert(isOCUVectorElt());
return VectorElts;
}
// bitfield lvalue
llvm::Value *getBitfieldAddr() const { assert(isBitfield()); return V; }
unsigned short getBitfieldStartBit() const {
assert(isBitfield());
return BitfieldData.StartBit;
}
unsigned short getBitfieldSize() const {
assert(isBitfield());
return BitfieldData.Size;
}
bool isBitfieldSigned() const {
assert(isBitfield());
return BitfieldData.IsSigned;
}
static LValue MakeAddr(llvm::Value *V) {
LValue R;
R.LVType = Simple;
@ -201,6 +219,17 @@ public:
R.VectorElts = Elements;
return R;
}
static LValue MakeBitfield(llvm::Value *V, unsigned short StartBit,
unsigned short Size, bool IsSigned) {
LValue R;
R.LVType = BitField;
R.V = V;
R.BitfieldData.StartBit = StartBit;
R.BitfieldData.Size = Size;
R.BitfieldData.IsSigned = IsSigned;
return R;
}
};
/// CodeGenFunction - This class organizes the per-function state that is used
@ -364,6 +393,7 @@ public:
/// rvalue, returning the rvalue.
RValue EmitLoadOfLValue(LValue V, QualType LVType);
RValue EmitLoadOfOCUElementLValue(LValue V, QualType LVType);
RValue EmitLoadOfBitfieldLValue(LValue LV, QualType ExprType);
/// EmitStoreThroughLValue - Store the specified rvalue into the specified

View File

@ -76,14 +76,17 @@ class CodeGenTypes {
/// field no. This info is populated by record organizer.
llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo;
public:
class BitFieldInfo {
public:
explicit BitFieldInfo(unsigned B, unsigned S)
explicit BitFieldInfo(unsigned short B, unsigned short S)
: Begin(B), Size(S) {}
unsigned Begin;
unsigned Size;
unsigned short Begin;
unsigned short Size;
};
private:
llvm::DenseMap<const FieldDecl *, BitFieldInfo> BitFields;
/// RecordTypesToResolve - This keeps track of record types that are not

View File

@ -0,0 +1,13 @@
// RUN: clang %s -emit-llvm > %t1
// RUN: grep "shl i32 %tmp, 19" %t1 &&
// RUN: grep "ashr i32 %tmp1, 19" %t1 &&
// RUN: grep "shl i16 %tmp4, 1" %t1 &&
// RUN: grep "lshr i16 %tmp5, 9" %t1
// Test bitfield access
struct STestB1 { int a:13; char b; unsigned short c:7;} stb1;
int f() {
return stb1.a + stb1.b + stb1.c;
}