summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/AlignmentLowering.cpp178
-rw-r--r--test/passes/alignment-lowering.txt1422
-rw-r--r--test/passes/alignment-lowering.wast40
3 files changed, 1613 insertions, 27 deletions
diff --git a/src/passes/AlignmentLowering.cpp b/src/passes/AlignmentLowering.cpp
index 818189056..26815b389 100644
--- a/src/passes/AlignmentLowering.cpp
+++ b/src/passes/AlignmentLowering.cpp
@@ -27,16 +27,15 @@
namespace wasm {
struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
- void visitLoad(Load* curr) {
+ // Core lowering of a 32-bit load: ensures it is done using aligned
+ // operations, which means we can leave it alone if it's already aligned, or
+ // else we break it up into smaller loads that are.
+ Expression* lowerLoadI32(Load* curr) {
if (curr->align == 0 || curr->align == curr->bytes) {
- return;
+ return curr;
}
Builder builder(*getModule());
- if (curr->type == Type::unreachable) {
- replaceCurrent(curr->ptr);
- return;
- }
- assert(curr->type == Type::i32); // TODO: i64, f32, f64
+ assert(curr->type == Type::i32);
auto temp = builder.addVar(getFunction(), Type::i32);
Expression* ret;
if (curr->bytes == 2) {
@@ -125,21 +124,16 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
} else {
WASM_UNREACHABLE("invalid size");
}
- replaceCurrent(
- builder.makeBlock({builder.makeLocalSet(temp, curr->ptr), ret}));
+ return builder.makeBlock({builder.makeLocalSet(temp, curr->ptr), ret});
}
- void visitStore(Store* curr) {
+ // Core lowering of a 32-bit store.
+ Expression* lowerStoreI32(Store* curr) {
if (curr->align == 0 || curr->align == curr->bytes) {
- return;
+ return curr;
}
Builder builder(*getModule());
- if (curr->type == Type::unreachable) {
- replaceCurrent(builder.makeBlock(
- {builder.makeDrop(curr->ptr), builder.makeDrop(curr->value)}));
- return;
- }
- assert(curr->value->type == Type::i32); // TODO: i64, f32, f64
+ assert(curr->value->type == Type::i32);
auto tempPtr = builder.addVar(getFunction(), Type::i32);
auto tempValue = builder.addVar(getFunction(), Type::i32);
auto* block =
@@ -222,7 +216,155 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
WASM_UNREACHABLE("invalid size");
}
block->finalize();
- replaceCurrent(block);
+ return block;
+ }
+
+ void visitLoad(Load* curr) {
+ // If unreachable, just remove the load, which removes the unaligned
+ // operation in a trivial way.
+ if (curr->type == Type::unreachable) {
+ replaceCurrent(curr->ptr);
+ return;
+ }
+ if (curr->align == 0 || curr->align == curr->bytes) {
+ // Nothing to do: leave the node unchanged. All code lower down assumes
+ // the operation is unaligned.
+ return;
+ }
+ Builder builder(*getModule());
+ auto type = curr->type.getSingle();
+ Expression* replacement;
+ switch (type) {
+ default:
+ WASM_UNREACHABLE("unhandled unaligned load");
+ case Type::i32:
+ replacement = lowerLoadI32(curr);
+ break;
+ case Type::f32:
+ curr->type = Type::i32;
+ replacement = builder.makeUnary(ReinterpretInt32, lowerLoadI32(curr));
+ break;
+ case Type::i64:
+ case Type::f64:
+ if (type == Type::i64 && curr->bytes != 8) {
+ // A load of <64 bits.
+ curr->type = Type::i32;
+ replacement = builder.makeUnary(
+ curr->signed_ ? ExtendSInt32 : ExtendUInt32, lowerLoadI32(curr));
+ break;
+ }
+ // Load two 32-bit pieces, and combine them.
+ auto temp = builder.addVar(getFunction(), Type::i32);
+ auto* set = builder.makeLocalSet(temp, curr->ptr);
+ Expression* low =
+ lowerLoadI32(builder.makeLoad(4,
+ false,
+ curr->offset,
+ curr->align,
+ builder.makeLocalGet(temp, Type::i32),
+ Type::i32));
+ low = builder.makeUnary(ExtendUInt32, low);
+ // Note that the alignment is assumed to be the same here, even though
+ // we add an offset of 4. That is because this is an unaligned load, so
+ // the alignment is 1, 2, or 4, which means it stays the same after
+ // adding 4.
+ Expression* high =
+ lowerLoadI32(builder.makeLoad(4,
+ false,
+ curr->offset + 4,
+ curr->align,
+ builder.makeLocalGet(temp, Type::i32),
+ Type::i32));
+ high = builder.makeUnary(ExtendUInt32, high);
+ high =
+ builder.makeBinary(ShlInt64, high, builder.makeConst(int64_t(32)));
+ auto* combined = builder.makeBinary(OrInt64, low, high);
+ replacement = builder.makeSequence(set, combined);
+ // Ensure the proper output type.
+ if (type == Type::f64) {
+ replacement = builder.makeUnary(ReinterpretInt64, replacement);
+ }
+ break;
+ }
+ replaceCurrent(replacement);
+ }
+
+ void visitStore(Store* curr) {
+ Builder builder(*getModule());
+ // If unreachable, just remove the store, which removes the unaligned
+ // operation in a trivial way.
+ if (curr->type == Type::unreachable) {
+ replaceCurrent(builder.makeBlock(
+ {builder.makeDrop(curr->ptr), builder.makeDrop(curr->value)}));
+ return;
+ }
+ if (curr->align == 0 || curr->align == curr->bytes) {
+ // Nothing to do: leave the node unchanged. All code lower down assumes
+ // the operation is unaligned.
+ return;
+ }
+ auto type = curr->value->type.getSingle();
+ Expression* replacement;
+ switch (type) {
+ default:
+ WASM_UNREACHABLE("unhandled unaligned store");
+ case Type::i32:
+ replacement = lowerStoreI32(curr);
+ break;
+ case Type::f32:
+ curr->type = Type::i32;
+ curr->value = builder.makeUnary(ReinterpretFloat32, curr->value);
+ replacement = lowerStoreI32(curr);
+ break;
+ case Type::i64:
+ case Type::f64:
+ if (type == Type::i64 && curr->bytes != 8) {
+ // A store of <64 bits.
+ curr->type = Type::i32;
+ curr->value = builder.makeUnary(WrapInt64, curr->value);
+ replacement = lowerStoreI32(curr);
+ break;
+ }
+ // Otherwise, fall through to f64 case for a 64-bit load.
+ // Ensure an integer input value.
+ auto* value = curr->value;
+ if (type == Type::f64) {
+ value = builder.makeUnary(ReinterpretFloat64, value);
+ }
+ // Store as two 32-bit pieces.
+ auto tempPtr = builder.addVar(getFunction(), Type::i32);
+ auto* setPtr = builder.makeLocalSet(tempPtr, curr->ptr);
+ auto tempValue = builder.addVar(getFunction(), Type::i64);
+ auto* setValue = builder.makeLocalSet(tempValue, value);
+ Expression* low = builder.makeUnary(
+ WrapInt64, builder.makeLocalGet(tempValue, Type::i64));
+ low = lowerStoreI32(
+ builder.makeStore(4,
+ curr->offset,
+ curr->align,
+ builder.makeLocalGet(tempPtr, Type::i32),
+ low,
+ Type::i32));
+ Expression* high =
+ builder.makeBinary(ShrUInt64,
+ builder.makeLocalGet(tempValue, Type::i64),
+ builder.makeConst(int64_t(32)));
+ high = builder.makeUnary(WrapInt64, high);
+ // Note that the alignment is assumed to be the same here, even though
+ // we add an offset of 4. That is because this is an unaligned store, so
+ // the alignment is 1, 2, or 4, which means it stays the same after
+ // adding 4.
+ high = lowerStoreI32(
+ builder.makeStore(4,
+ curr->offset + 4,
+ curr->align,
+ builder.makeLocalGet(tempPtr, Type::i32),
+ high,
+ Type::i32));
+ replacement = builder.makeBlock({setPtr, setValue, low, high});
+ break;
+ }
+ replaceCurrent(replacement);
}
};
diff --git a/test/passes/alignment-lowering.txt b/test/passes/alignment-lowering.txt
index b3e276a9f..0ea97136f 100644
--- a/test/passes/alignment-lowering.txt
+++ b/test/passes/alignment-lowering.txt
@@ -437,9 +437,7 @@
)
)
(drop
- (i32.load offset=100
- (unreachable)
- )
+ (unreachable)
)
(i32.store8
(i32.const 4)
@@ -457,13 +455,21 @@
(i32.const 4)
(i32.const 8)
)
- (i32.store8 offset=100
- (unreachable)
- (i32.const 8)
+ (block
+ (drop
+ (unreachable)
+ )
+ (drop
+ (i32.const 8)
+ )
)
- (i32.store8 offset=100
- (i32.const 4)
- (unreachable)
+ (block
+ (drop
+ (i32.const 4)
+ )
+ (drop
+ (unreachable)
+ )
)
)
(func $func_signed
@@ -541,4 +547,1402 @@
(unreachable)
)
)
+ (func $i64-load
+ (local $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i32)
+ (local $8 i32)
+ (local $9 i32)
+ (local $10 i32)
+ (local $11 i32)
+ (local $12 i32)
+ (local $13 i32)
+ (drop
+ (block (result i64)
+ (local.set $0
+ (i32.const 12)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $1
+ (local.get $0)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u
+ (local.get $1)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $1)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=2
+ (local.get $1)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=3
+ (local.get $1)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $2
+ (local.get $0)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=4
+ (local.get $2)
+ )
+ (i32.shl
+ (i32.load8_u offset=5
+ (local.get $2)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=6
+ (local.get $2)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=7
+ (local.get $2)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (drop
+ (block (result i64)
+ (local.set $3
+ (i32.const 16)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $4
+ (local.get $3)
+ )
+ (i32.or
+ (i32.load16_u
+ (local.get $4)
+ )
+ (i32.shl
+ (i32.load16_u offset=2
+ (local.get $4)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $5
+ (local.get $3)
+ )
+ (i32.or
+ (i32.load16_u offset=4
+ (local.get $5)
+ )
+ (i32.shl
+ (i32.load16_u offset=6
+ (local.get $5)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (drop
+ (block (result i64)
+ (local.set $6
+ (i32.const 20)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (i32.load
+ (local.get $6)
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (i32.load offset=4
+ (local.get $6)
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (drop
+ (block (result i64)
+ (local.set $7
+ (i32.const 20)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $8
+ (local.get $7)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=3
+ (local.get $8)
+ )
+ (i32.shl
+ (i32.load8_u offset=4
+ (local.get $8)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=5
+ (local.get $8)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=6
+ (local.get $8)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $9
+ (local.get $7)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=7
+ (local.get $9)
+ )
+ (i32.shl
+ (i32.load8_u offset=8
+ (local.get $9)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=9
+ (local.get $9)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=10
+ (local.get $9)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (drop
+ (i64.extend_i32_s
+ (block (result i32)
+ (local.set $10
+ (i32.const 28)
+ )
+ (i32.shr_s
+ (i32.shl
+ (i32.or
+ (i32.load8_u
+ (local.get $10)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $10)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (drop
+ (i64.extend_i32_s
+ (block (result i32)
+ (local.set $11
+ (i32.const 32)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u
+ (local.get $11)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $11)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=2
+ (local.get $11)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=3
+ (local.get $11)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $12
+ (i32.const 40)
+ )
+ (i32.or
+ (i32.load8_u
+ (local.get $12)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $12)
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $13
+ (i32.const 44)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u
+ (local.get $13)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $13)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=2
+ (local.get $13)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=3
+ (local.get $13)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $f32-load
+ (local $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (drop
+ (f32.reinterpret_i32
+ (block (result i32)
+ (local.set $0
+ (i32.const 12)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u
+ (local.get $0)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $0)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=2
+ (local.get $0)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=3
+ (local.get $0)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (f32.reinterpret_i32
+ (block (result i32)
+ (local.set $1
+ (i32.const 16)
+ )
+ (i32.or
+ (i32.load16_u
+ (local.get $1)
+ )
+ (i32.shl
+ (i32.load16_u offset=2
+ (local.get $1)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (f32.reinterpret_i32
+ (block (result i32)
+ (local.set $2
+ (i32.const 20)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=3
+ (local.get $2)
+ )
+ (i32.shl
+ (i32.load8_u offset=4
+ (local.get $2)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=5
+ (local.get $2)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=6
+ (local.get $2)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $f64-load
+ (local $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i32)
+ (local $8 i32)
+ (local $9 i32)
+ (drop
+ (f64.reinterpret_i64
+ (block (result i64)
+ (local.set $0
+ (i32.const 12)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $1
+ (local.get $0)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u
+ (local.get $1)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $1)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=2
+ (local.get $1)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=3
+ (local.get $1)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $2
+ (local.get $0)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=4
+ (local.get $2)
+ )
+ (i32.shl
+ (i32.load8_u offset=5
+ (local.get $2)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=6
+ (local.get $2)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=7
+ (local.get $2)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (f64.reinterpret_i64
+ (block (result i64)
+ (local.set $3
+ (i32.const 16)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $4
+ (local.get $3)
+ )
+ (i32.or
+ (i32.load16_u
+ (local.get $4)
+ )
+ (i32.shl
+ (i32.load16_u offset=2
+ (local.get $4)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $5
+ (local.get $3)
+ )
+ (i32.or
+ (i32.load16_u offset=4
+ (local.get $5)
+ )
+ (i32.shl
+ (i32.load16_u offset=6
+ (local.get $5)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (f64.reinterpret_i64
+ (block (result i64)
+ (local.set $6
+ (i32.const 20)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (i32.load
+ (local.get $6)
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (i32.load offset=4
+ (local.get $6)
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (f64.reinterpret_i64
+ (block (result i64)
+ (local.set $7
+ (i32.const 20)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $8
+ (local.get $7)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=3
+ (local.get $8)
+ )
+ (i32.shl
+ (i32.load8_u offset=4
+ (local.get $8)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=5
+ (local.get $8)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=6
+ (local.get $8)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $9
+ (local.get $7)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=7
+ (local.get $9)
+ )
+ (i32.shl
+ (i32.load8_u offset=8
+ (local.get $9)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=9
+ (local.get $9)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=10
+ (local.get $9)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $i64-store
+ (local $0 i32)
+ (local $1 i64)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i64)
+ (local $8 i32)
+ (local $9 i32)
+ (local $10 i32)
+ (local $11 i32)
+ (local $12 i32)
+ (local $13 i64)
+ (local $14 i32)
+ (local $15 i64)
+ (local $16 i32)
+ (local $17 i32)
+ (local $18 i32)
+ (local $19 i32)
+ (local $20 i32)
+ (local $21 i32)
+ (local $22 i32)
+ (local $23 i32)
+ (block
+ (local.set $0
+ (i32.const 12)
+ )
+ (local.set $1
+ (i64.const 100)
+ )
+ (block
+ (local.set $2
+ (local.get $0)
+ )
+ (local.set $3
+ (i32.wrap_i64
+ (local.get $1)
+ )
+ )
+ (i32.store8
+ (local.get $2)
+ (local.get $3)
+ )
+ (i32.store8 offset=1
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=2
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $4
+ (local.get $0)
+ )
+ (local.set $5
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $1)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store8 offset=4
+ (local.get $4)
+ (local.get $5)
+ )
+ (i32.store8 offset=5
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=6
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=7
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $6
+ (i32.const 16)
+ )
+ (local.set $7
+ (i64.const 200)
+ )
+ (block
+ (local.set $8
+ (local.get $6)
+ )
+ (local.set $9
+ (i32.wrap_i64
+ (local.get $7)
+ )
+ )
+ (i32.store16
+ (local.get $8)
+ (local.get $9)
+ )
+ (i32.store16 offset=2
+ (local.get $8)
+ (i32.shr_u
+ (local.get $9)
+ (i32.const 16)
+ )
+ )
+ )
+ (block
+ (local.set $10
+ (local.get $6)
+ )
+ (local.set $11
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $7)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store16 offset=4
+ (local.get $10)
+ (local.get $11)
+ )
+ (i32.store16 offset=6
+ (local.get $10)
+ (i32.shr_u
+ (local.get $11)
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $12
+ (i32.const 20)
+ )
+ (local.set $13
+ (i64.const 300)
+ )
+ (i32.store
+ (local.get $12)
+ (i32.wrap_i64
+ (local.get $13)
+ )
+ )
+ (i32.store offset=4
+ (local.get $12)
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $13)
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $14
+ (i32.const 24)
+ )
+ (local.set $15
+ (i64.const 400)
+ )
+ (block
+ (local.set $16
+ (local.get $14)
+ )
+ (local.set $17
+ (i32.wrap_i64
+ (local.get $15)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $16)
+ (local.get $17)
+ )
+ (i32.store8 offset=4
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=5
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=6
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $18
+ (local.get $14)
+ )
+ (local.set $19
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $15)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store8 offset=7
+ (local.get $18)
+ (local.get $19)
+ )
+ (i32.store8 offset=8
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=9
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=10
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $20
+ (i32.const 20)
+ )
+ (local.set $21
+ (i32.wrap_i64
+ (i64.const 600)
+ )
+ )
+ (i32.store8
+ (local.get $20)
+ (local.get $21)
+ )
+ (i32.store8 offset=1
+ (local.get $20)
+ (i32.shr_u
+ (local.get $21)
+ (i32.const 8)
+ )
+ )
+ )
+ (block
+ (local.set $22
+ (i32.const 20)
+ )
+ (local.set $23
+ (i32.wrap_i64
+ (i64.const 700)
+ )
+ )
+ (i32.store8
+ (local.get $22)
+ (local.get $23)
+ )
+ (i32.store8 offset=1
+ (local.get $22)
+ (i32.shr_u
+ (local.get $23)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=2
+ (local.get $22)
+ (i32.shr_u
+ (local.get $23)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $22)
+ (i32.shr_u
+ (local.get $23)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (func $f32-store
+ (local $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (block
+ (local.set $0
+ (i32.const 12)
+ )
+ (local.set $1
+ (i32.reinterpret_f32
+ (f32.const 100)
+ )
+ )
+ (i32.store8
+ (local.get $0)
+ (local.get $1)
+ )
+ (i32.store8 offset=1
+ (local.get $0)
+ (i32.shr_u
+ (local.get $1)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=2
+ (local.get $0)
+ (i32.shr_u
+ (local.get $1)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $0)
+ (i32.shr_u
+ (local.get $1)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $2
+ (i32.const 16)
+ )
+ (local.set $3
+ (i32.reinterpret_f32
+ (f32.const 200)
+ )
+ )
+ (i32.store16
+ (local.get $2)
+ (local.get $3)
+ )
+ (i32.store16 offset=2
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 16)
+ )
+ )
+ )
+ (block
+ (local.set $4
+ (i32.const 24)
+ )
+ (local.set $5
+ (i32.reinterpret_f32
+ (f32.const 400)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $4)
+ (local.get $5)
+ )
+ (i32.store8 offset=4
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=5
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=6
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (func $f64-store
+ (local $0 i32)
+ (local $1 i64)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i64)
+ (local $8 i32)
+ (local $9 i32)
+ (local $10 i32)
+ (local $11 i32)
+ (local $12 i32)
+ (local $13 i64)
+ (local $14 i32)
+ (local $15 i64)
+ (local $16 i32)
+ (local $17 i32)
+ (local $18 i32)
+ (local $19 i32)
+ (block
+ (local.set $0
+ (i32.const 12)
+ )
+ (local.set $1
+ (i64.reinterpret_f64
+ (f64.const 100)
+ )
+ )
+ (block
+ (local.set $2
+ (local.get $0)
+ )
+ (local.set $3
+ (i32.wrap_i64
+ (local.get $1)
+ )
+ )
+ (i32.store8
+ (local.get $2)
+ (local.get $3)
+ )
+ (i32.store8 offset=1
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=2
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $4
+ (local.get $0)
+ )
+ (local.set $5
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $1)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store8 offset=4
+ (local.get $4)
+ (local.get $5)
+ )
+ (i32.store8 offset=5
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=6
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=7
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $6
+ (i32.const 16)
+ )
+ (local.set $7
+ (i64.reinterpret_f64
+ (f64.const 200)
+ )
+ )
+ (block
+ (local.set $8
+ (local.get $6)
+ )
+ (local.set $9
+ (i32.wrap_i64
+ (local.get $7)
+ )
+ )
+ (i32.store16
+ (local.get $8)
+ (local.get $9)
+ )
+ (i32.store16 offset=2
+ (local.get $8)
+ (i32.shr_u
+ (local.get $9)
+ (i32.const 16)
+ )
+ )
+ )
+ (block
+ (local.set $10
+ (local.get $6)
+ )
+ (local.set $11
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $7)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store16 offset=4
+ (local.get $10)
+ (local.get $11)
+ )
+ (i32.store16 offset=6
+ (local.get $10)
+ (i32.shr_u
+ (local.get $11)
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $12
+ (i32.const 20)
+ )
+ (local.set $13
+ (i64.reinterpret_f64
+ (f64.const 300)
+ )
+ )
+ (i32.store
+ (local.get $12)
+ (i32.wrap_i64
+ (local.get $13)
+ )
+ )
+ (i32.store offset=4
+ (local.get $12)
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $13)
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $14
+ (i32.const 24)
+ )
+ (local.set $15
+ (i64.reinterpret_f64
+ (f64.const 400)
+ )
+ )
+ (block
+ (local.set $16
+ (local.get $14)
+ )
+ (local.set $17
+ (i32.wrap_i64
+ (local.get $15)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $16)
+ (local.get $17)
+ )
+ (i32.store8 offset=4
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=5
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=6
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $18
+ (local.get $14)
+ )
+ (local.set $19
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $15)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store8 offset=7
+ (local.get $18)
+ (local.get $19)
+ )
+ (i32.store8 offset=8
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=9
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=10
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
)
diff --git a/test/passes/alignment-lowering.wast b/test/passes/alignment-lowering.wast
index 135fd281e..bbfdd5cb2 100644
--- a/test/passes/alignment-lowering.wast
+++ b/test/passes/alignment-lowering.wast
@@ -60,4 +60,44 @@
(drop (i32.load16_s offset=100 align=2 (i32.const 4)))
(drop (i32.load16_s offset=100 align=1 (unreachable)))
)
+ (func $i64-load
+ (drop (i64.load align=1 (i32.const 12)))
+ (drop (i64.load align=2 (i32.const 16)))
+ (drop (i64.load align=4 (i32.const 20)))
+ (drop (i64.load align=1 offset=3 (i32.const 20)))
+ (drop (i64.load16_s align=1 (i32.const 28)))
+ (drop (i64.load32_s align=1 (i32.const 32)))
+ (drop (i64.load16_u align=1 (i32.const 40)))
+ (drop (i64.load32_u align=1 (i32.const 44)))
+ )
+ (func $f32-load
+ (drop (f32.load align=1 (i32.const 12)))
+ (drop (f32.load align=2 (i32.const 16)))
+ (drop (f32.load align=1 offset=3 (i32.const 20)))
+ )
+ (func $f64-load
+ (drop (f64.load align=1 (i32.const 12)))
+ (drop (f64.load align=2 (i32.const 16)))
+ (drop (f64.load align=4 (i32.const 20)))
+ (drop (f64.load align=1 offset=3 (i32.const 20)))
+ )
+ (func $i64-store
+ (i64.store align=1 (i32.const 12) (i64.const 100))
+ (i64.store align=2 (i32.const 16) (i64.const 200))
+ (i64.store align=4 (i32.const 20) (i64.const 300))
+ (i64.store align=1 offset=3 (i32.const 24) (i64.const 400))
+ (i64.store16 align=1 (i32.const 20) (i64.const 600))
+ (i64.store32 align=1 (i32.const 20) (i64.const 700))
+ )
+ (func $f32-store
+ (f32.store align=1 (i32.const 12) (f32.const 100))
+ (f32.store align=2 (i32.const 16) (f32.const 200))
+ (f32.store align=1 offset=3 (i32.const 24) (f32.const 400))
+ )
+ (func $f64-store
+ (f64.store align=1 (i32.const 12) (f64.const 100))
+ (f64.store align=2 (i32.const 16) (f64.const 200))
+ (f64.store align=4 (i32.const 20) (f64.const 300))
+ (f64.store align=1 offset=3 (i32.const 24) (f64.const 400))
+ )
)