1 #include <assert.h>
2 #include <stdio.h>
3
4 #include "binaryen-c.h"
5
6 // globals: address 4 is index
7 // decisions are at address 8+
8
main()9 int main() {
10 BinaryenModuleRef module = BinaryenModuleCreate();
11
12 // check()
13
14 // if the end, halt
15 BinaryenExpressionRef halter = BinaryenIf(module,
16 BinaryenBinary(module,
17 BinaryenGeUInt32(),
18 BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(),
19 BinaryenConst(module, BinaryenLiteralInt32(4))),
20 BinaryenConst(module, BinaryenLiteralInt32(4 * 12)) // jumps of 4 bytes
21 ),
22 BinaryenUnreachable(module),
23 NULL
24 );
25 // increment index
26 BinaryenExpressionRef incer = BinaryenStore(module,
27 4, 0, 0,
28 BinaryenConst(module, BinaryenLiteralInt32(4)),
29 BinaryenBinary(module,
30 BinaryenAddInt32(),
31 BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(),
32 BinaryenConst(module, BinaryenLiteralInt32(4))),
33 BinaryenConst(module, BinaryenLiteralInt32(4))
34 ),
35 BinaryenTypeInt32()
36 );
37
38 // optionally, print the return value
39 BinaryenExpressionRef args[] = {
40 BinaryenBinary(module,
41 BinaryenSubInt32(),
42 BinaryenConst(module, BinaryenLiteralInt32(0)),
43 BinaryenLoad(module,
44 4, 0, 4, 0, BinaryenTypeInt32(),
45 BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(),
46 BinaryenConst(module, BinaryenLiteralInt32(4)))
47 )
48 )
49 };
50 BinaryenExpressionRef debugger;
51 if (1) debugger = BinaryenCall(module, "print", args, 1,
52 BinaryenTypeNone());
53 else debugger = BinaryenNop(module);
54
55 // return the decision. need to subtract 4 that we just added,
56 // and add 8 since that's where we start, so overall offset 4
57 BinaryenExpressionRef returner = BinaryenLoad(module,
58 4, 0, 4, 0, BinaryenTypeInt32(),
59 BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(),
60 BinaryenConst(module, BinaryenLiteralInt32(4)))
61 );
62 BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger,
63 returner };
64 BinaryenExpressionRef checkBody = BinaryenBlock(module,
65 NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef),
66 BinaryenTypeInt32()
67 );
68 BinaryenAddFunction(module,
69 "check",
70 BinaryenTypeNone(),
71 BinaryenTypeInt32(),
72 NULL,
73 0,
74 checkBody);
75
76 // contents of main() begin here
77
78 RelooperRef relooper = RelooperCreate(module);
79
80
81 RelooperBlockRef b0;
82 {
83 BinaryenExpressionRef args[] = {
84 BinaryenConst(module, BinaryenLiteralInt32(0))
85 };
86 BinaryenExpressionRef list[] = {
87 BinaryenCall(module, "print", args, 1, BinaryenTypeNone()),
88 BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0,
89 BinaryenTypeInt32()))
90 };
91
92 b0 = RelooperAddBlockWithSwitch(relooper,
93 BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()),
94 BinaryenBinary(module,
95 BinaryenRemUInt32(),
96 BinaryenLocalGet(module, 0, BinaryenTypeInt32()),
97 BinaryenConst(module, BinaryenLiteralInt32(1))
98 )
99 );
100
101 }
102
103 RelooperBlockRef b1;
104 {
105 BinaryenExpressionRef args[] = {
106 BinaryenConst(module, BinaryenLiteralInt32(1))
107 };
108 BinaryenExpressionRef list[] = {
109 BinaryenCall(module, "print", args, 1, BinaryenTypeNone()),
110 BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0,
111 BinaryenTypeInt32()))
112 };
113
114 b1 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()));
115
116 }
117
118 RelooperBlockRef b2;
119 {
120 BinaryenExpressionRef args[] = {
121 BinaryenConst(module, BinaryenLiteralInt32(1))
122 };
123 BinaryenExpressionRef list[] = {
124 BinaryenCall(module, "print", args, 1, BinaryenTypeNone()),
125 BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0,
126 BinaryenTypeInt32()))
127 };
128
129 b2 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()));
130
131 }
132
133 RelooperBlockRef b3;
134 {
135 BinaryenExpressionRef args[] = {
136 BinaryenConst(module, BinaryenLiteralInt32(2))
137 };
138 BinaryenExpressionRef list[] = {
139 BinaryenCall(module, "print", args, 1, BinaryenTypeNone()),
140 BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0,
141 BinaryenTypeInt32()))
142 };
143
144 b3 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()));
145 }
146
147 RelooperBlockRef b4;
148 {
149 BinaryenExpressionRef args[] = {
150 BinaryenConst(module, BinaryenLiteralInt32(3))
151 };
152 BinaryenExpressionRef list[] = {
153 BinaryenCall(module, "print", args, 1, BinaryenTypeNone()),
154 BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0,
155 BinaryenTypeInt32()))
156 };
157
158 b4 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()));
159 }
160
161 // Separate branch for each.
162 // In this testcase, two blocks out of 4 can be merged.
163 RelooperAddBranchForSwitch(b0, b1, NULL, 0, NULL);
164 {
165 BinaryenIndex indexes[] = { 1, 4, 9 };
166 RelooperAddBranchForSwitch(b0, b4, indexes, 3, NULL);
167 }
168 {
169 BinaryenIndex indexes[] = { 3, 6 };
170 RelooperAddBranchForSwitch(b0, b2, indexes, 2, NULL);
171 }
172 {
173 BinaryenIndex indexes[] = { 5 };
174 RelooperAddBranchForSwitch(b0, b3, indexes, 1, NULL);
175 }
176
177 BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1);
178
179 // locals: state, free-for-label
180 BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32() };
181 BinaryenFunctionRef theMain = BinaryenAddFunction(module,
182 "main",
183 BinaryenTypeNone(),
184 BinaryenTypeNone(),
185 localTypes,
186 2,
187 body);
188 BinaryenSetStart(module, theMain);
189
190 // import
191 BinaryenAddFunctionImport(module,
192 "print",
193 "spectest",
194 "print",
195 BinaryenTypeInt32(),
196 BinaryenTypeNone());
197
198 // memory
199 BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0);
200
201 // optionally, optimize
202 if (0) BinaryenModuleOptimize(module);
203
204 assert(BinaryenModuleValidate(module));
205
206 // write it out
207
208 BinaryenModulePrint(module);
209
210 BinaryenModuleDispose(module);
211
212 return 0;
213 }
214