blob: f2b32c6fa499b05c08b23f66c3f0c33912d136b6 [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 Carlssona25ae3d2008-07-08 14:35:21 +0000110 APValue VisitBinaryOperator(const BinaryOperator *E);
111 APValue VisitUnaryOperator(const UnaryOperator *E);
Anders Carlsson06a36752008-07-08 05:49:43 +0000112
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000113 APValue HandleCast(const Expr* SubExpr, QualType DestType);
114};
115
116APValue IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
117 // The LHS of a constant expr is always evaluated and needed.
118 llvm::APSInt Result(32);
119 if (!Evaluate(E->getLHS(), Result, Ctx))
120 return APValue();
121
122 llvm::APSInt RHS(32);
123 if (!Evaluate(E->getRHS(), RHS, Ctx))
124 return APValue();
125
126 switch (E->getOpcode()) {
127 default:
128 return APValue();
129 case BinaryOperator::Mul:
130 Result *= RHS;
131 break;
132 case BinaryOperator::Div:
133 if (RHS == 0)
Anders Carlsson06a36752008-07-08 05:49:43 +0000134 return APValue();
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000135 Result /= RHS;
136 break;
137 case BinaryOperator::Rem:
138 if (RHS == 0)
139 return APValue();
140 Result %= RHS;
141 break;
142 case BinaryOperator::Add: Result += RHS; break;
143 case BinaryOperator::Sub: Result -= RHS; break;
144 case BinaryOperator::Shl:
145 Result <<=
146 static_cast<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
147 break;
148 case BinaryOperator::Shr:
149 Result >>=
150 static_cast<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
151 break;
152 case BinaryOperator::LT: Result = Result < RHS; break;
153 case BinaryOperator::GT: Result = Result > RHS; break;
154 case BinaryOperator::LE: Result = Result <= RHS; break;
155 case BinaryOperator::GE: Result = Result >= RHS; break;
156 case BinaryOperator::EQ: Result = Result == RHS; break;
157 case BinaryOperator::NE: Result = Result != RHS; break;
158 case BinaryOperator::And: Result &= RHS; break;
159 case BinaryOperator::Xor: Result ^= RHS; break;
160 case BinaryOperator::Or: Result |= RHS; break;
Anders Carlsson06a36752008-07-08 05:49:43 +0000161
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000162 case BinaryOperator::Comma:
163 // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
164 // *except* when they are contained within a subexpression that is not
165 // evaluated". Note that Assignment can never happen due to constraints
166 // on the LHS subexpr, so we don't need to check it here.
167 // FIXME: Need to come up with an efficient way to deal with the C99
168 // rules on evaluation while still evaluating this. Maybe a
169 // "evaluated comma" out parameter?
170 return APValue();
171 }
172
173 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
174
175 return APValue(Result);
176}
177
178APValue IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
179 llvm::APSInt Result(32);
180
181 if (E->isOffsetOfOp())
182 Result = E->evaluateOffsetOf(Ctx);
183 else if (E->isSizeOfAlignOfOp()) {
184 // Return the result in the right width.
185 Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));
186
187 // sizeof(void) and __alignof__(void) = 1 as a gcc extension.
188 if (E->getSubExpr()->getType()->isVoidType())
189 Result = 1;
190
191 // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
192 if (!E->getSubExpr()->getType()->isConstantSizeType()) {
193 // FIXME: Should we attempt to evaluate this?
194 return APValue();
195 }
196
197 // Get information about the size or align.
198 if (E->getSubExpr()->getType()->isFunctionType()) {
199 // GCC extension: sizeof(function) = 1.
200 // FIXME: AlignOf shouldn't be unconditionally 4!
201 Result = E->getOpcode() == UnaryOperator::AlignOf ? 4 : 1;
202 } else {
203 unsigned CharSize = Ctx.Target.getCharWidth();
204 if (E->getOpcode() == UnaryOperator::AlignOf)
205 Result = Ctx.getTypeAlign(E->getSubExpr()->getType()) / CharSize;
206 else
207 Result = Ctx.getTypeSize(E->getSubExpr()->getType()) / CharSize;
208 }
209 } else {
210 // Get the operand value. If this is sizeof/alignof, do not evalute the
211 // operand. This affects C99 6.6p3.
212 if (!Evaluate(E->getSubExpr(), Result, Ctx))
213 return APValue();
214
Anders Carlsson06a36752008-07-08 05:49:43 +0000215 switch (E->getOpcode()) {
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000216 // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
217 // See C99 6.6p3.
Anders Carlsson06a36752008-07-08 05:49:43 +0000218 default:
219 return APValue();
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000220 case UnaryOperator::Extension:
221 assert(0 && "Handle UnaryOperator::Extension");
222 return APValue();
223 case UnaryOperator::LNot: {
224 bool Val = Result == 0;
225 uint32_t typeSize = Ctx.getTypeSize(E->getType());
226 Result.zextOrTrunc(typeSize);
227 Result = Val;
Anders Carlsson06a36752008-07-08 05:49:43 +0000228 break;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000229 }
230 case UnaryOperator::Plus:
Anders Carlsson06a36752008-07-08 05:49:43 +0000231 break;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000232 case UnaryOperator::Minus:
233 Result = -Result;
Anders Carlsson06a36752008-07-08 05:49:43 +0000234 break;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000235 case UnaryOperator::Not:
236 Result = ~Result;
Anders Carlsson06a36752008-07-08 05:49:43 +0000237 break;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000238 }
239 }
240
241 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
242 return APValue(Result);
243}
244
245APValue IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) {
246 llvm::APSInt Result(32);
247
248 uint32_t DestWidth = static_cast<uint32_t>(Ctx.getTypeSize(DestType));
249
250 // Handle simple integer->integer casts.
251 if (SubExpr->getType()->isIntegerType()) {
252 if (!Evaluate(SubExpr, Result, Ctx))
Anders Carlsson06a36752008-07-08 05:49:43 +0000253 return APValue();
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000254
255 // Figure out if this is a truncate, extend or noop cast.
256 // If the input is signed, do a sign extend, noop, or truncate.
257 if (DestType->isBooleanType()) {
258 // Conversion to bool compares against zero.
259 Result = Result != 0;
260 Result.zextOrTrunc(DestWidth);
Anders Carlsson06a36752008-07-08 05:49:43 +0000261 }
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000262 else
263 Result.extOrTrunc(DestWidth);
264 } else if (SubExpr->getType()->isPointerType()) {
265 APValue LV;
266 if (!PointerExprEvaluator::Evaluate(SubExpr, LV, Ctx))
267 return APValue();
268 if (LV.getLValueBase())
269 return APValue();
Anders Carlsson06a36752008-07-08 05:49:43 +0000270
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000271 Result = llvm::APSInt(DestWidth, LV.getLValueOffset());
272 } else {
273 assert(0 && "Unhandled cast!");
Anders Carlsson2bad1682008-07-08 14:30:00 +0000274 }
275
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000276 Result.setIsUnsigned(DestType->isUnsignedIntegerType());
277 return APValue(Result);
278}
Anders Carlsson2bad1682008-07-08 14:30:00 +0000279
Anders Carlssonc754aa62008-07-08 05:13:58 +0000280}
281
Anders Carlssonc44eec62008-07-03 04:20:39 +0000282bool Expr::tryEvaluate(APValue& Result, ASTContext &Ctx) const
283{
284 llvm::APSInt sInt(1);
285
Anders Carlssonc754aa62008-07-08 05:13:58 +0000286#if USE_NEW_EVALUATOR
Anders Carlsson06a36752008-07-08 05:49:43 +0000287 if (getType()->isIntegerType()) {
288 if (IntExprEvaluator::Evaluate(this, sInt, Ctx)) {
289 Result = APValue(sInt);
290 return true;
291 }
292 } else
Anders Carlssonc754aa62008-07-08 05:13:58 +0000293 return false;
294
295#else
Anders Carlssonc44eec62008-07-03 04:20:39 +0000296 if (CalcFakeICEVal(this, sInt, Ctx)) {
297 Result = APValue(sInt);
298 return true;
299 }
Anders Carlssonc754aa62008-07-08 05:13:58 +0000300#endif
Anders Carlssonc44eec62008-07-03 04:20:39 +0000301
302 return false;
303}