[cfe-commits] r46515 - in /cfe/trunk: AST/Expr.cpp CodeGen/CGExprConstant.cpp CodeGen/CGExprScalar.cpp include/clang/AST/Expr.h test/Sema/offsetof.c

Anders Carlsson andersca at mac.com
Tue Jan 29 07:56:48 PST 2008


Author: andersca
Date: Tue Jan 29 09:56:48 2008
New Revision: 46515

URL: http://llvm.org/viewvc/llvm-project?rev=46515&view=rev
Log:
Implement __builtin_offsetof.

Modified:
    cfe/trunk/AST/Expr.cpp
    cfe/trunk/CodeGen/CGExprConstant.cpp
    cfe/trunk/CodeGen/CGExprScalar.cpp
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/test/Sema/offsetof.c

Modified: cfe/trunk/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Expr.cpp?rev=46515&r1=46514&r2=46515&view=diff

==============================================================================
--- cfe/trunk/AST/Expr.cpp (original)
+++ cfe/trunk/AST/Expr.cpp Tue Jan 29 09:56:48 2008
@@ -662,7 +662,7 @@
     
     // Get the operand value.  If this is sizeof/alignof, do not evalute the
     // operand.  This affects C99 6.6p3.
-    if (!Exp->isSizeOfAlignOfOp() &&
+    if (!Exp->isSizeOfAlignOfOp() && !Exp->isOffsetOfOp() &&
         !Exp->getSubExpr()->isIntegerConstantExpr(Result, Ctx, Loc,isEvaluated))
       return false;
 
@@ -718,6 +718,8 @@
     case UnaryOperator::Not:
       Result = ~Result;
       break;
+    case UnaryOperator::OffsetOf:
+      Result = Exp->evaluateOffsetOf(Ctx);
     }
     break;
   }
@@ -1069,6 +1071,50 @@
   return CondVal != 0;
 }
 
+static int64_t evaluateOffsetOf(ASTContext& C, const Expr *E)
+{
+  if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+    QualType Ty = ME->getBase()->getType();
+    
+    RecordDecl *RD = Ty->getAsRecordType()->getDecl();
+    const ASTRecordLayout &RL = C.getASTRecordLayout(RD, SourceLocation());
+    FieldDecl *FD = ME->getMemberDecl();
+    
+    // FIXME: This is linear time.
+    unsigned i = 0, e = 0;
+    for (i = 0, e = RD->getNumMembers(); i != e; i++) {
+      if (RD->getMember(i) == FD)
+        break;
+    }
+    
+    return RL.getFieldOffset(i) + evaluateOffsetOf(C, ME->getBase());
+  } else if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
+    const Expr *Base = ASE->getBase();
+    llvm::APSInt Idx(32);
+    bool ICE = ASE->getIdx()->isIntegerConstantExpr(Idx, C);
+    assert(ICE && "Array index is not a constant integer!");
+    
+    int64_t size = C.getTypeSize(ASE->getType(), SourceLocation());
+    size *= Idx.getSExtValue();
+    
+    return size + evaluateOffsetOf(C, Base);
+  } else if (isa<CompoundLiteralExpr>(E))
+    return 0;  
+
+  assert(0 && "Unknown offsetof subexpression!");
+  return 0;
+}
+
+int64_t UnaryOperator::evaluateOffsetOf(ASTContext& C) const
+{
+  assert(Opc == OffsetOf && "Unary operator not offsetof!");
+  
+  unsigned CharSize = 
+    C.Target.getCharWidth(C.getFullLoc(getOperatorLoc()));
+  
+  return ::evaluateOffsetOf(C, Val) / CharSize;
+}
+
 //===----------------------------------------------------------------------===//
 //  Child Iterators for iterating over subexpressions/substatements
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CGExprConstant.cpp?rev=46515&r1=46514&r2=46515&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/CodeGen/CGExprConstant.cpp Tue Jan 29 09:56:48 2008
@@ -235,6 +235,15 @@
   llvm::Constant *VisitUnaryAddrOf(const UnaryOperator *E) {
     return EmitLValue(E->getSubExpr());
   }
+  llvm::Constant *VisitUnaryOffsetOf(const UnaryOperator *E) {
+    int64_t Val = E->evaluateOffsetOf(CGM.getContext());
+    
+    assert(E->getType()->isIntegerType() && "Result type must be an integer!");
+    
+    uint32_t ResultWidth = static_cast<uint32_t>(
+      CGM.getContext().getTypeSize(E->getType(), SourceLocation()));
+    return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val));    
+  }
   
   // Binary operators
   llvm::Constant *VisitBinOr(const BinaryOperator *E) {

Modified: cfe/trunk/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CGExprScalar.cpp?rev=46515&r1=46514&r2=46515&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/CodeGen/CGExprScalar.cpp Tue Jan 29 09:56:48 2008
@@ -213,7 +213,8 @@
   Value *VisitUnaryExtension(const UnaryOperator *E) {
     return Visit(E->getSubExpr());
   }
-  
+  Value *VisitUnaryOffsetOf(const UnaryOperator *E);
+    
   // Binary Operators.
   Value *EmitMul(const BinOpInfo &Ops) {
     return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
@@ -628,6 +629,16 @@
   return llvm::Constant::getNullValue(ConvertType(E->getType()));
 }
 
+Value *ScalarExprEmitter::VisitUnaryOffsetOf(const UnaryOperator *E)
+{
+  int64_t Val = E->evaluateOffsetOf(CGF.getContext());
+  
+  assert(E->getType()->isIntegerType() && "Result type must be an integer!");
+  
+  uint32_t ResultWidth = static_cast<uint32_t>(
+    CGF.getContext().getTypeSize(E->getType(), SourceLocation()));
+  return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val));
+}
 
 //===----------------------------------------------------------------------===//
 //                           Binary Operators

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=46515&r1=46514&r2=46515&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue Jan 29 09:56:48 2008
@@ -429,6 +429,7 @@
   bool isPostfix() const { return isPostfix(Opc); }
   bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; }
   bool isSizeOfAlignOfOp() const { return Opc == SizeOf || Opc == AlignOf; }
+  bool isOffsetOfOp() const { return Opc == OffsetOf; }
   static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; }
   
   /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
@@ -448,6 +449,8 @@
   }
   static bool classof(const UnaryOperator *) { return true; }
   
+  int64_t evaluateOffsetOf(ASTContext& C) const;
+  
   // Iterators
   virtual child_iterator child_begin();
   virtual child_iterator child_end();

Modified: cfe/trunk/test/Sema/offsetof.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/offsetof.c?rev=46515&r1=46514&r2=46515&view=diff

==============================================================================
--- cfe/trunk/test/Sema/offsetof.c (original)
+++ cfe/trunk/test/Sema/offsetof.c Tue Jan 29 09:56:48 2008
@@ -19,5 +19,9 @@
   
   x = __builtin_offsetof(struct external_sun3_core, X[42].f2);  // expected-error {{no member named 'f2'}}
   x = __builtin_offsetof(int, X[42].f2);  // expected-error {{offsetof requires struct}}
+  
+  int a[__builtin_offsetof(struct external_sun3_core, X) == 4 ? 1 : -1];
+  int b[__builtin_offsetof(struct external_sun3_core, X[42]) == 340 ? 1 : -1];
+  int c[__builtin_offsetof(struct external_sun3_core, X[42].f2) == 344 ? 1 : -1];
 }    
 





More information about the cfe-commits mailing list