authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-02-05 23:23:07+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-03-22 19:56:35+01:00
log803f9e5dd02afc36014c292f3ebcf7ea5cd065ee
tree61855f9e44445be4cd0d68716bd2dd4c10508f86
parent3b48ea874ed4d0231a080ed583c7740478e58ed8
signaturelock-open Commit is signed but in an unrecognized format.

Implement more instructions for more control flow support


1 files changed, 41 insertions(+), 3 deletions(-)

src/codegen/wasm.zig+41-3
...@@ -95,7 +95,7 @@ pub const Context = struct {...@@ -95,7 +95,7 @@ pub const Context = struct {
95 return switch (ty.tag()) {95 return switch (ty.tag()) {
96 .f32 => wasm.valtype(.f32),96 .f32 => wasm.valtype(.f32),
97 .f64 => wasm.valtype(.f64),97 .f64 => wasm.valtype(.f64),
98 .u32, .i32 => wasm.valtype(.i32),98 .u32, .i32, .bool => wasm.valtype(.i32),
99 .u64, .i64 => wasm.valtype(.i64),99 .u64, .i64 => wasm.valtype(.i64),
100 else => self.fail(src, "TODO - Wasm genValtype for type '{s}'", .{ty.tag()}),100 else => self.fail(src, "TODO - Wasm genValtype for type '{s}'", .{ty.tag()}),
101 };101 };
...@@ -207,6 +207,7 @@ pub const Context = struct {...@@ -207,6 +207,7 @@ pub const Context = struct {
207 .add => self.genAdd(inst.castTag(.add).?),207 .add => self.genAdd(inst.castTag(.add).?),
208 .alloc => self.genAlloc(inst.castTag(.alloc).?),208 .alloc => self.genAlloc(inst.castTag(.alloc).?),
209 .arg => self.genArg(inst.castTag(.arg).?),209 .arg => self.genArg(inst.castTag(.arg).?),
210 .breakpoint => self.genBreakpoint(inst.castTag(.breakpoint).?),
210 .block => self.genBlock(inst.castTag(.block).?),211 .block => self.genBlock(inst.castTag(.block).?),
211 .br => self.genBr(inst.castTag(.br).?),212 .br => self.genBr(inst.castTag(.br).?),
212 .call => self.genCall(inst.castTag(.call).?),213 .call => self.genCall(inst.castTag(.call).?),
...@@ -221,9 +222,11 @@ pub const Context = struct {...@@ -221,9 +222,11 @@ pub const Context = struct {
221 .dbg_stmt => WValue.none,222 .dbg_stmt => WValue.none,
222 .load => self.genLoad(inst.castTag(.load).?),223 .load => self.genLoad(inst.castTag(.load).?),
223 .loop => self.genLoop(inst.castTag(.loop).?),224 .loop => self.genLoop(inst.castTag(.loop).?),
225 .not => self.genNot(inst.castTag(.not).?),
224 .ret => self.genRet(inst.castTag(.ret).?),226 .ret => self.genRet(inst.castTag(.ret).?),
225 .retvoid => WValue.none,227 .retvoid => WValue.none,
226 .store => self.genStore(inst.castTag(.store).?),228 .store => self.genStore(inst.castTag(.store).?),
229 .unreach => self.genUnreachable(inst.castTag(.unreach).?),
227 else => self.fail(inst.src, "TODO: Implement wasm inst: {s}", .{inst.tag}),230 else => self.fail(inst.src, "TODO: Implement wasm inst: {s}", .{inst.tag}),
228 };231 };
229 }232 }
...@@ -329,7 +332,7 @@ pub const Context = struct {...@@ -329,7 +332,7 @@ pub const Context = struct {
329 try writer.writeByte(wasm.opcode(.i32_const));332 try writer.writeByte(wasm.opcode(.i32_const));
330 try leb.writeILEB128(writer, inst.val.toUnsignedInt());333 try leb.writeILEB128(writer, inst.val.toUnsignedInt());
331 },334 },
332 .i32 => {335 .i32, .bool => {
333 try writer.writeByte(wasm.opcode(.i32_const));336 try writer.writeByte(wasm.opcode(.i32_const));
334 try leb.writeILEB128(writer, inst.val.toSignedInt());337 try leb.writeILEB128(writer, inst.val.toSignedInt());
335 },338 },
...@@ -414,7 +417,14 @@ pub const Context = struct {...@@ -414,7 +417,14 @@ pub const Context = struct {
414417
415 // insert blocks at the position of `offset` so418 // insert blocks at the position of `offset` so
416 // the condition can jump to it419 // the condition can jump to it
417 const offset = condition.code_offset;420 const offset = switch (condition) {
421 .code_offset => |offset| offset,
422 else => blk: {
423 const offset = self.code.items.len;
424 try self.emitWValue(condition);
425 break :blk offset;
426 },
427 };
418 const block_ty = try self.genBlockType(condbr.base.src, condbr.base.ty);428 const block_ty = try self.genBlockType(condbr.base.src, condbr.base.ty);
419 try self.startBlock(.block, block_ty, offset);429 try self.startBlock(.block, block_ty, offset);
420430
...@@ -523,4 +533,32 @@ pub const Context = struct {...@@ -523,4 +533,32 @@ pub const Context = struct {
523533
524 return .none;534 return .none;
525 }535 }
536
537 fn genNot(self: *Context, not: *Inst.UnOp) InnerError!WValue {
538 const offset = self.code.items.len;
539
540 const operand = self.resolveInst(not.operand);
541 try self.emitWValue(operand);
542
543 // wasm does not have booleans nor the `not` instruction, therefore compare with 0
544 // to create the same logic
545 const writer = self.code.writer();
546 try writer.writeByte(wasm.opcode(.i32_const));
547 try leb.writeILEB128(writer, @as(i32, 0));
548
549 try self.code.append(wasm.opcode(.i32_ne));
550
551 return WValue{ .code_offset = offset };
552 }
553
554 fn genBreakpoint(self: *Context, breakpoint: *Inst.NoOp) InnerError!WValue {
555 // unsupported by wasm itself. Can be implemented once we support DWARF
556 // for wasm
557 return .none;
558 }
559
560 fn genUnreachable(self: *Context, unreach: *Inst.NoOp) InnerError!WValue {
561 try self.code.append(wasm.opcode(.@"unreachable"));
562 return .none;
563 }
526};564};