diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index 1d685be3ba..52eff5b381 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -1358,22 +1358,28 @@ $${rule-prose: Instrs_ok} $${rule: Instrs_ok/empty} +$${rule: Instrs_ok/instr} + $${rule: Instrs_ok/seq} -$${rule: {Instrs_ok/sub Instrs_ok/frame}} +$${rule: Instrs_ok/sub} .. note:: - In combination with the previous rule, - subsumption allows to compose instructions whose types would not directly fit otherwise. + This *subsumption rule* allows to weaken the type of an instruction sequence to a supertype, + which includes the ability to drop init variables ${:x*} from the instruction type in a context where they are not needed, for example, at the end of the body of a :ref:`block `. + +$${rule: Instrs_ok/frame} + +.. note:: + In combination with the previous two rules, + this *frame rule* allows to compose instructions whose types would not directly fit otherwise. For example, consider the instruction sequence $${instr*: (CONST I32 1) (CONST I32 2) (BINOP I32 ADD)} To type this sequence, its subsequence ${instr*: (CONST I32 2) (BINOP I32 ADD)} needs to be valid with an intermediate type. But the direct type of ${instr: (CONST I32 2)} is ${instrtype: eps -> I32}, not matching the two inputs expected by ${instr: $($(BINOP I32 ADD))}. - The subsumption rule allows to weaken the type of ${instr: (CONST I32 2)} to the supertype ${instrtype: I32 -> I32 I32}, such that it can be composed with ${instr: $($(BINOP I32 ADD))} and yields the intermediate type ${instrtype: I32 -> I32 I32} for the subsequence. That can in turn be composed with the first constant. - - Furthermore, subsumption allows to drop init variables ${:x*} from the instruction type in a context where they are not needed, for example, at the end of the body of a :ref:`block `. + The rule allows to weaken the type of ${instr: (CONST I32 2)} to the supertype ${instrtype: I32 -> I32 I32}, such that it can be composed with ${instr: $($(BINOP I32 ADD))} and yields the intermediate type ${instrtype: I32 -> I32 I32} for the subsequence. That can in turn be composed with the first constant. .. index:: expression, result type diff --git a/specification/wasm-1.0/6-typing.spectec b/specification/wasm-1.0/6-typing.spectec index 32aad1b92a..0ae77d73dc 100644 --- a/specification/wasm-1.0/6-typing.spectec +++ b/specification/wasm-1.0/6-typing.spectec @@ -134,9 +134,13 @@ rule Expr_ok: rule Instrs_ok/empty: C |- eps : eps -> eps +rule Instrs_ok/instr: + C |- instr : t_1* -> t_2* + -- Instr_ok: C |- instr : t_1* -> t_2* + rule Instrs_ok/seq: - C |- instr_1 instr_2* : t_1* -> t_3* - -- Instr_ok: C |- instr_1 : t_1* -> t_2* + C |- instr_1* instr_2* : t_1* -> t_3* + -- Instrs_ok: C |- instr_1* : t_1* -> t_2* -- Instrs_ok: C |- instr_2* : t_2* -> t_3* rule Instrs_ok/frame: diff --git a/specification/wasm-2.0/6-typing.spectec b/specification/wasm-2.0/6-typing.spectec index caa2426d6e..3c5ec0d3e8 100644 --- a/specification/wasm-2.0/6-typing.spectec +++ b/specification/wasm-2.0/6-typing.spectec @@ -151,9 +151,13 @@ rule Expr_ok: rule Instrs_ok/empty: C |- eps : eps -> eps +rule Instrs_ok/instr: + C |- instr : t_1* -> t_2* + -- Instr_ok: C |- instr : t_1* -> t_2* + rule Instrs_ok/seq: - C |- instr_1 instr_2* : t_1* -> t_3* - -- Instr_ok: C |- instr_1 : t_1* -> t_2* + C |- instr_1* instr_2* : t_1* -> t_3* + -- Instrs_ok: C |- instr_1* : t_1* -> t_2* -- Instrs_ok: C |- instr_2* : t_2* -> t_3* rule Instrs_ok/sub: diff --git a/specification/wasm-3.0/2.3-validation.instructions.spectec b/specification/wasm-3.0/2.3-validation.instructions.spectec index 6766600a92..62ec9c61db 100644 --- a/specification/wasm-3.0/2.3-validation.instructions.spectec +++ b/specification/wasm-3.0/2.3-validation.instructions.spectec @@ -613,10 +613,14 @@ rule Instr_ok/vcvtop: rule Instrs_ok/empty: C |- eps : eps -> eps +rule Instrs_ok/instr: + C |- instr : t_1* ->_(x*) t_2* + -- Instr_ok: C |- instr : t_1* ->_(x*) t_2* + ;; TODO(3, rossberg): enable x_1*#x_2* to avoid space rule Instrs_ok/seq: - C |- instr_1 instr_2* : t_1* ->_(x_1* x_2*) t_3* - -- Instr_ok: C |- instr_1 : t_1* ->_(x_1*) t_2* + C |- instr_1* instr_2* : t_1* ->_(x_1* x_2*) t_3* + -- Instrs_ok: C |- instr_1* : t_1* ->_(x_1*) t_2* -- (if C.LOCALS[x_1] = init t)* -- Instrs_ok: $with_locals(C, x_1*, (SET t)*) |- instr_2* : t_2* ->_(x_2*) t_3* diff --git a/specification/wasm-latest/2.3-validation.instructions.spectec b/specification/wasm-latest/2.3-validation.instructions.spectec index 6766600a92..62ec9c61db 100644 --- a/specification/wasm-latest/2.3-validation.instructions.spectec +++ b/specification/wasm-latest/2.3-validation.instructions.spectec @@ -613,10 +613,14 @@ rule Instr_ok/vcvtop: rule Instrs_ok/empty: C |- eps : eps -> eps +rule Instrs_ok/instr: + C |- instr : t_1* ->_(x*) t_2* + -- Instr_ok: C |- instr : t_1* ->_(x*) t_2* + ;; TODO(3, rossberg): enable x_1*#x_2* to avoid space rule Instrs_ok/seq: - C |- instr_1 instr_2* : t_1* ->_(x_1* x_2*) t_3* - -- Instr_ok: C |- instr_1 : t_1* ->_(x_1*) t_2* + C |- instr_1* instr_2* : t_1* ->_(x_1* x_2*) t_3* + -- Instrs_ok: C |- instr_1* : t_1* ->_(x_1*) t_2* -- (if C.LOCALS[x_1] = init t)* -- Instrs_ok: $with_locals(C, x_1*, (SET t)*) |- instr_2* : t_2* ->_(x_2*) t_3* diff --git a/spectec/test-frontend/TEST.md b/spectec/test-frontend/TEST.md index 5cf6b649d2..ae3197e8b0 100644 --- a/spectec/test-frontend/TEST.md +++ b/spectec/test-frontend/TEST.md @@ -4463,21 +4463,26 @@ relation Instrs_ok: `%|-%:%`(context, instr*, instrtype) rule empty{C : context}: `%|-%:%`(C, [], `%->_%%`_instrtype(`%`_resulttype([],), [], `%`_resulttype([],))) - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:617.1-621.82 - rule seq{C : context, instr_1 : instr, `instr_2*` : instr*, `t_1*` : valtype*, `x_1*` : idx*, `x_2*` : idx*, `t_3*` : valtype*, `t_2*` : valtype*, `init*` : init*, `t*` : valtype*}: - `%|-%:%`(C, [instr_1] ++ instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`} ++ x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) - -- Instr_ok: `%|-%:%`(C, instr_1, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:616.1-618.46 + rule instr{C : context, instr : instr, `t_1*` : valtype*, `x*` : idx*, `t_2*` : valtype*}: + `%|-%:%`(C, [instr], `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + -- Instr_ok: `%|-%:%`(C, instr, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:621.1-625.82 + rule seq{C : context, `instr_1*` : instr*, `instr_2*` : instr*, `t_1*` : valtype*, `x_1*` : idx*, `x_2*` : idx*, `t_3*` : valtype*, `t_2*` : valtype*, `init*` : init*, `t*` : valtype*}: + `%|-%:%`(C, instr_1*{instr_1 <- `instr_1*`} ++ instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`} ++ x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) + -- Instrs_ok: `%|-%:%`(C, instr_1*{instr_1 <- `instr_1*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) -- (if (C.LOCALS_context[x_1!`%`_idx.0] = `%%`_localtype(init, t)))*{init <- `init*`, t <- `t*`, x_1 <- `x_1*`} -- Instrs_ok: `%|-%:%`($with_locals(C, x_1*{x_1 <- `x_1*`}, `%%`_localtype(SET_init, t)*{t <- `t*`}), instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_2*{t_2 <- `t_2*`},), x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:623.1-627.33 + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:627.1-631.33 rule sub{C : context, `instr*` : instr*, it' : instrtype, it : instrtype}: `%|-%:%`(C, instr*{instr <- `instr*`}, it') -- Instrs_ok: `%|-%:%`(C, instr*{instr <- `instr*`}, it) -- Instrtype_sub: `%|-%<:%`(C, it, it') -- Instrtype_ok: `%|-%:OK`(C, it') - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:630.1-633.33 + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:634.1-637.33 rule frame{C : context, `instr*` : instr*, `t*` : valtype*, `t_1*` : valtype*, `x*` : idx*, `t_2*` : valtype*}: `%|-%:%`(C, instr*{instr <- `instr*`}, `%->_%%`_instrtype(`%`_resulttype(t*{t <- `t*`} ++ t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t*{t <- `t*`} ++ t_2*{t_2 <- `t_2*`},))) -- Instrs_ok: `%|-%:%`(C, instr*{instr <- `instr*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) diff --git a/spectec/test-latex/TEST.md b/spectec/test-latex/TEST.md index c0f1ad2d3d..94e30c9ef6 100644 --- a/spectec/test-latex/TEST.md +++ b/spectec/test-latex/TEST.md @@ -7332,13 +7332,24 @@ $$ $$ \begin{array}{@{}c@{}}\displaystyle \frac{ -C \vdash {\mathit{instr}}_1 : {t_1^\ast} \rightarrow_{{x_1^\ast}} {t_2^\ast} +C \vdash {\mathit{instr}} : {t_1^\ast} \rightarrow_{{x^\ast}} {t_2^\ast} +}{ +C \vdash {\mathit{instr}} : {t_1^\ast} \rightarrow_{{x^\ast}} {t_2^\ast} +} \, {[\textsc{\scriptsize T{-}instr*{-}instr}]} +\qquad +\end{array} +$$ + +$$ +\begin{array}{@{}c@{}}\displaystyle +\frac{ +C \vdash {{\mathit{instr}}_1^\ast} : {t_1^\ast} \rightarrow_{{x_1^\ast}} {t_2^\ast} \qquad (C{.}\mathsf{locals}{}[x_1] = {\mathit{init}}~t)^\ast \qquad C{}[{.}\mathsf{local}{}[{x_1^\ast}] = {(\mathsf{set}~t)^\ast}] \vdash {{\mathit{instr}}_2^\ast} : {t_2^\ast} \rightarrow_{{x_2^\ast}} {t_3^\ast} }{ -C \vdash {\mathit{instr}}_1~{{\mathit{instr}}_2^\ast} : {t_1^\ast} \rightarrow_{{x_1^\ast}~{x_2^\ast}} {t_3^\ast} +C \vdash {{\mathit{instr}}_1^\ast}~{{\mathit{instr}}_2^\ast} : {t_1^\ast} \rightarrow_{{x_1^\ast}~{x_2^\ast}} {t_3^\ast} } \, {[\textsc{\scriptsize T{-}instr*{-}seq}]} \qquad \end{array} diff --git a/spectec/test-middlend/TEST.md b/spectec/test-middlend/TEST.md index 1dac047d81..fe9f803cb0 100644 --- a/spectec/test-middlend/TEST.md +++ b/spectec/test-middlend/TEST.md @@ -3986,21 +3986,26 @@ relation Instrs_ok: `%|-%:%`(context, instr*, instrtype) rule empty{C : context}: `%|-%:%`(C, [], `%->_%%`_instrtype(`%`_resulttype([],), [], `%`_resulttype([],))) - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:617.1-621.82 - rule seq{C : context, instr_1 : instr, `instr_2*` : instr*, `t_1*` : valtype*, `x_1*` : idx*, `x_2*` : idx*, `t_3*` : valtype*, `t_2*` : valtype*, `init*` : init*, `t*` : valtype*}: - `%|-%:%`(C, [instr_1] ++ instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`} ++ x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) - -- Instr_ok: `%|-%:%`(C, instr_1, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:616.1-618.46 + rule instr{C : context, instr : instr, `t_1*` : valtype*, `x*` : idx*, `t_2*` : valtype*}: + `%|-%:%`(C, [instr], `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + -- Instr_ok: `%|-%:%`(C, instr, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:621.1-625.82 + rule seq{C : context, `instr_1*` : instr*, `instr_2*` : instr*, `t_1*` : valtype*, `x_1*` : idx*, `x_2*` : idx*, `t_3*` : valtype*, `t_2*` : valtype*, `init*` : init*, `t*` : valtype*}: + `%|-%:%`(C, instr_1*{instr_1 <- `instr_1*`} ++ instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`} ++ x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) + -- Instrs_ok: `%|-%:%`(C, instr_1*{instr_1 <- `instr_1*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) -- (if (C.LOCALS_context[x_1!`%`_idx.0] = `%%`_localtype(init, t)))*{init <- `init*`, t <- `t*`, x_1 <- `x_1*`} -- Instrs_ok: `%|-%:%`($with_locals(C, x_1*{x_1 <- `x_1*`}, `%%`_localtype(SET_init, t)*{t <- `t*`}), instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_2*{t_2 <- `t_2*`},), x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:623.1-627.33 + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:627.1-631.33 rule sub{C : context, `instr*` : instr*, it' : instrtype, it : instrtype}: `%|-%:%`(C, instr*{instr <- `instr*`}, it') -- Instrs_ok: `%|-%:%`(C, instr*{instr <- `instr*`}, it) -- Instrtype_sub: `%|-%<:%`(C, it, it') -- Instrtype_ok: `%|-%:OK`(C, it') - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:630.1-633.33 + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:634.1-637.33 rule frame{C : context, `instr*` : instr*, `t*` : valtype*, `t_1*` : valtype*, `x*` : idx*, `t_2*` : valtype*}: `%|-%:%`(C, instr*{instr <- `instr*`}, `%->_%%`_instrtype(`%`_resulttype(t*{t <- `t*`} ++ t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t*{t <- `t*`} ++ t_2*{t_2 <- `t_2*`},))) -- Instrs_ok: `%|-%:%`(C, instr*{instr <- `instr*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) @@ -15853,21 +15858,26 @@ relation Instrs_ok: `%|-%:%`(context, instr*, instrtype) rule empty{C : context}: `%|-%:%`(C, [], `%->_%%`_instrtype(`%`_resulttype([],), [], `%`_resulttype([],))) - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:617.1-621.82 - rule seq{C : context, instr_1 : instr, `instr_2*` : instr*, `t_1*` : valtype*, `x_1*` : idx*, `x_2*` : idx*, `t_3*` : valtype*, `t_2*` : valtype*, `init*` : init*, `t*` : valtype*}: - `%|-%:%`(C, [instr_1] ++ instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`} ++ x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) - -- Instr_ok: `%|-%:%`(C, instr_1, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:616.1-618.46 + rule instr{C : context, instr : instr, `t_1*` : valtype*, `x*` : idx*, `t_2*` : valtype*}: + `%|-%:%`(C, [instr], `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + -- Instr_ok: `%|-%:%`(C, instr, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:621.1-625.82 + rule seq{C : context, `instr_1*` : instr*, `instr_2*` : instr*, `t_1*` : valtype*, `x_1*` : idx*, `x_2*` : idx*, `t_3*` : valtype*, `t_2*` : valtype*, `init*` : init*, `t*` : valtype*}: + `%|-%:%`(C, instr_1*{instr_1 <- `instr_1*`} ++ instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`} ++ x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) + -- Instrs_ok: `%|-%:%`(C, instr_1*{instr_1 <- `instr_1*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) -- (if (C.LOCALS_context[x_1!`%`_idx.0] = `%%`_localtype(init, t)))*{init <- `init*`, t <- `t*`, x_1 <- `x_1*`} -- Instrs_ok: `%|-%:%`($with_locals(C, x_1*{x_1 <- `x_1*`}, `%%`_localtype(SET_init, t)*{t <- `t*`}), instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_2*{t_2 <- `t_2*`},), x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:623.1-627.33 + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:627.1-631.33 rule sub{C : context, `instr*` : instr*, it' : instrtype, it : instrtype}: `%|-%:%`(C, instr*{instr <- `instr*`}, it') -- Instrs_ok: `%|-%:%`(C, instr*{instr <- `instr*`}, it) -- Instrtype_sub: `%|-%<:%`(C, it, it') -- Instrtype_ok: `%|-%:OK`(C, it') - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:630.1-633.33 + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:634.1-637.33 rule frame{C : context, `instr*` : instr*, `t*` : valtype*, `t_1*` : valtype*, `x*` : idx*, `t_2*` : valtype*}: `%|-%:%`(C, instr*{instr <- `instr*`}, `%->_%%`_instrtype(`%`_resulttype(t*{t <- `t*`} ++ t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t*{t <- `t*`} ++ t_2*{t_2 <- `t_2*`},))) -- Instrs_ok: `%|-%:%`(C, instr*{instr <- `instr*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) @@ -27826,24 +27836,29 @@ relation Instrs_ok: `%|-%:%`(context, instr*, instrtype) rule empty{C : context}: `%|-%:%`(C, [], `%->_%%`_instrtype(`%`_resulttype([],), [], `%`_resulttype([],))) - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:617.1-621.82 - rule seq{C : context, instr_1 : instr, `instr_2*` : instr*, `t_1*` : valtype*, `x_1*` : idx*, `x_2*` : idx*, `t_3*` : valtype*, `t_2*` : valtype*, `init*` : init*, `t*` : valtype*}: - `%|-%:%`(C, [instr_1] ++ instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`} ++ x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) - -- Instr_ok: `%|-%:%`(C, instr_1, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:616.1-618.46 + rule instr{C : context, instr : instr, `t_1*` : valtype*, `x*` : idx*, `t_2*` : valtype*}: + `%|-%:%`(C, [instr], `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + -- Instr_ok: `%|-%:%`(C, instr, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) + + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:621.1-625.82 + rule seq{C : context, `instr_1*` : instr*, `instr_2*` : instr*, `t_1*` : valtype*, `x_1*` : idx*, `x_2*` : idx*, `t_3*` : valtype*, `t_2*` : valtype*, `init*` : init*, `t*` : valtype*}: + `%|-%:%`(C, instr_1*{instr_1 <- `instr_1*`} ++ instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`} ++ x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) + -- Instrs_ok: `%|-%:%`(C, instr_1*{instr_1 <- `instr_1*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x_1*{x_1 <- `x_1*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) -- if (|`init*`| = |`t*`|) -- if (|`init*`| = |`x_1*`|) -- (if (x_1!`%`_idx.0 < |C.LOCALS_context|))*{x_1 <- `x_1*`} -- (if (C.LOCALS_context[x_1!`%`_idx.0] = `%%`_localtype(init, t)))*{init <- `init*`, t <- `t*`, x_1 <- `x_1*`} -- Instrs_ok: `%|-%:%`($with_locals(C, x_1*{x_1 <- `x_1*`}, `%%`_localtype(SET_init, t)*{t <- `t*`}), instr_2*{instr_2 <- `instr_2*`}, `%->_%%`_instrtype(`%`_resulttype(t_2*{t_2 <- `t_2*`},), x_2*{x_2 <- `x_2*`}, `%`_resulttype(t_3*{t_3 <- `t_3*`},))) - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:623.1-627.33 + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:627.1-631.33 rule sub{C : context, `instr*` : instr*, it' : instrtype, it : instrtype}: `%|-%:%`(C, instr*{instr <- `instr*`}, it') -- Instrs_ok: `%|-%:%`(C, instr*{instr <- `instr*`}, it) -- Instrtype_sub: `%|-%<:%`(C, it, it') -- Instrtype_ok: `%|-%:OK`(C, it') - ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:630.1-633.33 + ;; ../../../../specification/wasm-latest/2.3-validation.instructions.spectec:634.1-637.33 rule frame{C : context, `instr*` : instr*, `t*` : valtype*, `t_1*` : valtype*, `x*` : idx*, `t_2*` : valtype*}: `%|-%:%`(C, instr*{instr <- `instr*`}, `%->_%%`_instrtype(`%`_resulttype(t*{t <- `t*`} ++ t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t*{t <- `t*`} ++ t_2*{t_2 <- `t_2*`},))) -- Instrs_ok: `%|-%:%`(C, instr*{instr <- `instr*`}, `%->_%%`_instrtype(`%`_resulttype(t_1*{t_1 <- `t_1*`},), x*{x <- `x*`}, `%`_resulttype(t_2*{t_2 <- `t_2*`},))) diff --git a/spectec/test-prose/TEST.md b/spectec/test-prose/TEST.md index 0820f2e3dc..d963d31b1b 100644 --- a/spectec/test-prose/TEST.md +++ b/spectec/test-prose/TEST.md @@ -543,9 +543,14 @@ The instruction sequence :math:`{{\mathit{instr}}^\ast}` is :ref:`valid ` with the function type :math:`{{\mathit{valtype}}^\ast}~\rightarrow~{{\mathit{valtype}'}^\ast}`. + * Or: - * The instruction :math:`{\mathit{instr}}_1` is :ref:`valid ` with the function type :math:`{{\mathit{valtype}}^\ast}~\rightarrow~{t_2^\ast}`. + * The instruction sequence :math:`{{\mathit{instr}}^\ast}` is of the form :math:`{{\mathit{instr}}_1^\ast}~{{\mathit{instr}}_2^\ast}`. + + * The instruction sequence :math:`{{\mathit{instr}}_1^\ast}` is :ref:`valid ` with the function type :math:`{{\mathit{valtype}}^\ast}~\rightarrow~{t_2^\ast}`. * The instruction sequence :math:`{{\mathit{instr}}_2^\ast}` is :ref:`valid ` with the function type :math:`{t_2^\ast}~\rightarrow~{{\mathit{valtype}'}^\ast}`. * Or: @@ -564,10 +569,18 @@ The instruction sequence :math:`\epsilon` is :ref:`valid ` with the f -The instruction sequence :math:`{\mathit{instr}}_1~{{\mathit{instr}}_2^\ast}` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_3^\ast}` if: +The instruction sequence :math:`{\mathit{instr}}` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_2^\ast}` if: + + + * The instruction :math:`{\mathit{instr}}` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_2^\ast}`. - * The instruction :math:`{\mathit{instr}}_1` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_2^\ast}`. + + +The instruction sequence :math:`{{\mathit{instr}}_1^\ast}~{{\mathit{instr}}_2^\ast}` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_3^\ast}` if: + + + * The instruction sequence :math:`{{\mathit{instr}}_1^\ast}` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_2^\ast}`. * The instruction sequence :math:`{{\mathit{instr}}_2^\ast}` is :ref:`valid ` with the function type :math:`{t_2^\ast}~\rightarrow~{t_3^\ast}`. @@ -3312,8 +3325,11 @@ Instrs_ok - the number type sequence valtype* is []. - the number type sequence valtype'* is []. - Or: - - instr* is [instr_1] :: instr_2*. - - the instruction instr_1 is valid with the function type valtype* -> t_2*. + - instr* is [instr']. + - the instruction instr' is valid with valtype* -> valtype'*. + - Or: + - instr* is instr_1* :: instr_2*. + - the instruction sequence instr_1* is valid with the function type valtype* -> t_2*. - the instruction sequence instr_2* is valid with the function type t_2* -> valtype'*. - Or: - valtype* is t* :: t_1*. @@ -3323,9 +3339,13 @@ Instrs_ok Instrs_ok/empty - the instruction sequence [] is valid with the function type [] -> []. +Instrs_ok/instr +- the instruction sequence [instr] is valid with the function type t_1* -> t_2* if: + - the instruction instr is valid with t_1* -> t_2*. + Instrs_ok/seq -- the instruction sequence [instr_1] :: instr_2* is valid with the function type t_1* -> t_3* if: - - the instruction instr_1 is valid with the function type t_1* -> t_2*. +- the instruction sequence instr_1* :: instr_2* is valid with the function type t_1* -> t_3* if: + - the instruction sequence instr_1* is valid with the function type t_1* -> t_2*. - the instruction sequence instr_2* is valid with the function type t_2* -> t_3*. Instrs_ok/frame @@ -5460,9 +5480,14 @@ The instruction sequence :math:`{{\mathit{instr}}^\ast}` is :ref:`valid ` with the function type :math:`{{\mathit{valtype}}^\ast}~\rightarrow~{{\mathit{valtype}'}^\ast}`. + * Or: - * The instruction :math:`{\mathit{instr}}_1` is :ref:`valid ` with the function type :math:`{{\mathit{valtype}}^\ast}~\rightarrow~{t_2^\ast}`. + * The instruction sequence :math:`{{\mathit{instr}}^\ast}` is of the form :math:`{{\mathit{instr}}_1^\ast}~{{\mathit{instr}}_2^\ast}`. + + * The instruction sequence :math:`{{\mathit{instr}}_1^\ast}` is :ref:`valid ` with the function type :math:`{{\mathit{valtype}}^\ast}~\rightarrow~{t_2^\ast}`. * The instruction sequence :math:`{{\mathit{instr}}_2^\ast}` is :ref:`valid ` with the function type :math:`{t_2^\ast}~\rightarrow~{{\mathit{valtype}'}^\ast}`. * Or: @@ -5488,10 +5513,18 @@ The instruction sequence :math:`\epsilon` is :ref:`valid ` with the f -The instruction sequence :math:`{\mathit{instr}}_1~{{\mathit{instr}}_2^\ast}` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_3^\ast}` if: +The instruction sequence :math:`{\mathit{instr}}` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_2^\ast}` if: + + + * The instruction :math:`{\mathit{instr}}` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_2^\ast}`. + + - * The instruction :math:`{\mathit{instr}}_1` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_2^\ast}`. +The instruction sequence :math:`{{\mathit{instr}}_1^\ast}~{{\mathit{instr}}_2^\ast}` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_3^\ast}` if: + + + * The instruction sequence :math:`{{\mathit{instr}}_1^\ast}` is :ref:`valid ` with the function type :math:`{t_1^\ast}~\rightarrow~{t_2^\ast}`. * The instruction sequence :math:`{{\mathit{instr}}_2^\ast}` is :ref:`valid ` with the function type :math:`{t_2^\ast}~\rightarrow~{t_3^\ast}`. @@ -11225,8 +11258,11 @@ Instrs_ok - the value type sequence valtype* is []. - the value type sequence valtype'* is []. - Or: - - instr* is [instr_1] :: instr_2*. - - the instruction instr_1 is valid with the function type valtype* -> t_2*. + - instr* is [instr']. + - the instruction instr' is valid with valtype* -> valtype'*. + - Or: + - instr* is instr_1* :: instr_2*. + - the instruction sequence instr_1* is valid with the function type valtype* -> t_2*. - the instruction sequence instr_2* is valid with the function type t_2* -> valtype'*. - Or: - instr* is valid with the function type t_1* -> t_2*. @@ -11240,9 +11276,13 @@ Instrs_ok Instrs_ok/empty - the instruction sequence [] is valid with the function type [] -> []. +Instrs_ok/instr +- the instruction sequence [instr] is valid with the function type t_1* -> t_2* if: + - the instruction instr is valid with t_1* -> t_2*. + Instrs_ok/seq -- the instruction sequence [instr_1] :: instr_2* is valid with the function type t_1* -> t_3* if: - - the instruction instr_1 is valid with the function type t_1* -> t_2*. +- the instruction sequence instr_1* :: instr_2* is valid with the function type t_1* -> t_3* if: + - the instruction sequence instr_1* is valid with the function type t_1* -> t_2*. - the instruction sequence instr_2* is valid with the function type t_2* -> t_3*. Instrs_ok/sub @@ -16578,11 +16618,18 @@ The instruction sequence :math:`{{\mathit{instr}}^\ast}` is :ref:`valid ` with the instruction type :math:`{t_1^\ast}~{\rightarrow}_{{x^\ast}}\,{t_2^\ast}`. + * Or: + + * The instruction sequence :math:`{{\mathit{instr}}^\ast}` is of the form :math:`{{\mathit{instr}}_1^\ast}~{{\mathit{instr}}_2^\ast}`. * The instruction type :math:`{\mathit{it}}` is of the form :math:`{t_1^\ast}~{\rightarrow}_{{x_1^\ast}~{x_2^\ast}}\,{t_3^\ast}`. - * The instruction :math:`{\mathit{instr}}_1` is :ref:`valid ` with the instruction type :math:`{t_1^\ast}~{\rightarrow}_{{x_1^\ast}}\,{t_2^\ast}`. + * The instruction sequence :math:`{{\mathit{instr}}_1^\ast}` is :ref:`valid ` with the instruction type :math:`{t_1^\ast}~{\rightarrow}_{{x_1^\ast}}\,{t_2^\ast}`. * For all :math:`x_1` in :math:`{x_1^\ast}`: @@ -16614,10 +16661,18 @@ The instruction sequence :math:`\epsilon` is :ref:`valid ` with the i -The instruction sequence :math:`{\mathit{instr}}_1~{{\mathit{instr}}_2^\ast}` is :ref:`valid ` with the instruction type :math:`{t_1^\ast}~{\rightarrow}_{{x_1^\ast}~{x_2^\ast}}\,{t_3^\ast}` if: +The instruction sequence :math:`{\mathit{instr}}` is :ref:`valid ` with the instruction type :math:`{t_1^\ast}~{\rightarrow}_{{x^\ast}}\,{t_2^\ast}` if: - * The instruction :math:`{\mathit{instr}}_1` is :ref:`valid ` with the instruction type :math:`{t_1^\ast}~{\rightarrow}_{{x_1^\ast}}\,{t_2^\ast}`. + * The instruction :math:`{\mathit{instr}}` is :ref:`valid ` with the instruction type :math:`{t_1^\ast}~{\rightarrow}_{{x^\ast}}\,{t_2^\ast}`. + + + + +The instruction sequence :math:`{{\mathit{instr}}_1^\ast}~{{\mathit{instr}}_2^\ast}` is :ref:`valid ` with the instruction type :math:`{t_1^\ast}~{\rightarrow}_{{x_1^\ast}~{x_2^\ast}}\,{t_3^\ast}` if: + + + * The instruction sequence :math:`{{\mathit{instr}}_1^\ast}` is :ref:`valid ` with the instruction type :math:`{t_1^\ast}~{\rightarrow}_{{x_1^\ast}}\,{t_2^\ast}`. * For all :math:`x_1` in :math:`{x_1^\ast}`: @@ -29092,9 +29147,13 @@ Instrs_ok - instr* is []. - it is [] -> []. - Or: - - instr* is [instr_1] :: instr_2*. + - instr* is [instr']. + - it is t_1* ->_ x* t_2*. + - the instruction instr' is valid with the instruction type t_1* ->_ x* t_2*. + - Or: + - instr* is instr_1* :: instr_2*. - it is t_1* ->_ x_1* :: x_2* t_3*. - - the instruction instr_1 is valid with the instruction type t_1* ->_ x_1* t_2*. + - the instruction sequence instr_1* is valid with the instruction type t_1* ->_ x_1* t_2*. - For all x_1 in x_1*: - the local C.LOCALS[x_1] exists. - C.LOCALS[x_1] is (init t). @@ -29105,15 +29164,19 @@ Instrs_ok - it is valid. - Or: - it is t* :: t_1* ->_ x* t* :: t_2*. - - instr* is valid with the instruction type t_1* ->_ x* t_2*. + - instr* is valid with t_1* ->_ x* t_2*. - the result type t* is valid. Instrs_ok/empty - the instruction sequence [] is valid with the instruction type [] -> []. +Instrs_ok/instr +- the instruction sequence [instr] is valid with the instruction type t_1* ->_ x* t_2* if: + - the instruction instr is valid with t_1* ->_ x* t_2*. + Instrs_ok/seq -- the instruction sequence [instr_1] :: instr_2* is valid with the instruction type t_1* ->_ x_1* :: x_2* t_3* if: - - the instruction instr_1 is valid with the instruction type t_1* ->_ x_1* t_2*. +- the instruction sequence instr_1* :: instr_2* is valid with the instruction type t_1* ->_ x_1* :: x_2* t_3* if: + - the instruction sequence instr_1* is valid with the instruction type t_1* ->_ x_1* t_2*. - For all x_1 in x_1*: - the local C.LOCALS[x_1] exists. - C.LOCALS[x_1] is (init t). diff --git a/spectec/test-splice/TEST.md b/spectec/test-splice/TEST.md index 425de6fe65..89290fc118 100644 --- a/spectec/test-splice/TEST.md +++ b/spectec/test-splice/TEST.md @@ -104,13 +104,13 @@ C \vdash \epsilon : \epsilon \rightarrow \epsilon } \qquad \frac{ -C \vdash {\mathit{instr}}_1 : {t_1^\ast} \rightarrow_{{x_1^\ast}} {t_2^\ast} +C \vdash {{\mathit{instr}}_1^\ast} : {t_1^\ast} \rightarrow_{{x_1^\ast}} {t_2^\ast} \qquad (C{.}\mathsf{locals}{}[x_1] = {\mathit{init}}~t)^\ast \qquad C{}[{.}\mathsf{local}{}[{x_1^\ast}] = {(\mathsf{set}~t)^\ast}] \vdash {{\mathit{instr}}_2^\ast} : {t_2^\ast} \rightarrow_{{x_2^\ast}} {t_3^\ast} }{ -C \vdash {\mathit{instr}}_1~{{\mathit{instr}}_2^\ast} : {t_1^\ast} \rightarrow_{{x_1^\ast}~{x_2^\ast}} {t_3^\ast} +C \vdash {{\mathit{instr}}_1^\ast}~{{\mathit{instr}}_2^\ast} : {t_1^\ast} \rightarrow_{{x_1^\ast}~{x_2^\ast}} {t_3^\ast} } \\[3ex]\displaystyle \frac{ @@ -1192,6 +1192,7 @@ warning: rule `Instr_ok2/frame` was never spliced warning: rule `Instr_ok2/handler` was never spliced warning: rule `Instr_ok2/trap` was never spliced warning: rule `Instrs_ok/empty` was spliced more than once +warning: rule `Instrs_ok/instr` was never spliced warning: rule `Instrs_ok/sub` was never spliced warning: rule `Instrs_ok/frame` was spliced more than once warning: rule `Instrs_ok2/empty` was never spliced @@ -2210,6 +2211,7 @@ warning: rule prose `Instr_ok2/trap` was never spliced warning: rule prose `Instrs_ok` was never spliced warning: rule prose `Instrs_ok/empty` was never spliced warning: rule prose `Instrs_ok/frame` was never spliced +warning: rule prose `Instrs_ok/instr` was never spliced warning: rule prose `Instrs_ok/seq` was never spliced warning: rule prose `Instrs_ok/sub` was never spliced warning: rule prose `Instrs_ok2` was never spliced