blob: 5307a56fab2b95ac22e6b9212885572a1e95e315 [file] [log] [blame]
Anders Carlssonc44eec62008-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 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 +000020
21using namespace clang;
22
Anders Carlssonc754aa62008-07-08 05:13:58 +000023#define USE_NEW_EVALUATOR 0
Anders Carlssonc44eec62008-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 Carlssonc754aa62008-07-08 05:13:58 +000054namespace {
Anders Carlsson2bad1682008-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:
63 static bool Evaluate(const Expr* E, APValue& Result, ASTContext &Ctx) {
64 Result = PointerExprEvaluator(Ctx).Visit(const_cast<Expr*>(E));
65 return Result.isLValue();
66 }
67
68 APValue VisitStmt(Stmt *S) {
69 // FIXME: Remove this when we support more expressions.
70 printf("Unhandled statement\n");
71 S->dump();
72 return APValue();
73 }
74
75 APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
76
77};
78}
79
80namespace {
Anders Carlssonc754aa62008-07-08 05:13:58 +000081class VISIBILITY_HIDDEN IntExprEvaluator
82 : public StmtVisitor<IntExprEvaluator, APValue> {
83 ASTContext &Ctx;
84
85 IntExprEvaluator(ASTContext &ctx)
86 : Ctx(ctx) {}
87
88public:
Anders Carlsson06a36752008-07-08 05:49:43 +000089 static bool Evaluate(const Expr* E, llvm::APSInt& Result, ASTContext &Ctx) {
90 APValue Value = IntExprEvaluator(Ctx).Visit(const_cast<Expr*>(E));
91 if (!Value.isSInt())
92 return false;
93
94 Result = Value.getSInt();
95 return true;
Anders Carlssonc754aa62008-07-08 05:13:58 +000096 }
97
98 //===--------------------------------------------------------------------===//
99 // Visitor Methods
100 //===--------------------------------------------------------------------===//
101 APValue VisitStmt(Stmt *S) {
102 // FIXME: Remove this when we support more expressions.
103 printf("Unhandled statement\n");
104 S->dump();
105 return APValue();
106 }
107
Anders Carlsson06a36752008-07-08 05:49:43 +0000108 APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
Anders Carlssonc754aa62008-07-08 05:13:58 +0000109
Anders Carlsson06a36752008-07-08 05:49:43 +0000110 APValue VisitBinaryOperator(const BinaryOperator *E) {
111 // The LHS of a constant expr is always evaluated and needed.
112 llvm::APSInt Result(32);
Anders Carlsson2bad1682008-07-08 14:30:00 +0000113 if (!Evaluate(E->getLHS(), Result, Ctx))
Anders Carlsson06a36752008-07-08 05:49:43 +0000114 return APValue();
115
116 llvm::APSInt RHS(32);
117 if (!Evaluate(E->getRHS(), RHS, Ctx))
118 return APValue();
119
120 switch (E->getOpcode()) {
121 default:
122 return APValue();
123 case BinaryOperator::Mul:
124 Result *= RHS;
125 break;
126 case BinaryOperator::Div:
127 if (RHS == 0)
128 return APValue();
129 Result /= RHS;
130 break;
131 case BinaryOperator::Rem:
132 if (RHS == 0)
133 return APValue();
134 Result %= RHS;
135 break;
136 case BinaryOperator::Add: Result += RHS; break;
137 case BinaryOperator::Sub: Result -= RHS; break;
138 case BinaryOperator::Shl:
139 Result <<=
140 static_cast<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
141 break;
142 case BinaryOperator::Shr:
143 Result >>=
144 static_cast<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
145 break;
146 case BinaryOperator::LT: Result = Result < RHS; break;
147 case BinaryOperator::GT: Result = Result > RHS; break;
148 case BinaryOperator::LE: Result = Result <= RHS; break;
149 case BinaryOperator::GE: Result = Result >= RHS; break;
150 case BinaryOperator::EQ: Result = Result == RHS; break;
151 case BinaryOperator::NE: Result = Result != RHS; break;
152 case BinaryOperator::And: Result &= RHS; break;
153 case BinaryOperator::Xor: Result ^= RHS; break;
154 case BinaryOperator::Or: Result |= RHS; break;
155
156 case BinaryOperator::Comma:
157 // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
158 // *except* when they are contained within a subexpression that is not
159 // evaluated". Note that Assignment can never happen due to constraints
160 // on the LHS subexpr, so we don't need to check it here.
161 // FIXME: Need to come up with an efficient way to deal with the C99
162 // rules on evaluation while still evaluating this. Maybe a
163 // "evaluated comma" out parameter?
164 return APValue();
165 }
166
167 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
168
169 return APValue(Result);
170 }
171
172 APValue VisitUnaryOperator(const UnaryOperator *E) {
173 llvm::APSInt Result(32);
174
175 if (E->isOffsetOfOp())
176 Result = E->evaluateOffsetOf(Ctx);
177 else if (E->isSizeOfAlignOfOp()) {
178 // Return the result in the right width.
179 Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));
180
181 // sizeof(void) and __alignof__(void) = 1 as a gcc extension.
182 if (E->getSubExpr()->getType()->isVoidType())
183 Result = 1;
184
185 // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
186 if (!E->getSubExpr()->getType()->isConstantSizeType()) {
187 // FIXME: Should we attempt to evaluate this?
188 return APValue();
189 }
190
191 // Get information about the size or align.
192 if (E->getSubExpr()->getType()->isFunctionType()) {
193 // GCC extension: sizeof(function) = 1.
194 // FIXME: AlignOf shouldn't be unconditionally 4!
195 Result = E->getOpcode() == UnaryOperator::AlignOf ? 4 : 1;
196 } else {
197 unsigned CharSize = Ctx.Target.getCharWidth();
198 if (E->getOpcode() == UnaryOperator::AlignOf)
199 Result = Ctx.getTypeAlign(E->getSubExpr()->getType()) / CharSize;
200 else
201 Result = Ctx.getTypeSize(E->getSubExpr()->getType()) / CharSize;
202 }
203 } else {
204 // Get the operand value. If this is sizeof/alignof, do not evalute the
205 // operand. This affects C99 6.6p3.
206 if (!Evaluate(E->getSubExpr(), Result, Ctx))
207 return APValue();
208
209 switch (E->getOpcode()) {
210 // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
211 // See C99 6.6p3.
212 default:
213 return APValue();
214 case UnaryOperator::Extension:
215 assert(0 && "Handle UnaryOperator::Extension");
216 return APValue();
217 case UnaryOperator::LNot: {
218 bool Val = Result == 0;
219 uint32_t typeSize = Ctx.getTypeSize(E->getType());
220 Result.zextOrTrunc(typeSize);
221 Result = Val;
222 break;
223 }
224 case UnaryOperator::Plus:
225 break;
226 case UnaryOperator::Minus:
227 Result = -Result;
228 break;
229 case UnaryOperator::Not:
230 Result = ~Result;
231 break;
232 }
233 }
234
235 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
236 return APValue(Result);
237 }
Anders Carlsson2bad1682008-07-08 14:30:00 +0000238
239 APValue HandleCast(const Expr* SubExpr, QualType DestType) {
240 llvm::APSInt Result(32);
241
242 uint32_t DestWidth = static_cast<uint32_t>(Ctx.getTypeSize(DestType));
243
244 // Handle simple integer->integer casts.
245 if (SubExpr->getType()->isIntegerType()) {
246 if (!Evaluate(SubExpr, Result, Ctx))
247 return APValue();
248
249 // Figure out if this is a truncate, extend or noop cast.
250 // If the input is signed, do a sign extend, noop, or truncate.
251 if (DestType->isBooleanType()) {
252 // Conversion to bool compares against zero.
253 Result = Result != 0;
254 Result.zextOrTrunc(DestWidth);
255 }
256 else
257 Result.extOrTrunc(DestWidth);
258 } else if (SubExpr->getType()->isPointerType()) {
259 APValue LV;
260 if (!PointerExprEvaluator::Evaluate(SubExpr, LV, Ctx))
261 return APValue();
262 if (LV.getLValueBase())
263 return APValue();
264
265 Result = llvm::APSInt(DestWidth, LV.getLValueOffset());
266 } else {
267 assert(0 && "Unhandled cast!");
268 }
269
270 Result.setIsUnsigned(DestType->isUnsignedIntegerType());
271 return APValue(Result);
272 }
273
274 APValue VisitImplicitCastExpr(const ImplicitCastExpr *E) {
275 return HandleCast(E->getSubExpr(), E->getType());
276 }
277
278 APValue VisitCastExpr(const CastExpr *E) {
279 return HandleCast(E->getSubExpr(), E->getType());
280 }
281
282 APValue VisitIntegerLiteral(const IntegerLiteral *E) {
283 llvm::APSInt Result(Ctx.getTypeSize(E->getType()));
284
285 Result = E->getValue();
286 return APValue(Result);
287 }
288
Anders Carlssonc754aa62008-07-08 05:13:58 +0000289};
290}
291
Anders Carlssonc44eec62008-07-03 04:20:39 +0000292bool Expr::tryEvaluate(APValue& Result, ASTContext &Ctx) const
293{
294 llvm::APSInt sInt(1);
295
Anders Carlssonc754aa62008-07-08 05:13:58 +0000296#if USE_NEW_EVALUATOR
Anders Carlsson06a36752008-07-08 05:49:43 +0000297 if (getType()->isIntegerType()) {
298 if (IntExprEvaluator::Evaluate(this, sInt, Ctx)) {
299 Result = APValue(sInt);
300 return true;
301 }
302 } else
Anders Carlssonc754aa62008-07-08 05:13:58 +0000303 return false;
304
305#else
Anders Carlssonc44eec62008-07-03 04:20:39 +0000306 if (CalcFakeICEVal(this, sInt, Ctx)) {
307 Result = APValue(sInt);
308 return true;
309 }
Anders Carlssonc754aa62008-07-08 05:13:58 +0000310#endif
Anders Carlssonc44eec62008-07-03 04:20:39 +0000311
312 return false;
313}