summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm/wat-parser.cpp90
-rw-r--r--test/lit/wat-kitchen-sink.wast14
2 files changed, 87 insertions, 17 deletions
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index e17701094..0114d9477 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -558,6 +558,7 @@ struct NullInstrParserCtx {
using ExprT = Ok;
using LocalT = Ok;
+ using GlobalT = Ok;
InstrsT makeInstrs() { return Ok{}; }
void appendInstr(InstrsT&, InstrT) {}
@@ -565,26 +566,31 @@ struct NullInstrParserCtx {
ExprT makeExpr(InstrsT) { return Ok{}; }
- LocalT getLocalFromIdx(uint32_t idx) { return Ok{}; }
- LocalT getLocalFromName(Name name) { return Ok{}; }
+ LocalT getLocalFromIdx(uint32_t) { return Ok{}; }
+ LocalT getLocalFromName(Name) { return Ok{}; }
+ GlobalT getGlobalFromIdx(uint32_t) { return Ok{}; }
+ GlobalT getGlobalFromName(Name) { return Ok{}; }
- InstrT makeUnreachable(Index pos) { return Ok{}; }
- InstrT makeNop(Index pos) { return Ok{}; }
- InstrT makeBinary(Index pos, BinaryOp op) { return Ok{}; }
- InstrT makeUnary(Index pos, UnaryOp op) { return Ok{}; }
- template<typename ResultsT> InstrT makeSelect(Index pos, ResultsT* res) {
+ InstrT makeUnreachable(Index) { return Ok{}; }
+ InstrT makeNop(Index) { return Ok{}; }
+ InstrT makeBinary(Index, BinaryOp) { return Ok{}; }
+ InstrT makeUnary(Index, UnaryOp) { return Ok{}; }
+ template<typename ResultsT> InstrT makeSelect(Index, ResultsT*) {
return Ok{};
}
- InstrT makeDrop(Index pos) { return Ok{}; }
+ InstrT makeDrop(Index) { return Ok{}; }
InstrT makeI32Const(Index, uint32_t) { return Ok{}; }
InstrT makeI64Const(Index, uint64_t) { return Ok{}; }
InstrT makeF32Const(Index, float) { return Ok{}; }
InstrT makeF64Const(Index, double) { return Ok{}; }
- InstrT makeLocalGet(Index pos, LocalT local) { return Ok{}; }
- InstrT makeLocalTee(Index pos, LocalT local) { return Ok{}; }
- InstrT makeLocalSet(Index pos, LocalT local) { return Ok{}; }
+ InstrT makeLocalGet(Index, LocalT) { return Ok{}; }
+ InstrT makeLocalTee(Index, LocalT) { return Ok{}; }
+ InstrT makeLocalSet(Index, LocalT) { return Ok{}; }
+
+ InstrT makeGlobalGet(Index, GlobalT) { return Ok{}; }
+ InstrT makeGlobalSet(Index, GlobalT) { return Ok{}; }
template<typename HeapTypeT> InstrT makeRefNull(Index, HeapTypeT) {
return {};
@@ -599,6 +605,7 @@ template<typename Ctx> struct InstrParserCtx : TypeParserCtx<Ctx> {
using ExprT = Expression*;
using LocalT = Index;
+ using GlobalT = Name;
Builder builder;
@@ -1167,7 +1174,16 @@ struct ParseDefsCtx : InstrParserCtx<ParseDefsCtx> {
return types[idx];
}
- Index getLocalFromIdx(uint32_t idx) { return idx; }
+ Result<Index> getLocalFromIdx(uint32_t idx) {
+ if (!func) {
+ return in.err("cannot access locals outside of a funcion");
+ }
+ if (idx >= func->getNumLocals()) {
+ return in.err("local index out of bounds");
+ }
+ return idx;
+ }
+
Result<Index> getLocalFromName(Name name) {
if (!func) {
return in.err("cannot access locals outside of a function");
@@ -1178,6 +1194,20 @@ struct ParseDefsCtx : InstrParserCtx<ParseDefsCtx> {
return func->getLocalIndex(name);
}
+ Result<Name> getGlobalFromIdx(uint32_t idx) {
+ if (idx >= wasm.globals.size()) {
+ return in.err("global index out of bounds");
+ }
+ return wasm.globals[idx]->name;
+ }
+
+ Result<Name> getGlobalFromName(Name name) {
+ if (!wasm.getGlobalOrNull(name)) {
+ return in.err("global $" + name.toString() + " does not exist");
+ }
+ return name;
+ }
+
Result<TypeUseT> makeTypeUse(Index pos,
std::optional<HeapTypeT> type,
ParamsT* params,
@@ -1285,6 +1315,19 @@ struct ParseDefsCtx : InstrParserCtx<ParseDefsCtx> {
CHECK_ERR(val);
return push(pos, builder.makeLocalSet(local, *val));
}
+
+ Result<> makeGlobalGet(Index pos, Name global) {
+ assert(wasm.getGlobalOrNull(global));
+ auto type = wasm.getGlobal(global)->type;
+ return push(pos, builder.makeGlobalGet(global, type));
+ }
+
+ Result<> makeGlobalSet(Index pos, Name global) {
+ assert(wasm.getGlobalOrNull(global));
+ auto val = pop(pos);
+ CHECK_ERR(val);
+ return push(pos, builder.makeGlobalSet(global, *val));
+ }
};
// ================
@@ -1463,6 +1506,7 @@ Result<typename Ctx::InstrT> makeStringSliceIter(Ctx&, Index);
// Modules
template<typename Ctx> MaybeResult<Index> maybeTypeidx(Ctx& ctx);
template<typename Ctx> Result<typename Ctx::HeapTypeT> typeidx(Ctx&);
+template<typename Ctx> Result<typename Ctx::GlobalT> globalidx(Ctx&);
template<typename Ctx> Result<typename Ctx::LocalT> localidx(Ctx&);
template<typename Ctx> Result<typename Ctx::TypeUseT> typeuse(Ctx&);
MaybeResult<ImportNames> inlineImport(ParseInput&);
@@ -1922,12 +1966,16 @@ Result<typename Ctx::InstrT> makeLocalSet(Ctx& ctx, Index pos) {
template<typename Ctx>
Result<typename Ctx::InstrT> makeGlobalGet(Ctx& ctx, Index pos) {
- return ctx.in.err("unimplemented instruction");
+ auto global = globalidx(ctx);
+ CHECK_ERR(global);
+ return ctx.makeGlobalGet(pos, *global);
}
template<typename Ctx>
Result<typename Ctx::InstrT> makeGlobalSet(Ctx& ctx, Index pos) {
- return ctx.in.err("unimplemented instruction");
+ auto global = globalidx(ctx);
+ CHECK_ERR(global);
+ return ctx.makeGlobalSet(pos, *global);
}
template<typename Ctx>
@@ -2402,8 +2450,20 @@ template<typename Ctx> Result<typename Ctx::HeapTypeT> typeidx(Ctx& ctx) {
return ctx.in.err("expected type index or identifier");
}
+// globalidx ::= x:u32 => x
+// | v:id => x (if globals[x] = v)
+template<typename Ctx> Result<typename Ctx::GlobalT> globalidx(Ctx& ctx) {
+ if (auto x = ctx.in.takeU32()) {
+ return ctx.getGlobalFromIdx(*x);
+ }
+ if (auto id = ctx.in.takeID()) {
+ return ctx.getGlobalFromName(*id);
+ }
+ return ctx.in.err("expected global index or identifier");
+}
+
// localidx ::= x:u32 => x
-// | v:id => x (if types[x] = v)
+// | v:id => x (if locals[x] = v)
template<typename Ctx> Result<typename Ctx::LocalT> localidx(Ctx& ctx) {
if (auto x = ctx.in.takeU32()) {
return ctx.getLocalFromIdx(*x);
diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast
index a0e3c3bef..1ddaa610d 100644
--- a/test/lit/wat-kitchen-sink.wast
+++ b/test/lit/wat-kitchen-sink.wast
@@ -77,7 +77,7 @@
(global (import "" "g3") (ref 0))
(global (import "mod" "") (ref null $many))
- (global i32 i32.const 0)
+ (global (mut i32) i32.const 0)
;; CHECK: (type $ref|$s0|_ref|$s1|_ref|$s2|_ref|$s3|_ref|$s4|_ref|$s5|_ref|$s6|_ref|$s7|_ref|$s8|_ref|$a0|_ref|$a1|_ref|$a2|_ref|$a3|_ref|$subvoid|_ref|$submany|_=>_none (func_subtype (param (ref $s0) (ref $s1) (ref $s2) (ref $s3) (ref $s4) (ref $s5) (ref $s6) (ref $s7) (ref $s8) (ref $a0) (ref $a1) (ref $a2) (ref $a3) (ref $subvoid) (ref $submany)) func))
;; CHECK: (import "mod" "g1" (global $g1 i32))
@@ -90,7 +90,7 @@
;; CHECK: (import "mod" "f5" (func $fimport$1))
- ;; CHECK: (global $2 i32 (i32.const 0))
+ ;; CHECK: (global $2 (mut i32) (i32.const 0))
;; CHECK: (global $i32 i32 (i32.const 42))
(global $i32 i32 i32.const 42)
@@ -693,6 +693,16 @@
drop
)
+ ;; CHECK: (func $globals (type $void)
+ ;; CHECK-NEXT: (global.set $2
+ ;; CHECK-NEXT: (global.get $i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $globals
+ global.get $i32
+ global.set 4
+ )
+
;; CHECK: (func $use-types (type $ref|$s0|_ref|$s1|_ref|$s2|_ref|$s3|_ref|$s4|_ref|$s5|_ref|$s6|_ref|$s7|_ref|$s8|_ref|$a0|_ref|$a1|_ref|$a2|_ref|$a3|_ref|$subvoid|_ref|$submany|_=>_none) (param $0 (ref $s0)) (param $1 (ref $s1)) (param $2 (ref $s2)) (param $3 (ref $s3)) (param $4 (ref $s4)) (param $5 (ref $s5)) (param $6 (ref $s6)) (param $7 (ref $s7)) (param $8 (ref $s8)) (param $9 (ref $a0)) (param $10 (ref $a1)) (param $11 (ref $a2)) (param $12 (ref $a3)) (param $13 (ref $subvoid)) (param $14 (ref $submany))
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )