blob: db2fc458a26210e0c05cc15a8f977de9d1a4a16f [file] [log] [blame]
Anders Carlssonc7436af2008-07-03 04:20:39 +00001//===--- Expr.cpp - Expression Constant Evaluator -------------------------===//
2//
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 Sanghyeonefddb9c2008-07-08 07:23:12 +000017#include "clang/AST/StmtVisitor.h"
Anders Carlssonc0328012008-07-08 05:49:43 +000018#include "clang/Basic/TargetInfo.h"
Anders Carlssoncad17b52008-07-08 05:13:58 +000019#include "llvm/Support/Compiler.h"
Anders Carlssonc7436af2008-07-03 04:20:39 +000020
21using namespace clang;
22
Anders Carlssoncad17b52008-07-08 05:13:58 +000023#define USE_NEW_EVALUATOR 0
Anders Carlssonc7436af2008-07-03 04:20:39 +000024
25static bool CalcFakeICEVal(const Expr* Expr,
26 llvm::APSInt& Result,
27 ASTContext& Context) {
28 // 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
Anders Carlssoncad17b52008-07-08 05:13:58 +000054namespace {
Anders Carlsson02a34c32008-07-08 14:30:00 +000055class VISIBILITY_HIDDEN PointerExprEvaluator
56 : public StmtVisitor<PointerExprEvaluator, APValue> {
57 ASTContext &Ctx;
58
59 PointerExprEvaluator(ASTContext &ctx)
60 : Ctx(ctx) {}
61
62public:
Anders Carlssonc43f44b2008-07-08 15:34:11 +000063 static bool Evaluate(const Expr* E, APValue& Result, ASTContext &Ctx) {
64 if (!E->getType()->isPointerType())
65 return false;
Anders Carlsson02a34c32008-07-08 14:30:00 +000066 Result = PointerExprEvaluator(Ctx).Visit(const_cast<Expr*>(E));
67 return Result.isLValue();
68 }
69
70 APValue VisitStmt(Stmt *S) {
71 // FIXME: Remove this when we support more expressions.
Anders Carlssonc43f44b2008-07-08 15:34:11 +000072 printf("Unhandled pointer statement\n");
Anders Carlsson02a34c32008-07-08 14:30:00 +000073 S->dump();
74 return APValue();
75 }
76
77 APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
78
Anders Carlssonc43f44b2008-07-08 15:34:11 +000079 APValue VisitBinaryOperator(const BinaryOperator *E);
80 APValue VisitCastExpr(const CastExpr* E);
Anders Carlsson02a34c32008-07-08 14:30:00 +000081
Anders Carlssonc43f44b2008-07-08 15:34:11 +000082};
83
Anders Carlssoncad17b52008-07-08 05:13:58 +000084class VISIBILITY_HIDDEN IntExprEvaluator
85 : public StmtVisitor<IntExprEvaluator, APValue> {
86 ASTContext &Ctx;
87
88 IntExprEvaluator(ASTContext &ctx)
89 : Ctx(ctx) {}
90
91public:
Anders Carlssonc43f44b2008-07-08 15:34:11 +000092 static bool Evaluate(const Expr* E, llvm::APSInt& Result, ASTContext &Ctx) {
Anders Carlssonc0328012008-07-08 05:49:43 +000093 APValue Value = IntExprEvaluator(Ctx).Visit(const_cast<Expr*>(E));
94 if (!Value.isSInt())
95 return false;
96
97 Result = Value.getSInt();
98 return true;
Anders Carlssoncad17b52008-07-08 05:13:58 +000099 }
100
101 //===--------------------------------------------------------------------===//
102 // Visitor Methods
103 //===--------------------------------------------------------------------===//
104 APValue VisitStmt(Stmt *S) {
105 // FIXME: Remove this when we support more expressions.
Anders Carlssonc43f44b2008-07-08 15:34:11 +0000106 printf("unhandled int expression");
Anders Carlssoncad17b52008-07-08 05:13:58 +0000107 S->dump();
108 return APValue();
109 }
110
Anders Carlssonc0328012008-07-08 05:49:43 +0000111 APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
Anders Carlssoncad17b52008-07-08 05:13:58 +0000112
Anders Carlssond1aa5812008-07-08 14:35:21 +0000113 APValue VisitBinaryOperator(const BinaryOperator *E);
114 APValue VisitUnaryOperator(const UnaryOperator *E);
Anders Carlssonc0328012008-07-08 05:49:43 +0000115
Anders Carlssond1aa5812008-07-08 14:35:21 +0000116 APValue HandleCast(const Expr* SubExpr, QualType DestType);
Anders Carlssonc43f44b2008-07-08 15:34:11 +0000117 APValue VisitCastExpr(const CastExpr* E) {
118 return HandleCast(E->getSubExpr(), E->getType());
119 }
120 APValue VisitImplicitCastExpr(const ImplicitCastExpr* E) {
121 return HandleCast(E->getSubExpr(), E->getType());
122 }
123 APValue VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E);
124
125 APValue VisitIntegerLiteral(const IntegerLiteral *E) {
126 llvm::APSInt Result(Ctx.getTypeSize(E->getType()));
127
128 Result = E->getValue();
129 return APValue(Result);
130 }
131
Anders Carlssond1aa5812008-07-08 14:35:21 +0000132};
133
Anders Carlssonc43f44b2008-07-08 15:34:11 +0000134APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E)
135{
136 if (E->getOpcode() != BinaryOperator::Add &&
137 E->getOpcode() != BinaryOperator::Sub)
138 return APValue();
139
140 const Expr *PExp = E->getLHS();
141 const Expr *IExp = E->getRHS();
142 if (IExp->getType()->isPointerType())
143 std::swap(PExp, IExp);
144
145 APValue ResultLValue;
146 if (!PointerExprEvaluator::Evaluate(PExp, ResultLValue, Ctx))
147 return APValue();
148 llvm::APSInt AdditionalOffset(32);
149 if (!IntExprEvaluator::Evaluate(IExp, AdditionalOffset, Ctx))
150 return APValue();
151
152 uint64_t Offset = ResultLValue.getLValueOffset();
153 if (E->getOpcode() == BinaryOperator::Add)
154 Offset += AdditionalOffset.getZExtValue();
155 else
156 Offset -= AdditionalOffset.getZExtValue();
157
158 return APValue(ResultLValue.getLValueBase(), Offset);
159}
160
161
162APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E)
163{
164 const Expr* SubExpr = E->getSubExpr();
165
166 // Check for pointer->pointer cast
167 if (SubExpr->getType()->isPointerType()) {
168 APValue Result;
169 if (PointerExprEvaluator::Evaluate(SubExpr, Result, Ctx))
170 return Result;
171 else
172 return APValue();
173 }
174
175 if (SubExpr->getType()->isArithmeticType()) {
176 llvm::APSInt Result(32);
177 if (IntExprEvaluator::Evaluate(SubExpr, Result, Ctx)) {
178 Result.extOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));
179 return APValue(0, Result.getZExtValue());
180 }
181 }
182
183 assert(0 && "Unhandled cast");
184 return APValue();
185}
186
Anders Carlssond1aa5812008-07-08 14:35:21 +0000187APValue IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
188 // The LHS of a constant expr is always evaluated and needed.
189 llvm::APSInt Result(32);
190 if (!Evaluate(E->getLHS(), Result, Ctx))
191 return APValue();
192
193 llvm::APSInt RHS(32);
194 if (!Evaluate(E->getRHS(), RHS, Ctx))
195 return APValue();
196
197 switch (E->getOpcode()) {
198 default:
199 return APValue();
200 case BinaryOperator::Mul:
201 Result *= RHS;
202 break;
203 case BinaryOperator::Div:
204 if (RHS == 0)
Anders Carlssonc0328012008-07-08 05:49:43 +0000205 return APValue();
Anders Carlssond1aa5812008-07-08 14:35:21 +0000206 Result /= RHS;
207 break;
208 case BinaryOperator::Rem:
209 if (RHS == 0)
210 return APValue();
211 Result %= RHS;
212 break;
213 case BinaryOperator::Add: Result += RHS; break;
214 case BinaryOperator::Sub: Result -= RHS; break;
215 case BinaryOperator::Shl:
216 Result <<=
217 static_cast<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
218 break;
219 case BinaryOperator::Shr:
220 Result >>=
221 static_cast<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
222 break;
223 case BinaryOperator::LT: Result = Result < RHS; break;
224 case BinaryOperator::GT: Result = Result > RHS; break;
225 case BinaryOperator::LE: Result = Result <= RHS; break;
226 case BinaryOperator::GE: Result = Result >= RHS; break;
227 case BinaryOperator::EQ: Result = Result == RHS; break;
228 case BinaryOperator::NE: Result = Result != RHS; break;
229 case BinaryOperator::And: Result &= RHS; break;
230 case BinaryOperator::Xor: Result ^= RHS; break;
231 case BinaryOperator::Or: Result |= RHS; break;
Anders Carlssonc0328012008-07-08 05:49:43 +0000232
Anders Carlssond1aa5812008-07-08 14:35:21 +0000233 case BinaryOperator::Comma:
234 // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
235 // *except* when they are contained within a subexpression that is not
236 // evaluated". Note that Assignment can never happen due to constraints
237 // on the LHS subexpr, so we don't need to check it here.
238 // FIXME: Need to come up with an efficient way to deal with the C99
239 // rules on evaluation while still evaluating this. Maybe a
240 // "evaluated comma" out parameter?
241 return APValue();
242 }
243
244 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
245
246 return APValue(Result);
247}
248
249APValue IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
250 llvm::APSInt Result(32);
251
252 if (E->isOffsetOfOp())
253 Result = E->evaluateOffsetOf(Ctx);
254 else if (E->isSizeOfAlignOfOp()) {
255 // Return the result in the right width.
256 Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));
257
258 // sizeof(void) and __alignof__(void) = 1 as a gcc extension.
259 if (E->getSubExpr()->getType()->isVoidType())
260 Result = 1;
261
262 // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
263 if (!E->getSubExpr()->getType()->isConstantSizeType()) {
264 // FIXME: Should we attempt to evaluate this?
265 return APValue();
266 }
267
268 // Get information about the size or align.
269 if (E->getSubExpr()->getType()->isFunctionType()) {
270 // GCC extension: sizeof(function) = 1.
271 // FIXME: AlignOf shouldn't be unconditionally 4!
272 Result = E->getOpcode() == UnaryOperator::AlignOf ? 4 : 1;
273 } else {
274 unsigned CharSize = Ctx.Target.getCharWidth();
275 if (E->getOpcode() == UnaryOperator::AlignOf)
276 Result = Ctx.getTypeAlign(E->getSubExpr()->getType()) / CharSize;
277 else
278 Result = Ctx.getTypeSize(E->getSubExpr()->getType()) / CharSize;
279 }
280 } else {
281 // Get the operand value. If this is sizeof/alignof, do not evalute the
282 // operand. This affects C99 6.6p3.
283 if (!Evaluate(E->getSubExpr(), Result, Ctx))
284 return APValue();
285
Anders Carlssonc0328012008-07-08 05:49:43 +0000286 switch (E->getOpcode()) {
Anders Carlssond1aa5812008-07-08 14:35:21 +0000287 // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
288 // See C99 6.6p3.
Anders Carlssonc0328012008-07-08 05:49:43 +0000289 default:
290 return APValue();
Anders Carlssond1aa5812008-07-08 14:35:21 +0000291 case UnaryOperator::Extension:
292 assert(0 && "Handle UnaryOperator::Extension");
293 return APValue();
294 case UnaryOperator::LNot: {
295 bool Val = Result == 0;
296 uint32_t typeSize = Ctx.getTypeSize(E->getType());
297 Result.zextOrTrunc(typeSize);
298 Result = Val;
Anders Carlssonc0328012008-07-08 05:49:43 +0000299 break;
Anders Carlssond1aa5812008-07-08 14:35:21 +0000300 }
301 case UnaryOperator::Plus:
Anders Carlssonc0328012008-07-08 05:49:43 +0000302 break;
Anders Carlssond1aa5812008-07-08 14:35:21 +0000303 case UnaryOperator::Minus:
304 Result = -Result;
Anders Carlssonc0328012008-07-08 05:49:43 +0000305 break;
Anders Carlssond1aa5812008-07-08 14:35:21 +0000306 case UnaryOperator::Not:
307 Result = ~Result;
Anders Carlssonc0328012008-07-08 05:49:43 +0000308 break;
Anders Carlssond1aa5812008-07-08 14:35:21 +0000309 }
310 }
311
312 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
313 return APValue(Result);
314}
315
316APValue IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) {
317 llvm::APSInt Result(32);
318
319 uint32_t DestWidth = static_cast<uint32_t>(Ctx.getTypeSize(DestType));
320
321 // Handle simple integer->integer casts.
322 if (SubExpr->getType()->isIntegerType()) {
323 if (!Evaluate(SubExpr, Result, Ctx))
Anders Carlssonc0328012008-07-08 05:49:43 +0000324 return APValue();
Anders Carlssond1aa5812008-07-08 14:35:21 +0000325
326 // Figure out if this is a truncate, extend or noop cast.
327 // If the input is signed, do a sign extend, noop, or truncate.
328 if (DestType->isBooleanType()) {
329 // Conversion to bool compares against zero.
330 Result = Result != 0;
331 Result.zextOrTrunc(DestWidth);
Anders Carlssonc0328012008-07-08 05:49:43 +0000332 }
Anders Carlssond1aa5812008-07-08 14:35:21 +0000333 else
334 Result.extOrTrunc(DestWidth);
335 } else if (SubExpr->getType()->isPointerType()) {
336 APValue LV;
337 if (!PointerExprEvaluator::Evaluate(SubExpr, LV, Ctx))
338 return APValue();
339 if (LV.getLValueBase())
340 return APValue();
Anders Carlssonc0328012008-07-08 05:49:43 +0000341
Anders Carlsson8ab15c82008-07-08 16:49:00 +0000342 Result.extOrTrunc(DestWidth);
343 Result = LV.getLValueOffset();
Anders Carlssond1aa5812008-07-08 14:35:21 +0000344 } else {
345 assert(0 && "Unhandled cast!");
Anders Carlsson02a34c32008-07-08 14:30:00 +0000346 }
347
Anders Carlssond1aa5812008-07-08 14:35:21 +0000348 Result.setIsUnsigned(DestType->isUnsignedIntegerType());
349 return APValue(Result);
350}
Anders Carlsson02a34c32008-07-08 14:30:00 +0000351
Anders Carlssonc43f44b2008-07-08 15:34:11 +0000352APValue IntExprEvaluator::VisitSizeOfAlignOfTypeExpr
353 (const SizeOfAlignOfTypeExpr *E)
354{
355 llvm::APSInt Result(32);
356
357 // Return the result in the right width.
358 Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));
359
360 // sizeof(void) and __alignof__(void) = 1 as a gcc extension.
361 if (E->getArgumentType()->isVoidType()) {
362 Result = 1;
363 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
364 return APValue(Result);
365 }
366
367 // alignof always evaluates to a constant, sizeof does if arg is not VLA.
368 if (E->isSizeOf() && !E->getArgumentType()->isConstantSizeType())
369 return APValue();
370
371 // Get information about the size or align.
372 if (E->getArgumentType()->isFunctionType()) {
373 // GCC extension: sizeof(function) = 1.
374 Result = E->isSizeOf() ? 1 : 4;
375 } else {
376 unsigned CharSize = Ctx.Target.getCharWidth();
377 if (E->isSizeOf())
378 Result = Ctx.getTypeSize(E->getArgumentType()) / CharSize;
379 else
380 Result = Ctx.getTypeAlign(E->getArgumentType()) / CharSize;
381 }
382
383 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
384 return APValue(Result);
385}
386
Anders Carlssoncad17b52008-07-08 05:13:58 +0000387}
388
Anders Carlssonc7436af2008-07-03 04:20:39 +0000389bool Expr::tryEvaluate(APValue& Result, ASTContext &Ctx) const
390{
391 llvm::APSInt sInt(1);
392
Anders Carlssoncad17b52008-07-08 05:13:58 +0000393#if USE_NEW_EVALUATOR
Anders Carlssonc0328012008-07-08 05:49:43 +0000394 if (getType()->isIntegerType()) {
395 if (IntExprEvaluator::Evaluate(this, sInt, Ctx)) {
396 Result = APValue(sInt);
397 return true;
398 }
399 } else
Anders Carlssoncad17b52008-07-08 05:13:58 +0000400 return false;
401
402#else
Anders Carlssonc7436af2008-07-03 04:20:39 +0000403 if (CalcFakeICEVal(this, sInt, Ctx)) {
404 Result = APValue(sInt);
405 return true;
406 }
Anders Carlssoncad17b52008-07-08 05:13:58 +0000407#endif
Anders Carlssonc7436af2008-07-03 04:20:39 +0000408
409 return false;
410}