[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