| ... | ... | @@ -95,7 +95,7 @@ pub const Context = struct { |
| 95 | 95 | return switch (ty.tag()) { |
| 96 | 96 | .f32 => wasm.valtype(.f32), |
| 97 | 97 | .f64 => wasm.valtype(.f64), |
| 98 | | .u32, .i32 => wasm.valtype(.i32), |
| 98 | .u32, .i32, .bool => wasm.valtype(.i32), |
| 99 | 99 | .u64, .i64 => wasm.valtype(.i64), |
| 100 | 100 | else => self.fail(src, "TODO - Wasm genValtype for type '{s}'", .{ty.tag()}), |
| 101 | 101 | }; |
| ... | ... | @@ -208,6 +208,7 @@ pub const Context = struct { |
| 208 | 208 | .alloc => self.genAlloc(inst.castTag(.alloc).?), |
| 209 | 209 | .arg => self.genArg(inst.castTag(.arg).?), |
| 210 | 210 | .block => self.genBlock(inst.castTag(.block).?), |
| 211 | .breakpoint => self.genBreakpoint(inst.castTag(.breakpoint).?), |
| 211 | 212 | .br => self.genBr(inst.castTag(.br).?), |
| 212 | 213 | .call => self.genCall(inst.castTag(.call).?), |
| 213 | 214 | .cmp_eq => self.genCmp(inst.castTag(.cmp_eq).?, .eq), |
| ... | ... | @@ -221,9 +222,11 @@ pub const Context = struct { |
| 221 | 222 | .dbg_stmt => WValue.none, |
| 222 | 223 | .load => self.genLoad(inst.castTag(.load).?), |
| 223 | 224 | .loop => self.genLoop(inst.castTag(.loop).?), |
| 225 | .not => self.genNot(inst.castTag(.not).?), |
| 224 | 226 | .ret => self.genRet(inst.castTag(.ret).?), |
| 225 | 227 | .retvoid => WValue.none, |
| 226 | 228 | .store => self.genStore(inst.castTag(.store).?), |
| 229 | .unreach => self.genUnreachable(inst.castTag(.unreach).?), |
| 227 | 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 | 332 | try writer.writeByte(wasm.opcode(.i32_const)); |
| 330 | 333 | try leb.writeILEB128(writer, inst.val.toUnsignedInt()); |
| 331 | 334 | }, |
| 332 | | .i32 => { |
| 335 | .i32, .bool => { |
| 333 | 336 | try writer.writeByte(wasm.opcode(.i32_const)); |
| 334 | 337 | try leb.writeILEB128(writer, inst.val.toSignedInt()); |
| 335 | 338 | }, |
| ... | ... | @@ -414,7 +417,14 @@ pub const Context = struct { |
| 414 | 417 | |
| 415 | 418 | // insert blocks at the position of `offset` so |
| 416 | 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 | 428 | const block_ty = try self.genBlockType(condbr.base.src, condbr.base.ty); |
| 419 | 429 | try self.startBlock(.block, block_ty, offset); |
| 420 | 430 | |
| ... | ... | @@ -523,4 +533,32 @@ pub const Context = struct { |
| 523 | 533 | |
| 524 | 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 writer.writeByte(wasm.opcode(.i32_eq)); |
| 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 | }; |