blob: 1dd14ed2291b71b239e8c5ef4becdc8fadec829f [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 Hong52165692016-08-12 18:06:40 -070021#include <utils/String8.h>
Yifan Hong57886972016-08-17 10:42:15 -070022#include <android-base/parseint.h>
23#include <android-base/logging.h>
24#include <sstream>
25
26// The macros are really nasty here. Consider removing
27// as many macros as possible.
28
29#define STREQ(__x__, __y__) (strcmp((__x__), (__y__)) == 0)
30#define OPEQ(__y__) STREQ(op, __y__)
31#define COMPUTE_UNARY(__op__) if(OPEQ(#__op__)) return __op__ val;
32#define COMPUTE_BINARY(__op__) if(OPEQ(#__op__)) return lval __op__ rval;
33#define OP_IS_BIN_ARITHMETIC (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
34#define OP_IS_BIN_BITFLIP (OPEQ("|") || OPEQ("^") || OPEQ("&"))
35#define OP_IS_BIN_COMP (OPEQ("<") || OPEQ(">") || OPEQ("<=") || OPEQ(">=") || OPEQ("==") || OPEQ("!="))
36#define OP_IS_BIN_SHIFT (OPEQ(">>") || OPEQ("<<"))
37#define OP_IS_BIN_LOGICAL (OPEQ("||") || OPEQ("&&"))
38#define SK(__x__) ScalarType::Kind::KIND_##__x__
39
40#define SWITCH_KIND(__cond__, __action__, __def__) \
41 switch(__cond__) { \
42 case SK(BOOL): __action__(bool) \
43 case SK(UINT8): __action__(uint8_t) \
44 case SK(INT8): __action__(int8_t) \
45 case SK(UINT16): __action__(uint16_t) \
46 case SK(INT16): __action__(int16_t) \
47 case SK(UINT32): __action__(uint32_t) \
48 case SK(INT32): __action__(int32_t) \
49 case SK(UINT64): __action__(uint64_t) \
50 case SK(INT64): __action__(int64_t) \
51 default: __def__ \
52 } \
Yifan Hong52165692016-08-12 18:06:40 -070053
54namespace android {
55
Yifan Hong57886972016-08-17 10:42:15 -070056/* See docs at the end for details on integral promotion. */
57ScalarType::Kind integralPromotion(ScalarType::Kind in) {
58 return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
Yifan Hong52165692016-08-12 18:06:40 -070059}
60
Yifan Hong57886972016-08-17 10:42:15 -070061/* See docs at the end for details on usual arithmetic conversion. */
62ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft, 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;
80
81 // 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) {
96 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);
103}
104
105template <class T>
106T handleBinaryCommon(T lval, const char *op, T rval) {
107 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);
126}
127
128template <class T>
129T handleShift(T lval, const char *op, int64_t rval) {
130 // 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);
137}
138
139bool handleLogical(bool lval, const char *op, bool rval) {
140 COMPUTE_BINARY(||);
141 COMPUTE_BINARY(&&);
142 // Should not reach here.
143 LOG(FATAL) << "Could not handleLogical for"
144 << lval << " " << op << " " << rval;
145 return false;
146}
147
148/* Literals. */
149ConstantExpression::ConstantExpression(const char *value,
150 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--;
161 }
162 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 }
201}
202
203/* Unary operations. */
Yifan Hong52165692016-08-12 18:06:40 -0700204ConstantExpression::ConstantExpression(const char *op, const ConstantExpression *value)
Yifan Hong57886972016-08-17 10:42:15 -0700205 : mFormatted(android::String8::format("(%s%s)", op, value->expr()).string()),
206 mType(kConstExprUnary),
207 mValueKind(value->mValueKind) {
208 if(value->mType == kConstExprUnknown) {
209 mType = kConstExprUnknown;
210 return;
211 }
212#define CASE_UNARY(__type__)\
213 mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
214
215 SWITCH_KIND(mValueKind, CASE_UNARY, mType = kConstExprUnknown; return;)
Yifan Hong52165692016-08-12 18:06:40 -0700216}
Yifan Hong57886972016-08-17 10:42:15 -0700217
218/* Binary operations. */
219ConstantExpression::ConstantExpression(const ConstantExpression *lval, const char *op, const ConstantExpression* rval)
220 : mFormatted(android::String8::format("(%s %s %s)", lval->expr(), op, rval->expr()).string()),
221 mType(kConstExprBinary)
222{
223 if(lval->mType == kConstExprUnknown || rval->mType == kConstExprUnknown) {
224 mType = kConstExprUnknown;
225 return;
226 }
227
228 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
229
230 // CASE 1: + - * / % | ^ & < > <= >= == !=
231 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
232 // promoted kind for both operands.
233 ScalarType::Kind promoted = usualArithmeticConversion(
234 integralPromotion(lval->mValueKind),
235 integralPromotion(rval->mValueKind));
236 // result kind.
237 mValueKind = isArithmeticOrBitflip
238 ? promoted // arithmetic or bitflip operators generates promoted type
239 : SK(BOOL); // comparison operators generates bool
240
241#define CASE_BINARY_COMMON(__type__)\
242 mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
243
244 SWITCH_KIND(promoted, CASE_BINARY_COMMON, mType = kConstExprUnknown; return;)
245 }
246
247 // CASE 2: << >>
248 if(OP_IS_BIN_SHIFT) {
249 mValueKind = integralPromotion(lval->mValueKind);
250 // instead of promoting rval, simply casting it to int64 should also be good.
Yifan Hong19ca75a2016-08-31 10:20:03 -0700251 int64_t numBits = rval->cast<int64_t>();
Yifan Hong57886972016-08-17 10:42:15 -0700252 if(numBits < 0) {
253 // shifting with negative number of bits is undefined in C. In HIDL it
254 // is defined as shifting into the other direction.
255 op = OPEQ("<<") ? ">>" : "<<";
256 numBits = -numBits;
257 }
258
259#define CASE_SHIFT(__type__)\
260 mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
261
262 SWITCH_KIND(mValueKind, CASE_SHIFT, mType = kConstExprUnknown; return;)
263 }
264
265 // CASE 3: && ||
266 if(OP_IS_BIN_LOGICAL) {
267 mValueKind = SK(BOOL);
268 // easy; everything is bool.
269 mValue = handleLogical(lval->mValue, op, rval->mValue);
270 return;
271 }
272
273 mType = kConstExprUnknown;
274}
275
276/* Ternary ?: operation. */
Yifan Hong52165692016-08-12 18:06:40 -0700277ConstantExpression::ConstantExpression(const ConstantExpression *cond,
278 const ConstantExpression *trueVal,
279 const ConstantExpression *falseVal)
Yifan Hong57886972016-08-17 10:42:15 -0700280 : mFormatted(android::String8::format("(%s?%s:%s)",
281 cond->expr(), trueVal->expr(), falseVal->expr()).string()),
282 mType(kConstExprTernary) {
283 // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
284 mValueKind = usualArithmeticConversion(trueVal->mValueKind,
285 falseVal->mValueKind);
286
287#define CASE_TERNARY(__type__)\
288 mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
289
290 SWITCH_KIND(mValueKind, CASE_TERNARY, mType = kConstExprUnknown; return;)
Yifan Hong52165692016-08-12 18:06:40 -0700291}
292
Yifan Hong57886972016-08-17 10:42:15 -0700293const char *ConstantExpression::expr() const {
294 return mFormatted.c_str();
Yifan Hong52165692016-08-12 18:06:40 -0700295}
Yifan Hong57886972016-08-17 10:42:15 -0700296
297const char *ConstantExpression::description() const {
298 static const char *const kName[] = {
299 "bool",
300 "void *",
301 "int8_t",
302 "uint8_t",
303 "int16_t",
304 "uint16_t",
305 "int32_t",
306 "uint32_t",
307 "int64_t",
308 "uint64_t",
309 "float",
310 "double"
311 };
312 if(mType == kConstExprUnknown)
313 return expr();
314 std::ostringstream os;
315 os << "(" << kName[mValueKind] << ")" << expr();
316 return strdup(os.str().c_str());
317}
318
Yifan Hong52165692016-08-12 18:06:40 -0700319const char *ConstantExpression::value() const {
Yifan Hong57886972016-08-17 10:42:15 -0700320 return value0(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700321}
322
Yifan Hong57886972016-08-17 10:42:15 -0700323const char *ConstantExpression::cppValue(ScalarType::Kind castKind) const {
324 std::string literal(value0(castKind));
325 // this is a hack to translate
326 // enum x : int64_t { y = 1l << 63 };
327 // into
328 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
329 // by adding the explicit cast.
330 // Because 9223372036854775808 is uint64_t, and
331 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
332 // be narrowed to int64_t.
333 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
334 std::string extra;
335 return strdup(("("
Steven Moreland979e0992016-09-07 09:18:08 -0700336 + ScalarType(SK(INT64)).getCppType(
337 android::Type::StorageMode_Stack,
338 &extra,
339 true /* specify namespaces */) // "int64_t"
Yifan Hong57886972016-08-17 10:42:15 -0700340 + ")(" + literal + "ull)").c_str());
341 }
342
343 // add suffix if necessary.
344 if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
345 if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
346 return strdup(literal.c_str());
347}
348
Yifan Hong19ca75a2016-08-31 10:20:03 -0700349const char *ConstantExpression::javaValue(ScalarType::Kind castKind) const {
350 switch(castKind) {
351 case SK(UINT64): return value0(SK(INT64));
352 case SK(UINT32): return value0(SK(INT32));
353 case SK(UINT16): return value0(SK(INT16));
354 case SK(UINT8) : return value0(SK(INT8));
355 case SK(BOOL) :
356 if(mType == kConstExprUnknown)
357 return expr();
358 return this->cast<bool>() ? strdup("true") : strdup("false");
359 default: break;
360 }
361 return value0(castKind);
362}
363
Yifan Hong57886972016-08-17 10:42:15 -0700364const char *ConstantExpression::value0(ScalarType::Kind castKind) const {
365 if(mType == kConstExprUnknown)
366 return expr();
367
Yifan Hong19ca75a2016-08-31 10:20:03 -0700368#define CASE_STR(__type__) return strdup(std::to_string(this->cast<__type__>()).c_str());
Yifan Hong57886972016-08-17 10:42:15 -0700369
370 SWITCH_KIND(castKind, CASE_STR, return expr(); );
371}
372
Yifan Hong19ca75a2016-08-31 10:20:03 -0700373template<typename T>
374T ConstantExpression::cast() const {
Yifan Hong57886972016-08-17 10:42:15 -0700375 CHECK(mType != kConstExprUnknown);
376
Yifan Hong19ca75a2016-08-31 10:20:03 -0700377#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700378
Yifan Hong19ca75a2016-08-31 10:20:03 -0700379 SWITCH_KIND(mValueKind, CASE_CAST_T, CHECK(false); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700380}
381
382/*
383
384Evaluating expressions in HIDL language
385
386The following rules are mostly like that in:
387http://en.cppreference.com/w/cpp/language/operator_arithmetic
388http://en.cppreference.com/w/cpp/language/operator_logical
389http://en.cppreference.com/w/cpp/language/operator_comparison
390http://en.cppreference.com/w/cpp/language/operator_other
391
392The type of literal is the first type which the value
393can fit from the list of types depending on the suffix and bases.
394
395suffix decimal bases hexadecimal bases
396no suffix int32_t int32_t
397 int64_t uint32_t
398 int64_t
399 uint64_t
400
401u/U uint32_t (same as left)
402 uint64_t
403
404l/L int64_t int64_t
405
406ul/UL/uL/Ul uint64_t uint64_t
407
408
409Note: There are no negative integer literals.
410 -1 is the unary minus applied to 1.
411
412Unary arithmetic and bitwise operators (~ + -):
413 don't change the type of the argument.
414 (so -1u = -(1u) has type uint32_t)
415
416Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
4171. Integral promotion is first applied on both sides.
4182. If both operands have the same type, no promotion is necessary.
4193. Usual arithmetic conversions.
420
421Integral promotion: if an operand is of a type with less than 32 bits,
422(including bool), it is promoted to int32_t.
423
424Usual arithmetic conversions:
4251. If operands are both signed or both unsigned, lesser conversion rank is
426 converted to greater conversion rank.
4272. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
4283. Otherwise, if signed's type can hold all values in unsigned's type,
429 -> signed's type
4304. Otherwise, both converted to the unsigned counterpart of the signed operand's
431 type.
432rank: bool < int8_t < int16_t < int32_t < int64_t
433
434
435Shift operators (<< >>):
4361. Integral promotion is applied on both sides.
4372. For unsigned a, a << b discards bits that shifts out.
438 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
439 For signed negative a, a << b gives error.
4403. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
441 For signed negative a, a >> b discards bits that shifts out, and the signed
442 bit gets extended. ("arithmetic right shift")
4434. Shifting with negative number of bits is undefined. (Currently, the
444 parser will shift into the other direction. This behavior may change.)
4455. Shifting with number of bits exceeding the width of the type is undefined.
446 (Currently, 1 << 32 == 1. This behavior may change.)
447
448Logical operators (!, &&, ||):
4491. Convert first operand to bool. (true if non-zero, false otherwise)
4502. If short-circuited, return the result as type bool, value 1 or 0.
4513. Otherwise, convert second operand to bool, evaluate the result, and return
452 the result in the same fashion.
453
454Arithmetic comparison operators (< > <= >= == !=):
4551. Promote operands in the same way as binary arithmetic and bitwise operators.
456 (Integral promotion + Usual arithmetic conversions)
4572. Return type bool, value 0 or 1 the same way as logical operators.
458
459Ternary conditional operator (?:):
4601. Evaluate the conditional and evaluate the operands.
4612. Return type of expression is the type under usual arithmetic conversions on
462 the second and third operand. (No integral promotions necessary.)
463
464*/
465
Yifan Hong52165692016-08-12 18:06:40 -0700466} // namespace android
467