blob: ca9dde28218b4b0428f385be2d78dcc669a7d1fa [file] [log] [blame]
Chris Lattnerb542afe2008-07-11 19:10:17 +00001//===--- ExprConstant.cpp - Expression Constant Evaluator -----------------===//
Anders Carlssonc44eec62008-07-03 04:20:39 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Expr constant evaluator.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/APValue.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Expr.h"
Seo Sanghyeon0fe52e12008-07-08 07:23:12 +000017#include "clang/AST/StmtVisitor.h"
Anders Carlsson06a36752008-07-08 05:49:43 +000018#include "clang/Basic/TargetInfo.h"
Anders Carlssonc754aa62008-07-08 05:13:58 +000019#include "llvm/Support/Compiler.h"
Anders Carlssonc44eec62008-07-03 04:20:39 +000020using namespace clang;
Chris Lattnerf5eeb052008-07-11 18:11:29 +000021using llvm::APSInt;
Anders Carlssonc44eec62008-07-03 04:20:39 +000022
Anders Carlssonc754aa62008-07-08 05:13:58 +000023#define USE_NEW_EVALUATOR 0
Anders Carlssonc44eec62008-07-03 04:20:39 +000024
Chris Lattnerf5eeb052008-07-11 18:11:29 +000025static bool CalcFakeICEVal(const Expr *Expr,
26 llvm::APSInt &Result,
27 ASTContext &Context) {
Anders Carlssonc44eec62008-07-03 04:20:39 +000028 // Calculate the value of an expression that has a calculatable
29 // value, but isn't an ICE. Currently, this only supports
30 // a very narrow set of extensions, but it can be expanded if needed.
31 if (const ParenExpr *PE = dyn_cast<ParenExpr>(Expr))
32 return CalcFakeICEVal(PE->getSubExpr(), Result, Context);
33
34 if (const CastExpr *CE = dyn_cast<CastExpr>(Expr)) {
35 QualType CETy = CE->getType();
36 if ((CETy->isIntegralType() && !CETy->isBooleanType()) ||
37 CETy->isPointerType()) {
38 if (CalcFakeICEVal(CE->getSubExpr(), Result, Context)) {
39 Result.extOrTrunc(Context.getTypeSize(CETy));
40 // FIXME: This assumes pointers are signed.
41 Result.setIsSigned(CETy->isSignedIntegerType() ||
42 CETy->isPointerType());
43 return true;
44 }
45 }
46 }
47
48 if (Expr->getType()->isIntegralType())
49 return Expr->isIntegerConstantExpr(Result, Context);
50
51 return false;
52}
53
Chris Lattnerf5eeb052008-07-11 18:11:29 +000054static bool EvaluatePointer(const Expr *E, APValue &Result, ASTContext &Ctx);
55static bool EvaluateInteger(const Expr *E, APSInt &Result, ASTContext &Ctx);
56
57
58//===----------------------------------------------------------------------===//
59// Pointer Evaluation
60//===----------------------------------------------------------------------===//
61
Anders Carlssonc754aa62008-07-08 05:13:58 +000062namespace {
Anders Carlsson2bad1682008-07-08 14:30:00 +000063class VISIBILITY_HIDDEN PointerExprEvaluator
64 : public StmtVisitor<PointerExprEvaluator, APValue> {
65 ASTContext &Ctx;
Anders Carlsson2bad1682008-07-08 14:30:00 +000066public:
Anders Carlsson2bad1682008-07-08 14:30:00 +000067
Chris Lattnerf5eeb052008-07-11 18:11:29 +000068 PointerExprEvaluator(ASTContext &ctx) : Ctx(ctx) {}
69
Anders Carlsson2bad1682008-07-08 14:30:00 +000070 APValue VisitStmt(Stmt *S) {
71 // FIXME: Remove this when we support more expressions.
Anders Carlsson650c92f2008-07-08 15:34:11 +000072 printf("Unhandled pointer statement\n");
Anders Carlsson2bad1682008-07-08 14:30:00 +000073 S->dump();
74 return APValue();
75 }
76
77 APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
78
Anders Carlsson650c92f2008-07-08 15:34:11 +000079 APValue VisitBinaryOperator(const BinaryOperator *E);
80 APValue VisitCastExpr(const CastExpr* E);
Anders Carlsson650c92f2008-07-08 15:34:11 +000081};
Chris Lattnerf5eeb052008-07-11 18:11:29 +000082} // end anonymous namespace
Anders Carlsson650c92f2008-07-08 15:34:11 +000083
Chris Lattnerf5eeb052008-07-11 18:11:29 +000084static bool EvaluatePointer(const Expr* E, APValue& Result, ASTContext &Ctx) {
85 if (!E->getType()->isPointerType())
86 return false;
87 Result = PointerExprEvaluator(Ctx).Visit(const_cast<Expr*>(E));
88 return Result.isLValue();
89}
90
91APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
92 if (E->getOpcode() != BinaryOperator::Add &&
93 E->getOpcode() != BinaryOperator::Sub)
94 return APValue();
95
96 const Expr *PExp = E->getLHS();
97 const Expr *IExp = E->getRHS();
98 if (IExp->getType()->isPointerType())
99 std::swap(PExp, IExp);
100
101 APValue ResultLValue;
102 if (!EvaluatePointer(PExp, ResultLValue, Ctx))
103 return APValue();
104
105 llvm::APSInt AdditionalOffset(32);
106 if (!EvaluateInteger(IExp, AdditionalOffset, Ctx))
107 return APValue();
108
109 uint64_t Offset = ResultLValue.getLValueOffset();
110 if (E->getOpcode() == BinaryOperator::Add)
111 Offset += AdditionalOffset.getZExtValue();
112 else
113 Offset -= AdditionalOffset.getZExtValue();
114
115 return APValue(ResultLValue.getLValueBase(), Offset);
116}
117
118
Chris Lattnerb542afe2008-07-11 19:10:17 +0000119APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000120 const Expr* SubExpr = E->getSubExpr();
121
122 // Check for pointer->pointer cast
123 if (SubExpr->getType()->isPointerType()) {
124 APValue Result;
125 if (EvaluatePointer(SubExpr, Result, Ctx))
126 return Result;
127 return APValue();
128 }
129
130 if (SubExpr->getType()->isArithmeticType()) {
131 llvm::APSInt Result(32);
132 if (EvaluateInteger(SubExpr, Result, Ctx)) {
133 Result.extOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));
134 return APValue(0, Result.getZExtValue());
135 }
136 }
137
138 assert(0 && "Unhandled cast");
139 return APValue();
140}
141
142
143//===----------------------------------------------------------------------===//
144// Integer Evaluation
145//===----------------------------------------------------------------------===//
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000146
147namespace {
Anders Carlssonc754aa62008-07-08 05:13:58 +0000148class VISIBILITY_HIDDEN IntExprEvaluator
Chris Lattnerb542afe2008-07-11 19:10:17 +0000149 : public StmtVisitor<IntExprEvaluator, bool> {
Anders Carlssonc754aa62008-07-08 05:13:58 +0000150 ASTContext &Ctx;
Chris Lattnerb542afe2008-07-11 19:10:17 +0000151 APSInt &Result;
Anders Carlssonc754aa62008-07-08 05:13:58 +0000152public:
Chris Lattnerb542afe2008-07-11 19:10:17 +0000153 IntExprEvaluator(ASTContext &ctx, APSInt &result) : Ctx(ctx), Result(result){}
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000154
Chris Lattner7a767782008-07-11 19:24:49 +0000155 unsigned getIntTypeSizeInBits(QualType T) const {
156 return (unsigned)Ctx.getTypeSize(T);
157 }
158
Anders Carlssonc754aa62008-07-08 05:13:58 +0000159 //===--------------------------------------------------------------------===//
160 // Visitor Methods
161 //===--------------------------------------------------------------------===//
Chris Lattner7a767782008-07-11 19:24:49 +0000162
Chris Lattnerb542afe2008-07-11 19:10:17 +0000163 bool VisitStmt(Stmt *S) {
Anders Carlssonc754aa62008-07-08 05:13:58 +0000164 // FIXME: Remove this when we support more expressions.
Anders Carlsson650c92f2008-07-08 15:34:11 +0000165 printf("unhandled int expression");
Anders Carlssonc754aa62008-07-08 05:13:58 +0000166 S->dump();
Chris Lattnerb542afe2008-07-11 19:10:17 +0000167 return false;
Anders Carlssonc754aa62008-07-08 05:13:58 +0000168 }
169
Chris Lattnerb542afe2008-07-11 19:10:17 +0000170 bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
Anders Carlssonc754aa62008-07-08 05:13:58 +0000171
Chris Lattnerb542afe2008-07-11 19:10:17 +0000172 bool VisitBinaryOperator(const BinaryOperator *E);
Chris Lattner75a48812008-07-11 22:15:16 +0000173
Chris Lattnerb542afe2008-07-11 19:10:17 +0000174 bool VisitUnaryOperator(const UnaryOperator *E);
Anders Carlsson06a36752008-07-08 05:49:43 +0000175
Chris Lattnerb542afe2008-07-11 19:10:17 +0000176 bool VisitCastExpr(const CastExpr* E) {
Anders Carlsson650c92f2008-07-08 15:34:11 +0000177 return HandleCast(E->getSubExpr(), E->getType());
178 }
Chris Lattnerb542afe2008-07-11 19:10:17 +0000179 bool VisitImplicitCastExpr(const ImplicitCastExpr* E) {
Anders Carlsson650c92f2008-07-08 15:34:11 +0000180 return HandleCast(E->getSubExpr(), E->getType());
181 }
Chris Lattnerfcee0012008-07-11 21:24:13 +0000182 bool VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) {
183 return EvaluateSizeAlignOf(E->isSizeOf(),E->getArgumentType(),E->getType());
184 }
Anders Carlsson650c92f2008-07-08 15:34:11 +0000185
Chris Lattnerb542afe2008-07-11 19:10:17 +0000186 bool VisitIntegerLiteral(const IntegerLiteral *E) {
Anders Carlsson650c92f2008-07-08 15:34:11 +0000187 Result = E->getValue();
Chris Lattnerb542afe2008-07-11 19:10:17 +0000188 return true;
Anders Carlsson650c92f2008-07-08 15:34:11 +0000189 }
Chris Lattnerfcee0012008-07-11 21:24:13 +0000190private:
191 bool HandleCast(const Expr* SubExpr, QualType DestType);
192 bool EvaluateSizeAlignOf(bool isSizeOf, QualType SrcTy, QualType DstTy);
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000193};
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000194} // end anonymous namespace
Anders Carlsson650c92f2008-07-08 15:34:11 +0000195
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000196static bool EvaluateInteger(const Expr* E, APSInt &Result, ASTContext &Ctx) {
Chris Lattnerb542afe2008-07-11 19:10:17 +0000197 return IntExprEvaluator(Ctx, Result).Visit(const_cast<Expr*>(E));
Anders Carlsson650c92f2008-07-08 15:34:11 +0000198}
Anders Carlsson650c92f2008-07-08 15:34:11 +0000199
Anders Carlsson650c92f2008-07-08 15:34:11 +0000200
Chris Lattnerb542afe2008-07-11 19:10:17 +0000201bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000202 // The LHS of a constant expr is always evaluated and needed.
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000203 llvm::APSInt RHS(32);
Chris Lattner75a48812008-07-11 22:15:16 +0000204 if (!Visit(E->getLHS()) || !EvaluateInteger(E->getRHS(), RHS, Ctx))
Chris Lattnerb542afe2008-07-11 19:10:17 +0000205 return false;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000206
207 switch (E->getOpcode()) {
Chris Lattner75a48812008-07-11 22:15:16 +0000208 default: return false;
209 case BinaryOperator::Mul: Result *= RHS; break;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000210 case BinaryOperator::Add: Result += RHS; break;
211 case BinaryOperator::Sub: Result -= RHS; break;
Chris Lattnerac7cb602008-07-11 19:29:32 +0000212 case BinaryOperator::And: Result &= RHS; break;
213 case BinaryOperator::Xor: Result ^= RHS; break;
214 case BinaryOperator::Or: Result |= RHS; break;
Chris Lattner75a48812008-07-11 22:15:16 +0000215 case BinaryOperator::Div:
216 if (RHS == 0) return false;
217 Result /= RHS;
218 break;
219 case BinaryOperator::Rem:
220 if (RHS == 0) return false;
221 Result %= RHS;
222 break;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000223 case BinaryOperator::Shl:
Chris Lattnerb542afe2008-07-11 19:10:17 +0000224 Result <<= (unsigned)RHS.getLimitedValue(Result.getBitWidth()-1);
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000225 break;
226 case BinaryOperator::Shr:
Chris Lattnerb542afe2008-07-11 19:10:17 +0000227 Result >>= (unsigned)RHS.getLimitedValue(Result.getBitWidth()-1);
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000228 break;
Chris Lattnerb542afe2008-07-11 19:10:17 +0000229
Chris Lattnerac7cb602008-07-11 19:29:32 +0000230 case BinaryOperator::LT:
231 Result = Result < RHS;
232 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
233 break;
234 case BinaryOperator::GT:
235 Result = Result > RHS;
236 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
237 break;
238 case BinaryOperator::LE:
239 Result = Result <= RHS;
240 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
241 break;
242 case BinaryOperator::GE:
243 Result = Result >= RHS;
244 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
245 break;
246 case BinaryOperator::EQ:
247 Result = Result == RHS;
248 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
249 break;
250 case BinaryOperator::NE:
251 Result = Result != RHS;
252 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
253 break;
Anders Carlsson06a36752008-07-08 05:49:43 +0000254
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000255 case BinaryOperator::Comma:
256 // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
257 // *except* when they are contained within a subexpression that is not
258 // evaluated". Note that Assignment can never happen due to constraints
259 // on the LHS subexpr, so we don't need to check it here.
260 // FIXME: Need to come up with an efficient way to deal with the C99
261 // rules on evaluation while still evaluating this. Maybe a
262 // "evaluated comma" out parameter?
Chris Lattnerb542afe2008-07-11 19:10:17 +0000263 return false;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000264 }
265
266 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
Chris Lattnerb542afe2008-07-11 19:10:17 +0000267 return true;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000268}
269
Chris Lattnerfcee0012008-07-11 21:24:13 +0000270/// EvaluateSizeAlignOf - Evaluate sizeof(SrcTy) or alignof(SrcTy) with a result
271/// as a DstTy type.
272bool IntExprEvaluator::EvaluateSizeAlignOf(bool isSizeOf, QualType SrcTy,
273 QualType DstTy) {
274 // Return the result in the right width.
275 Result.zextOrTrunc(getIntTypeSizeInBits(DstTy));
276 Result.setIsUnsigned(DstTy->isUnsignedIntegerType());
277
278 // sizeof(void) and __alignof__(void) = 1 as a gcc extension.
279 if (SrcTy->isVoidType())
280 Result = 1;
281
282 // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
283 if (!SrcTy->isConstantSizeType()) {
284 // FIXME: Should we attempt to evaluate this?
285 return false;
286 }
287
288 // GCC extension: sizeof(function) = 1.
289 if (SrcTy->isFunctionType()) {
290 // FIXME: AlignOf shouldn't be unconditionally 4!
291 Result = isSizeOf ? 1 : 4;
292 return true;
293 }
294
295 // Get information about the size or align.
296 unsigned CharSize = Ctx.Target.getCharWidth();
297 if (isSizeOf)
298 Result = getIntTypeSizeInBits(SrcTy) / CharSize;
299 else
300 Result = Ctx.getTypeAlign(SrcTy) / CharSize;
301 return true;
302}
303
Chris Lattnerb542afe2008-07-11 19:10:17 +0000304bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
Chris Lattner75a48812008-07-11 22:15:16 +0000305 if (E->isOffsetOfOp()) {
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000306 Result = E->evaluateOffsetOf(Ctx);
Chris Lattner75a48812008-07-11 22:15:16 +0000307 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
308 return true;
309 }
310
311 if (E->isSizeOfAlignOfOp())
Chris Lattnerfcee0012008-07-11 21:24:13 +0000312 return EvaluateSizeAlignOf(E->getOpcode() == UnaryOperator::SizeOf,
313 E->getSubExpr()->getType(), E->getType());
Chris Lattner75a48812008-07-11 22:15:16 +0000314
315 // Get the operand value.
316 if (!EvaluateInteger(E->getSubExpr(), Result, Ctx))
317 return false;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000318
Chris Lattner75a48812008-07-11 22:15:16 +0000319 switch (E->getOpcode()) {
320 // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
321 // See C99 6.6p3.
322 default:
323 return false;
324 case UnaryOperator::LNot: {
325 bool Val = Result == 0;
326 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
327 Result = Val;
328 break;
329 }
330 case UnaryOperator::Extension:
331 case UnaryOperator::Plus:
332 // The result is always just the subexpr
333 break;
334 case UnaryOperator::Minus:
335 Result = -Result;
336 break;
337 case UnaryOperator::Not:
338 Result = ~Result;
339 break;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000340 }
341
342 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
Chris Lattnerb542afe2008-07-11 19:10:17 +0000343 return true;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000344}
345
Chris Lattnerb542afe2008-07-11 19:10:17 +0000346bool IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) {
Chris Lattner7a767782008-07-11 19:24:49 +0000347 unsigned DestWidth = getIntTypeSizeInBits(DestType);
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000348
349 // Handle simple integer->integer casts.
350 if (SubExpr->getType()->isIntegerType()) {
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000351 if (!EvaluateInteger(SubExpr, Result, Ctx))
Chris Lattnerb542afe2008-07-11 19:10:17 +0000352 return false;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000353
354 // Figure out if this is a truncate, extend or noop cast.
355 // If the input is signed, do a sign extend, noop, or truncate.
356 if (DestType->isBooleanType()) {
357 // Conversion to bool compares against zero.
358 Result = Result != 0;
359 Result.zextOrTrunc(DestWidth);
Chris Lattner7a767782008-07-11 19:24:49 +0000360 } else
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000361 Result.extOrTrunc(DestWidth);
362 } else if (SubExpr->getType()->isPointerType()) {
363 APValue LV;
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000364 if (!EvaluatePointer(SubExpr, LV, Ctx))
Chris Lattnerb542afe2008-07-11 19:10:17 +0000365 return false;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000366 if (LV.getLValueBase())
Chris Lattnerb542afe2008-07-11 19:10:17 +0000367 return false;
Anders Carlsson06a36752008-07-08 05:49:43 +0000368
Anders Carlsson559e56b2008-07-08 16:49:00 +0000369 Result.extOrTrunc(DestWidth);
370 Result = LV.getLValueOffset();
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000371 } else {
372 assert(0 && "Unhandled cast!");
Anders Carlsson2bad1682008-07-08 14:30:00 +0000373 }
374
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000375 Result.setIsUnsigned(DestType->isUnsignedIntegerType());
Chris Lattnerb542afe2008-07-11 19:10:17 +0000376 return true;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000377}
Anders Carlsson2bad1682008-07-08 14:30:00 +0000378
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000379//===----------------------------------------------------------------------===//
380// Top level TryEvaluate.
381//===----------------------------------------------------------------------===//
382
Chris Lattnerb542afe2008-07-11 19:10:17 +0000383bool Expr::tryEvaluate(APValue &Result, ASTContext &Ctx) const {
Chris Lattnercf0f51d2008-07-11 19:19:21 +0000384 llvm::APSInt sInt(32);
Anders Carlssonc754aa62008-07-08 05:13:58 +0000385#if USE_NEW_EVALUATOR
Anders Carlsson06a36752008-07-08 05:49:43 +0000386 if (getType()->isIntegerType()) {
Chris Lattnerb542afe2008-07-11 19:10:17 +0000387 if (EvaluateInteger(this, sInt, Ctx)) {
Anders Carlsson06a36752008-07-08 05:49:43 +0000388 Result = APValue(sInt);
389 return true;
390 }
391 } else
Anders Carlssonc754aa62008-07-08 05:13:58 +0000392 return false;
393
394#else
Anders Carlssonc44eec62008-07-03 04:20:39 +0000395 if (CalcFakeICEVal(this, sInt, Ctx)) {
396 Result = APValue(sInt);
397 return true;
398 }
Anders Carlssonc754aa62008-07-08 05:13:58 +0000399#endif
Anders Carlssonc44eec62008-07-03 04:20:39 +0000400
401 return false;
402}