blob: 46c2985a46049945594ca96da54be60dfe228cd0 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Yifan Hong52165692016-08-12 18:06:40 -070017#include "ConstantExpression.h"
18
Yifan Hong57886972016-08-17 10:42:15 -070019#include <stdio.h>
20#include <string>
Yifan Hong57886972016-08-17 10:42:15 -070021#include <android-base/parseint.h>
22#include <android-base/logging.h>
23#include <sstream>
24
25// The macros are really nasty here. Consider removing
26// as many macros as possible.
27
28#define STREQ(__x__, __y__) (strcmp((__x__), (__y__)) == 0)
29#define OPEQ(__y__) STREQ(op, __y__)
30#define COMPUTE_UNARY(__op__) if(OPEQ(#__op__)) return __op__ val;
31#define COMPUTE_BINARY(__op__) if(OPEQ(#__op__)) return lval __op__ rval;
32#define OP_IS_BIN_ARITHMETIC (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
33#define OP_IS_BIN_BITFLIP (OPEQ("|") || OPEQ("^") || OPEQ("&"))
34#define OP_IS_BIN_COMP (OPEQ("<") || OPEQ(">") || OPEQ("<=") || OPEQ(">=") || OPEQ("==") || OPEQ("!="))
35#define OP_IS_BIN_SHIFT (OPEQ(">>") || OPEQ("<<"))
36#define OP_IS_BIN_LOGICAL (OPEQ("||") || OPEQ("&&"))
37#define SK(__x__) ScalarType::Kind::KIND_##__x__
38
39#define SWITCH_KIND(__cond__, __action__, __def__) \
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070040 switch(__cond__) { \
41 case SK(BOOL): __action__(bool) \
42 case SK(UINT8): __action__(uint8_t) \
43 case SK(INT8): __action__(int8_t) \
44 case SK(UINT16): __action__(uint16_t) \
45 case SK(INT16): __action__(int16_t) \
46 case SK(UINT32): __action__(uint32_t) \
47 case SK(INT32): __action__(int32_t) \
48 case SK(UINT64): __action__(uint64_t) \
49 case SK(INT64): __action__(int64_t) \
50 default: __def__ \
51 } \
Yifan Hong52165692016-08-12 18:06:40 -070052
53namespace android {
54
Yifan Hong57886972016-08-17 10:42:15 -070055/* See docs at the end for details on integral promotion. */
56ScalarType::Kind integralPromotion(ScalarType::Kind in) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070057 return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
Yifan Hong52165692016-08-12 18:06:40 -070058}
59
Yifan Hong57886972016-08-17 10:42:15 -070060/* See docs at the end for details on usual arithmetic conversion. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070061ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
62 ScalarType::Kind rgt) {
63 CHECK(SK(BOOL) <= lft && lft <= SK(UINT64)
64 && SK(BOOL) <= rgt && rgt <= SK(UINT64)
65 && lft != SK(OPAQUE) && rgt != SK(OPAQUE)
66 );
67 // Kinds in concern: bool, (u)int[8|16|32|64]
68 if(lft == rgt) return lft; // easy case
69 if(lft == SK(BOOL)) return rgt;
70 if(rgt == SK(BOOL)) return lft;
71 bool isLftSigned = (lft == SK(INT8)) || (lft == SK(INT16))
72 || (lft == SK(INT32)) || (lft == SK(INT64));
73 bool isRgtSigned = (rgt == SK(INT8)) || (rgt == SK(INT16))
74 || (rgt == SK(INT32)) || (rgt == SK(INT64));
75 if(isLftSigned == isRgtSigned) return lft < rgt ? rgt : lft;
76 ScalarType::Kind unsignedRank = isLftSigned ? rgt : lft;
77 ScalarType::Kind signedRank = isLftSigned ? lft : rgt;
78 if(unsignedRank >= signedRank) return unsignedRank;
79 if(signedRank > unsignedRank) return signedRank;
Yifan Hong57886972016-08-17 10:42:15 -070080
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070081 // Although there is such rule to return "the unsigned counterpart of
82 // the signed operand", it should not reach here in our HIDL grammar.
83 LOG(FATAL) << "Could not do usual arithmetic conversion for type "
84 << lft << "and" << rgt;
85 switch(signedRank) {
86 case SK(INT8): return SK(UINT8);
87 case SK(INT16): return SK(UINT16);
88 case SK(INT32): return SK(UINT32);
89 case SK(INT64): return SK(UINT64);
90 default: return SK(UINT64);
91 }
Yifan Hong52165692016-08-12 18:06:40 -070092}
Yifan Hong57886972016-08-17 10:42:15 -070093
94template <class T>
95T handleUnary(const char *op, T val) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070096 COMPUTE_UNARY(+)
97 COMPUTE_UNARY(-)
98 COMPUTE_UNARY(!)
99 COMPUTE_UNARY(~)
100 // Should not reach here.
101 LOG(FATAL) << "Could not handleUnary for " << op << " " << val;
102 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700103}
104
105template <class T>
106T handleBinaryCommon(T lval, const char *op, T rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700107 COMPUTE_BINARY(+)
108 COMPUTE_BINARY(-)
109 COMPUTE_BINARY(*)
110 COMPUTE_BINARY(/)
111 COMPUTE_BINARY(%)
112 COMPUTE_BINARY(|)
113 COMPUTE_BINARY(^)
114 COMPUTE_BINARY(&)
115 // comparison operators: return 0 or 1 by nature.
116 COMPUTE_BINARY(==)
117 COMPUTE_BINARY(!=)
118 COMPUTE_BINARY(<)
119 COMPUTE_BINARY(>)
120 COMPUTE_BINARY(<=)
121 COMPUTE_BINARY(>=)
122 // Should not reach here.
123 LOG(FATAL) << "Could not handleBinaryCommon for "
124 << lval << " " << op << " " << rval;
125 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700126}
127
128template <class T>
129T handleShift(T lval, const char *op, int64_t rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700130 // just cast rval to int64_t and it should fit.
131 COMPUTE_BINARY(>>)
132 COMPUTE_BINARY(<<)
133 // Should not reach here.
134 LOG(FATAL) << "Could not handleShift for"
135 << lval << " " << op << " " << rval;
136 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700137}
138
139bool handleLogical(bool lval, const char *op, bool rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700140 COMPUTE_BINARY(||);
141 COMPUTE_BINARY(&&);
142 // Should not reach here.
143 LOG(FATAL) << "Could not handleLogical for"
144 << lval << " " << op << " " << rval;
145 return false;
Yifan Hong57886972016-08-17 10:42:15 -0700146}
147
148/* Literals. */
149ConstantExpression::ConstantExpression(const char *value,
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700150 ConstantExpression::ConstExprType type)
151 : mFormatted(value), mType(type) {
152 if(mType == kConstExprUnknown)
153 return;
154 const char* head = value, *tail = head + strlen(value) - 1;
155 bool isLong = false, isUnsigned = false;
156 bool isHex = (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'));
157 while(tail >= head && (*tail == 'u' || *tail == 'U' || *tail == 'l' || *tail == 'L')) {
158 isUnsigned |= *tail == 'u' || *tail == 'U';
159 isLong |= *tail == 'l' || *tail == 'L';
160 tail--;
Yifan Hong57886972016-08-17 10:42:15 -0700161 }
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700162 char *newVal = strndup(value, tail - head + 1);
163 bool parseOK = base::ParseUint(newVal, &mValue);
164 free(newVal);
165 if(!parseOK) {
166 LOG(FATAL) << "Could not parse as integer: " << value;
167 mType = kConstExprUnknown;
168 return;
169 }
170
171 // guess literal type.
172 if(isLong) {
173 if(isUnsigned) // ul
174 mValueKind = SK(UINT64);
175 else // l
176 mValueKind = SK(INT64);
177 } else { // no l suffix
178 if(isUnsigned) { // u
179 if(mValue <= UINT32_MAX)
180 mValueKind = SK(UINT32);
181 else
182 mValueKind = SK(UINT64);
183 } else { // no suffix
184 if(isHex) {
185 if(mValue <= INT32_MAX) // mValue always >= 0
186 mValueKind = SK(INT32);
187 else if(mValue <= UINT32_MAX)
188 mValueKind = SK(UINT32);
189 else if(mValue <= INT64_MAX) // mValue always >= 0
190 mValueKind = SK(INT64);
191 else if(mValue <= UINT64_MAX)
192 mValueKind = SK(UINT64);
193 } else {
194 if(mValue <= INT32_MAX) // mValue always >= 0
195 mValueKind = SK(INT32);
196 else
197 mValueKind = SK(INT64);
198 }
199 }
200 }
Yifan Hong57886972016-08-17 10:42:15 -0700201}
202
203/* Unary operations. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700204ConstantExpression::ConstantExpression(const char *op,
205 const ConstantExpression *value)
206 : mFormatted(std::string("(") + op + value->expr() + ")"),
207 mType(kConstExprUnary),
208 mValueKind(value->mValueKind) {
209 if(value->mType == kConstExprUnknown) {
210 mType = kConstExprUnknown;
211 return;
212 }
Yifan Hong57886972016-08-17 10:42:15 -0700213#define CASE_UNARY(__type__)\
214 mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
215
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700216 SWITCH_KIND(mValueKind, CASE_UNARY, mType = kConstExprUnknown; return;)
Yifan Hong52165692016-08-12 18:06:40 -0700217}
Yifan Hong57886972016-08-17 10:42:15 -0700218
219/* Binary operations. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700220ConstantExpression::ConstantExpression(const ConstantExpression *lval,
221 const char *op,
222 const ConstantExpression* rval)
223 : mFormatted(std::string("(") + lval->expr() + " "
224 + op + " " + rval->expr() + ")"),
225 mType(kConstExprBinary)
Yifan Hong57886972016-08-17 10:42:15 -0700226{
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700227 if(lval->mType == kConstExprUnknown || rval->mType == kConstExprUnknown) {
228 mType = kConstExprUnknown;
229 return;
Yifan Hong57886972016-08-17 10:42:15 -0700230 }
231
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700232 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
233
234 // CASE 1: + - * / % | ^ & < > <= >= == !=
235 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
236 // promoted kind for both operands.
237 ScalarType::Kind promoted = usualArithmeticConversion(
238 integralPromotion(lval->mValueKind),
239 integralPromotion(rval->mValueKind));
240 // result kind.
241 mValueKind = isArithmeticOrBitflip
242 ? promoted // arithmetic or bitflip operators generates promoted type
243 : SK(BOOL); // comparison operators generates bool
244
245#define CASE_BINARY_COMMON(__type__)\
246 mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
247
248 SWITCH_KIND(promoted, CASE_BINARY_COMMON, mType = kConstExprUnknown; return;)
249 }
250
251 // CASE 2: << >>
252 if(OP_IS_BIN_SHIFT) {
253 mValueKind = integralPromotion(lval->mValueKind);
254 // instead of promoting rval, simply casting it to int64 should also be good.
255 int64_t numBits = rval->cast<int64_t>();
256 if(numBits < 0) {
257 // shifting with negative number of bits is undefined in C. In HIDL it
258 // is defined as shifting into the other direction.
259 op = OPEQ("<<") ? ">>" : "<<";
260 numBits = -numBits;
261 }
262
Yifan Hong57886972016-08-17 10:42:15 -0700263#define CASE_SHIFT(__type__)\
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700264 mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
Yifan Hong57886972016-08-17 10:42:15 -0700265
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700266 SWITCH_KIND(mValueKind, CASE_SHIFT, mType = kConstExprUnknown; return;)
267 }
Yifan Hong57886972016-08-17 10:42:15 -0700268
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700269 // CASE 3: && ||
270 if(OP_IS_BIN_LOGICAL) {
271 mValueKind = SK(BOOL);
272 // easy; everything is bool.
273 mValue = handleLogical(lval->mValue, op, rval->mValue);
274 return;
275 }
Yifan Hong57886972016-08-17 10:42:15 -0700276
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700277 mType = kConstExprUnknown;
Yifan Hong57886972016-08-17 10:42:15 -0700278}
279
280/* Ternary ?: operation. */
Yifan Hong52165692016-08-12 18:06:40 -0700281ConstantExpression::ConstantExpression(const ConstantExpression *cond,
282 const ConstantExpression *trueVal,
283 const ConstantExpression *falseVal)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700284 : mFormatted(std::string("(") + cond->expr() + "?" + trueVal->expr()
285 + ":" + falseVal->expr() + ")"),
286 mType(kConstExprTernary) {
287 // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
288 mValueKind = usualArithmeticConversion(trueVal->mValueKind,
289 falseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700290
291#define CASE_TERNARY(__type__)\
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700292 mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
Yifan Hong57886972016-08-17 10:42:15 -0700293
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700294 SWITCH_KIND(mValueKind, CASE_TERNARY, mType = kConstExprUnknown; return;)
Yifan Hong52165692016-08-12 18:06:40 -0700295}
296
Yifan Hong57886972016-08-17 10:42:15 -0700297const char *ConstantExpression::expr() const {
298 return mFormatted.c_str();
Yifan Hong52165692016-08-12 18:06:40 -0700299}
Yifan Hong57886972016-08-17 10:42:15 -0700300
301const char *ConstantExpression::description() const {
302 static const char *const kName[] = {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700303 "bool",
304 "void *",
305 "int8_t",
306 "uint8_t",
307 "int16_t",
308 "uint16_t",
309 "int32_t",
310 "uint32_t",
311 "int64_t",
312 "uint64_t",
313 "float",
314 "double"
315 };
316 if(mType == kConstExprUnknown)
317 return expr();
318 std::ostringstream os;
319 os << "(" << kName[mValueKind] << ")" << expr();
320 return strdup(os.str().c_str());
Yifan Hong57886972016-08-17 10:42:15 -0700321}
322
Yifan Hong52165692016-08-12 18:06:40 -0700323const char *ConstantExpression::value() const {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700324 return value0(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700325}
326
Yifan Hong57886972016-08-17 10:42:15 -0700327const char *ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700328 std::string literal(value0(castKind));
329 // this is a hack to translate
330 // enum x : int64_t { y = 1l << 63 };
331 // into
332 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
333 // by adding the explicit cast.
334 // Because 9223372036854775808 is uint64_t, and
335 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
336 // be narrowed to int64_t.
337 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
338 std::string extra;
339 return strdup(("("
340 + ScalarType(SK(INT64)).getCppType(
341 android::Type::StorageMode_Stack,
342 &extra,
343 true /* specify namespaces */) // "int64_t"
344 + ")(" + literal + "ull)").c_str());
345 }
Yifan Hong57886972016-08-17 10:42:15 -0700346
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700347 // add suffix if necessary.
348 if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
349 if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
350 return strdup(literal.c_str());
Yifan Hong57886972016-08-17 10:42:15 -0700351}
352
Yifan Hong19ca75a2016-08-31 10:20:03 -0700353const char *ConstantExpression::javaValue(ScalarType::Kind castKind) const {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700354 switch(castKind) {
355 case SK(UINT64): return value0(SK(INT64));
356 case SK(UINT32): return value0(SK(INT32));
357 case SK(UINT16): return value0(SK(INT16));
358 case SK(UINT8) : return value0(SK(INT8));
359 case SK(BOOL) :
360 if(mType == kConstExprUnknown)
361 return expr();
362 return this->cast<bool>() ? strdup("true") : strdup("false");
363 default: break;
364 }
365 return value0(castKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700366}
367
Yifan Hong57886972016-08-17 10:42:15 -0700368const char *ConstantExpression::value0(ScalarType::Kind castKind) const {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700369 if(mType == kConstExprUnknown)
370 return expr();
Yifan Hong57886972016-08-17 10:42:15 -0700371
Yifan Hong19ca75a2016-08-31 10:20:03 -0700372#define CASE_STR(__type__) return strdup(std::to_string(this->cast<__type__>()).c_str());
Yifan Hong57886972016-08-17 10:42:15 -0700373
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700374 SWITCH_KIND(castKind, CASE_STR, return expr(); );
Yifan Hong57886972016-08-17 10:42:15 -0700375}
376
Yifan Hong19ca75a2016-08-31 10:20:03 -0700377template<typename T>
378T ConstantExpression::cast() const {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700379 CHECK(mType != kConstExprUnknown);
Yifan Hong57886972016-08-17 10:42:15 -0700380
Yifan Hong19ca75a2016-08-31 10:20:03 -0700381#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700382
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700383 SWITCH_KIND(mValueKind, CASE_CAST_T, CHECK(false); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700384}
385
386/*
387
388Evaluating expressions in HIDL language
389
390The following rules are mostly like that in:
391http://en.cppreference.com/w/cpp/language/operator_arithmetic
392http://en.cppreference.com/w/cpp/language/operator_logical
393http://en.cppreference.com/w/cpp/language/operator_comparison
394http://en.cppreference.com/w/cpp/language/operator_other
395
396The type of literal is the first type which the value
397can fit from the list of types depending on the suffix and bases.
398
399suffix decimal bases hexadecimal bases
400no suffix int32_t int32_t
401 int64_t uint32_t
402 int64_t
403 uint64_t
404
405u/U uint32_t (same as left)
406 uint64_t
407
408l/L int64_t int64_t
409
410ul/UL/uL/Ul uint64_t uint64_t
411
412
413Note: There are no negative integer literals.
414 -1 is the unary minus applied to 1.
415
416Unary arithmetic and bitwise operators (~ + -):
417 don't change the type of the argument.
418 (so -1u = -(1u) has type uint32_t)
419
420Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
4211. Integral promotion is first applied on both sides.
4222. If both operands have the same type, no promotion is necessary.
4233. Usual arithmetic conversions.
424
425Integral promotion: if an operand is of a type with less than 32 bits,
426(including bool), it is promoted to int32_t.
427
428Usual arithmetic conversions:
4291. If operands are both signed or both unsigned, lesser conversion rank is
430 converted to greater conversion rank.
4312. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
4323. Otherwise, if signed's type can hold all values in unsigned's type,
433 -> signed's type
4344. Otherwise, both converted to the unsigned counterpart of the signed operand's
435 type.
436rank: bool < int8_t < int16_t < int32_t < int64_t
437
438
439Shift operators (<< >>):
4401. Integral promotion is applied on both sides.
4412. For unsigned a, a << b discards bits that shifts out.
442 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
443 For signed negative a, a << b gives error.
4443. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
445 For signed negative a, a >> b discards bits that shifts out, and the signed
446 bit gets extended. ("arithmetic right shift")
4474. Shifting with negative number of bits is undefined. (Currently, the
448 parser will shift into the other direction. This behavior may change.)
4495. Shifting with number of bits exceeding the width of the type is undefined.
450 (Currently, 1 << 32 == 1. This behavior may change.)
451
452Logical operators (!, &&, ||):
4531. Convert first operand to bool. (true if non-zero, false otherwise)
4542. If short-circuited, return the result as type bool, value 1 or 0.
4553. Otherwise, convert second operand to bool, evaluate the result, and return
456 the result in the same fashion.
457
458Arithmetic comparison operators (< > <= >= == !=):
4591. Promote operands in the same way as binary arithmetic and bitwise operators.
460 (Integral promotion + Usual arithmetic conversions)
4612. Return type bool, value 0 or 1 the same way as logical operators.
462
463Ternary conditional operator (?:):
4641. Evaluate the conditional and evaluate the operands.
4652. Return type of expression is the type under usual arithmetic conversions on
466 the second and third operand. (No integral promotions necessary.)
467
468*/
469
Yifan Hong52165692016-08-12 18:06:40 -0700470} // namespace android
471