From 76afc4c1a05785c437c45779fa108c34b4a48999 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 25 Jan 2024 18:04:20 -0800 Subject: [PATCH] [Parser] Parse local.set and global.set of tuple values correctly These instructions always pop a single value, except when tuples are involved, in which case they need special handling to know how many values to pop. --- src/wasm-ir-builder.h | 2 ++ src/wasm/wasm-ir-builder.cpp | 17 ++++++++++ test/lit/wat-kitchen-sink.wast | 57 +++++++++++++++++++++++++++++----- 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h index 77ad2490e06..fce8bd43120 100644 --- a/src/wasm-ir-builder.h +++ b/src/wasm-ir-builder.h @@ -223,6 +223,8 @@ class IRBuilder : public UnifiedExpressionVisitor> { [[nodiscard]] Result<> visitCall(Call*); [[nodiscard]] Result<> visitCallIndirect(CallIndirect*); [[nodiscard]] Result<> visitCallRef(CallRef*); + [[nodiscard]] Result<> visitLocalSet(LocalSet*); + [[nodiscard]] Result<> visitGlobalSet(GlobalSet*); [[nodiscard]] Result<> visitThrow(Throw*); [[nodiscard]] Result<> visitStringNew(StringNew*); [[nodiscard]] Result<> visitStringEncode(StringEncode*); diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index aace2b1ac7a..657f570051b 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -492,6 +492,21 @@ Result<> IRBuilder::visitCallRef(CallRef* curr) { return Ok{}; } +Result<> IRBuilder::visitLocalSet(LocalSet* curr) { + auto type = func->getLocalType(curr->index); + auto val = pop(type.size()); + CHECK_ERR(val); + curr->value = *val; + return Ok{}; +} + +Result<> IRBuilder::visitGlobalSet(GlobalSet* curr) { + auto type = wasm.getGlobal(curr->name)->type; + auto val = pop(type.size()); + CHECK_ERR(val); + curr->value = *val; + return Ok{}; +} Result<> IRBuilder::visitThrow(Throw* curr) { auto numArgs = wasm.getTag(curr->tag)->sig.params.size(); curr->operands.resize(numArgs); @@ -1032,6 +1047,7 @@ Result<> IRBuilder::makeLocalGet(Index local) { Result<> IRBuilder::makeLocalSet(Index local) { LocalSet curr; + curr.index = local; CHECK_ERR(visitLocalSet(&curr)); push(builder.makeLocalSet(local, curr.value)); return Ok{}; @@ -1051,6 +1067,7 @@ Result<> IRBuilder::makeGlobalGet(Name global) { Result<> IRBuilder::makeGlobalSet(Name global) { GlobalSet curr; + curr.name = global; CHECK_ERR(visitGlobalSet(&curr)); push(builder.makeGlobalSet(global, curr.value)); return Ok{}; diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast index bbb8146dbb9..eff63523782 100644 --- a/test/lit/wat-kitchen-sink.wast +++ b/test/lit/wat-kitchen-sink.wast @@ -296,6 +296,12 @@ ;; CHECK: (global $i32 i32 (i32.const 42)) (global $i32 i32 i32.const 42) + ;; CHECK: (global $pair (mut (tuple i32 i64)) (tuple.make 2 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i64.const 1) + ;; CHECK-NEXT: )) + (global $pair (mut (tuple i32 i64)) (tuple.make 2 (i32.const 0) (i64.const 1))) + ;; memories ;; CHECK: (memory $mem 1 1 shared) (memory $mem 1 1 shared) @@ -457,12 +463,6 @@ ;; CHECK-NEXT: ) (func $f4 (type 18) (local i32 i64) (local $l f32)) - ;; CHECK: (func $tuple-locals (type $void) - ;; CHECK-NEXT: (local $0 (tuple i32 i32)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $tuple-locals (local (tuple i32 i32))) - ;; CHECK: (func $nop-skate (type $void) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: (nop) @@ -930,6 +930,30 @@ drop ) + ;; CHECK: (func $tuple-locals (type $void) + ;; CHECK-NEXT: (local $0 (tuple i32 i64)) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (local.tee $0 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i64.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $tuple-locals + (local (tuple i32 i64)) + local.get 0 + local.tee 0 + local.set 0 + i32.const 1 + i64.const 2 + local.set 0 + ) + ;; CHECK: (func $block (type $void) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: (block $l @@ -3064,6 +3088,25 @@ global.set 4 ) + ;; CHECK: (func $tuple-globals (type $void) + ;; CHECK-NEXT: (global.set $pair + ;; CHECK-NEXT: (global.get $pair) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (global.set $pair + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i64.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $tuple-globals + global.get $pair + global.set $pair + i32.const 1 + i64.const 2 + global.set $pair + ) + ;; CHECK: (func $load (type $4) (param $0 i32) (param $1 i64) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.load $mimport$0 offset=42 @@ -3525,7 +3568,7 @@ (func $ref-func ref.func $ref-func drop - ref.func 152 + ref.func 153 drop )