summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binary-reader.cc7
-rw-r--r--src/c-writer.cc4
-rw-r--r--src/common.h27
-rw-r--r--src/interp/interp-inl.h10
-rw-r--r--src/interp/interp.cc48
-rw-r--r--src/interp/interp.h13
-rw-r--r--src/prebuilt/wasm2c.include.c32
-rw-r--r--src/stream.h7
-rw-r--r--src/wasm2c.c.tmpl32
-rw-r--r--src/wast-parser.cc7
-rw-r--r--src/wat-writer.cc4
11 files changed, 164 insertions, 27 deletions
diff --git a/src/binary-reader.cc b/src/binary-reader.cc
index daeeeff1..0cf06a0e 100644
--- a/src/binary-reader.cc
+++ b/src/binary-reader.cc
@@ -250,7 +250,14 @@ Result BinaryReader::ReadT(T* out_value,
PrintError("unable to read %s: %s", type_name, desc);
return Result::Error;
}
+#if WABT_BIG_ENDIAN
+ uint8_t tmp[sizeof(T)];
+ memcpy(tmp, state_.data + state_.offset, sizeof(tmp));
+ SwapBytesSized(tmp, sizeof(tmp));
+ memcpy(out_value, tmp, sizeof(T));
+#else
memcpy(out_value, state_.data + state_.offset, sizeof(T));
+#endif
state_.offset += sizeof(T);
return Result::Ok;
}
diff --git a/src/c-writer.cc b/src/c-writer.cc
index 29bf131a..96ca2980 100644
--- a/src/c-writer.cc
+++ b/src/c-writer.cc
@@ -1033,9 +1033,9 @@ void CWriter::WriteDataInitializers() {
}
data_segment_index = 0;
for (const DataSegment* data_segment : module_->data_segments) {
- Write("memcpy(&(", ExternalRef(memory->name), ".data[");
+ Write("LOAD_DATA(", ExternalRef(memory->name), ", ");
WriteInitExpr(data_segment->offset);
- Write("]), data_segment_data_", data_segment_index, ", ",
+ Write(", data_segment_data_", data_segment_index, ", ",
data_segment->data.size(), ");", Newline());
++data_segment_index;
}
diff --git a/src/common.h b/src/common.h
index f5555c23..45b75afd 100644
--- a/src/common.h
+++ b/src/common.h
@@ -101,6 +101,22 @@
#define PRIaddress PRIu64
#define PRIoffset PRIzx
+namespace wabt {
+#if WABT_BIG_ENDIAN
+ inline void MemcpyEndianAware(void *dst, const void *src, size_t dsize, size_t ssize, size_t doff, size_t soff, size_t len) {
+ memcpy(static_cast<char*>(dst) + (dsize) - (len) - (doff),
+ static_cast<const char*>(src) + (ssize) - (len) - (soff),
+ (len));
+ }
+#else
+ inline void MemcpyEndianAware(void *dst, const void *src, size_t dsize, size_t ssize, size_t doff, size_t soff, size_t len) {
+ memcpy(static_cast<char*>(dst) + (doff),
+ static_cast<const char*>(src) + (soff),
+ (len));
+ }
+#endif
+}
+
struct v128 {
v128() = default;
v128(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) {
@@ -140,7 +156,7 @@ struct v128 {
static_assert(sizeof(T) <= sizeof(v), "Invalid cast!");
assert((lane + 1) * sizeof(T) <= sizeof(v));
T result;
- memcpy(&result, &v[lane * sizeof(T)], sizeof(result));
+ wabt::MemcpyEndianAware(&result, v, sizeof(result), sizeof(v), 0, lane * sizeof(T), sizeof(result));
return result;
}
@@ -148,7 +164,7 @@ struct v128 {
void From(int lane, T data) {
static_assert(sizeof(T) <= sizeof(v), "Invalid cast!");
assert((lane + 1) * sizeof(T) <= sizeof(v));
- memcpy(&v[lane * sizeof(T)], &data, sizeof(data));
+ wabt::MemcpyEndianAware(v, &data, sizeof(v), sizeof(data), lane * sizeof(T), 0, sizeof(data));
}
uint8_t v[16];
@@ -449,6 +465,13 @@ inline void ConvertBackslashToSlash(std::string* s) {
ConvertBackslashToSlash(s->begin(), s->end());
}
+inline void SwapBytesSized(void *addr, size_t size) {
+ auto bytes = static_cast<uint8_t*>(addr);
+ for (size_t i = 0; i < size / 2; i++) {
+ std::swap(bytes[i], bytes[size-1-i]);
+ }
+}
+
} // namespace wabt
#endif // WABT_COMMON_H_
diff --git a/src/interp/interp-inl.h b/src/interp/interp-inl.h
index f10efaab..e1dcb72d 100644
--- a/src/interp/interp-inl.h
+++ b/src/interp/interp-inl.h
@@ -652,7 +652,7 @@ Result Memory::Load(u64 offset, u64 addend, T* out) const {
if (!IsValidAccess(offset, addend, sizeof(T))) {
return Result::Error;
}
- memcpy(out, data_.data() + offset + addend, sizeof(T));
+ wabt::MemcpyEndianAware(out, data_.data(), sizeof(T), data_.size(), 0, offset + addend, sizeof(T));
return Result::Ok;
}
@@ -660,7 +660,7 @@ template <typename T>
T WABT_VECTORCALL Memory::UnsafeLoad(u64 offset, u64 addend) const {
assert(IsValidAccess(offset, addend, sizeof(T)));
T val;
- memcpy(&val, data_.data() + offset + addend, sizeof(T));
+ wabt::MemcpyEndianAware(&val, data_.data(), sizeof(T), data_.size(), 0, offset + addend, sizeof(T));
return val;
}
@@ -669,7 +669,7 @@ Result WABT_VECTORCALL Memory::Store(u64 offset, u64 addend, T val) {
if (!IsValidAccess(offset, addend, sizeof(T))) {
return Result::Error;
}
- memcpy(data_.data() + offset + addend, &val, sizeof(T));
+ wabt::MemcpyEndianAware(data_.data(), &val, data_.size(), sizeof(T), offset + addend, 0, sizeof(T));
return Result::Ok;
}
@@ -678,7 +678,7 @@ Result Memory::AtomicLoad(u64 offset, u64 addend, T* out) const {
if (!IsValidAtomicAccess(offset, addend, sizeof(T))) {
return Result::Error;
}
- memcpy(out, data_.data() + offset + addend, sizeof(T));
+ wabt::MemcpyEndianAware(out, data_.data(), sizeof(T), data_.size(), 0, offset + addend, sizeof(T));
return Result::Ok;
}
@@ -687,7 +687,7 @@ Result Memory::AtomicStore(u64 offset, u64 addend, T val) {
if (!IsValidAtomicAccess(offset, addend, sizeof(T))) {
return Result::Error;
}
- memcpy(data_.data() + offset + addend, &val, sizeof(T));
+ wabt::MemcpyEndianAware(data_.data(), &val, data_.size(), sizeof(T), offset + addend, 0, sizeof(T));
return Result::Ok;
}
diff --git a/src/interp/interp.cc b/src/interp/interp.cc
index e5f91f5e..8d8ccc99 100644
--- a/src/interp/interp.cc
+++ b/src/interp/interp.cc
@@ -531,8 +531,15 @@ Result Memory::Match(class Store& store,
Result Memory::Grow(u64 count) {
u64 new_pages;
if (CanGrow<u64>(type_.limits, pages_, count, &new_pages)) {
+#if WABT_BIG_ENDIAN
+ auto old_size = data_.size();
+#endif
pages_ = new_pages;
data_.resize(new_pages * WABT_PAGE_SIZE);
+#if WABT_BIG_ENDIAN
+ std::move_backward(data_.begin(), data_.begin() + old_size, data_.end());
+ std::fill(data_.begin(), data_.end() - old_size, 0);
+#endif
return Result::Ok;
}
return Result::Error;
@@ -540,7 +547,11 @@ Result Memory::Grow(u64 count) {
Result Memory::Fill(u64 offset, u8 value, u64 size) {
if (IsValidAccess(offset, 0, size)) {
+#if WABT_BIG_ENDIAN
+ std::fill(data_.end() - offset - size, data_.end() - offset, value);
+#else
std::fill(data_.begin() + offset, data_.begin() + offset + size, value);
+#endif
return Result::Ok;
}
return Result::Error;
@@ -554,7 +565,11 @@ Result Memory::Init(u64 dst_offset,
src.IsValidRange(src_offset, size)) {
std::copy(src.desc().data.begin() + src_offset,
src.desc().data.begin() + src_offset + size,
+#if WABT_BIG_ENDIAN
+ data_.rbegin() + dst_offset);
+#else
data_.begin() + dst_offset);
+#endif
return Result::Ok;
}
return Result::Error;
@@ -568,9 +583,14 @@ Result Memory::Copy(Memory& dst,
u64 size) {
if (dst.IsValidAccess(dst_offset, 0, size) &&
src.IsValidAccess(src_offset, 0, size)) {
+#if WABT_BIG_ENDIAN
+ auto src_begin = src.data_.end() - src_offset - size;
+ auto dst_begin = dst.data_.end() - dst_offset - size;
+#else
auto src_begin = src.data_.begin() + src_offset;
- auto src_end = src_begin + size;
auto dst_begin = dst.data_.begin() + dst_offset;
+#endif
+ auto src_end = src_begin + size;
auto dst_end = dst_begin + size;
if (src.self() == dst.self() && src_begin < dst_begin) {
std::move_backward(src_begin, src_end, dst_end);
@@ -1970,7 +1990,7 @@ RunResult Thread::DoSimdSplat() {
template <typename R, typename T>
RunResult Thread::DoSimdExtract(Instr instr) {
- Push<T>(Pop<R>().v[instr.imm_u8]);
+ Push<T>(Pop<R>()[instr.imm_u8]);
return RunResult::Ok;
}
@@ -1978,7 +1998,7 @@ template <typename R, typename T>
RunResult Thread::DoSimdReplace(Instr instr) {
auto val = Pop<T>();
auto simd = Pop<R>();
- simd.v[instr.imm_u8] = val;
+ simd[instr.imm_u8] = val;
Push(simd);
return RunResult::Ok;
}
@@ -2015,7 +2035,7 @@ RunResult Thread::DoSimdBinop(BinopFunc<R, T> f) {
auto lhs = Pop<ST>();
SR result;
for (u8 i = 0; i < SR::lanes; ++i) {
- result.v[i] = f(lhs.v[i], rhs.v[i]);
+ result[i] = f(lhs[i], rhs[i]);
}
Push(result);
return RunResult::Ok;
@@ -2028,7 +2048,7 @@ RunResult Thread::DoSimdBitSelect() {
auto lhs = Pop<S>();
S result;
for (u8 i = 0; i < S::lanes; ++i) {
- result.v[i] = (lhs.v[i] & c.v[i]) | (rhs.v[i] & ~c.v[i]);
+ result[i] = (lhs[i] & c[i]) | (rhs[i] & ~c[i]);
}
Push(result);
return RunResult::Ok;
@@ -2048,7 +2068,7 @@ RunResult Thread::DoSimdBitmask() {
auto val = Pop<S>();
u32 result = 0;
for (u8 i = 0; i < S::lanes; ++i) {
- if (val.v[i] < 0) {
+ if (val[i] < 0) {
result |= 1 << i;
}
}
@@ -2065,7 +2085,7 @@ RunResult Thread::DoSimdShift(BinopFunc<R, T> f) {
auto lhs = Pop<ST>();
SR result;
for (u8 i = 0; i < SR::lanes; ++i) {
- result.v[i] = f(lhs.v[i], amount);
+ result[i] = f(lhs[i], amount);
}
Push(result);
return RunResult::Ok;
@@ -2090,7 +2110,7 @@ RunResult Thread::DoSimdSwizzle() {
auto lhs = Pop<S>();
S result;
for (u8 i = 0; i < S::lanes; ++i) {
- result.v[i] = rhs.v[i] < S::lanes ? lhs.v[rhs.v[i]] : 0;
+ result[i] = rhs[i] < S::lanes ? lhs[rhs[i]] : 0;
}
Push(result);
return RunResult::Ok;
@@ -2103,8 +2123,8 @@ RunResult Thread::DoSimdShuffle(Instr instr) {
auto lhs = Pop<S>();
S result;
for (u8 i = 0; i < S::lanes; ++i) {
- result.v[i] =
- sel.v[i] < S::lanes ? lhs.v[sel.v[i]] : rhs.v[sel.v[i] - S::lanes];
+ result[i] =
+ sel[i] < S::lanes ? lhs[sel[i]] : rhs[sel[i] - S::lanes];
}
Push(result);
return RunResult::Ok;
@@ -2118,10 +2138,10 @@ RunResult Thread::DoSimdNarrow() {
auto lhs = Pop<T>();
S result;
for (u8 i = 0; i < T::lanes; ++i) {
- result.v[i] = Saturate<SL, TL>(lhs.v[i]);
+ result[i] = Saturate<SL, TL>(lhs[i]);
}
for (u8 i = 0; i < T::lanes; ++i) {
- result.v[T::lanes + i] = Saturate<SL, TL>(rhs.v[i]);
+ result[T::lanes + i] = Saturate<SL, TL>(rhs[i]);
}
Push(result);
return RunResult::Ok;
@@ -2132,7 +2152,7 @@ RunResult Thread::DoSimdWiden() {
auto val = Pop<T>();
S result;
for (u8 i = 0; i < S::lanes; ++i) {
- result.v[i] = val.v[(low ? 0 : S::lanes) + i];
+ result[i] = val[(low ? 0 : S::lanes) + i];
}
Push(result);
return RunResult::Ok;
@@ -2146,7 +2166,7 @@ RunResult Thread::DoSimdLoadExtend(Instr instr, Trap::Ptr* out_trap) {
}
S result;
for (u8 i = 0; i < S::lanes; ++i) {
- result.v[i] = val.v[i];
+ result[i] = val[i];
}
Push(result);
return RunResult::Ok;
diff --git a/src/interp/interp.h b/src/interp/interp.h
index b4de72e4..95d89088 100644
--- a/src/interp/interp.h
+++ b/src/interp/interp.h
@@ -138,6 +138,19 @@ struct Simd {
static const u8 lanes = L;
T v[L];
+
+ inline T& operator[](u8 idx) {
+#if WABT_BIG_ENDIAN
+ idx = (~idx) & (L-1);
+#endif
+ return v[idx];
+ }
+ inline T operator[](u8 idx) const {
+#if WABT_BIG_ENDIAN
+ idx = (~idx) & (L-1);
+#endif
+ return v[idx];
+ }
};
using s8x16 = Simd<s8, 16>;
using u8x16 = Simd<u8, 16>;
diff --git a/src/prebuilt/wasm2c.include.c b/src/prebuilt/wasm2c.include.c
index 0f1b4b31..63ab825d 100644
--- a/src/prebuilt/wasm2c.include.c
+++ b/src/prebuilt/wasm2c.include.c
@@ -32,6 +32,37 @@ const char SECTION_NAME(declarations)[] =
" if (UNLIKELY((a) + sizeof(t) > mem->size)) TRAP(OOB)\n"
"#endif\n"
"\n"
+"#if WABT_BIG_ENDIAN\n"
+"static inline void load_data(void *dest, const void *src, size_t n) {\n"
+" size_t i = 0;\n"
+" u8 *dest_chars = dest;\n"
+" memcpy(dest, src, n);\n"
+" for (i = 0; i < (n>>1); i++) {\n"
+" u8 cursor = dest_chars[i];\n"
+" dest_chars[i] = dest_chars[n - i - 1];\n"
+" dest_chars[n - i - 1] = cursor;\n"
+" }\n"
+"}\n"
+"#define LOAD_DATA(m, o, i, s) load_data(&(m.data[m.size - o - s]), i, s)\n"
+"#define DEFINE_LOAD(name, t1, t2, t3) \\\n"
+" static inline t3 name(wasm_rt_memory_t* mem, u64 addr) { \\\n"
+" MEMCHECK(mem, addr, t1); \\\n"
+" t1 result; \\\n"
+" __builtin_memcpy(&result, &mem->data[mem->size - addr - sizeof(t1)], sizeof(t1)); \\\n"
+" return (t3)(t2)result; \\\n"
+" }\n"
+"\n"
+"#define DEFINE_STORE(name, t1, t2) \\\n"
+" static inline void name(wasm_rt_memory_t* mem, u64 addr, t2 value) { \\\n"
+" MEMCHECK(mem, addr, t1); \\\n"
+" t1 wrapped = (t1)value; \\\n"
+" __builtin_memcpy(&mem->data[mem->size - addr - sizeof(t1)], &wrapped, sizeof(t1)); \\\n"
+" }\n"
+"#else\n"
+"static inline void load_data(void *dest, const void *src, size_t n) {\n"
+" memcpy(dest, src, n);\n"
+"}\n"
+"#define LOAD_DATA(m, o, i, s) load_data(&(m.data[o]), i, s)\n"
"#define DEFINE_LOAD(name, t1, t2, t3) \\\n"
" static inline t3 name(wasm_rt_memory_t* mem, u64 addr) { \\\n"
" MEMCHECK(mem, addr, t1); \\\n"
@@ -46,6 +77,7 @@ const char SECTION_NAME(declarations)[] =
" t1 wrapped = (t1)value; \\\n"
" __builtin_memcpy(&mem->data[addr], &wrapped, sizeof(t1)); \\\n"
" }\n"
+"#endif\n"
"\n"
"DEFINE_LOAD(i32_load, u32, u32, u32);\n"
"DEFINE_LOAD(i64_load, u64, u64, u64);\n"
diff --git a/src/stream.h b/src/stream.h
index 485c4561..66582fa6 100644
--- a/src/stream.h
+++ b/src/stream.h
@@ -141,7 +141,14 @@ class Stream {
private:
template <typename T>
void Write(const T& data, const char* desc, PrintChars print_chars) {
+#if WABT_BIG_ENDIAN
+ char tmp[sizeof(T)];
+ memcpy(tmp, &data, sizeof(tmp));
+ SwapBytesSized(tmp, sizeof(tmp));
+ WriteData(tmp, sizeof(tmp), desc, print_chars);
+#else
WriteData(&data, sizeof(data), desc, print_chars);
+#endif
}
size_t offset_;
diff --git a/src/wasm2c.c.tmpl b/src/wasm2c.c.tmpl
index c932b98c..8e0fb172 100644
--- a/src/wasm2c.c.tmpl
+++ b/src/wasm2c.c.tmpl
@@ -29,6 +29,37 @@
if (UNLIKELY((a) + sizeof(t) > mem->size)) TRAP(OOB)
#endif
+#if WABT_BIG_ENDIAN
+static inline void load_data(void *dest, const void *src, size_t n) {
+ size_t i = 0;
+ u8 *dest_chars = dest;
+ memcpy(dest, src, n);
+ for (i = 0; i < (n>>1); i++) {
+ u8 cursor = dest_chars[i];
+ dest_chars[i] = dest_chars[n - i - 1];
+ dest_chars[n - i - 1] = cursor;
+ }
+}
+#define LOAD_DATA(m, o, i, s) load_data(&(m.data[m.size - o - s]), i, s)
+#define DEFINE_LOAD(name, t1, t2, t3) \
+ static inline t3 name(wasm_rt_memory_t* mem, u64 addr) { \
+ MEMCHECK(mem, addr, t1); \
+ t1 result; \
+ __builtin_memcpy(&result, &mem->data[mem->size - addr - sizeof(t1)], sizeof(t1)); \
+ return (t3)(t2)result; \
+ }
+
+#define DEFINE_STORE(name, t1, t2) \
+ static inline void name(wasm_rt_memory_t* mem, u64 addr, t2 value) { \
+ MEMCHECK(mem, addr, t1); \
+ t1 wrapped = (t1)value; \
+ __builtin_memcpy(&mem->data[mem->size - addr - sizeof(t1)], &wrapped, sizeof(t1)); \
+ }
+#else
+static inline void load_data(void *dest, const void *src, size_t n) {
+ memcpy(dest, src, n);
+}
+#define LOAD_DATA(m, o, i, s) load_data(&(m.data[o]), i, s)
#define DEFINE_LOAD(name, t1, t2, t3) \
static inline t3 name(wasm_rt_memory_t* mem, u64 addr) { \
MEMCHECK(mem, addr, t1); \
@@ -43,6 +74,7 @@
t1 wrapped = (t1)value; \
__builtin_memcpy(&mem->data[addr], &wrapped, sizeof(t1)); \
}
+#endif
DEFINE_LOAD(i32_load, u32, u32, u32);
DEFINE_LOAD(i64_load, u64, u64, u64);
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index 1ff68e48..e07289cb 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -2142,7 +2142,7 @@ Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) {
case TokenType::SimdShuffleOp: {
Token token = Consume();
ErrorUnlessOpcodeEnabled(token);
- uint8_t values[16];
+ v128 values;
for (int lane = 0; lane < 16; ++lane) {
Location loc = GetLocation();
@@ -2175,12 +2175,11 @@ Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) {
return Result::Error;
}
- values[lane] = static_cast<uint8_t>(value);
+ values.set_u8(lane, static_cast<uint8_t>(value));
}
- v128 value = Bitcast<v128>(values);
out_expr->reset(
- new SimdShuffleOpExpr(token.opcode(), value, loc));
+ new SimdShuffleOpExpr(token.opcode(), values, loc));
break;
}
diff --git a/src/wat-writer.cc b/src/wat-writer.cc
index 5e08af96..a4c703dc 100644
--- a/src/wat-writer.cc
+++ b/src/wat-writer.cc
@@ -965,7 +965,11 @@ Result WatWriter::ExprVisitorDelegate::OnSimdShuffleOpExpr(
writer_->WritePutsSpace(expr->opcode.GetName());
std::array<uint8_t, 16> values = Bitcast<std::array<uint8_t, 16>>(expr->val);
for (int32_t lane = 0; lane < 16; ++lane) {
+#if WABT_BIG_ENDIAN
+ writer_->Writef("%u", values[15 - lane]);
+#else
writer_->Writef("%u", values[lane]);
+#endif
}
writer_->WriteNewline(NO_FORCE_NEWLINE);
return Result::Ok;