Implement bitfield read.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46257 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp
index 1bbf2c1..9e90721 100644
--- a/CodeGen/CGExpr.cpp
+++ b/CodeGen/CGExpr.cpp
@@ -132,13 +132,37 @@
// 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 @@
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 @@
"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);
}
//===--------------------------------------------------------------------===//
diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h
index 55a02a8..d56e438 100644
--- a/CodeGen/CodeGenFunction.h
+++ b/CodeGen/CodeGenFunction.h
@@ -159,6 +159,11 @@
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 @@
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 @@
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 @@
/// 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
diff --git a/CodeGen/CodeGenTypes.h b/CodeGen/CodeGenTypes.h
index db3ba9c..5ae4955 100644
--- a/CodeGen/CodeGenTypes.h
+++ b/CodeGen/CodeGenTypes.h
@@ -76,14 +76,17 @@
/// 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