]> granicus.if.org Git - clang/commitdiff
Implement bitfield read.
authorLauro Ramos Venancio <lauro.venancio@gmail.com>
Tue, 22 Jan 2008 20:17:04 +0000 (20:17 +0000)
committerLauro Ramos Venancio <lauro.venancio@gmail.com>
Tue, 22 Jan 2008 20:17:04 +0000 (20:17 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46257 91177308-0d34-0410-b5e6-96231b3b80d8

CodeGen/CGExpr.cpp
CodeGen/CodeGenFunction.h
CodeGen/CodeGenTypes.h
test/CodeGen/bitfield.c [new file with mode: 0644]

index 1bbf2c1f81a6ebf656c09a27bb99560b3e371161..9e907216ee2822fef539721f0b07dde7f061efa4 100644 (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);
 }
 
 //===--------------------------------------------------------------------===//
index 55a02a89b96e9d79e2b497a53b7d258e857010ab..d56e438df82c1572f9519660d277dc6fc6d2455c 100644 (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
index db3ba9c2af4175d0ecc96e73968d0c882cbc90a1..5ae49553ab588a3d46b8e5cb9542946c16c9cb79 100644 (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 
diff --git a/test/CodeGen/bitfield.c b/test/CodeGen/bitfield.c
new file mode 100644 (file)
index 0000000..5198765
--- /dev/null
@@ -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;
+}