summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/literal.cc43
-rw-r--r--src/literal.h8
-rw-r--r--src/test-literal.cc130
-rw-r--r--src/wast-parser.cc50
4 files changed, 190 insertions, 41 deletions
diff --git a/src/literal.cc b/src/literal.cc
index 3560a451..4c367ed9 100644
--- a/src/literal.cc
+++ b/src/literal.cc
@@ -21,6 +21,8 @@
#include <cmath>
#include <cstdlib>
#include <cstring>
+#include <limits>
+#include <type_traits>
namespace wabt {
@@ -620,10 +622,12 @@ Result ParseInt64(const char* s,
return result;
}
-Result ParseInt32(const char* s,
- const char* end,
- uint32_t* out,
- ParseIntType parse_type) {
+template <typename U>
+Result ParseInt(const char* s,
+ const char* end,
+ U* out,
+ ParseIntType parse_type) {
+ typedef typename std::make_signed<U>::type S;
uint64_t value;
bool has_sign = false;
if (*s == '-' || *s == '+') {
@@ -638,20 +642,41 @@ Result ParseInt32(const char* s,
CHECK_RESULT(ParseUint64(s, end, &value));
if (has_sign) {
- // abs(INT32_MIN) == INT32_MAX + 1.
- if (value > static_cast<uint64_t>(INT32_MAX) + 1) {
+ // abs(INTN_MIN) == INTN_MAX + 1.
+ if (value > static_cast<uint64_t>(std::numeric_limits<S>::max()) + 1) {
return Result::Error;
}
- value = UINT32_MAX - value + 1;
+ value = std::numeric_limits<U>::max() - value + 1;
} else {
- if (value > static_cast<uint64_t>(UINT32_MAX)) {
+ if (value > static_cast<uint64_t>(std::numeric_limits<U>::max())) {
return Result::Error;
}
}
- *out = static_cast<uint32_t>(value);
+ *out = static_cast<U>(value);
return Result::Ok;
}
+Result ParseInt8(const char* s,
+ const char* end,
+ uint8_t* out,
+ ParseIntType parse_type) {
+ return ParseInt(s, end, out, parse_type);
+}
+
+Result ParseInt16(const char* s,
+ const char* end,
+ uint16_t* out,
+ ParseIntType parse_type) {
+ return ParseInt(s, end, out, parse_type);
+}
+
+Result ParseInt32(const char* s,
+ const char* end,
+ uint32_t* out,
+ ParseIntType parse_type) {
+ return ParseInt(s, end, out, parse_type);
+}
+
Result ParseFloat(LiteralType literal_type,
const char* s,
const char* end,
diff --git a/src/literal.h b/src/literal.h
index 40b395ed..b1315a1a 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -49,6 +49,14 @@ enum class ParseIntType {
#define WABT_MAX_DOUBLE_HEX 40
Result ParseHexdigit(char c, uint32_t* out);
+Result ParseInt8(const char* s,
+ const char* end,
+ uint8_t* out,
+ ParseIntType parse_type);
+Result ParseInt16(const char* s,
+ const char* end,
+ uint16_t* out,
+ ParseIntType parse_type);
Result ParseInt32(const char* s,
const char* end,
uint32_t* out,
diff --git a/src/test-literal.cc b/src/test-literal.cc
index 269470bd..e094d879 100644
--- a/src/test-literal.cc
+++ b/src/test-literal.cc
@@ -62,6 +62,18 @@ void AssertIntEquals(T expected,
}
}
+void AssertInt8Equals(uint8_t expected,
+ const char* s,
+ ParseIntTypeCombo parse_type = Both) {
+ AssertIntEquals(expected, s, ParseInt8, parse_type);
+}
+
+void AssertInt16Equals(uint16_t expected,
+ const char* s,
+ ParseIntTypeCombo parse_type = Both) {
+ AssertIntEquals(expected, s, ParseInt16, parse_type);
+}
+
void AssertInt32Equals(uint32_t expected,
const char* s,
ParseIntTypeCombo parse_type = Both) {
@@ -74,6 +86,28 @@ void AssertInt64Equals(uint64_t expected,
AssertIntEquals(expected, s, ParseInt64, parse_type);
}
+void AssertInt8Fails(const char* s) {
+ const char* const end = s + strlen(s);
+ uint8_t actual;
+ ASSERT_EQ(Result::Error,
+ ParseInt8(s, end, &actual, ParseIntType::SignedAndUnsigned))
+ << s;
+ ASSERT_EQ(Result::Error,
+ ParseInt8(s, end, &actual, ParseIntType::UnsignedOnly))
+ << s;
+}
+
+void AssertInt16Fails(const char* s) {
+ const char* const end = s + strlen(s);
+ uint16_t actual;
+ ASSERT_EQ(Result::Error,
+ ParseInt16(s, end, &actual, ParseIntType::SignedAndUnsigned))
+ << s;
+ ASSERT_EQ(Result::Error,
+ ParseInt16(s, end, &actual, ParseIntType::UnsignedOnly))
+ << s;
+}
+
void AssertInt32Fails(const char* s) {
const char* const end = s + strlen(s);
uint32_t actual;
@@ -139,6 +173,102 @@ void AssertHexDoubleFails(const char* s) {
} // end anonymous namespace
+TEST(ParseInt8, Both) {
+ AssertInt8Equals(0, "0");
+ AssertInt8Equals(100, "100");
+ AssertInt8Equals(123, "123");
+ AssertInt8Equals(127, "127");
+ AssertInt8Equals(255, "255");
+ AssertInt8Equals(0xca, "0xca");
+ AssertInt8Equals(0x7f, "0x7f");
+ AssertInt8Equals(0x80, "0x80");
+ AssertInt8Equals(0xff, "0xff");
+}
+
+TEST(ParseInt8, SignedAndUnsigned) {
+ AssertInt8Equals(128, "-128", SignedAndUnsigned);
+ AssertInt8Equals(-0x80, "-0x80", SignedAndUnsigned);
+ AssertInt8Equals(255, "-1", SignedAndUnsigned);
+ AssertInt8Equals(-1, "-0x1", SignedAndUnsigned);
+ AssertInt8Equals(1, "+1", SignedAndUnsigned);
+ AssertInt8Equals(-0x7b, "-0x7B", SignedAndUnsigned);
+ AssertInt8Equals(0xab, "+0xab", SignedAndUnsigned);
+}
+
+TEST(ParseInt8, Invalid) {
+ AssertInt8Fails("");
+ AssertInt8Fails("-100hello");
+ AssertInt8Fails("0XAB");
+ AssertInt8Fails("0xga");
+ AssertInt8Fails("two");
+}
+
+TEST(ParseInt8, Underscores) {
+ AssertInt8Equals(123, "12_3", Both);
+ AssertInt8Equals(123, "+12_3", SignedAndUnsigned);
+ AssertInt8Equals(-123, "-1_23", SignedAndUnsigned);
+ AssertInt8Equals(19, "1______9", Both);
+ AssertInt8Equals(0xab, "0xa_b", Both);
+ AssertInt8Equals(0xab, "+0xa_b", SignedAndUnsigned);
+ AssertInt8Equals(-0x7b, "-0x7_b", SignedAndUnsigned);
+}
+
+TEST(ParseInt8, Overflow) {
+ AssertInt8Fails("256");
+ AssertInt8Fails("-129");
+ AssertInt8Fails("0x100");
+ AssertInt8Fails("-0x81");
+ AssertInt8Fails("1231231231231231231231");
+}
+
+TEST(ParseInt16, Both) {
+ AssertInt16Equals(0, "0");
+ AssertInt16Equals(1000, "1000");
+ AssertInt16Equals(12345, "12345");
+ AssertInt16Equals(32767, "32767");
+ AssertInt16Equals(65535, "65535");
+ AssertInt16Equals(0xcafe, "0xcafe");
+ AssertInt16Equals(0x7fff, "0x7fff");
+ AssertInt16Equals(0x8000, "0x8000");
+ AssertInt16Equals(0xffff, "0xffff");
+}
+
+TEST(ParseInt16, SignedAndUnsigned) {
+ AssertInt16Equals(32768, "-32768", SignedAndUnsigned);
+ AssertInt16Equals(-0x8000, "-0x8000", SignedAndUnsigned);
+ AssertInt16Equals(65535, "-1", SignedAndUnsigned);
+ AssertInt16Equals(-1, "-0x1", SignedAndUnsigned);
+ AssertInt16Equals(1, "+1", SignedAndUnsigned);
+ AssertInt16Equals(-0x7bcd, "-0x7BCD", SignedAndUnsigned);
+ AssertInt16Equals(0xabcd, "+0xabcd", SignedAndUnsigned);
+}
+
+TEST(ParseInt16, Invalid) {
+ AssertInt16Fails("");
+ AssertInt16Fails("-100hello");
+ AssertInt16Fails("0XABCD");
+ AssertInt16Fails("0xgabb");
+ AssertInt16Fails("two");
+}
+
+TEST(ParseInt16, Underscores) {
+ AssertInt16Equals(12345, "12_345", Both);
+ AssertInt16Equals(12345, "+12_345", SignedAndUnsigned);
+ AssertInt16Equals(-12345, "-123_45", SignedAndUnsigned);
+ AssertInt16Equals(19, "1______9", Both);
+ AssertInt16Equals(0xabcd, "0xa_b_c_d", Both);
+ AssertInt16Equals(0xabcd, "+0xa_b_c_d", SignedAndUnsigned);
+ AssertInt16Equals(-0x7bcd, "-0x7_b_c_d", SignedAndUnsigned);
+}
+
+TEST(ParseInt16, Overflow) {
+ AssertInt16Fails("65536");
+ AssertInt16Fails("-32769");
+ AssertInt16Fails("0x10000");
+ AssertInt16Fails("-0x8001");
+ AssertInt16Fails("1231231231231231231231");
+}
+
TEST(ParseInt32, Both) {
AssertInt32Equals(0, "0");
AssertInt32Equals(1000, "1000");
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index 92beffcc..98c22967 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -1791,47 +1791,33 @@ Result WastParser::ParseSimdV128Const(Const* const_, TokenType token_type) {
// the array of bytes:
if (integer) {
switch(lane_count) {
- case 16: {
- int32_t value;
- result = ParseInt32(s, end, Bitcast<uint32_t*>(&value), ParseIntType::SignedAndUnsigned);
- if (value < static_cast<int32_t>(std::numeric_limits<int8_t>::min()) ||
- value > static_cast<int32_t>(std::numeric_limits<uint8_t>::max())) {
- Error(loc, "literal \"%s\" out-of-bounds of i8", literal.text.c_str());
- return Result::Error;
- }
- *lane_ptr = static_cast<uint8_t>(value);
+ case 16:
+ result = ParseInt8(s, end, reinterpret_cast<uint8_t*>(lane_ptr),
+ ParseIntType::SignedAndUnsigned);
break;
- }
- case 8: {
- int32_t value;
- result = ParseInt32(s, end, Bitcast<uint32_t*>(&value), ParseIntType::SignedAndUnsigned);
- if (value < static_cast<int32_t>(std::numeric_limits<int16_t>::min()) ||
- value > static_cast<int32_t>(std::numeric_limits<uint16_t>::max())) {
- Error(loc, "literal \"%s\" out-of-bounds of i16", literal.text.c_str());
- return Result::Error;
- }
- *lane_ptr = static_cast<uint16_t>(value);
+ case 8:
+ result = ParseInt16(s, end, reinterpret_cast<uint16_t*>(lane_ptr),
+ ParseIntType::SignedAndUnsigned);
break;
- }
- case 4: {
- result = ParseInt32(s, end, Bitcast<uint32_t*>(lane_ptr), ParseIntType::SignedAndUnsigned);
+ case 4:
+ result = ParseInt32(s, end, reinterpret_cast<uint32_t*>(lane_ptr),
+ ParseIntType::SignedAndUnsigned);
break;
- }
- case 2: {
- result = ParseInt64(s, end, Bitcast<uint64_t*>(lane_ptr), ParseIntType::SignedAndUnsigned);
+ case 2:
+ result = ParseInt64(s, end, reinterpret_cast<uint64_t*>(lane_ptr),
+ ParseIntType::SignedAndUnsigned);
break;
- }
}
} else {
switch(lane_count) {
- case 4: {
- result = ParseFloat(literal.type, s, end, Bitcast<uint32_t*>(lane_ptr));
+ case 4:
+ result = ParseFloat(literal.type, s, end,
+ reinterpret_cast<uint32_t*>(lane_ptr));
break;
- }
- case 2: {
- result = ParseDouble(literal.type,s, end, Bitcast<uint64_t*>(lane_ptr));
+ case 2:
+ result = ParseDouble(literal.type, s, end,
+ reinterpret_cast<uint64_t*>(lane_ptr));
break;
- }
}
}