summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-s-parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-s-parser.cpp')
-rw-r--r--src/wasm/wasm-s-parser.cpp205
1 files changed, 205 insertions, 0 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 3874bd2c0..87a6e7abd 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -1456,6 +1456,211 @@ Expression* SExpressionWasmBuilder::makeThenOrElse(Element& s) {
return ret;
}
+static Expression*
+parseConst(cashew::IString s, Type type, MixedArena& allocator) {
+ const char* str = s.str;
+ auto ret = allocator.alloc<Const>();
+ ret->type = type;
+ if (type.isFloat()) {
+ if (s == _INFINITY) {
+ switch (type.getBasic()) {
+ case Type::f32:
+ ret->value = Literal(std::numeric_limits<float>::infinity());
+ break;
+ case Type::f64:
+ ret->value = Literal(std::numeric_limits<double>::infinity());
+ break;
+ default:
+ return nullptr;
+ }
+ // std::cerr << "make constant " << str << " ==> " << ret->value << '\n';
+ return ret;
+ }
+ if (s == NEG_INFINITY) {
+ switch (type.getBasic()) {
+ case Type::f32:
+ ret->value = Literal(-std::numeric_limits<float>::infinity());
+ break;
+ case Type::f64:
+ ret->value = Literal(-std::numeric_limits<double>::infinity());
+ break;
+ default:
+ return nullptr;
+ }
+ // std::cerr << "make constant " << str << " ==> " << ret->value << '\n';
+ return ret;
+ }
+ if (s == _NAN) {
+ switch (type.getBasic()) {
+ case Type::f32:
+ ret->value = Literal(float(std::nan("")));
+ break;
+ case Type::f64:
+ ret->value = Literal(double(std::nan("")));
+ break;
+ default:
+ return nullptr;
+ }
+ // std::cerr << "make constant " << str << " ==> " << ret->value << '\n';
+ return ret;
+ }
+ bool negative = str[0] == '-';
+ const char* positive = negative ? str + 1 : str;
+ if (!negative) {
+ if (positive[0] == '+') {
+ positive++;
+ }
+ }
+ if (positive[0] == 'n' && positive[1] == 'a' && positive[2] == 'n') {
+ const char* modifier = positive[3] == ':' ? positive + 4 : nullptr;
+ if (!(modifier ? positive[4] == '0' && positive[5] == 'x' : 1)) {
+ throw ParseException("bad nan input");
+ }
+ switch (type.getBasic()) {
+ case Type::f32: {
+ uint32_t pattern;
+ if (modifier) {
+ std::istringstream istr(modifier);
+ istr >> std::hex >> pattern;
+ if (istr.fail()) {
+ throw ParseException("invalid f32 format");
+ }
+ pattern |= 0x7f800000U;
+ } else {
+ pattern = 0x7fc00000U;
+ }
+ if (negative) {
+ pattern |= 0x80000000U;
+ }
+ if (!std::isnan(bit_cast<float>(pattern))) {
+ pattern |= 1U;
+ }
+ ret->value = Literal(pattern).castToF32();
+ break;
+ }
+ case Type::f64: {
+ uint64_t pattern;
+ if (modifier) {
+ std::istringstream istr(modifier);
+ istr >> std::hex >> pattern;
+ if (istr.fail()) {
+ throw ParseException("invalid f64 format");
+ }
+ pattern |= 0x7ff0000000000000ULL;
+ } else {
+ pattern = 0x7ff8000000000000UL;
+ }
+ if (negative) {
+ pattern |= 0x8000000000000000ULL;
+ }
+ if (!std::isnan(bit_cast<double>(pattern))) {
+ pattern |= 1ULL;
+ }
+ ret->value = Literal(pattern).castToF64();
+ break;
+ }
+ default:
+ return nullptr;
+ }
+ // std::cerr << "make constant " << str << " ==> " << ret->value << '\n';
+ return ret;
+ }
+ if (s == NEG_NAN) {
+ switch (type.getBasic()) {
+ case Type::f32:
+ ret->value = Literal(float(-std::nan("")));
+ break;
+ case Type::f64:
+ ret->value = Literal(double(-std::nan("")));
+ break;
+ default:
+ return nullptr;
+ }
+ // std::cerr << "make constant " << str << " ==> " << ret->value << '\n';
+ return ret;
+ }
+ }
+ switch (type.getBasic()) {
+ case Type::i32: {
+ if ((str[0] == '0' && str[1] == 'x') ||
+ (str[0] == '-' && str[1] == '0' && str[2] == 'x')) {
+ bool negative = str[0] == '-';
+ if (negative) {
+ str++;
+ }
+ std::istringstream istr(str);
+ uint32_t temp;
+ istr >> std::hex >> temp;
+ if (istr.fail()) {
+ throw ParseException("invalid i32 format");
+ }
+ ret->value = Literal(negative ? -temp : temp);
+ } else {
+ std::istringstream istr(str[0] == '-' ? str + 1 : str);
+ uint32_t temp;
+ istr >> temp;
+ if (istr.fail()) {
+ throw ParseException("invalid i32 format");
+ }
+ ret->value = Literal(str[0] == '-' ? -temp : temp);
+ }
+ break;
+ }
+ case Type::i64: {
+ if ((str[0] == '0' && str[1] == 'x') ||
+ (str[0] == '-' && str[1] == '0' && str[2] == 'x')) {
+ bool negative = str[0] == '-';
+ if (negative) {
+ str++;
+ }
+ std::istringstream istr(str);
+ uint64_t temp;
+ istr >> std::hex >> temp;
+ if (istr.fail()) {
+ throw ParseException("invalid i64 format");
+ }
+ ret->value = Literal(negative ? -temp : temp);
+ } else {
+ std::istringstream istr(str[0] == '-' ? str + 1 : str);
+ uint64_t temp;
+ istr >> temp;
+ if (istr.fail()) {
+ throw ParseException("invalid i64 format");
+ }
+ ret->value = Literal(str[0] == '-' ? -temp : temp);
+ }
+ break;
+ }
+ case Type::f32: {
+ char* end;
+ ret->value = Literal(strtof(str, &end));
+ break;
+ }
+ case Type::f64: {
+ char* end;
+ ret->value = Literal(strtod(str, &end));
+ break;
+ }
+ case Type::v128:
+ case Type::funcref:
+ case Type::externref:
+ case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
+ case Type::dataref:
+ WASM_UNREACHABLE("unexpected const type");
+ case Type::none:
+ case Type::unreachable: {
+ return nullptr;
+ }
+ }
+ if (ret->value.type != type) {
+ throw ParseException("parsed type does not match expected type");
+ }
+ // std::cerr << "make constant " << str << " ==> " << ret->value << '\n';
+ return ret;
+}
+
template<int Lanes>
static Literal makeLanes(Element& s, MixedArena& allocator, Type lane_t) {
std::array<Literal, Lanes> lanes;