| ... | @@ -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 { |
| 414 | | 417 | |
| 415 | // insert blocks at the position of `offset` so | 418 | // insert blocks at the position of `offset` so |
| 416 | // the condition can jump to it | 419 | // 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); |
| 420 | | 430 | |
| ... | @@ -523,4 +533,32 @@ pub const Context = struct { | ... | @@ -523,4 +533,32 @@ pub const Context = struct { |
| 523 | | 533 | |
| 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 | }; |