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