mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 19:16:05 +00:00
Implement bitfield read.
llvm-svn: 46257
This commit is contained in:
parent
97ff7763dc
commit
2ddcb25a3b
@ -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);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
13
clang/test/CodeGen/bitfield.c
Normal file
13
clang/test/CodeGen/bitfield.c
Normal 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user