@@ -218,66 +218,97 @@ Function[] decodeCodeSection(ref const(ubyte)[] input)
218
218
const count = input.leb128! uint ();
219
219
foreach (_; 0 .. count)
220
220
{
221
- input.leb128! uint (); // size
222
- functions ~= input.decodeFunctionBody();
221
+ auto size = input.leb128! uint (); // func body size
222
+ functions ~= input.decodeFunctionBody(size );
223
223
}
224
224
return functions;
225
225
}
226
226
227
227
// /
228
- Function decodeFunctionBody (ref const (ubyte )[] input)
228
+ Function decodeFunctionBody (ref const (ubyte )[] input, ref uint remaining )
229
229
{
230
230
Function body ;
231
231
const count = input.leb128! uint ();
232
+ remaining-- ;
232
233
foreach (_; 0 .. count)
233
234
{
234
235
auto typeCount = input.leb128! uint ();
236
+ remaining-- ;
235
237
auto valueType = input.decodeValueSection();
238
+ remaining-- ;
236
239
body .locals ~= FunctionLocal(typeCount, valueType);
237
240
}
238
241
239
- // FIXME: 命令だけconsumeするようにしないといけない
240
- while (input.length)
242
+ while (remaining > 0 )
241
243
{
242
- auto instruction = input.decodeInstruction();
244
+ auto instruction = input.decodeInstruction(remaining );
243
245
body .code ~= instruction;
244
- if (instruction.isEndInstruction())
245
- {
246
- break ;
247
- }
248
246
}
249
247
return body ;
250
248
}
251
249
252
250
// /
253
- Instruction decodeInstruction (ref const (ubyte )[] input)
251
+ Instruction decodeInstruction (ref const (ubyte )[] input, ref uint remaining )
254
252
{
255
253
auto op = cast (OpCode) input.read! ubyte ();
254
+ remaining-- ;
256
255
switch (op)
257
256
{
257
+ case OpCode.If:
258
+ auto block = input.decodeBlockSection(remaining);
259
+ return Instruction (If(block));
260
+ case OpCode.Return:
261
+ return Instruction (Return());
258
262
case OpCode.LocalGet:
259
263
auto idx = input.leb128! uint ();
264
+ remaining-- ;
260
265
return Instruction (LocalGet(idx));
261
266
case OpCode.LocalSet:
262
267
auto idx = input.leb128! uint ();
268
+ remaining-- ;
263
269
return Instruction (LocalSet(idx));
264
270
case OpCode.I32Store:
265
271
auto align_ = input.leb128! uint ();
266
272
auto offset = input.leb128! uint ();
273
+ remaining -= 2 ;
267
274
return Instruction (I32Store(align_, offset));
268
275
case OpCode.I32Const:
269
276
auto value = input.leb128! int ();
277
+ remaining-- ;
270
278
return Instruction (I32Const(value));
279
+ case OpCode.I32LtS:
280
+ return Instruction (I32LtS());
271
281
case OpCode.I32Add:
272
282
return Instruction (I32Add());
283
+ case OpCode.I32Sub:
284
+ return Instruction (I32Sub());
273
285
case OpCode.End:
274
286
return Instruction (End());
275
287
case OpCode.Call:
276
288
auto idx = input.leb128! uint ();
289
+ remaining-- ;
277
290
return Instruction (Call(idx));
278
291
default :
279
- assert (false , " invalid opcode" );
292
+ import std.format : format;
293
+ assert (false , op.format! " invalid opcode: %d" ());
294
+ }
295
+ }
296
+
297
+ // /
298
+ Block decodeBlockSection (ref const (ubyte )[] input, ref uint remaining)
299
+ {
300
+ const mark = input.read! ubyte ();
301
+ remaining-- ;
302
+ BlockType blockType;
303
+ if (mark == 0x40 )
304
+ {
305
+ blockType = BlockType(Void());
306
+ }
307
+ else
308
+ {
309
+ blockType = BlockType([cast (ValueType) mark]);
280
310
}
311
+ return Block (blockType: blockType);
281
312
}
282
313
283
314
// /
@@ -604,3 +635,59 @@ unittest
604
635
assert (actual == expected);
605
636
}
606
637
}
638
+
639
+ @(" decode fib" )
640
+ unittest
641
+ {
642
+ import std.process ;
643
+ const p = executeShell(" wasm-tools parse source/fixtures/fib.wat" );
644
+ const (ubyte )[] wasm = cast (ubyte []) p.output;
645
+ const actual = decodeModule(wasm);
646
+ const Module expected = {
647
+ magic: [' \0 ' , ' a' , ' s' , ' m' ],
648
+ version _: 1 ,
649
+ typeSection: [
650
+ {
651
+ params: [ValueType.I32 ],
652
+ results: [ValueType.I32 ]
653
+ }
654
+ ],
655
+ functionSection: [0 ],
656
+ codeSection: [
657
+ {
658
+ locals: [],
659
+ code: [
660
+ Instruction(LocalGet(0 )),
661
+ Instruction(I32Const(2 )),
662
+ Instruction(I32LtS()),
663
+ Instruction(
664
+ If(Block(BlockType(Void())))
665
+ ),
666
+ Instruction(I32Const(1 )),
667
+ Instruction(Return()),
668
+ Instruction(End()),
669
+ Instruction(LocalGet(0 )),
670
+ Instruction(I32Const(2 )),
671
+ Instruction(I32Sub()),
672
+ Instruction(Call(0 )),
673
+ Instruction(LocalGet(0 )),
674
+ Instruction(I32Const(1 )),
675
+ Instruction(I32Sub()),
676
+ Instruction(Call(0 )),
677
+ Instruction(I32Add()),
678
+ Instruction(Return()),
679
+ Instruction(End())
680
+ ]
681
+ }
682
+ ]
683
+ ,
684
+ exportSection: [
685
+ Export(
686
+ name: " fib" ,
687
+ desc: ExportDesc (Func(0 )),
688
+ )
689
+ ],
690
+ importSection: []
691
+ };
692
+ assert (actual == expected);
693
+ }
0 commit comments