authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-07-16 14:48:51+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-20 12:19:16-07:00
log424f260f850cb22637888bbfdf5bfaf9c08a4dae
tree627d18c4ab1a7905cfa041028a8fdb4d680b651b
parent8082660118bba78de00e1e103e53730a87b2b70f

Fix wasm-related compile errors:

- Update `fail()` to not require a `srcLoc`. This brings it in line with other backends, and we were always passing 'node_offset = 0', anyway. - Fix unused local due to change of architecture wrt function/decl generation. - Replace all old instructions to indexes within the function signatures.

2 files changed, 118 insertions(+), 120 deletions(-)

src/codegen/wasm.zig+108-113
......@@ -25,7 +25,7 @@ const WValue = union(enum) {
2525 /// Index of the local variable
2626 local: u32,
2727 /// Instruction holding a constant `Value`
28 constant: *Inst,
28 constant: Air.Inst.Index,
2929 /// Offset position in the list of bytecode instructions
3030 code_offset: usize,
3131 /// Used for variables that create multiple locals on the stack when allocated
......@@ -484,7 +484,7 @@ pub const Result = union(enum) {
484484};
485485
486486/// Hashmap to store generated `WValue` for each `Inst`
487pub const ValueTable = std.AutoHashMapUnmanaged(*Inst, WValue);
487pub const ValueTable = std.AutoHashMapUnmanaged(Air.Inst.Index, WValue);
488488
489489/// Code represents the `Code` section of wasm that
490490/// belongs to a function
......@@ -497,8 +497,8 @@ pub const Context = struct {
497497 gpa: *mem.Allocator,
498498 /// Table to save `WValue`'s generated by an `Inst`
499499 values: ValueTable,
500 /// Mapping from *Inst.Block to block ids
501 blocks: std.AutoArrayHashMapUnmanaged(*Inst.Block, u32) = .{},
500 /// Mapping from Air.Inst.Index to block ids
501 blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, u32) = .{},
502502 /// `bytes` contains the wasm bytecode belonging to the 'code' section.
503503 code: ArrayList(u8),
504504 /// Contains the generated function type bytecode for the current function
......@@ -538,7 +538,8 @@ pub const Context = struct {
538538 }
539539
540540 /// 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 };
542543 const src_loc = src.toSrcLocWithDecl(self.decl);
543544 self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, fmt, args);
544545 return error.CodegenFail;
......@@ -546,7 +547,7 @@ pub const Context = struct {
546547
547548 /// Resolves the `WValue` for the given instruction `inst`
548549 /// 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 {
550551 if (!inst.ty.hasCodeGenBits()) return .none;
551552
552553 if (inst.value()) |_| {
......@@ -557,48 +558,45 @@ pub const Context = struct {
557558 }
558559
559560 /// 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 {
561562 return switch (ty.zigTypeTag()) {
562563 .Float => blk: {
563564 const bits = ty.floatBits(self.target);
564565 if (bits == 16 or bits == 32) break :blk wasm.Valtype.f32;
565566 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});
567568 },
568569 .Int => blk: {
569570 const info = ty.intInfo(self.target);
570571 if (info.bits <= 32) break :blk wasm.Valtype.i32;
571572 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});
573574 },
574575 .Enum => switch (ty.tag()) {
575576 .enum_simple => wasm.Valtype.i32,
576 else => self.typeToValtype(
577 src,
578 ty.cast(Type.Payload.EnumFull).?.data.tag_ty,
579 ),
577 else => self.typeToValtype(ty.cast(Type.Payload.EnumFull).?.data.tag_ty),
580578 },
581579 .Bool,
582580 .Pointer,
583581 .ErrorSet,
584582 => wasm.Valtype.i32,
585583 .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()}),
587585 };
588586 }
589587
590588 /// Using a given `Type`, returns the byte representation of its wasm value type
591 fn genValtype(self: *Context, src: LazySrcLoc, ty: Type) InnerError!u8 {
592 return wasm.valtype(try self.typeToValtype(src, ty));
589 fn genValtype(self: *Context, ty: Type) InnerError!u8 {
590 return wasm.valtype(try self.typeToValtype(ty));
593591 }
594592
595593 /// Using a given `Type`, returns the corresponding wasm value type
596594 /// Differently from `genValtype` this also allows `void` to create a block
597595 /// with no return type
598 fn genBlockType(self: *Context, src: LazySrcLoc, ty: Type) InnerError!u8 {
596 fn genBlockType(self: *Context, ty: Type) InnerError!u8 {
599597 return switch (ty.tag()) {
600598 .void, .noreturn => wasm.block_empty,
601 else => self.genValtype(src, ty),
599 else => self.genValtype(ty),
602600 };
603601 }
604602
......@@ -612,7 +610,7 @@ pub const Context = struct {
612610 try writer.writeByte(wasm.opcode(.local_get));
613611 try leb.writeULEB128(writer, idx);
614612 },
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
616614 }
617615 }
618616
......@@ -682,7 +680,7 @@ pub const Context = struct {
682680 ty.fnParamTypes(params);
683681 for (params) |param_type| {
684682 // 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);
686684 try writer.writeByte(val_type);
687685 }
688686 }
......@@ -691,13 +689,10 @@ pub const Context = struct {
691689 const return_type = ty.fnReturnType();
692690 switch (return_type.zigTypeTag()) {
693691 .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", .{}),
695 .Optional => return self.fail(.{ .node_offset = 0 }, "TODO: Implement optionals as return type for wasm", .{}),
692 .Struct => return self.fail("TODO: Implement struct as return type for wasm", .{}),
693 .Optional => return self.fail("TODO: Implement optionals as return type for wasm", .{}),
696694 .ErrorUnion => {
697 const val_type = try self.genValtype(
698 .{ .node_offset = 0 },
699 return_type.errorUnionChild(),
700 );
695 const val_type = try self.genValtype(return_type.errorUnionChild());
701696
702697 // write down the amount of return values
703698 try leb.writeULEB128(writer, @as(u32, 2));
......@@ -707,22 +702,21 @@ pub const Context = struct {
707702 else => {
708703 try leb.writeULEB128(writer, @as(u32, 1));
709704 // 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);
711706 try writer.writeByte(val_type);
712707 },
713708 }
714709 }
715710
716711 pub fn genFunc(self: *Context, func: *Module.Fn) InnerError!Result {
712 _ = func;
717713 try self.genFunctype();
718
719 // Write instructions
720714 // TODO: check for and handle death of instructions
721715
722716 // Reserve space to write the size after generating the code as well as space for locals count
723717 try self.code.resize(10);
724718
725 try self.genBody(func.body);
719 try self.genBody(self.air.getMainBody());
726720
727721 // finally, write our local types at the 'offset' position
728722 {
......@@ -753,7 +747,7 @@ pub const Context = struct {
753747 return Result.appended;
754748 }
755749
756 /// Generates the wasm bytecode for the function declaration belonging to `Context`
750 /// Generates the wasm bytecode for the declaration belonging to `Context`
757751 pub fn gen(self: *Context, typed_value: TypedValue) InnerError!Result {
758752 switch (typed_value.ty.zigTypeTag()) {
759753 .Fn => {
......@@ -793,58 +787,59 @@ pub const Context = struct {
793787 }
794788 }
795789
796 fn genInst(self: *Context, inst: *Inst) InnerError!WValue {
797 return switch (inst.tag) {
798 .add => self.genBinOp(inst.castTag(.add).?, .add),
799 .alloc => self.genAlloc(inst.castTag(.alloc).?),
800 .arg => self.genArg(inst.castTag(.arg).?),
801 .bit_and => self.genBinOp(inst.castTag(.bit_and).?, .@"and"),
802 .bitcast => self.genBitcast(inst.castTag(.bitcast).?),
803 .bit_or => self.genBinOp(inst.castTag(.bit_or).?, .@"or"),
804 .block => self.genBlock(inst.castTag(.block).?),
805 .bool_and => self.genBinOp(inst.castTag(.bool_and).?, .@"and"),
806 .bool_or => self.genBinOp(inst.castTag(.bool_or).?, .@"or"),
807 .breakpoint => self.genBreakpoint(inst.castTag(.breakpoint).?),
808 .br => self.genBr(inst.castTag(.br).?),
809 .call => self.genCall(inst.castTag(.call).?),
810 .cmp_eq => self.genCmp(inst.castTag(.cmp_eq).?, .eq),
811 .cmp_gte => self.genCmp(inst.castTag(.cmp_gte).?, .gte),
812 .cmp_gt => self.genCmp(inst.castTag(.cmp_gt).?, .gt),
813 .cmp_lte => self.genCmp(inst.castTag(.cmp_lte).?, .lte),
814 .cmp_lt => self.genCmp(inst.castTag(.cmp_lt).?, .lt),
815 .cmp_neq => self.genCmp(inst.castTag(.cmp_neq).?, .neq),
816 .condbr => self.genCondBr(inst.castTag(.condbr).?),
817 .constant => unreachable,
818 .dbg_stmt => WValue.none,
819 .div => self.genBinOp(inst.castTag(.div).?, .div),
820 .is_err => self.genIsErr(inst.castTag(.is_err).?, .i32_ne),
821 .is_non_err => self.genIsErr(inst.castTag(.is_non_err).?, .i32_eq),
822 .load => self.genLoad(inst.castTag(.load).?),
823 .loop => self.genLoop(inst.castTag(.loop).?),
824 .mul => self.genBinOp(inst.castTag(.mul).?, .mul),
825 .not => self.genNot(inst.castTag(.not).?),
826 .ret => self.genRet(inst.castTag(.ret).?),
827 .retvoid => WValue.none,
828 .store => self.genStore(inst.castTag(.store).?),
829 .struct_field_ptr => self.genStructFieldPtr(inst.castTag(.struct_field_ptr).?),
830 .sub => self.genBinOp(inst.castTag(.sub).?, .sub),
831 .switchbr => self.genSwitchBr(inst.castTag(.switchbr).?),
832 .unreach => self.genUnreachable(inst.castTag(.unreach).?),
833 .unwrap_errunion_payload => self.genUnwrapErrUnionPayload(inst.castTag(.unwrap_errunion_payload).?),
834 .wrap_errunion_payload => self.genWrapErrUnionPayload(inst.castTag(.wrap_errunion_payload).?),
835 .xor => self.genBinOp(inst.castTag(.xor).?, .xor),
836 else => self.fail(.{ .node_offset = 0 }, "TODO: Implement wasm inst: {s}", .{inst.tag}),
790 fn genInst(self: *Context, inst: Air.Inst.Index) !WValue {
791 const air_tags = self.air.instructions.items(.tag);
792 return switch (air_tags[inst]) {
793 // .add => self.genBinOp(inst.castTag(.add).?, .add),
794 // .alloc => self.genAlloc(inst.castTag(.alloc).?),
795 // .arg => self.genArg(inst.castTag(.arg).?),
796 // .bit_and => self.genBinOp(inst.castTag(.bit_and).?, .@"and"),
797 // .bitcast => self.genBitcast(inst.castTag(.bitcast).?),
798 // .bit_or => self.genBinOp(inst.castTag(.bit_or).?, .@"or"),
799 // .block => self.genBlock(inst.castTag(.block).?),
800 // .bool_and => self.genBinOp(inst.castTag(.bool_and).?, .@"and"),
801 // .bool_or => self.genBinOp(inst.castTag(.bool_or).?, .@"or"),
802 // .breakpoint => self.genBreakpoint(inst.castTag(.breakpoint).?),
803 // .br => self.genBr(inst.castTag(.br).?),
804 // .call => self.genCall(inst.castTag(.call).?),
805 // .cmp_eq => self.genCmp(inst.castTag(.cmp_eq).?, .eq),
806 // .cmp_gte => self.genCmp(inst.castTag(.cmp_gte).?, .gte),
807 // .cmp_gt => self.genCmp(inst.castTag(.cmp_gt).?, .gt),
808 // .cmp_lte => self.genCmp(inst.castTag(.cmp_lte).?, .lte),
809 // .cmp_lt => self.genCmp(inst.castTag(.cmp_lt).?, .lt),
810 // .cmp_neq => self.genCmp(inst.castTag(.cmp_neq).?, .neq),
811 // .condbr => self.genCondBr(inst.castTag(.condbr).?),
812 // .constant => unreachable,
813 // .dbg_stmt => WValue.none,
814 // .div => self.genBinOp(inst.castTag(.div).?, .div),
815 // .is_err => self.genIsErr(inst.castTag(.is_err).?, .i32_ne),
816 // .is_non_err => self.genIsErr(inst.castTag(.is_non_err).?, .i32_eq),
817 // .load => self.genLoad(inst.castTag(.load).?),
818 // .loop => self.genLoop(inst.castTag(.loop).?),
819 // .mul => self.genBinOp(inst.castTag(.mul).?, .mul),
820 // .not => self.genNot(inst.castTag(.not).?),
821 // .ret => self.genRet(inst.castTag(.ret).?),
822 // .retvoid => WValue.none,
823 // .store => self.genStore(inst.castTag(.store).?),
824 // .struct_field_ptr => self.genStructFieldPtr(inst.castTag(.struct_field_ptr).?),
825 // .sub => self.genBinOp(inst.castTag(.sub).?, .sub),
826 // .switchbr => self.genSwitchBr(inst.castTag(.switchbr).?),
827 // .unreach => self.genUnreachable(inst.castTag(.unreach).?),
828 // .unwrap_errunion_payload => self.genUnwrapErrUnionPayload(inst.castTag(.unwrap_errunion_payload).?),
829 // .wrap_errunion_payload => self.genWrapErrUnionPayload(inst.castTag(.wrap_errunion_payload).?),
830 // .xor => self.genBinOp(inst.castTag(.xor).?, .xor),
831 else => |tag| self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
837832 };
838833 }
839834
840 fn genBody(self: *Context, body: ir.Body) InnerError!void {
841 for (body.instructions) |inst| {
835 fn genBody(self: *Context, body: []const Air.Inst.Index) InnerError!void {
836 for (body) |inst| {
842837 const result = try self.genInst(inst);
843838 try self.values.putNoClobber(self.gpa, inst, result);
844839 }
845840 }
846841
847 fn genRet(self: *Context, inst: *Inst.UnOp) InnerError!WValue {
842 fn genRet(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
848843 // TODO: Implement tail calls
849844 const operand = self.resolveInst(inst.operand);
850845 try self.emitWValue(operand);
......@@ -852,7 +847,7 @@ pub const Context = struct {
852847 return .none;
853848 }
854849
855 fn genCall(self: *Context, inst: *Inst.Call) InnerError!WValue {
850 fn genCall(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
856851 const func_val = inst.func.value().?;
857852
858853 const target: *Decl = blk: {
......@@ -861,7 +856,7 @@ pub const Context = struct {
861856 } else if (func_val.castTag(.extern_fn)) |ext_fn| {
862857 break :blk ext_fn.data;
863858 }
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()});
865860 };
866861
867862 for (inst.args) |arg| {
......@@ -881,12 +876,12 @@ pub const Context = struct {
881876 return .none;
882877 }
883878
884 fn genAlloc(self: *Context, inst: *Inst.NoOp) InnerError!WValue {
879 fn genAlloc(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
885880 const elem_type = inst.base.ty.elemType();
886881 return self.allocLocal(elem_type);
887882 }
888883
889 fn genStore(self: *Context, inst: *Inst.BinOp) InnerError!WValue {
884 fn genStore(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
890885 const writer = self.code.writer();
891886
892887 const lhs = self.resolveInst(inst.lhs);
......@@ -924,18 +919,18 @@ pub const Context = struct {
924919 return .none;
925920 }
926921
927 fn genLoad(self: *Context, inst: *Inst.UnOp) InnerError!WValue {
922 fn genLoad(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
928923 return self.resolveInst(inst.operand);
929924 }
930925
931 fn genArg(self: *Context, inst: *Inst.Arg) InnerError!WValue {
926 fn genArg(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
932927 _ = inst;
933928 // arguments share the index with locals
934929 defer self.local_index += 1;
935930 return WValue{ .local = self.local_index };
936931 }
937932
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 {
939934 const lhs = self.resolveInst(inst.lhs);
940935 const rhs = self.resolveInst(inst.rhs);
941936
......@@ -952,21 +947,21 @@ pub const Context = struct {
952947
953948 const opcode: wasm.Opcode = buildOpcode(.{
954949 .op = op,
955 .valtype1 = try self.typeToValtype(inst.base.src, inst.base.ty),
950 .valtype1 = try self.typeToValtype(inst.base.ty),
956951 .signedness = if (inst.base.ty.isSignedInt()) .signed else .unsigned,
957952 });
958953 try self.code.append(wasm.opcode(opcode));
959954 return WValue{ .code_offset = offset };
960955 }
961956
962 fn emitConstant(self: *Context, src: LazySrcLoc, value: Value, ty: Type) InnerError!void {
957 fn emitConstant(self: *Context, value: Value, ty: Type) InnerError!void {
963958 const writer = self.code.writer();
964959 switch (ty.zigTypeTag()) {
965960 .Int => {
966961 // write opcode
967962 const opcode: wasm.Opcode = buildOpcode(.{
968963 .op = .@"const",
969 .valtype1 = try self.typeToValtype(src, ty),
964 .valtype1 = try self.typeToValtype(ty),
970965 });
971966 try writer.writeByte(wasm.opcode(opcode));
972967 // write constant
......@@ -985,14 +980,14 @@ pub const Context = struct {
985980 // write opcode
986981 const opcode: wasm.Opcode = buildOpcode(.{
987982 .op = .@"const",
988 .valtype1 = try self.typeToValtype(src, ty),
983 .valtype1 = try self.typeToValtype(ty),
989984 });
990985 try writer.writeByte(wasm.opcode(opcode));
991986 // write constant
992987 switch (ty.floatBits(self.target)) {
993988 0...32 => try writer.writeIntLittle(u32, @bitCast(u32, value.toFloat(f32))),
994989 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}),
996991 }
997992 },
998993 .Pointer => {
......@@ -1009,7 +1004,7 @@ pub const Context = struct {
10091004 try writer.writeByte(wasm.opcode(.i32_load));
10101005 try leb.writeULEB128(writer, @as(u32, 0));
10111006 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()});
10131008 },
10141009 .Void => {},
10151010 .Enum => {
......@@ -1023,7 +1018,7 @@ pub const Context = struct {
10231018 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;
10241019 if (enum_full.values.count() != 0) {
10251020 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);
10271022 } else {
10281023 try writer.writeByte(wasm.opcode(.i32_const));
10291024 try leb.writeULEB128(writer, field_index.data);
......@@ -1034,7 +1029,7 @@ pub const Context = struct {
10341029 } else {
10351030 var int_tag_buffer: Type.Payload.Bits = undefined;
10361031 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);
10381033 }
10391034 },
10401035 .ErrorSet => {
......@@ -1048,12 +1043,12 @@ pub const Context = struct {
10481043 const payload_type = ty.errorUnionChild();
10491044 if (value.getError()) |_| {
10501045 // write the error value
1051 try self.emitConstant(src, data, error_type);
1046 try self.emitConstant(data, error_type);
10521047
10531048 // no payload, so write a '0' const
10541049 const opcode: wasm.Opcode = buildOpcode(.{
10551050 .op = .@"const",
1056 .valtype1 = try self.typeToValtype(src, payload_type),
1051 .valtype1 = try self.typeToValtype(payload_type),
10571052 });
10581053 try writer.writeByte(wasm.opcode(opcode));
10591054 try leb.writeULEB128(writer, @as(u32, 0));
......@@ -1062,15 +1057,15 @@ pub const Context = struct {
10621057 try writer.writeByte(wasm.opcode(.i32_const));
10631058 try leb.writeULEB128(writer, @as(u32, 0));
10641059 // after the error code, we emit the payload
1065 try self.emitConstant(src, data, payload_type);
1060 try self.emitConstant(data, payload_type);
10661061 }
10671062 },
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}),
10691064 }
10701065 }
10711066
1072 fn genBlock(self: *Context, block: *Inst.Block) InnerError!WValue {
1073 const block_ty = try self.genBlockType(block.base.src, block.base.ty);
1067 fn genBlock(self: *Context, block: Air.Inst.Index) InnerError!WValue {
1068 const block_ty = try self.genBlockType(block.base.ty);
10741069
10751070 try self.startBlock(.block, block_ty, null);
10761071 // Here we set the current block idx, so breaks know the depth to jump
......@@ -1100,8 +1095,8 @@ pub const Context = struct {
11001095 self.block_depth -= 1;
11011096 }
11021097
1103 fn genLoop(self: *Context, loop: *Inst.Loop) InnerError!WValue {
1104 const loop_ty = try self.genBlockType(loop.base.src, loop.base.ty);
1098 fn genLoop(self: *Context, loop: Air.Inst.Index) InnerError!WValue {
1099 const loop_ty = try self.genBlockType(loop.base.ty);
11051100
11061101 try self.startBlock(.loop, loop_ty, null);
11071102 try self.genBody(loop.body);
......@@ -1115,7 +1110,7 @@ pub const Context = struct {
11151110 return .none;
11161111 }
11171112
1118 fn genCondBr(self: *Context, condbr: *Inst.CondBr) InnerError!WValue {
1113 fn genCondBr(self: *Context, condbr: Air.Inst.Index) InnerError!WValue {
11191114 const condition = self.resolveInst(condbr.condition);
11201115 const writer = self.code.writer();
11211116
......@@ -1131,7 +1126,7 @@ pub const Context = struct {
11311126 break :blk offset;
11321127 },
11331128 };
1134 const block_ty = try self.genBlockType(condbr.base.src, condbr.base.ty);
1129 const block_ty = try self.genBlockType(condbr.base.ty);
11351130 try self.startBlock(.block, block_ty, offset);
11361131
11371132 // we inserted the block in front of the condition
......@@ -1149,7 +1144,7 @@ pub const Context = struct {
11491144 return .none;
11501145 }
11511146
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 {
11531148 // save offset, so potential conditions can insert blocks in front of
11541149 // the comparison that we can later jump back to
11551150 const offset = self.code.items.len;
......@@ -1168,7 +1163,7 @@ pub const Context = struct {
11681163 break :blk inst.lhs.ty.intInfo(self.target).signedness;
11691164 };
11701165 const opcode: wasm.Opcode = buildOpcode(.{
1171 .valtype1 = try self.typeToValtype(inst.base.src, inst.lhs.ty),
1166 .valtype1 = try self.typeToValtype(inst.lhs.ty),
11721167 .op = switch (op) {
11731168 .lt => .lt,
11741169 .lte => .le,
......@@ -1183,7 +1178,7 @@ pub const Context = struct {
11831178 return WValue{ .code_offset = offset };
11841179 }
11851180
1186 fn genBr(self: *Context, br: *Inst.Br) InnerError!WValue {
1181 fn genBr(self: *Context, br: Air.Inst.Index) InnerError!WValue {
11871182 // if operand has codegen bits we should break with a value
11881183 if (br.operand.ty.hasCodeGenBits()) {
11891184 const operand = self.resolveInst(br.operand);
......@@ -1200,7 +1195,7 @@ pub const Context = struct {
12001195 return .none;
12011196 }
12021197
1203 fn genNot(self: *Context, not: *Inst.UnOp) InnerError!WValue {
1198 fn genNot(self: *Context, not: Air.Inst.Index) InnerError!WValue {
12041199 const offset = self.code.items.len;
12051200
12061201 const operand = self.resolveInst(not.operand);
......@@ -1217,7 +1212,7 @@ pub const Context = struct {
12171212 return WValue{ .code_offset = offset };
12181213 }
12191214
1220 fn genBreakpoint(self: *Context, breakpoint: *Inst.NoOp) InnerError!WValue {
1215 fn genBreakpoint(self: *Context, breakpoint: Air.Inst.Index) InnerError!WValue {
12211216 _ = self;
12221217 _ = breakpoint;
12231218 // unsupported by wasm itself. Can be implemented once we support DWARF
......@@ -1225,27 +1220,27 @@ pub const Context = struct {
12251220 return .none;
12261221 }
12271222
1228 fn genUnreachable(self: *Context, unreach: *Inst.NoOp) InnerError!WValue {
1223 fn genUnreachable(self: *Context, unreach: Air.Inst.Index) InnerError!WValue {
12291224 _ = unreach;
12301225 try self.code.append(wasm.opcode(.@"unreachable"));
12311226 return .none;
12321227 }
12331228
1234 fn genBitcast(self: *Context, bitcast: *Inst.UnOp) InnerError!WValue {
1229 fn genBitcast(self: *Context, bitcast: Air.Inst.Index) InnerError!WValue {
12351230 return self.resolveInst(bitcast.operand);
12361231 }
12371232
1238 fn genStructFieldPtr(self: *Context, inst: *Inst.StructFieldPtr) InnerError!WValue {
1233 fn genStructFieldPtr(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
12391234 const struct_ptr = self.resolveInst(inst.struct_ptr);
12401235
12411236 return WValue{ .local = struct_ptr.multi_value.index + @intCast(u32, inst.field_index) };
12421237 }
12431238
1244 fn genSwitchBr(self: *Context, inst: *Inst.SwitchBr) InnerError!WValue {
1239 fn genSwitchBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
12451240 const target = self.resolveInst(inst.target);
12461241 const target_ty = inst.target.ty;
12471242 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);
12491244
12501245 const signedness: std.builtin.Signedness = blk: {
12511246 // by default we tell the operand type is unsigned (i.e. bools and enum values)
......@@ -1282,7 +1277,7 @@ pub const Context = struct {
12821277 return .none;
12831278 }
12841279
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 {
12861281 const operand = self.resolveInst(inst.operand);
12871282 const offset = self.code.items.len;
12881283 const writer = self.code.writer();
......@@ -1298,7 +1293,7 @@ pub const Context = struct {
12981293 return WValue{ .code_offset = offset };
12991294 }
13001295
1301 fn genUnwrapErrUnionPayload(self: *Context, inst: *Inst.UnOp) InnerError!WValue {
1296 fn genUnwrapErrUnionPayload(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
13021297 const operand = self.resolveInst(inst.operand);
13031298 // The index of multi_value contains the error code. To get the initial index of the payload we get
13041299 // the following index. Next, convert it to a `WValue.local`
......@@ -1307,7 +1302,7 @@ pub const Context = struct {
13071302 return WValue{ .local = operand.multi_value.index + 1 };
13081303 }
13091304
1310 fn genWrapErrUnionPayload(self: *Context, inst: *Inst.UnOp) InnerError!WValue {
1305 fn genWrapErrUnionPayload(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
13111306 return self.resolveInst(inst.operand);
13121307 }
13131308};
src/link/Wasm.zig+10-7
......@@ -228,7 +228,7 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live
228228 },
229229 else => |e| return e,
230230 };
231 return self.finishUpdateDecl(decl, result);
231 return self.finishUpdateDecl(decl, result, &context);
232232}
233233
234234// Generate code for the Decl, storing it in memory to be later written to
......@@ -270,18 +270,21 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
270270 },
271271 else => |e| return e,
272272 };
273 return self.finishUpdateDecl(decl, result);
273
274 return self.finishUpdateDecl(decl, result, &context);
274275}
275276
276fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, result: codegen.Result) !void {
277 const code: []const u8 = switch (result) {
278 .appended => @as([]const u8, context.code.items),
279 .externally_managed => |payload| payload,
280 };
277fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, result: codegen.Result, context: *codegen.Context) !void {
278 const fn_data: *FnData = &decl.fn_link.wasm;
281279
282280 fn_data.code = context.code.toUnmanaged();
283281 fn_data.functype = context.func_type_data.toUnmanaged();
284282
283 const code: []const u8 = switch (result) {
284 .appended => @as([]const u8, fn_data.code.items),
285 .externally_managed => |payload| payload,
286 };
287
285288 const block = &decl.link.wasm;
286289 if (decl.ty.zigTypeTag() == .Fn) {
287290 // as locals are patched afterwards, the offsets of funcidx's are off,