diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binary-reader.cc | 7 | ||||
-rw-r--r-- | src/c-writer.cc | 4 | ||||
-rw-r--r-- | src/common.h | 27 | ||||
-rw-r--r-- | src/interp/interp-inl.h | 10 | ||||
-rw-r--r-- | src/interp/interp.cc | 48 | ||||
-rw-r--r-- | src/interp/interp.h | 13 | ||||
-rw-r--r-- | src/prebuilt/wasm2c.include.c | 32 | ||||
-rw-r--r-- | src/stream.h | 7 | ||||
-rw-r--r-- | src/wasm2c.c.tmpl | 32 | ||||
-rw-r--r-- | src/wast-parser.cc | 7 | ||||
-rw-r--r-- | src/wat-writer.cc | 4 |
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; |