| ... | @@ -25,7 +25,7 @@ const WValue = union(enum) { | ... | @@ -25,7 +25,7 @@ const WValue = union(enum) { |
| 25 | /// Index of the local variable | 25 | /// Index of the local variable |
| 26 | local: u32, | 26 | local: u32, |
| 27 | /// Instruction holding a constant `Value` | 27 | /// Instruction holding a constant `Value` |
| 28 | constant: *Inst, | 28 | constant: Air.Inst.Index, |
| 29 | /// Offset position in the list of bytecode instructions | 29 | /// Offset position in the list of bytecode instructions |
| 30 | code_offset: usize, | 30 | code_offset: usize, |
| 31 | /// Used for variables that create multiple locals on the stack when allocated | 31 | /// Used for variables that create multiple locals on the stack when allocated |
| ... | @@ -484,7 +484,7 @@ pub const Result = union(enum) { | ... | @@ -484,7 +484,7 @@ pub const Result = union(enum) { |
| 484 | }; | 484 | }; |
| 485 | | 485 | |
| 486 | /// Hashmap to store generated `WValue` for each `Inst` | 486 | /// Hashmap to store generated `WValue` for each `Inst` |
| 487 | pub const ValueTable = std.AutoHashMapUnmanaged(*Inst, WValue); | 487 | pub const ValueTable = std.AutoHashMapUnmanaged(Air.Inst.Index, WValue); |
| 488 | | 488 | |
| 489 | /// Code represents the `Code` section of wasm that | 489 | /// Code represents the `Code` section of wasm that |
| 490 | /// belongs to a function | 490 | /// belongs to a function |
| ... | @@ -497,8 +497,8 @@ pub const Context = struct { | ... | @@ -497,8 +497,8 @@ pub const Context = struct { |
| 497 | gpa: *mem.Allocator, | 497 | gpa: *mem.Allocator, |
| 498 | /// Table to save `WValue`'s generated by an `Inst` | 498 | /// Table to save `WValue`'s generated by an `Inst` |
| 499 | values: ValueTable, | 499 | values: ValueTable, |
| 500 | /// Mapping from *Inst.Block to block ids | 500 | /// Mapping from Air.Inst.Index to block ids |
| 501 | blocks: std.AutoArrayHashMapUnmanaged(*Inst.Block, u32) = .{}, | 501 | blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, u32) = .{}, |
| 502 | /// `bytes` contains the wasm bytecode belonging to the 'code' section. | 502 | /// `bytes` contains the wasm bytecode belonging to the 'code' section. |
| 503 | code: ArrayList(u8), | 503 | code: ArrayList(u8), |
| 504 | /// Contains the generated function type bytecode for the current function | 504 | /// Contains the generated function type bytecode for the current function |
| ... | @@ -538,7 +538,8 @@ pub const Context = struct { | ... | @@ -538,7 +538,8 @@ pub const Context = struct { |
| 538 | } | 538 | } |
| 539 | | 539 | |
| 540 | /// Sets `err_msg` on `Context` and returns `error.CodegemFail` which is caught in link/Wasm.zig | 540 | /// Sets `err_msg` on `Context` and returns `error.CodegemFail` which is caught in link/Wasm.zig |
| 541 | fn fail(self: *Context, src: LazySrcLoc, comptime fmt: []const u8, args: anytype) InnerError { | 541 | fn fail(self: *Context, comptime fmt: []const u8, args: anytype) InnerError { |
| | 542 | const src: LazySrcLoc = .{ .node_offset = 0 }; |
| 542 | const src_loc = src.toSrcLocWithDecl(self.decl); | 543 | const src_loc = src.toSrcLocWithDecl(self.decl); |
| 543 | self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, fmt, args); | 544 | self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, fmt, args); |
| 544 | return error.CodegenFail; | 545 | return error.CodegenFail; |
| ... | @@ -546,7 +547,7 @@ pub const Context = struct { | ... | @@ -546,7 +547,7 @@ pub const Context = struct { |
| 546 | | 547 | |
| 547 | /// Resolves the `WValue` for the given instruction `inst` | 548 | /// Resolves the `WValue` for the given instruction `inst` |
| 548 | /// When the given instruction has a `Value`, it returns a constant instead | 549 | /// When the given instruction has a `Value`, it returns a constant instead |
| 549 | fn resolveInst(self: Context, inst: *Inst) WValue { | 550 | fn resolveInst(self: Context, inst: Air.Inst) Index { |
| 550 | if (!inst.ty.hasCodeGenBits()) return .none; | 551 | if (!inst.ty.hasCodeGenBits()) return .none; |
| 551 | | 552 | |
| 552 | if (inst.value()) |_| { | 553 | if (inst.value()) |_| { |
| ... | @@ -557,48 +558,45 @@ pub const Context = struct { | ... | @@ -557,48 +558,45 @@ pub const Context = struct { |
| 557 | } | 558 | } |
| 558 | | 559 | |
| 559 | /// Using a given `Type`, returns the corresponding wasm Valtype | 560 | /// Using a given `Type`, returns the corresponding wasm Valtype |
| 560 | fn typeToValtype(self: *Context, src: LazySrcLoc, ty: Type) InnerError!wasm.Valtype { | 561 | fn typeToValtype(self: *Context, ty: Type) InnerError!wasm.Valtype { |
| 561 | return switch (ty.zigTypeTag()) { | 562 | return switch (ty.zigTypeTag()) { |
| 562 | .Float => blk: { | 563 | .Float => blk: { |
| 563 | const bits = ty.floatBits(self.target); | 564 | const bits = ty.floatBits(self.target); |
| 564 | if (bits == 16 or bits == 32) break :blk wasm.Valtype.f32; | 565 | if (bits == 16 or bits == 32) break :blk wasm.Valtype.f32; |
| 565 | if (bits == 64) break :blk wasm.Valtype.f64; | 566 | if (bits == 64) break :blk wasm.Valtype.f64; |
| 566 | return self.fail(src, "Float bit size not supported by wasm: '{d}'", .{bits}); | 567 | return self.fail("Float bit size not supported by wasm: '{d}'", .{bits}); |
| 567 | }, | 568 | }, |
| 568 | .Int => blk: { | 569 | .Int => blk: { |
| 569 | const info = ty.intInfo(self.target); | 570 | const info = ty.intInfo(self.target); |
| 570 | if (info.bits <= 32) break :blk wasm.Valtype.i32; | 571 | if (info.bits <= 32) break :blk wasm.Valtype.i32; |
| 571 | if (info.bits > 32 and info.bits <= 64) break :blk wasm.Valtype.i64; | 572 | if (info.bits > 32 and info.bits <= 64) break :blk wasm.Valtype.i64; |
| 572 | return self.fail(src, "Integer bit size not supported by wasm: '{d}'", .{info.bits}); | 573 | return self.fail("Integer bit size not supported by wasm: '{d}'", .{info.bits}); |
| 573 | }, | 574 | }, |
| 574 | .Enum => switch (ty.tag()) { | 575 | .Enum => switch (ty.tag()) { |
| 575 | .enum_simple => wasm.Valtype.i32, | 576 | .enum_simple => wasm.Valtype.i32, |
| 576 | else => self.typeToValtype( | 577 | else => self.typeToValtype(ty.cast(Type.Payload.EnumFull).?.data.tag_ty), |
| 577 | src, | | |
| 578 | ty.cast(Type.Payload.EnumFull).?.data.tag_ty, | | |
| 579 | ), | | |
| 580 | }, | 578 | }, |
| 581 | .Bool, | 579 | .Bool, |
| 582 | .Pointer, | 580 | .Pointer, |
| 583 | .ErrorSet, | 581 | .ErrorSet, |
| 584 | => wasm.Valtype.i32, | 582 | => wasm.Valtype.i32, |
| 585 | .Struct, .ErrorUnion => unreachable, // Multi typed, must be handled individually. | 583 | .Struct, .ErrorUnion => unreachable, // Multi typed, must be handled individually. |
| 586 | else => self.fail(src, "TODO - Wasm valtype for type '{s}'", .{ty.zigTypeTag()}), | 584 | else => self.fail("TODO - Wasm valtype for type '{s}'", .{ty.zigTypeTag()}), |
| 587 | }; | 585 | }; |
| 588 | } | 586 | } |
| 589 | | 587 | |
| 590 | /// Using a given `Type`, returns the byte representation of its wasm value type | 588 | /// Using a given `Type`, returns the byte representation of its wasm value type |
| 591 | fn genValtype(self: *Context, src: LazySrcLoc, ty: Type) InnerError!u8 { | 589 | fn genValtype(self: *Context, ty: Type) InnerError!u8 { |
| 592 | return wasm.valtype(try self.typeToValtype(src, ty)); | 590 | return wasm.valtype(try self.typeToValtype(ty)); |
| 593 | } | 591 | } |
| 594 | | 592 | |
| 595 | /// Using a given `Type`, returns the corresponding wasm value type | 593 | /// Using a given `Type`, returns the corresponding wasm value type |
| 596 | /// Differently from `genValtype` this also allows `void` to create a block | 594 | /// Differently from `genValtype` this also allows `void` to create a block |
| 597 | /// with no return type | 595 | /// with no return type |
| 598 | fn genBlockType(self: *Context, src: LazySrcLoc, ty: Type) InnerError!u8 { | 596 | fn genBlockType(self: *Context, ty: Type) InnerError!u8 { |
| 599 | return switch (ty.tag()) { | 597 | return switch (ty.tag()) { |
| 600 | .void, .noreturn => wasm.block_empty, | 598 | .void, .noreturn => wasm.block_empty, |
| 601 | else => self.genValtype(src, ty), | 599 | else => self.genValtype(ty), |
| 602 | }; | 600 | }; |
| 603 | } | 601 | } |
| 604 | | 602 | |
| ... | @@ -612,7 +610,7 @@ pub const Context = struct { | ... | @@ -612,7 +610,7 @@ pub const Context = struct { |
| 612 | try writer.writeByte(wasm.opcode(.local_get)); | 610 | try writer.writeByte(wasm.opcode(.local_get)); |
| 613 | try leb.writeULEB128(writer, idx); | 611 | try leb.writeULEB128(writer, idx); |
| 614 | }, | 612 | }, |
| 615 | .constant => |inst| try self.emitConstant(inst.src, inst.value().?, inst.ty), // creates a new constant onto the stack | 613 | .constant => |inst| try self.emitConstant(inst.value().?, inst.ty), // creates a new constant onto the stack |
| 616 | } | 614 | } |
| 617 | } | 615 | } |
| 618 | | 616 | |
| ... | @@ -682,7 +680,7 @@ pub const Context = struct { | ... | @@ -682,7 +680,7 @@ pub const Context = struct { |
| 682 | ty.fnParamTypes(params); | 680 | ty.fnParamTypes(params); |
| 683 | for (params) |param_type| { | 681 | for (params) |param_type| { |
| 684 | // Can we maybe get the source index of each param? | 682 | // Can we maybe get the source index of each param? |
| 685 | const val_type = try self.genValtype(.{ .node_offset = 0 }, param_type); | 683 | const val_type = try self.genValtype(param_type); |
| 686 | try writer.writeByte(val_type); | 684 | try writer.writeByte(val_type); |
| 687 | } | 685 | } |
| 688 | } | 686 | } |
| ... | @@ -691,13 +689,10 @@ pub const Context = struct { | ... | @@ -691,13 +689,10 @@ pub const Context = struct { |
| 691 | const return_type = ty.fnReturnType(); | 689 | const return_type = ty.fnReturnType(); |
| 692 | switch (return_type.zigTypeTag()) { | 690 | switch (return_type.zigTypeTag()) { |
| 693 | .Void, .NoReturn => try leb.writeULEB128(writer, @as(u32, 0)), | 691 | .Void, .NoReturn => try leb.writeULEB128(writer, @as(u32, 0)), |
| 694 | .Struct => return self.fail(.{ .node_offset = 0 }, "TODO: Implement struct as return type for wasm", .{}), | 692 | .Struct => return self.fail("TODO: Implement struct as return type for wasm", .{}), |
| 695 | .Optional => return self.fail(.{ .node_offset = 0 }, "TODO: Implement optionals as return type for wasm", .{}), | 693 | .Optional => return self.fail("TODO: Implement optionals as return type for wasm", .{}), |
| 696 | .ErrorUnion => { | 694 | .ErrorUnion => { |
| 697 | const val_type = try self.genValtype( | 695 | const val_type = try self.genValtype(return_type.errorUnionChild()); |
| 698 | .{ .node_offset = 0 }, | | |
| 699 | return_type.errorUnionChild(), | | |
| 700 | ); | | |
| 701 | | 696 | |
| 702 | // write down the amount of return values | 697 | // write down the amount of return values |
| 703 | try leb.writeULEB128(writer, @as(u32, 2)); | 698 | try leb.writeULEB128(writer, @as(u32, 2)); |
| ... | @@ -707,22 +702,21 @@ pub const Context = struct { | ... | @@ -707,22 +702,21 @@ pub const Context = struct { |
| 707 | else => { | 702 | else => { |
| 708 | try leb.writeULEB128(writer, @as(u32, 1)); | 703 | try leb.writeULEB128(writer, @as(u32, 1)); |
| 709 | // Can we maybe get the source index of the return type? | 704 | // Can we maybe get the source index of the return type? |
| 710 | const val_type = try self.genValtype(.{ .node_offset = 0 }, return_type); | 705 | const val_type = try self.genValtype(return_type); |
| 711 | try writer.writeByte(val_type); | 706 | try writer.writeByte(val_type); |
| 712 | }, | 707 | }, |
| 713 | } | 708 | } |
| 714 | } | 709 | } |
| 715 | | 710 | |
| 716 | pub fn genFunc(self: *Context, func: *Module.Fn) InnerError!Result { | 711 | pub fn genFunc(self: *Context, func: *Module.Fn) InnerError!Result { |
| | 712 | _ = func; |
| 717 | try self.genFunctype(); | 713 | try self.genFunctype(); |
| 718 | | | |
| 719 | // Write instructions | | |
| 720 | // TODO: check for and handle death of instructions | 714 | // TODO: check for and handle death of instructions |
| 721 | | 715 | |
| 722 | // Reserve space to write the size after generating the code as well as space for locals count | 716 | // Reserve space to write the size after generating the code as well as space for locals count |
| 723 | try self.code.resize(10); | 717 | try self.code.resize(10); |
| 724 | | 718 | |
| 725 | try self.genBody(func.body); | 719 | try self.genBody(self.air.getMainBody()); |
| 726 | | 720 | |
| 727 | // finally, write our local types at the 'offset' position | 721 | // finally, write our local types at the 'offset' position |
| 728 | { | 722 | { |
| ... | @@ -753,7 +747,7 @@ pub const Context = struct { | ... | @@ -753,7 +747,7 @@ pub const Context = struct { |
| 753 | return Result.appended; | 747 | return Result.appended; |
| 754 | } | 748 | } |
| 755 | | 749 | |
| 756 | /// Generates the wasm bytecode for the function declaration belonging to `Context` | 750 | /// Generates the wasm bytecode for the declaration belonging to `Context` |
| 757 | pub fn gen(self: *Context, typed_value: TypedValue) InnerError!Result { | 751 | pub fn gen(self: *Context, typed_value: TypedValue) InnerError!Result { |
| 758 | switch (typed_value.ty.zigTypeTag()) { | 752 | switch (typed_value.ty.zigTypeTag()) { |
| 759 | .Fn => { | 753 | .Fn => { |
| ... | @@ -793,58 +787,59 @@ pub const Context = struct { | ... | @@ -793,58 +787,59 @@ pub const Context = struct { |
| 793 | } | 787 | } |
| 794 | } | 788 | } |
| 795 | | 789 | |
| 796 | fn genInst(self: *Context, inst: *Inst) InnerError!WValue { | 790 | fn genInst(self: *Context, inst: Air.Inst.Index) !WValue { |
| 797 | return switch (inst.tag) { | 791 | const air_tags = self.air.instructions.items(.tag); |
| 798 | .add => self.genBinOp(inst.castTag(.add).?, .add), | 792 | return switch (air_tags[inst]) { |
| 799 | .alloc => self.genAlloc(inst.castTag(.alloc).?), | 793 | // .add => self.genBinOp(inst.castTag(.add).?, .add), |
| 800 | .arg => self.genArg(inst.castTag(.arg).?), | 794 | // .alloc => self.genAlloc(inst.castTag(.alloc).?), |
| 801 | .bit_and => self.genBinOp(inst.castTag(.bit_and).?, .@"and"), | 795 | // .arg => self.genArg(inst.castTag(.arg).?), |
| 802 | .bitcast => self.genBitcast(inst.castTag(.bitcast).?), | 796 | // .bit_and => self.genBinOp(inst.castTag(.bit_and).?, .@"and"), |
| 803 | .bit_or => self.genBinOp(inst.castTag(.bit_or).?, .@"or"), | 797 | // .bitcast => self.genBitcast(inst.castTag(.bitcast).?), |
| 804 | .block => self.genBlock(inst.castTag(.block).?), | 798 | // .bit_or => self.genBinOp(inst.castTag(.bit_or).?, .@"or"), |
| 805 | .bool_and => self.genBinOp(inst.castTag(.bool_and).?, .@"and"), | 799 | // .block => self.genBlock(inst.castTag(.block).?), |
| 806 | .bool_or => self.genBinOp(inst.castTag(.bool_or).?, .@"or"), | 800 | // .bool_and => self.genBinOp(inst.castTag(.bool_and).?, .@"and"), |
| 807 | .breakpoint => self.genBreakpoint(inst.castTag(.breakpoint).?), | 801 | // .bool_or => self.genBinOp(inst.castTag(.bool_or).?, .@"or"), |
| 808 | .br => self.genBr(inst.castTag(.br).?), | 802 | // .breakpoint => self.genBreakpoint(inst.castTag(.breakpoint).?), |
| 809 | .call => self.genCall(inst.castTag(.call).?), | 803 | // .br => self.genBr(inst.castTag(.br).?), |
| 810 | .cmp_eq => self.genCmp(inst.castTag(.cmp_eq).?, .eq), | 804 | // .call => self.genCall(inst.castTag(.call).?), |
| 811 | .cmp_gte => self.genCmp(inst.castTag(.cmp_gte).?, .gte), | 805 | // .cmp_eq => self.genCmp(inst.castTag(.cmp_eq).?, .eq), |
| 812 | .cmp_gt => self.genCmp(inst.castTag(.cmp_gt).?, .gt), | 806 | // .cmp_gte => self.genCmp(inst.castTag(.cmp_gte).?, .gte), |
| 813 | .cmp_lte => self.genCmp(inst.castTag(.cmp_lte).?, .lte), | 807 | // .cmp_gt => self.genCmp(inst.castTag(.cmp_gt).?, .gt), |
| 814 | .cmp_lt => self.genCmp(inst.castTag(.cmp_lt).?, .lt), | 808 | // .cmp_lte => self.genCmp(inst.castTag(.cmp_lte).?, .lte), |
| 815 | .cmp_neq => self.genCmp(inst.castTag(.cmp_neq).?, .neq), | 809 | // .cmp_lt => self.genCmp(inst.castTag(.cmp_lt).?, .lt), |
| 816 | .condbr => self.genCondBr(inst.castTag(.condbr).?), | 810 | // .cmp_neq => self.genCmp(inst.castTag(.cmp_neq).?, .neq), |
| 817 | .constant => unreachable, | 811 | // .condbr => self.genCondBr(inst.castTag(.condbr).?), |
| 818 | .dbg_stmt => WValue.none, | 812 | // .constant => unreachable, |
| 819 | .div => self.genBinOp(inst.castTag(.div).?, .div), | 813 | // .dbg_stmt => WValue.none, |
| 820 | .is_err => self.genIsErr(inst.castTag(.is_err).?, .i32_ne), | 814 | // .div => self.genBinOp(inst.castTag(.div).?, .div), |
| 821 | .is_non_err => self.genIsErr(inst.castTag(.is_non_err).?, .i32_eq), | 815 | // .is_err => self.genIsErr(inst.castTag(.is_err).?, .i32_ne), |
| 822 | .load => self.genLoad(inst.castTag(.load).?), | 816 | // .is_non_err => self.genIsErr(inst.castTag(.is_non_err).?, .i32_eq), |
| 823 | .loop => self.genLoop(inst.castTag(.loop).?), | 817 | // .load => self.genLoad(inst.castTag(.load).?), |
| 824 | .mul => self.genBinOp(inst.castTag(.mul).?, .mul), | 818 | // .loop => self.genLoop(inst.castTag(.loop).?), |
| 825 | .not => self.genNot(inst.castTag(.not).?), | 819 | // .mul => self.genBinOp(inst.castTag(.mul).?, .mul), |
| 826 | .ret => self.genRet(inst.castTag(.ret).?), | 820 | // .not => self.genNot(inst.castTag(.not).?), |
| 827 | .retvoid => WValue.none, | 821 | // .ret => self.genRet(inst.castTag(.ret).?), |
| 828 | .store => self.genStore(inst.castTag(.store).?), | 822 | // .retvoid => WValue.none, |
| 829 | .struct_field_ptr => self.genStructFieldPtr(inst.castTag(.struct_field_ptr).?), | 823 | // .store => self.genStore(inst.castTag(.store).?), |
| 830 | .sub => self.genBinOp(inst.castTag(.sub).?, .sub), | 824 | // .struct_field_ptr => self.genStructFieldPtr(inst.castTag(.struct_field_ptr).?), |
| 831 | .switchbr => self.genSwitchBr(inst.castTag(.switchbr).?), | 825 | // .sub => self.genBinOp(inst.castTag(.sub).?, .sub), |
| 832 | .unreach => self.genUnreachable(inst.castTag(.unreach).?), | 826 | // .switchbr => self.genSwitchBr(inst.castTag(.switchbr).?), |
| 833 | .unwrap_errunion_payload => self.genUnwrapErrUnionPayload(inst.castTag(.unwrap_errunion_payload).?), | 827 | // .unreach => self.genUnreachable(inst.castTag(.unreach).?), |
| 834 | .wrap_errunion_payload => self.genWrapErrUnionPayload(inst.castTag(.wrap_errunion_payload).?), | 828 | // .unwrap_errunion_payload => self.genUnwrapErrUnionPayload(inst.castTag(.unwrap_errunion_payload).?), |
| 835 | .xor => self.genBinOp(inst.castTag(.xor).?, .xor), | 829 | // .wrap_errunion_payload => self.genWrapErrUnionPayload(inst.castTag(.wrap_errunion_payload).?), |
| 836 | else => self.fail(.{ .node_offset = 0 }, "TODO: Implement wasm inst: {s}", .{inst.tag}), | 830 | // .xor => self.genBinOp(inst.castTag(.xor).?, .xor), |
| | 831 | else => |tag| self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}), |
| 837 | }; | 832 | }; |
| 838 | } | 833 | } |
| 839 | | 834 | |
| 840 | fn genBody(self: *Context, body: ir.Body) InnerError!void { | 835 | fn genBody(self: *Context, body: []const Air.Inst.Index) InnerError!void { |
| 841 | for (body.instructions) |inst| { | 836 | for (body) |inst| { |
| 842 | const result = try self.genInst(inst); | 837 | const result = try self.genInst(inst); |
| 843 | try self.values.putNoClobber(self.gpa, inst, result); | 838 | try self.values.putNoClobber(self.gpa, inst, result); |
| 844 | } | 839 | } |
| 845 | } | 840 | } |
| 846 | | 841 | |
| 847 | fn genRet(self: *Context, inst: *Inst.UnOp) InnerError!WValue { | 842 | fn genRet(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 848 | // TODO: Implement tail calls | 843 | // TODO: Implement tail calls |
| 849 | const operand = self.resolveInst(inst.operand); | 844 | const operand = self.resolveInst(inst.operand); |
| 850 | try self.emitWValue(operand); | 845 | try self.emitWValue(operand); |
| ... | @@ -852,7 +847,7 @@ pub const Context = struct { | ... | @@ -852,7 +847,7 @@ pub const Context = struct { |
| 852 | return .none; | 847 | return .none; |
| 853 | } | 848 | } |
| 854 | | 849 | |
| 855 | fn genCall(self: *Context, inst: *Inst.Call) InnerError!WValue { | 850 | fn genCall(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 856 | const func_val = inst.func.value().?; | 851 | const func_val = inst.func.value().?; |
| 857 | | 852 | |
| 858 | const target: *Decl = blk: { | 853 | const target: *Decl = blk: { |
| ... | @@ -861,7 +856,7 @@ pub const Context = struct { | ... | @@ -861,7 +856,7 @@ pub const Context = struct { |
| 861 | } else if (func_val.castTag(.extern_fn)) |ext_fn| { | 856 | } else if (func_val.castTag(.extern_fn)) |ext_fn| { |
| 862 | break :blk ext_fn.data; | 857 | break :blk ext_fn.data; |
| 863 | } | 858 | } |
| 864 | return self.fail(inst.base.src, "Expected a function, but instead found type '{s}'", .{func_val.tag()}); | 859 | return self.fail("Expected a function, but instead found type '{s}'", .{func_val.tag()}); |
| 865 | }; | 860 | }; |
| 866 | | 861 | |
| 867 | for (inst.args) |arg| { | 862 | for (inst.args) |arg| { |
| ... | @@ -881,12 +876,12 @@ pub const Context = struct { | ... | @@ -881,12 +876,12 @@ pub const Context = struct { |
| 881 | return .none; | 876 | return .none; |
| 882 | } | 877 | } |
| 883 | | 878 | |
| 884 | fn genAlloc(self: *Context, inst: *Inst.NoOp) InnerError!WValue { | 879 | fn genAlloc(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 885 | const elem_type = inst.base.ty.elemType(); | 880 | const elem_type = inst.base.ty.elemType(); |
| 886 | return self.allocLocal(elem_type); | 881 | return self.allocLocal(elem_type); |
| 887 | } | 882 | } |
| 888 | | 883 | |
| 889 | fn genStore(self: *Context, inst: *Inst.BinOp) InnerError!WValue { | 884 | fn genStore(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 890 | const writer = self.code.writer(); | 885 | const writer = self.code.writer(); |
| 891 | | 886 | |
| 892 | const lhs = self.resolveInst(inst.lhs); | 887 | const lhs = self.resolveInst(inst.lhs); |
| ... | @@ -924,18 +919,18 @@ pub const Context = struct { | ... | @@ -924,18 +919,18 @@ pub const Context = struct { |
| 924 | return .none; | 919 | return .none; |
| 925 | } | 920 | } |
| 926 | | 921 | |
| 927 | fn genLoad(self: *Context, inst: *Inst.UnOp) InnerError!WValue { | 922 | fn genLoad(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 928 | return self.resolveInst(inst.operand); | 923 | return self.resolveInst(inst.operand); |
| 929 | } | 924 | } |
| 930 | | 925 | |
| 931 | fn genArg(self: *Context, inst: *Inst.Arg) InnerError!WValue { | 926 | fn genArg(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 932 | _ = inst; | 927 | _ = inst; |
| 933 | // arguments share the index with locals | 928 | // arguments share the index with locals |
| 934 | defer self.local_index += 1; | 929 | defer self.local_index += 1; |
| 935 | return WValue{ .local = self.local_index }; | 930 | return WValue{ .local = self.local_index }; |
| 936 | } | 931 | } |
| 937 | | 932 | |
| 938 | fn genBinOp(self: *Context, inst: *Inst.BinOp, op: Op) InnerError!WValue { | 933 | fn genBinOp(self: *Context, inst: Air.Inst.Index, op: Op) InnerError!WValue { |
| 939 | const lhs = self.resolveInst(inst.lhs); | 934 | const lhs = self.resolveInst(inst.lhs); |
| 940 | const rhs = self.resolveInst(inst.rhs); | 935 | const rhs = self.resolveInst(inst.rhs); |
| 941 | | 936 | |
| ... | @@ -952,21 +947,21 @@ pub const Context = struct { | ... | @@ -952,21 +947,21 @@ pub const Context = struct { |
| 952 | | 947 | |
| 953 | const opcode: wasm.Opcode = buildOpcode(.{ | 948 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 954 | .op = op, | 949 | .op = op, |
| 955 | .valtype1 = try self.typeToValtype(inst.base.src, inst.base.ty), | 950 | .valtype1 = try self.typeToValtype(inst.base.ty), |
| 956 | .signedness = if (inst.base.ty.isSignedInt()) .signed else .unsigned, | 951 | .signedness = if (inst.base.ty.isSignedInt()) .signed else .unsigned, |
| 957 | }); | 952 | }); |
| 958 | try self.code.append(wasm.opcode(opcode)); | 953 | try self.code.append(wasm.opcode(opcode)); |
| 959 | return WValue{ .code_offset = offset }; | 954 | return WValue{ .code_offset = offset }; |
| 960 | } | 955 | } |
| 961 | | 956 | |
| 962 | fn emitConstant(self: *Context, src: LazySrcLoc, value: Value, ty: Type) InnerError!void { | 957 | fn emitConstant(self: *Context, value: Value, ty: Type) InnerError!void { |
| 963 | const writer = self.code.writer(); | 958 | const writer = self.code.writer(); |
| 964 | switch (ty.zigTypeTag()) { | 959 | switch (ty.zigTypeTag()) { |
| 965 | .Int => { | 960 | .Int => { |
| 966 | // write opcode | 961 | // write opcode |
| 967 | const opcode: wasm.Opcode = buildOpcode(.{ | 962 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 968 | .op = .@"const", | 963 | .op = .@"const", |
| 969 | .valtype1 = try self.typeToValtype(src, ty), | 964 | .valtype1 = try self.typeToValtype(ty), |
| 970 | }); | 965 | }); |
| 971 | try writer.writeByte(wasm.opcode(opcode)); | 966 | try writer.writeByte(wasm.opcode(opcode)); |
| 972 | // write constant | 967 | // write constant |
| ... | @@ -985,14 +980,14 @@ pub const Context = struct { | ... | @@ -985,14 +980,14 @@ pub const Context = struct { |
| 985 | // write opcode | 980 | // write opcode |
| 986 | const opcode: wasm.Opcode = buildOpcode(.{ | 981 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 987 | .op = .@"const", | 982 | .op = .@"const", |
| 988 | .valtype1 = try self.typeToValtype(src, ty), | 983 | .valtype1 = try self.typeToValtype(ty), |
| 989 | }); | 984 | }); |
| 990 | try writer.writeByte(wasm.opcode(opcode)); | 985 | try writer.writeByte(wasm.opcode(opcode)); |
| 991 | // write constant | 986 | // write constant |
| 992 | switch (ty.floatBits(self.target)) { | 987 | switch (ty.floatBits(self.target)) { |
| 993 | 0...32 => try writer.writeIntLittle(u32, @bitCast(u32, value.toFloat(f32))), | 988 | 0...32 => try writer.writeIntLittle(u32, @bitCast(u32, value.toFloat(f32))), |
| 994 | 64 => try writer.writeIntLittle(u64, @bitCast(u64, value.toFloat(f64))), | 989 | 64 => try writer.writeIntLittle(u64, @bitCast(u64, value.toFloat(f64))), |
| 995 | else => |bits| return self.fail(src, "Wasm TODO: emitConstant for float with {d} bits", .{bits}), | 990 | else => |bits| return self.fail("Wasm TODO: emitConstant for float with {d} bits", .{bits}), |
| 996 | } | 991 | } |
| 997 | }, | 992 | }, |
| 998 | .Pointer => { | 993 | .Pointer => { |
| ... | @@ -1009,7 +1004,7 @@ pub const Context = struct { | ... | @@ -1009,7 +1004,7 @@ pub const Context = struct { |
| 1009 | try writer.writeByte(wasm.opcode(.i32_load)); | 1004 | try writer.writeByte(wasm.opcode(.i32_load)); |
| 1010 | try leb.writeULEB128(writer, @as(u32, 0)); | 1005 | try leb.writeULEB128(writer, @as(u32, 0)); |
| 1011 | try leb.writeULEB128(writer, @as(u32, 0)); | 1006 | try leb.writeULEB128(writer, @as(u32, 0)); |
| 1012 | } else return self.fail(src, "Wasm TODO: emitConstant for other const pointer tag {s}", .{value.tag()}); | 1007 | } else return self.fail("Wasm TODO: emitConstant for other const pointer tag {s}", .{value.tag()}); |
| 1013 | }, | 1008 | }, |
| 1014 | .Void => {}, | 1009 | .Void => {}, |
| 1015 | .Enum => { | 1010 | .Enum => { |
| ... | @@ -1023,7 +1018,7 @@ pub const Context = struct { | ... | @@ -1023,7 +1018,7 @@ pub const Context = struct { |
| 1023 | const enum_full = ty.cast(Type.Payload.EnumFull).?.data; | 1018 | const enum_full = ty.cast(Type.Payload.EnumFull).?.data; |
| 1024 | if (enum_full.values.count() != 0) { | 1019 | if (enum_full.values.count() != 0) { |
| 1025 | const tag_val = enum_full.values.keys()[field_index.data]; | 1020 | const tag_val = enum_full.values.keys()[field_index.data]; |
| 1026 | try self.emitConstant(src, tag_val, enum_full.tag_ty); | 1021 | try self.emitConstant(tag_val, enum_full.tag_ty); |
| 1027 | } else { | 1022 | } else { |
| 1028 | try writer.writeByte(wasm.opcode(.i32_const)); | 1023 | try writer.writeByte(wasm.opcode(.i32_const)); |
| 1029 | try leb.writeULEB128(writer, field_index.data); | 1024 | try leb.writeULEB128(writer, field_index.data); |
| ... | @@ -1034,7 +1029,7 @@ pub const Context = struct { | ... | @@ -1034,7 +1029,7 @@ pub const Context = struct { |
| 1034 | } else { | 1029 | } else { |
| 1035 | var int_tag_buffer: Type.Payload.Bits = undefined; | 1030 | var int_tag_buffer: Type.Payload.Bits = undefined; |
| 1036 | const int_tag_ty = ty.intTagType(&int_tag_buffer); | 1031 | const int_tag_ty = ty.intTagType(&int_tag_buffer); |
| 1037 | try self.emitConstant(src, value, int_tag_ty); | 1032 | try self.emitConstant(value, int_tag_ty); |
| 1038 | } | 1033 | } |
| 1039 | }, | 1034 | }, |
| 1040 | .ErrorSet => { | 1035 | .ErrorSet => { |
| ... | @@ -1048,12 +1043,12 @@ pub const Context = struct { | ... | @@ -1048,12 +1043,12 @@ pub const Context = struct { |
| 1048 | const payload_type = ty.errorUnionChild(); | 1043 | const payload_type = ty.errorUnionChild(); |
| 1049 | if (value.getError()) |_| { | 1044 | if (value.getError()) |_| { |
| 1050 | // write the error value | 1045 | // write the error value |
| 1051 | try self.emitConstant(src, data, error_type); | 1046 | try self.emitConstant(data, error_type); |
| 1052 | | 1047 | |
| 1053 | // no payload, so write a '0' const | 1048 | // no payload, so write a '0' const |
| 1054 | const opcode: wasm.Opcode = buildOpcode(.{ | 1049 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 1055 | .op = .@"const", | 1050 | .op = .@"const", |
| 1056 | .valtype1 = try self.typeToValtype(src, payload_type), | 1051 | .valtype1 = try self.typeToValtype(payload_type), |
| 1057 | }); | 1052 | }); |
| 1058 | try writer.writeByte(wasm.opcode(opcode)); | 1053 | try writer.writeByte(wasm.opcode(opcode)); |
| 1059 | try leb.writeULEB128(writer, @as(u32, 0)); | 1054 | try leb.writeULEB128(writer, @as(u32, 0)); |
| ... | @@ -1062,15 +1057,15 @@ pub const Context = struct { | ... | @@ -1062,15 +1057,15 @@ pub const Context = struct { |
| 1062 | try writer.writeByte(wasm.opcode(.i32_const)); | 1057 | try writer.writeByte(wasm.opcode(.i32_const)); |
| 1063 | try leb.writeULEB128(writer, @as(u32, 0)); | 1058 | try leb.writeULEB128(writer, @as(u32, 0)); |
| 1064 | // after the error code, we emit the payload | 1059 | // after the error code, we emit the payload |
| 1065 | try self.emitConstant(src, data, payload_type); | 1060 | try self.emitConstant(data, payload_type); |
| 1066 | } | 1061 | } |
| 1067 | }, | 1062 | }, |
| 1068 | else => |zig_type| return self.fail(src, "Wasm TODO: emitConstant for zigTypeTag {s}", .{zig_type}), | 1063 | else => |zig_type| return self.fail("Wasm TODO: emitConstant for zigTypeTag {s}", .{zig_type}), |
| 1069 | } | 1064 | } |
| 1070 | } | 1065 | } |
| 1071 | | 1066 | |
| 1072 | fn genBlock(self: *Context, block: *Inst.Block) InnerError!WValue { | 1067 | fn genBlock(self: *Context, block: Air.Inst.Index) InnerError!WValue { |
| 1073 | const block_ty = try self.genBlockType(block.base.src, block.base.ty); | 1068 | const block_ty = try self.genBlockType(block.base.ty); |
| 1074 | | 1069 | |
| 1075 | try self.startBlock(.block, block_ty, null); | 1070 | try self.startBlock(.block, block_ty, null); |
| 1076 | // Here we set the current block idx, so breaks know the depth to jump | 1071 | // Here we set the current block idx, so breaks know the depth to jump |
| ... | @@ -1100,8 +1095,8 @@ pub const Context = struct { | ... | @@ -1100,8 +1095,8 @@ pub const Context = struct { |
| 1100 | self.block_depth -= 1; | 1095 | self.block_depth -= 1; |
| 1101 | } | 1096 | } |
| 1102 | | 1097 | |
| 1103 | fn genLoop(self: *Context, loop: *Inst.Loop) InnerError!WValue { | 1098 | fn genLoop(self: *Context, loop: Air.Inst.Index) InnerError!WValue { |
| 1104 | const loop_ty = try self.genBlockType(loop.base.src, loop.base.ty); | 1099 | const loop_ty = try self.genBlockType(loop.base.ty); |
| 1105 | | 1100 | |
| 1106 | try self.startBlock(.loop, loop_ty, null); | 1101 | try self.startBlock(.loop, loop_ty, null); |
| 1107 | try self.genBody(loop.body); | 1102 | try self.genBody(loop.body); |
| ... | @@ -1115,7 +1110,7 @@ pub const Context = struct { | ... | @@ -1115,7 +1110,7 @@ pub const Context = struct { |
| 1115 | return .none; | 1110 | return .none; |
| 1116 | } | 1111 | } |
| 1117 | | 1112 | |
| 1118 | fn genCondBr(self: *Context, condbr: *Inst.CondBr) InnerError!WValue { | 1113 | fn genCondBr(self: *Context, condbr: Air.Inst.Index) InnerError!WValue { |
| 1119 | const condition = self.resolveInst(condbr.condition); | 1114 | const condition = self.resolveInst(condbr.condition); |
| 1120 | const writer = self.code.writer(); | 1115 | const writer = self.code.writer(); |
| 1121 | | 1116 | |
| ... | @@ -1131,7 +1126,7 @@ pub const Context = struct { | ... | @@ -1131,7 +1126,7 @@ pub const Context = struct { |
| 1131 | break :blk offset; | 1126 | break :blk offset; |
| 1132 | }, | 1127 | }, |
| 1133 | }; | 1128 | }; |
| 1134 | const block_ty = try self.genBlockType(condbr.base.src, condbr.base.ty); | 1129 | const block_ty = try self.genBlockType(condbr.base.ty); |
| 1135 | try self.startBlock(.block, block_ty, offset); | 1130 | try self.startBlock(.block, block_ty, offset); |
| 1136 | | 1131 | |
| 1137 | // we inserted the block in front of the condition | 1132 | // we inserted the block in front of the condition |
| ... | @@ -1149,7 +1144,7 @@ pub const Context = struct { | ... | @@ -1149,7 +1144,7 @@ pub const Context = struct { |
| 1149 | return .none; | 1144 | return .none; |
| 1150 | } | 1145 | } |
| 1151 | | 1146 | |
| 1152 | fn genCmp(self: *Context, inst: *Inst.BinOp, op: std.math.CompareOperator) InnerError!WValue { | 1147 | fn genCmp(self: *Context, inst: Air.Inst.Index, op: std.math.CompareOperator) InnerError!WValue { |
| 1153 | // save offset, so potential conditions can insert blocks in front of | 1148 | // save offset, so potential conditions can insert blocks in front of |
| 1154 | // the comparison that we can later jump back to | 1149 | // the comparison that we can later jump back to |
| 1155 | const offset = self.code.items.len; | 1150 | const offset = self.code.items.len; |
| ... | @@ -1168,7 +1163,7 @@ pub const Context = struct { | ... | @@ -1168,7 +1163,7 @@ pub const Context = struct { |
| 1168 | break :blk inst.lhs.ty.intInfo(self.target).signedness; | 1163 | break :blk inst.lhs.ty.intInfo(self.target).signedness; |
| 1169 | }; | 1164 | }; |
| 1170 | const opcode: wasm.Opcode = buildOpcode(.{ | 1165 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 1171 | .valtype1 = try self.typeToValtype(inst.base.src, inst.lhs.ty), | 1166 | .valtype1 = try self.typeToValtype(inst.lhs.ty), |
| 1172 | .op = switch (op) { | 1167 | .op = switch (op) { |
| 1173 | .lt => .lt, | 1168 | .lt => .lt, |
| 1174 | .lte => .le, | 1169 | .lte => .le, |
| ... | @@ -1183,7 +1178,7 @@ pub const Context = struct { | ... | @@ -1183,7 +1178,7 @@ pub const Context = struct { |
| 1183 | return WValue{ .code_offset = offset }; | 1178 | return WValue{ .code_offset = offset }; |
| 1184 | } | 1179 | } |
| 1185 | | 1180 | |
| 1186 | fn genBr(self: *Context, br: *Inst.Br) InnerError!WValue { | 1181 | fn genBr(self: *Context, br: Air.Inst.Index) InnerError!WValue { |
| 1187 | // if operand has codegen bits we should break with a value | 1182 | // if operand has codegen bits we should break with a value |
| 1188 | if (br.operand.ty.hasCodeGenBits()) { | 1183 | if (br.operand.ty.hasCodeGenBits()) { |
| 1189 | const operand = self.resolveInst(br.operand); | 1184 | const operand = self.resolveInst(br.operand); |
| ... | @@ -1200,7 +1195,7 @@ pub const Context = struct { | ... | @@ -1200,7 +1195,7 @@ pub const Context = struct { |
| 1200 | return .none; | 1195 | return .none; |
| 1201 | } | 1196 | } |
| 1202 | | 1197 | |
| 1203 | fn genNot(self: *Context, not: *Inst.UnOp) InnerError!WValue { | 1198 | fn genNot(self: *Context, not: Air.Inst.Index) InnerError!WValue { |
| 1204 | const offset = self.code.items.len; | 1199 | const offset = self.code.items.len; |
| 1205 | | 1200 | |
| 1206 | const operand = self.resolveInst(not.operand); | 1201 | const operand = self.resolveInst(not.operand); |
| ... | @@ -1217,7 +1212,7 @@ pub const Context = struct { | ... | @@ -1217,7 +1212,7 @@ pub const Context = struct { |
| 1217 | return WValue{ .code_offset = offset }; | 1212 | return WValue{ .code_offset = offset }; |
| 1218 | } | 1213 | } |
| 1219 | | 1214 | |
| 1220 | fn genBreakpoint(self: *Context, breakpoint: *Inst.NoOp) InnerError!WValue { | 1215 | fn genBreakpoint(self: *Context, breakpoint: Air.Inst.Index) InnerError!WValue { |
| 1221 | _ = self; | 1216 | _ = self; |
| 1222 | _ = breakpoint; | 1217 | _ = breakpoint; |
| 1223 | // unsupported by wasm itself. Can be implemented once we support DWARF | 1218 | // unsupported by wasm itself. Can be implemented once we support DWARF |
| ... | @@ -1225,27 +1220,27 @@ pub const Context = struct { | ... | @@ -1225,27 +1220,27 @@ pub const Context = struct { |
| 1225 | return .none; | 1220 | return .none; |
| 1226 | } | 1221 | } |
| 1227 | | 1222 | |
| 1228 | fn genUnreachable(self: *Context, unreach: *Inst.NoOp) InnerError!WValue { | 1223 | fn genUnreachable(self: *Context, unreach: Air.Inst.Index) InnerError!WValue { |
| 1229 | _ = unreach; | 1224 | _ = unreach; |
| 1230 | try self.code.append(wasm.opcode(.@"unreachable")); | 1225 | try self.code.append(wasm.opcode(.@"unreachable")); |
| 1231 | return .none; | 1226 | return .none; |
| 1232 | } | 1227 | } |
| 1233 | | 1228 | |
| 1234 | fn genBitcast(self: *Context, bitcast: *Inst.UnOp) InnerError!WValue { | 1229 | fn genBitcast(self: *Context, bitcast: Air.Inst.Index) InnerError!WValue { |
| 1235 | return self.resolveInst(bitcast.operand); | 1230 | return self.resolveInst(bitcast.operand); |
| 1236 | } | 1231 | } |
| 1237 | | 1232 | |
| 1238 | fn genStructFieldPtr(self: *Context, inst: *Inst.StructFieldPtr) InnerError!WValue { | 1233 | fn genStructFieldPtr(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1239 | const struct_ptr = self.resolveInst(inst.struct_ptr); | 1234 | const struct_ptr = self.resolveInst(inst.struct_ptr); |
| 1240 | | 1235 | |
| 1241 | return WValue{ .local = struct_ptr.multi_value.index + @intCast(u32, inst.field_index) }; | 1236 | return WValue{ .local = struct_ptr.multi_value.index + @intCast(u32, inst.field_index) }; |
| 1242 | } | 1237 | } |
| 1243 | | 1238 | |
| 1244 | fn genSwitchBr(self: *Context, inst: *Inst.SwitchBr) InnerError!WValue { | 1239 | fn genSwitchBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1245 | const target = self.resolveInst(inst.target); | 1240 | const target = self.resolveInst(inst.target); |
| 1246 | const target_ty = inst.target.ty; | 1241 | const target_ty = inst.target.ty; |
| 1247 | const valtype = try self.typeToValtype(.{ .node_offset = 0 }, target_ty); | 1242 | const valtype = try self.typeToValtype(.{ .node_offset = 0 }, target_ty); |
| 1248 | const blocktype = try self.genBlockType(inst.base.src, inst.base.ty); | 1243 | const blocktype = try self.genBlockType(inst.base.ty); |
| 1249 | | 1244 | |
| 1250 | const signedness: std.builtin.Signedness = blk: { | 1245 | const signedness: std.builtin.Signedness = blk: { |
| 1251 | // by default we tell the operand type is unsigned (i.e. bools and enum values) | 1246 | // by default we tell the operand type is unsigned (i.e. bools and enum values) |
| ... | @@ -1282,7 +1277,7 @@ pub const Context = struct { | ... | @@ -1282,7 +1277,7 @@ pub const Context = struct { |
| 1282 | return .none; | 1277 | return .none; |
| 1283 | } | 1278 | } |
| 1284 | | 1279 | |
| 1285 | fn genIsErr(self: *Context, inst: *Inst.UnOp, opcode: wasm.Opcode) InnerError!WValue { | 1280 | fn genIsErr(self: *Context, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!WValue { |
| 1286 | const operand = self.resolveInst(inst.operand); | 1281 | const operand = self.resolveInst(inst.operand); |
| 1287 | const offset = self.code.items.len; | 1282 | const offset = self.code.items.len; |
| 1288 | const writer = self.code.writer(); | 1283 | const writer = self.code.writer(); |
| ... | @@ -1298,7 +1293,7 @@ pub const Context = struct { | ... | @@ -1298,7 +1293,7 @@ pub const Context = struct { |
| 1298 | return WValue{ .code_offset = offset }; | 1293 | return WValue{ .code_offset = offset }; |
| 1299 | } | 1294 | } |
| 1300 | | 1295 | |
| 1301 | fn genUnwrapErrUnionPayload(self: *Context, inst: *Inst.UnOp) InnerError!WValue { | 1296 | fn genUnwrapErrUnionPayload(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1302 | const operand = self.resolveInst(inst.operand); | 1297 | const operand = self.resolveInst(inst.operand); |
| 1303 | // The index of multi_value contains the error code. To get the initial index of the payload we get | 1298 | // The index of multi_value contains the error code. To get the initial index of the payload we get |
| 1304 | // the following index. Next, convert it to a `WValue.local` | 1299 | // the following index. Next, convert it to a `WValue.local` |
| ... | @@ -1307,7 +1302,7 @@ pub const Context = struct { | ... | @@ -1307,7 +1302,7 @@ pub const Context = struct { |
| 1307 | return WValue{ .local = operand.multi_value.index + 1 }; | 1302 | return WValue{ .local = operand.multi_value.index + 1 }; |
| 1308 | } | 1303 | } |
| 1309 | | 1304 | |
| 1310 | fn genWrapErrUnionPayload(self: *Context, inst: *Inst.UnOp) InnerError!WValue { | 1305 | fn genWrapErrUnionPayload(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1311 | return self.resolveInst(inst.operand); | 1306 | return self.resolveInst(inst.operand); |
| 1312 | } | 1307 | } |
| 1313 | }; | 1308 | }; |