WebAssembly Specification Release 1.1 (Draft 2021-12-18) - page 9

 

  Главная      Manuals     WebAssembly Specification Release 1.1 (Draft 2021-12-18)

 

Search            copyright infringement  

 

 

 

 

 

 

 

 

 

 

 

Content      ..     7      8      9      10     ..

 

 

 

WebAssembly Specification Release 1.1 (Draft 2021-12-18) - page 9

 

 

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

(

table

.

copy

𝑥 𝑦

)

˓

𝑆

;

𝐹

;

trap

(

if

𝑠

+

𝑛 >

|

𝑆.

tables

[

𝐹.

module

.

tableaddrs

[

𝑦

]]

.

elem

|

𝑑

+

𝑛 >

|

𝑆.

tables

[

𝐹.

module

.

tableaddrs

[

𝑥

]]

.

elem

|

)

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

0) (

table

.

copy

𝑥 𝑦

)

˓

𝑆

;

𝐹

;

𝜖

(

otherwise

)

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

+ 1) (

table

.

copy

𝑥 𝑦

)

˓

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

table

.

get

𝑦

(

table

.

set

𝑥

)

(

i32

.

const

𝑑

+ 1) (

i32

.

const

𝑠

+ 1) (

i32

.

const

𝑛

(

table

.

copy

𝑥 𝑦

)

(

otherwise

,

if

𝑑

𝑠

)

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

+ 1) (

table

.

copy

𝑥 𝑦

)

˓

𝑆

;

𝐹

(

i32

.

const

𝑑

+

𝑛

1) (

i32

.

const

𝑠

+

𝑛

1) (

table

.

get

𝑦

(

table

.

set

𝑥

)

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

(

table

.

copy

𝑥 𝑦

)

(

otherwise

,

if

𝑑 > 𝑠

)

table

.

init

𝑥 𝑦

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

tableaddrs

[

𝑥

]

exists.

3. Let

ta

be the

table address

𝐹.

module

.

tableaddrs

[

𝑥

]

.

4. Assert: due to

validation

,

𝑆.

tables

[

ta

]

exists.

5. Let

tab

be the

table instance

𝑆.

tables

[

ta

]

.

6. Assert: due to

validation

,

𝐹.

module

.

elemaddrs

[

𝑦

]

exists.

7. Let

ea

be the

element address

𝐹.

module

.

elemaddrs

[

𝑦

]

.

8. Assert: due to

validation

,

𝑆.

elems

[

ea

]

exists.

9. Let

elem

be the

element instance

𝑆.

elems

[

ea

]

.

10. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

11. Pop the value

i32

.

const

𝑛

from the stack.

12. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

13. Pop the value

i32

.

const

𝑠

from the stack.

14. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

15. Pop the value

i32

.

const

𝑑

from the stack.

16. If

𝑠

+

𝑛

is larger than the length of

elem

.

elem

or

𝑑

+

𝑛

is larger than the length of

tab

.

elem

then:

a. Trap.

17. If

𝑛

= 0

, then:

a. Return.

18. Let

val

be the

reference value

elem

.

elem

[

𝑠

]

.

19. Push the value

i32

.

const

𝑑

to the stack.

20. Push the value

val

to the stack.

21. Execute the instruction

table

.

set

𝑥

.

22. Assert: due to the earlier check against the table size,

𝑑

+ 1

<

2

32

.

23. Push the value

i32

.

const

(

𝑑

+ 1)

to the stack.

24. Assert: due to the earlier check against the segment size,

𝑠

+ 1

<

2

32

.

25. Push the value

i32

.

const

(

𝑠

+ 1)

to the stack.

4.4. Instructions

103

26. Push the value

i32

.

const

(

𝑛

1)

to the stack.

27. Execute the instruction

table

.

init

𝑥 𝑦

.

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

(

table

.

init

𝑥 𝑦

)

˓

𝑆

;

𝐹

;

trap

(

if

𝑠

+

𝑛 >

|

𝑆.

elems

[

𝐹.

module

.

elemaddrs

[

𝑦

]]

.

elem

|

𝑑

+

𝑛 >

|

𝑆.

tables

[

𝐹.

module

.

tableaddrs

[

𝑥

]]

.

elem

|

)

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

0) (

table

.

init

𝑥 𝑦

)

˓

𝑆

;

𝐹

;

𝜖

(

otherwise

)

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

+ 1) (

table

.

init

𝑥 𝑦

)

˓

𝑆

;

𝐹

(

i32

.

const

𝑑

)

val

(

table

.

set

𝑥

)

(

i32

.

const

𝑑

+ 1) (

i32

.

const

𝑠

+ 1) (

i32

.

const

𝑛

(

table

.

init

𝑥 𝑦

)

(

otherwise

,

if

val

=

𝑆.

elems

[

𝐹.

module

.

elemaddrs

[

𝑦

]]

.

elem

[

𝑠

])

elem

.

drop

𝑥

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

elemaddrs

[

𝑥

]

exists.

3. Let

𝑎

be the

element address

𝐹.

module

.

elemaddrs

[

𝑥

]

.

4. Assert: due to

validation

,

𝑆.

elems

[

𝑎

]

exists.

5. Replace

𝑆.

elems

[

𝑎

]

with the

element instance

{

elem

𝜖

}

.

𝑆

;

𝐹

(

elem

.

drop

𝑥

)

˓

𝑆

;

𝐹

;

𝜖

(

if

𝑆

=

𝑆

with

elems

[

𝐹.

module

.

elemaddrs

[

𝑥

]] =

{

elem

𝜖

}

)

4.4.7 Memory Instructions

Note:

The alignment

memarg

.

align

in load and store instructions does not affect the semantics. It is an indication

that the offset

ea

at which the memory is accessed is intended to satisfy the property

ea

mod 2

memarg

.

align

= 0

. A

WebAssembly implementation can use this hint to optimize for the intended use. Unaligned access violating that

property is still allowed and must succeed regardless of the annotation. However, it may be substantially slower on

some hardware.

𝑡.

load

memarg

and

𝑡.

load

𝑁

_

sx memarg

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

𝑎

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

𝑎

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

𝑎

]

.

6. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

7. Pop the value

i32

.

const

𝑖

from the stack.

8. Let

ea

be the integer

𝑖

+

memarg

.

offset

.

9. If

𝑁

is not part of the instruction, then:

a. Let

𝑁

be the

bit width

|

𝑡

|

of

number type

𝑡

.

104

Chapter 4. Execution

10. If

ea

+

𝑁/

8

is larger than the length of

mem

.

data

then:

a. Trap.

11. Let

𝑏

*

be the byte sequence

mem

.

data

[

ea

:

𝑁/

8]

.

12. If

𝑁

and

sx

are part of the instruction, then:

a. Let

𝑛

be the integer for which

bytes

i

𝑁

(

𝑛

) =

𝑏

*

.

b. Let

𝑐

be the result of computing

extend

sx

𝑁,

|

𝑡

|

(

𝑛

)

.

13. Else:

a. Let

𝑐

be the constant for which

bytes

𝑡

(

𝑐

) =

𝑏

*

.

14. Push the value

𝑡.

const

𝑐

to the stack.

𝑆

;

𝐹

(

i32

.

const

𝑖

) (

𝑡.

load

memarg

)

˓

𝑆

;

𝐹

; (

𝑡.

const

𝑐

)

(

if

ea

=

𝑖

+

memarg

.

offset

ea

+

|

𝑡

|

/

8

≤ |

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

bytes

𝑡

(

𝑐

) =

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

[

ea

:

|

𝑡

|

/

8])

𝑆

;

𝐹

(

i32

.

const

𝑖

) (

𝑡.

load

𝑁

_

sx memarg

)

˓

𝑆

;

𝐹

; (

𝑡.

const

extend

sx

𝑁,

|

𝑡

|

(

𝑛

))

(

if

ea

=

𝑖

+

memarg

.

offset

ea

+

𝑁/

8

≤ |

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

bytes

i

𝑁

(

𝑛

) =

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

[

ea

:

𝑁/

8])

𝑆

;

𝐹

(

i32

.

const

𝑘

) (

𝑡.

load

(

𝑁

_

sx

)

?

memarg

)

˓

𝑆

;

𝐹

;

trap

(

otherwise

)

v128

.

load

𝑀

x

𝑁

_

sx memarg

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

𝑎

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

𝑎

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

𝑎

]

.

6. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

7. Pop the value

i32

.

const

𝑖

from the stack.

8. Let

ea

be the integer

𝑖

+

memarg

.

offset

.

9. If

ea

+

𝑀

·

𝑁/

8

is larger than the length of

mem

.

data

then:

a. Trap.

10. Let

𝑏

*

be the byte sequence

mem

.

data

[

ea

:

𝑀

·

𝑁/

8]

.

11. Let

𝑚

𝑘

be the integer for which

bytes

i

𝑀

(

𝑚

𝑘

) =

𝑏

*

[

𝑘

·

𝑀/

8

:

𝑀/

8]

.

12. Let

𝑊

be the integer

𝑀

·

2

.

13. Let

𝑛

𝑘

be the result of

extend

sx

𝑀,𝑊

(

𝑚

𝑘

)

.

14. Let

𝑐

be the result of computing

lanes

1

i

𝑊

x

𝑁

(

𝑛

0

. . . 𝑛

𝑁

1

)

.

15. Push the value

v128

.

const

𝑐

to the stack.

4.4. Instructions

105

𝑆

;

𝐹

(

i32

.

const

𝑖

(

v128

.

load

𝑀

x

𝑁

_

sx memarg

)

˓

𝑆

;

𝐹

(

v128

.

const

𝑐

)

(

if

ea

=

𝑖

+

memarg

.

offset

ea

+

𝑀

·

𝑁/

8

≤ |

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

bytes

i

𝑀

(

𝑚

𝑘

) =

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

[

ea

+

𝑘

·

𝑀/

8

:

𝑀/

8])

𝑊

=

𝑀

·

2

𝑐

=

lanes

1

i

𝑊

x

𝑁

(

extend

sx

𝑀,𝑊

(

𝑚

0

)

. . .

extend

sx

𝑀,𝑊

(

𝑚

𝑁

1

))

𝑆

;

𝐹

(

i32

.

const

𝑘

(

v128

.

load

𝑀

x

𝑁

_

sx memarg

)

˓

𝑆

;

𝐹

;

trap

(

otherwise

)

v128

.

load

𝑁

_

splat

memarg

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

𝑎

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

𝑎

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

𝑎

]

.

6. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

7. Pop the value

i32

.

const

𝑖

from the stack.

8. Let

ea

be the integer

𝑖

+

memarg

.

offset

.

9. If

ea

+

𝑁/

8

is larger than the length of

mem

.

data

then:

a. Trap.

10. Let

𝑏

*

be the byte sequence

mem

.

data

[

ea

:

𝑁/

8]

.

11. Let

𝑛

be the integer for which

bytes

i

𝑁

(

𝑛

) =

𝑏

*

.

12. Let

𝐿

be the integer

128

/𝑁

.

13. Let

𝑐

be the result of computing

lanes

1

i

𝑁

x

𝐿

(

𝑛

𝐿

)

.

14. Push the value

v128

.

const

𝑐

to the stack.

𝑆

;

𝐹

(

i32

.

const

𝑖

(

v128

.

load

𝑁

_

splat

memarg

)

˓

𝑆

;

𝐹

(

v128

.

const

𝑐

)

(

if

ea

=

𝑖

+

memarg

.

offset

ea

+

𝑁/

8

≤ |

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

bytes

i

𝑁

(

𝑛

) =

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

[

ea

:

𝑁/

8])

𝑐

=

lanes

1

i

𝑁

x

𝐿

(

𝑛

𝐿

)

𝑆

;

𝐹

(

i32

.

const

𝑘

(

v128

.

load

𝑁

_

splat

memarg

)

˓

𝑆

;

𝐹

;

trap

(

otherwise

)

v128

.

load

𝑁

_

zero

memarg

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

𝑎

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

𝑎

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

𝑎

]

.

6. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

7. Pop the value

i32

.

const

𝑖

from the stack.

8. Let

ea

be the integer

𝑖

+

memarg

.

offset

.

106

Chapter 4. Execution

9. If

ea

+

𝑁/

8

is larger than the length of

mem

.

data

then:

a. Trap.

10. Let

𝑏

*

be the byte sequence

mem

.

data

[

ea

:

𝑁/

8]

.

11. Let

𝑛

be the integer for which

bytes

i

𝑁

(

𝑛

) =

𝑏

*

.

12. Let

𝑐

be the result of

extend

u

𝑁,

128

(

𝑛

)

.

13. Push the value

v128

.

const

𝑐

to the stack.

𝑆

;

𝐹

(

i32

.

const

𝑖

(

v128

.

load

𝑁

_

zero

memarg

)

˓

𝑆

;

𝐹

(

v128

.

const

𝑐

)

(

if

ea

=

𝑖

+

memarg

.

offset

ea

+

𝑁/

8

≤ |

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

bytes

i

𝑁

(

𝑛

) =

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

[

ea

:

𝑁/

8])

𝑐

=

extend

u

𝑁,

128

(

𝑛

)

𝑆

;

𝐹

(

i32

.

const

𝑘

(

v128

.

load

𝑁

_

zero

memarg

)

˓

𝑆

;

𝐹

;

trap

(

otherwise

)

v128

.

load

𝑁

_

lane

memarg

𝑥

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

𝑎

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

𝑎

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

𝑎

]

.

6. Assert: due to

validation

a value of

value type

v128

is on the top of the stack.

7. Pop the value

v128

.

const

𝑣

from the stack.

8. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

9. Pop the value

i32

.

const

𝑖

from the stack.

10. Let

ea

be the integer

𝑖

+

memarg

.

offset

.

11. If

ea

+

𝑁/

8

is larger than the length of

mem

.

data

then:

a. Trap.

12. Let

𝑏

*

be the byte sequence

mem

.

data

[

ea

:

𝑁/

8]

.

13. Let

𝑟

be the constant for which

bytes

i

𝑁

(

𝑟

) =

𝑏

*

.

14. Let

𝐿

be

128

/𝑁

.

15. Let

𝑐

be the result of computing

lanes

1

i

𝑁

x

𝐿

(

lanes

i

𝑁

x

𝐿

(

𝑣

)

with

[

𝑥

] =

𝑟

)

.

16. Push the value

v128

.

const

𝑐

to the stack.

𝑆

;

𝐹

(

i32

.

const

𝑖

(

v128

.

const

𝑣

(

v128

.

load

𝑁

_

lane

memarg

𝑥

)

˓

𝑆

;

𝐹

(

v128

.

const

𝑐

)

(

if

ea

=

𝑖

+

memarg

.

offset

ea

+

𝑁/

8

≤ |

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

bytes

i

𝑁

(

𝑟

) =

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

[

ea

:

𝑁/

8])

𝐿

= 128

/𝑁

𝑐

=

lanes

1

i

𝑁

x

𝐿

(

lanes

i

𝑁

x

𝐿

(

𝑣

)

with

[

𝑥

] =

𝑟

)

𝑆

;

𝐹

(

i32

.

const

𝑘

(

v128

.

const

𝑣

(

v128

.

load

𝑁

_

lane

memarg

𝑥

)

˓

𝑆

;

𝐹

;

trap

(

otherwise

)

4.4. Instructions

107

𝑡.

store

memarg

and

𝑡.

store

𝑁

memarg

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

𝑎

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

𝑎

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

𝑎

]

.

6. Assert: due to

validation

a value of

value type

𝑡

is on the top of the stack.

7. Pop the value

𝑡.

const

𝑐

from the stack.

8. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

9. Pop the value

i32

.

const

𝑖

from the stack.

10. Let

ea

be the integer

𝑖

+

memarg

.

offset

.

11. If

𝑁

is not part of the instruction, then:

a. Let

𝑁

be the

bit width

|

𝑡

|

of

number type

𝑡

.

12. If

ea

+

𝑁/

8

is larger than the length of

mem

.

data

then:

a. Trap.

13. If

𝑁

is part of the instruction, then:

a. Let

𝑛

be the result of computing

wrap

|

𝑡

|

,𝑁

(

𝑐

)

.

b. Let

𝑏

*

be the byte sequence

bytes

i

𝑁

(

𝑛

)

.

14. Else:

a. Let

𝑏

*

be the byte sequence

bytes

𝑡

(

𝑐

)

.

15. Replace the bytes

mem

.

data

[

ea

:

𝑁/

8]

with

𝑏

*

.

𝑆

;

𝐹

(

i32

.

const

𝑖

) (

𝑡.

const

𝑐

) (

𝑡.

store

memarg

)

˓

𝑆

;

𝐹

;

𝜖

(

if

ea

=

𝑖

+

memarg

.

offset

ea

+

|

𝑡

|

/

8

≤ |

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

𝑆

=

𝑆

with

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

[

ea

:

|

𝑡

|

/

8] =

bytes

𝑡

(

𝑐

))

𝑆

;

𝐹

(

i32

.

const

𝑖

) (

𝑡.

const

𝑐

) (

𝑡.

store

𝑁

memarg

)

˓

𝑆

;

𝐹

;

𝜖

(

if

ea

=

𝑖

+

memarg

.

offset

ea

+

𝑁/

8

≤ |

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

𝑆

=

𝑆

with

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

[

ea

:

𝑁/

8] =

bytes

i

𝑁

(

wrap

|

𝑡

|

,𝑁

(

𝑐

))

𝑆

;

𝐹

(

i32

.

const

𝑘

) (

𝑡.

const

𝑐

) (

𝑡.

store

𝑁

?

memarg

)

˓

𝑆

;

𝐹

;

trap

(

otherwise

)

v128

.

store

𝑁

_

lane

memarg

𝑥

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

𝑎

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

𝑎

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

𝑎

]

.

6. Assert: due to

validation

a value of

value type

v128

is on the top of the stack.

7. Pop the value

v128

.

const

𝑐

from the stack.

108

Chapter 4. Execution

8. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

9. Pop the value

i32

.

const

𝑖

from the stack.

10. Let

ea

be the integer

𝑖

+

memarg

.

offset

.

11. If

ea

+

𝑁/

8

is larger than the length of

mem

.

data

then:

a. Trap.

12. Let

𝐿

be

128

/𝑁

.

13. Let

𝑏

*

be the byte sequence

bytes

i

𝑁

(

lanes

i

𝑁

x

𝐿

(

𝑐

)[

𝑥

])

.

14. Replace the bytes

mem

.

data

[

ea

:

𝑁/

8]

with

𝑏

*

.

𝑆

;

𝐹

(

i32

.

const

𝑖

(

v128

.

const

𝑐

(

v128

.

store

𝑁

_

lane

memarg

𝑥

)

˓

𝑆

;

𝐹

;

𝜖

(

if

ea

=

𝑖

+

memarg

.

offset

ea

+

𝑁

≤ |

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

𝐿

= 128

/𝑁

𝑆

=

𝑆

with

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

[

ea

:

𝑁/

8] =

bytes

i

𝑁

(

lanes

i

𝑁

x

𝐿

(

𝑐

)[

𝑥

])

𝑆

;

𝐹

(

i32

.

const

𝑘

(

v128

.

const

𝑐

(

v128

.

store

𝑁

_

lane

memarg

𝑥

)

˓

𝑆

;

𝐹

;

trap

(

otherwise

)

memory

.

size

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

𝑎

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

𝑎

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

𝑎

]

.

6. Let

sz

be the length of

mem

.

data

divided by the

page size

.

7. Push the value

i32

.

const

sz

to the stack.

𝑆

;

𝐹

;

memory

.

size

˓

𝑆

;

𝐹

(

i32

.

const

sz

)

(

if

|

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

=

sz

·

64 Ki)

memory

.

grow

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

𝑎

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

𝑎

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

𝑎

]

.

6. Let

sz

be the length of

𝑆.

mems

[

𝑎

]

divided by the

page size

.

7. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

8. Pop the value

i32

.

const

𝑛

from the stack.

9. Let

err

be the

i32

value

2

32

1

, for which

signed

32

(

err

)

is

1

.

10. Either, try

growing

mem

by

𝑛

pages

:

a. If it succeeds, push the value

i32

.

const

sz

to the stack.

b. Else, push the value

i32

.

const

err

to the stack.

4.4. Instructions

109

11. Or, push the value

i32

.

const

err

to the stack.

𝑆

;

𝐹

(

i32

.

const

𝑛

)

memory

.

grow

˓

𝑆

;

𝐹

(

i32

.

const

sz

)

(

if

𝐹.

module

.

memaddrs

[0] =

𝑎

sz

=

|

𝑆.

mems

[

𝑎

]

.

data

|

/

64 Ki

𝑆

=

𝑆

with

mems

[

𝑎

=

growmem

(

𝑆.

mems

[

𝑎

]

, 𝑛

))

𝑆

;

𝐹

(

i32

.

const

𝑛

)

memory

.

grow

˓

𝑆

;

𝐹

(

i32

.

const

signed

1

32

(

1))

Note:

The

memory

.

grow

instruction is non-deterministic. It may either succeed, returning the old memory size

sz

, or fail, returning

1

. Failure

must

occur if the referenced memory instance has a maximum size defined that

would be exceeded. However, failure

can

occur in other cases as well. In practice, the choice depends on the

resources

available to the

embedder

.

memory

.

fill

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

ma

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

ma

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

ma

]

.

6. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

7. Pop the value

i32

.

const

𝑛

from the stack.

8. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

9. Pop the value

val

from the stack.

10. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

11. Pop the value

i32

.

const

𝑑

from the stack.

12. If

𝑑

+

𝑛

is larger than the length of

mem

.

data

then:

a. Trap.

13. If

𝑛

= 0

, then:

a. Return.

14. Push the value

i32

.

const

𝑑

to the stack.

15. Push the value

val

to the stack.

16. Execute the instruction

i32

.

store

8

{

offset

0

,

align

0

}

.

17. Assert: due to the earlier check against the memory size,

𝑑

+ 1

<

2

32

.

18. Push the value

i32

.

const

(

𝑑

+ 1)

to the stack.

19. Push the value

val

to the stack.

20. Push the value

i32

.

const

(

𝑛

1)

to the stack.

21. Execute the instruction

memory

.

fill

.

110

Chapter 4. Execution

𝑆

;

𝐹

(

i32

.

const

𝑑

)

val

(

i32

.

const

𝑛

)

memory

.

fill

˓

𝑆

;

𝐹

;

trap

(

if

𝑑

+

𝑛 >

|

𝑆.

mems

[

𝐹.

module

.

memaddrs

[

𝑥

]]

.

data

|

)

𝑆

;

𝐹

(

i32

.

const

𝑑

)

val

(

i32

.

const

0)

memory

.

fill

˓

𝑆

;

𝐹

;

𝜖

(

otherwise

)

𝑆

;

𝐹

(

i32

.

const

𝑑

)

val

(

i32

.

const

𝑛

+ 1)

memory

.

fill

˓

𝑆

;

𝐹

(

i32

.

const

𝑑

)

val

(

i32

.

store

8

{

offset

0

,

align

0

}

)

(

i32

.

const

𝑑

+ 1)

val

(

i32

.

const

𝑛

)

memory

.

fill

(

otherwise

)

memory

.

copy

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

ma

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

ma

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

ma

]

.

6. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

7. Pop the value

i32

.

const

𝑛

from the stack.

8. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

9. Pop the value

i32

.

const

𝑠

from the stack.

10. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

11. Pop the value

i32

.

const

𝑑

from the stack.

12. If

𝑠

+

𝑛

is larger than the length of

mem

.

data

or

𝑑

+

𝑛

is larger than the length of

mem

.

data

then:

a. Trap.

13. If

𝑛

= 0

, then:

a. Return.

14. If

𝑑

𝑠

, then:

a. Push the value

i32

.

const

𝑑

to the stack.

b. Push the value

i32

.

const

𝑠

to the stack.

c. Execute the instruction

i32

.

load

8

_

u

{

offset

0

,

align

0

}

.

d. Execute the instruction

i32

.

store

8

{

offset

0

,

align

0

}

.

e. Assert: due to the earlier check against the memory size,

𝑑

+ 1

<

2

32

.

f. Push the value

i32

.

const

(

𝑑

+ 1)

to the stack.

g. Assert: due to the earlier check against the memory size,

𝑠

+ 1

<

2

32

.

h. Push the value

i32

.

const

(

𝑠

+ 1)

to the stack.

15. Else:

a. Assert: due to the earlier check against the memory size,

𝑑

+

𝑛

1

<

2

32

.

b. Push the value

i32

.

const

(

𝑑

+

𝑛

1)

to the stack.

c. Assert: due to the earlier check against the memory size,

𝑠

+

𝑛

1

<

2

32

.

d. Push the value

i32

.

const

(

𝑠

+

𝑛

1)

to the stack.

e. Execute the instruction

i32

.

load

8

_

u

{

offset

0

,

align

0

}

.

4.4. Instructions

111

f. Execute the instruction

i32

.

store

8

{

offset

0

,

align

0

}

.

g. Push the value

i32

.

const

𝑑

to the stack.

h. Push the value

i32

.

const

𝑠

to the stack.

16. Push the value

i32

.

const

(

𝑛

1)

to the stack.

17. Execute the instruction

memory

.

copy

.

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

)

memory

.

copy

˓

𝑆

;

𝐹

;

trap

(

if

𝑠

+

𝑛 >

|

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

𝑑

+

𝑛 >

|

𝑆.

mems

[

𝐹.

module

.

memaddrs

[0]]

.

data

|

)

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

0)

memory

.

copy

˓

𝑆

;

𝐹

;

𝜖

(

otherwise

)

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

+ 1)

memory

.

copy

˓

𝑆

;

𝐹

(

i32

.

const

𝑑

)

(

i32

.

const

𝑠

(

i32

.

load

8

_

u

{

offset

0

,

align

0

}

)

(

i32

.

store

8

{

offset

0

,

align

0

}

)

(

i32

.

const

𝑑

+ 1) (

i32

.

const

𝑠

+ 1) (

i32

.

const

𝑛

)

memory

.

copy

(

otherwise

,

if

𝑑

𝑠

)

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

+ 1)

memory

.

copy

˓

𝑆

;

𝐹

(

i32

.

const

𝑑

+

𝑛

1)

(

i32

.

const

𝑠

+

𝑛

1) (

i32

.

load

8

_

u

{

offset

0

,

align

0

}

)

(

i32

.

store

8

{

offset

0

,

align

0

}

)

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

)

memory

.

copy

(

otherwise

,

if

𝑑 > 𝑠

)

memory

.

init

𝑥

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

memaddrs

[0]

exists.

3. Let

ma

be the

memory address

𝐹.

module

.

memaddrs

[0]

.

4. Assert: due to

validation

,

𝑆.

mems

[

ma

]

exists.

5. Let

mem

be the

memory instance

𝑆.

mems

[

ma

]

.

6. Assert: due to

validation

,

𝐹.

module

.

dataaddrs

[

𝑥

]

exists.

7. Let

da

be the

data address

𝐹.

module

.

dataaddrs

[

𝑥

]

.

8. Assert: due to

validation

,

𝑆.

datas

[

da

]

exists.

9. Let

data

be the

data instance

𝑆.

datas

[

da

]

.

10. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

11. Pop the value

i32

.

const

𝑛

from the stack.

12. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

13. Pop the value

i32

.

const

𝑠

from the stack.

14. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

15. Pop the value

i32

.

const

𝑑

from the stack.

16. If

𝑠

+

𝑛

is larger than the length of

data

.

data

or

𝑑

+

𝑛

is larger than the length of

mem

.

data

then:

a. Trap.

17. If

𝑛

= 0

, then:

a. Return.

112

Chapter 4. Execution

18. Let

𝑏

be the byte

data

.

data

[

𝑠

]

.

19. Push the value

i32

.

const

𝑑

to the stack.

20. Push the value

i32

.

const

𝑏

to the stack.

21. Execute the instruction

i32

.

store

8

{

offset

0

,

align

0

}

.

22. Assert: due to the earlier check against the memory size,

𝑑

+ 1

<

2

32

.

23. Push the value

i32

.

const

(

𝑑

+ 1)

to the stack.

24. Assert: due to the earlier check against the memory size,

𝑠

+ 1

<

2

32

.

25. Push the value

i32

.

const

(

𝑠

+ 1)

to the stack.

26. Push the value

i32

.

const

(

𝑛

1)

to the stack.

27. Execute the instruction

memory

.

init

𝑥

.

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

(

memory

.

init

𝑥

)

˓

𝑆

;

𝐹

;

trap

(

if

𝑠

+

𝑛 >

|

𝑆.

datas

[

𝐹.

module

.

dataaddrs

[

𝑥

]]

.

data

|

𝑑

+

𝑛 >

|

𝑆.

mems

[

𝐹.

module

.

memaddrs

[

𝑥

]]

.

data

|

)

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

0) (

memory

.

init

𝑥

)

˓

𝑆

;

𝐹

;

𝜖

(

otherwise

)

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑠

(

i32

.

const

𝑛

+ 1) (

memory

.

init

𝑥

)

˓

𝑆

;

𝐹

(

i32

.

const

𝑑

(

i32

.

const

𝑏

(

i32

.

store

8

{

offset

0

,

align

0

}

)

(

i32

.

const

𝑑

+ 1) (

i32

.

const

𝑠

+ 1) (

i32

.

const

𝑛

(

memory

.

init

𝑥

)

(

otherwise

,

if

𝑏

=

𝑆.

datas

[

𝐹.

module

.

dataaddrs

[

𝑥

]]

.

data

[

𝑠

])

data

.

drop

𝑥

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

dataaddrs

[

𝑥

]

exists.

3. Let

𝑎

be the

data address

𝐹.

module

.

dataaddrs

[

𝑥

]

.

4. Assert: due to

validation

,

𝑆.

datas

[

𝑎

]

exists.

5. Replace

𝑆.

datas

[

𝑎

]

with the

data instance

{

data

𝜖

}

.

𝑆

;

𝐹

(

data

.

drop

𝑥

)

˓

𝑆

;

𝐹

;

𝜖

(

if

𝑆

=

𝑆

with

datas

[

𝐹.

module

.

dataaddrs

[

𝑥

]] =

{

data

𝜖

}

)

4.4.8 Control Instructions

nop

1. Do nothing.

nop

˓

𝜖

4.4. Instructions

113

unreachable

1. Trap.

unreachable

˓

trap

block

blocktype instr

*

end

1. Assert: due to

validation

,

expand

𝐹

(

blocktype

)

is defined.

2. Let

[

𝑡

𝑚

1

]

[

𝑡

𝑛

2

]

be the

function type

expand

𝐹

(

blocktype

)

.

3. Let

𝐿

be the label whose arity is

𝑛

and whose continuation is the end of the block.

4. Assert: due to

validation

there are at least

𝑚

values on the top of the stack.

5. Pop the values

val

𝑚

from the stack.

6.

Enter

the block

val

𝑚

instr

*

with label

𝐿

.

𝐹

;

val

𝑚

block

bt

instr

*

end

˓

𝐹

;

label

𝑛

{

𝜖

}

val

𝑚

instr

*

end

(

if

expand

𝐹

(

bt

) = [

𝑡

𝑚

1

]

[

𝑡

𝑛

2

])

loop

blocktype instr

*

end

1. Assert: due to

validation

,

expand

𝐹

(

blocktype

)

is defined.

2. Let

[

𝑡

𝑚

1

]

[

𝑡

𝑛

2

]

be the

function type

expand

𝐹

(

blocktype

)

.

3. Let

𝐿

be the label whose arity is

𝑚

and whose continuation is the start of the loop.

4. Assert: due to

validation

there are at least

𝑚

values on the top of the stack.

5. Pop the values

val

𝑚

from the stack.

6.

Enter

the block

val

𝑚

instr

*

with label

𝐿

.

𝐹

;

val

𝑚

loop

bt

instr

*

end

˓

𝐹

;

label

𝑚

{

loop

bt

instr

*

end

}

val

𝑚

instr

*

end

(

if

expand

𝐹

(

bt

) = [

𝑡

𝑚

1

]

[

𝑡

𝑛

2

])

if

blocktype instr

*

1

else

instr

*

2

end

1. Assert: due to

validation

,

expand

𝐹

(

blocktype

)

is defined.

2. Let

[

𝑡

𝑚

1

]

[

𝑡

𝑛

2

]

be the

function type

expand

𝐹

(

blocktype

)

.

3. Let

𝐿

be the label whose arity is

𝑛

and whose continuation is the end of the

if

instruction.

4. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

5. Pop the value

i32

.

const

𝑐

from the stack.

6. Assert: due to

validation

there are at least

𝑚

values on the top of the stack.

7. Pop the values

val

𝑚

from the stack.

8. If

𝑐

is non-zero, then:

a.

Enter

the block

val

𝑚

instr

*

1

with label

𝐿

.

9. Else:

a.

Enter

the block

val

𝑚

instr

*

2

with label

𝐿

.

114

Chapter 4. Execution

𝐹

;

val

𝑚

(

i32

.

const

𝑐

)

if

bt

instr

*

1

else

instr

*

2

end

˓

𝐹

;

label

𝑛

{

𝜖

}

val

𝑚

instr

*

1

end

(

if

𝑐

̸

= 0

expand

𝐹

(

bt

) = [

𝑡

𝑚

1

]

[

𝑡

𝑛

2

])

𝐹

;

val

𝑚

(

i32

.

const

𝑐

)

if

bt

instr

*

1

else

instr

*

2

end

˓

𝐹

;

label

𝑛

{

𝜖

}

val

𝑚

instr

*

2

end

(

if

𝑐

= 0

expand

𝐹

(

bt

) = [

𝑡

𝑚

1

]

[

𝑡

𝑛

2

])

br

𝑙

1. Assert: due to

validation

the stack contains at least

𝑙

+ 1

labels.

2. Let

𝐿

be the

𝑙

-th label appearing on the stack, starting from the top and counting from zero.

3. Let

𝑛

be the arity of

𝐿

.

4. Assert: due to

validation

there are at least

𝑛

values on the top of the stack.

5. Pop the values

val

𝑛

from the stack.

6. Repeat

𝑙

+ 1

times:

a. While the top of the stack is a value, do:

i. Pop the value from the stack.

b. Assert: due to

validation

the top of the stack now is a label.

c. Pop the label from the stack.

7. Push the values

val

𝑛

to the stack.

8. Jump to the continuation of

𝐿

.

label

𝑛

{

instr

*

}

𝐵

𝑙

[

val

𝑛

(

br

𝑙

)]

end

˓

val

𝑛

instr

*

br

_

if

𝑙

1. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

2. Pop the value

i32

.

const

𝑐

from the stack.

3. If

𝑐

is non-zero, then:

a.

Execute

the instruction

(

br

𝑙

)

.

4. Else:

a. Do nothing.

(

i32

.

const

𝑐

(

br

_

if

𝑙

)

˓

(

br

𝑙

)

(

if

𝑐

̸

= 0)

(

i32

.

const

𝑐

(

br

_

if

𝑙

)

˓

𝜖

(

if

𝑐

= 0)

br

_

table

𝑙

*

𝑙

𝑁

1. Assert: due to

validation

a value of

value type

i32

is on the top of the stack.

2. Pop the value

i32

.

const

𝑖

from the stack.

3. If

𝑖

is smaller than the length of

𝑙

*

, then:

a. Let

𝑙

𝑖

be the label

𝑙

*

[

𝑖

]

.

b.

Execute

the instruction

(

br

𝑙

𝑖

)

.

4. Else:

a.

Execute

the instruction

(

br

𝑙

𝑁

)

.

4.4. Instructions

115

(

i32

.

const

𝑖

(

br

_

table

𝑙

*

𝑙

𝑁

)

˓

(

br

𝑙

𝑖

)

(

if

𝑙

*

[

𝑖

] =

𝑙

𝑖

)

(

i32

.

const

𝑖

(

br

_

table

𝑙

*

𝑙

𝑁

)

˓

(

br

𝑙

𝑁

)

(

if

|

𝑙

*

| ≤

𝑖

)

return

1. Let

𝐹

be the

current frame

.

2. Let

𝑛

be the arity of

𝐹

.

3. Assert: due to

validation

there are at least

𝑛

values on the top of the stack.

4. Pop the results

val

𝑛

from the stack.

5. Assert: due to

validation

the stack contains at least one

frame

.

6. While the top of the stack is not a frame, do:

a. Pop the top element from the stack.

7. Assert: the top of the stack is the frame

𝐹

.

8. Pop the frame from the stack.
9. Push

val

𝑛

to the stack.

10. Jump to the instruction after the original call that pushed the frame.

frame

𝑛

{

𝐹

}

𝐵

𝑘

[

val

𝑛

return

]

end

˓

val

𝑛

call

𝑥

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

funcaddrs

[

𝑥

]

exists.

3. Let

𝑎

be the

function address

𝐹.

module

.

funcaddrs

[

𝑥

]

.

4.

Invoke

the function instance at address

𝑎

.

𝐹

(

call

𝑥

)

˓

𝐹

(

invoke

𝑎

)

(

if

𝐹.

module

.

funcaddrs

[

𝑥

] =

𝑎

)

call

_

indirect

𝑥 𝑦

1. Let

𝐹

be the

current frame

.

2. Assert: due to

validation

,

𝐹.

module

.

tableaddrs

[

𝑥

]

exists.

3. Let

ta

be the

table address

𝐹.

module

.

tableaddrs

[

𝑥

]

.

4. Assert: due to

validation

,

𝑆.

tables

[

ta

]

exists.

5. Let

tab

be the

table instance

𝑆.

tables

[

ta

]

.

6. Assert: due to

validation

,

𝐹.

module

.

types

[

𝑦

]

exists.

7. Let

ft

expect

be the

function type

𝐹.

module

.

types

[

𝑦

]

.

8. Assert: due to

validation

a value with

value type

i32

is on the top of the stack.

9. Pop the value

i32

.

const

𝑖

from the stack.

10. If

𝑖

is not smaller than the length of

tab

.

elem

then:

a. Trap.

11. Let

𝑟

be the

reference

tab

.

elem

[

𝑖

]

.

12. If

𝑟

is

ref

.

null

𝑡

, then:

116

Chapter 4. Execution

a. Trap.

13. Assert: due to

validation of table mutation

,

𝑟

is a

function reference

.

14. Let

ref

𝑎

be the

function reference

𝑟

.

15. Assert: due to

validation of table mutation

,

𝑆.

funcs

[

𝑎

]

exists.

16. Let

f

be the

function instance

𝑆.

funcs

[

𝑎

]

.

17. Let

ft

actual

be the

function type

f

.

type

.

18. If

ft

actual

and

ft

expect

differ, then:

a. Trap.

19.

Invoke

the function instance at address

𝑎

.

𝑆

;

𝐹

(

i32

.

const

𝑖

(

call

_

indirect

𝑥 𝑦

)

˓

𝑆

;

𝐹

(

invoke

𝑎

)

(

if

𝑆.

tables

[

𝐹.

module

.

tableaddrs

[

𝑥

]]

.

elem

[

𝑖

=

ref

𝑎

𝑆.

funcs

[

𝑎

] =

𝑓

𝐹.

module

.

types

[

𝑦

] =

𝑓.

type

)

𝑆

;

𝐹

(

i32

.

const

𝑖

(

call

_

indirect

𝑥 𝑦

)

˓

𝑆

;

𝐹

;

trap

(

otherwise

)

4.4.9 Blocks

The following auxiliary rules define the semantics of executing an

instruction sequence

that forms a

block

.

Entering

instr

*

with label

𝐿

1. Push

𝐿

to the stack.

2. Jump to the start of the instruction sequence

instr

*

.

Note:

No formal reduction rule is needed for entering an instruction sequence, because the label

𝐿

is embedded

in the

administrative instruction

that structured control instructions reduce to directly.

Exiting

instr

*

with label

𝐿

When the end of a block is reached without a jump or trap aborting it, then the following steps are performed.

1. Let

𝑚

be the number of values on the top of the stack.

2. Pop the values

val

𝑚

from the stack.

3. Assert: due to

validation

the label

𝐿

is now on the top of the stack.

4. Pop the label from the stack.
5. Push

val

𝑚

back to the stack.

6. Jump to the position after the

end

of the

structured control instruction

associated with the label

𝐿

.

label

𝑛

{

instr

*

}

val

𝑚

end

˓

val

𝑚

Note:

This semantics also applies to the instruction sequence contained in a

loop

instruction. Therefore, execution

of a loop falls off the end, unless a backwards branch is performed explicitly.

4.4. Instructions

117

4.4.10 Function Calls

The following auxiliary rules define the semantics of invoking a

function instance

through one of the

call instruc-

tions

and returning from it.

Invocation of function address

𝑎

1. Assert: due to

validation

,

𝑆.

funcs

[

𝑎

]

exists.

2. Let

𝑓

be the

function instance

,

𝑆.

funcs

[

𝑎

]

.

3. Let

[

𝑡

𝑛

1

]

[

𝑡

𝑚

2

]

be the

function type

𝑓.

type

.

4. Let

𝑡

*

be the list of

value types

𝑓.

code

.

locals

.

5. Let

instr

*

end

be the

expression

𝑓.

code

.

body

.

6. Assert: due to

validation

,

𝑛

values are on the top of the stack.

7. Pop the values

val

𝑛

from the stack.

8. Let

val

*

0

be the list of zero values of types

𝑡

*

.

9. Let

𝐹

be the

frame

{

module

𝑓.

module

,

locals

val

𝑛

(

default

𝑡

)

*

}

.

10. Push the activation of

𝐹

with arity

𝑚

to the stack.

11. Let

𝐿

be the

label

whose arity is

𝑚

and whose continuation is the end of the function.

12.

Enter

the instruction sequence

instr

*

with label

𝐿

.

𝑆

;

val

𝑛

(

invoke

𝑎

)

˓

𝑆

;

frame

𝑚

{

𝐹

}

label

𝑚

{}

instr

*

end end

(

if

𝑆.

funcs

[

𝑎

] =

𝑓

𝑓.

type

= [

𝑡

𝑛

1

]

[

𝑡

𝑚

2

]

𝑓.

code

=

{

type

𝑥,

locals

𝑡

𝑘

,

body

instr

*

end

}

𝐹

=

{

module

𝑓.

module

,

locals

val

𝑛

(

default

𝑡

)

𝑘

}

)

Returning from a function

When the end of a function is reached without a jump (i.e.,

return

or trap aborting it, then the following steps are

performed.

1. Let

𝐹

be the

current frame

.

2. Let

𝑛

be the arity of the activation of

𝐹

.

3. Assert: due to

validation

there are

𝑛

values on the top of the stack.

4. Pop the results

val

𝑛

from the stack.

5. Assert: due to

validation

the frame

𝐹

is now on the top of the stack.

6. Pop the frame from the stack.
7. Push

val

𝑛

back to the stack.

8. Jump to the instruction after the original call.

frame

𝑛

{

𝐹

}

val

𝑛

end

˓

val

𝑛

118

Chapter 4. Execution

 

 

 

 

 

 

 

Content      ..     7      8      9      10     ..