blob: 3d682dbacad7972c14eff23499aa482e544556b8 (
about) (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
;; The idea is - we have 4 blocks, one inside another. We enter subsequent
;; blocks (how many we enter, depends on $blockfun's first arg) and then we
;; start leaving them. We "normally" (e.g. without br) exit some blocks (number
;; depending on $blockfun's 2nd arg) and then we break out of the outermost one
;; with the use of br_if.
;; When making this "path" through blocks, we also construct a result value.
;; The result value is initially 0 and upon each "normal" exit from a block,
;; one bit is being set to 1 in the result. Which bit is set, depends on the
;; block being left. Block 1 sets bit 0, block 2 sets bit 1, etc.
;; So, the entire function actually computes an integer with bits a1-a2 through
;; a1 set, with a1 and a2 being arguments to the function.
;; To keep things simple, we limit this to 4 block and 4 bits, that can be set
(module
(memory 0 1)
(func $blockfun
(param $blocks_to_enter i32)
(param $ones_to_set i32)
(result i32)
i32.const 0 ;; initial result value
get_local $blocks_to_enter
i32.const 0
i32.eq
br_if 0 ;; if number of blocks to enter is 0 - just return
block $b1 (param i32) (result i32)
get_local $blocks_to_enter
i32.const 1
i32.sub
set_local $blocks_to_enter
get_local $blocks_to_enter
if (param i32) (result i32)
block $b2 (param i32) (result i32)
get_local $blocks_to_enter
i32.const 1
i32.sub
set_local $blocks_to_enter
get_local $blocks_to_enter
if (param i32) (result i32)
block $b3 (param i32) (result i32)
get_local $blocks_to_enter
i32.const 1
i32.sub
set_local $blocks_to_enter
get_local $blocks_to_enter
if (param i32) (result i32)
block $b4 (param i32) (result i32)
get_local $ones_to_set
i32.const 0
i32.eq
br_if $b1
get_local $ones_to_set
i32.const 1
i32.sub
set_local $ones_to_set
i32.const 8 ;; block $b4 adds (1 << 3) to the result
i32.add
end
end
get_local $ones_to_set
i32.const 0
i32.eq
br_if $b1
get_local $ones_to_set
i32.const 1
i32.sub
set_local $ones_to_set
i32.const 4 ;; block $b3 adds (1 << 2) to the result
i32.add
end
end
get_local $ones_to_set
i32.const 0
i32.eq
br_if $b1
get_local $ones_to_set
i32.const 1
i32.sub
set_local $ones_to_set
i32.const 2 ;; block $b2 adds (1 << 1) to the result
i32.add
end
end
get_local $ones_to_set
i32.const 0
i32.eq
br_if $b1
get_local $ones_to_set
i32.const 1
i32.sub
set_local $ones_to_set
i32.const 1 ;; block $b1 adds (1 << 0) to the result
i32.add
end)
(func $main
(i32.store offset=0x0 align=4 (i32.const 0x0)
(call $blockfun (i32.const 4) (i32.const 2)))
(i32.store offset=0x0 align=4 (i32.const 0x4)
(call $blockfun (i32.const 3) (i32.const 2)))
(i32.store offset=0x0 align=4 (i32.const 0x8)
(call $blockfun (i32.const 2) (i32.const 0)))
(i32.store offset=0x0 align=4 (i32.const 0xC)
(call $blockfun (i32.const 4) (i32.const 4)))
)
(export "main" (func $main)))
|