| ... | ... | @@ -542,10 +542,9 @@ locals: std.ArrayListUnmanaged(u8), |
| 542 | 542 | target: std.Target, |
| 543 | 543 | /// Represents the wasm binary file that is being linked. |
| 544 | 544 | bin_file: *link.File.Wasm, |
| 545 | | /// Table with the global error set. Consists of every error found in |
| 546 | | /// the compiled code. Each error name maps to a `Module.ErrorInt` which is emitted |
| 547 | | /// during codegen to determine the error value. |
| 548 | | global_error_set: std.StringHashMapUnmanaged(Module.ErrorInt), |
| 545 | /// Reference to the Module that this decl is part of. |
| 546 | /// Used to find the error value. |
| 547 | module: *Module, |
| 549 | 548 | /// List of MIR Instructions |
| 550 | 549 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, |
| 551 | 550 | /// Contains extra data for MIR |
| ... | ... | @@ -581,7 +580,7 @@ pub fn deinit(self: *Self) void { |
| 581 | 580 | self.* = undefined; |
| 582 | 581 | } |
| 583 | 582 | |
| 584 | | /// Sets `err_msg` on `Context` and returns `error.CodegemFail` which is caught in link/Wasm.zig |
| 583 | /// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig |
| 585 | 584 | fn fail(self: *Self, comptime fmt: []const u8, args: anytype) InnerError { |
| 586 | 585 | const src: LazySrcLoc = .{ .node_offset = 0 }; |
| 587 | 586 | const src_loc = src.toSrcLoc(self.decl); |
| ... | ... | @@ -674,50 +673,41 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) error{OutOfMemory}!u32 { |
| 674 | 673 | return result; |
| 675 | 674 | } |
| 676 | 675 | |
| 677 | | /// Using a given `Type`, returns the corresponding wasm Valtype |
| 678 | | fn typeToValtype(self: *Self, ty: Type) InnerError!wasm.Valtype { |
| 676 | /// Using a given `Type`, returns the corresponding type |
| 677 | fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { |
| 679 | 678 | return switch (ty.zigTypeTag()) { |
| 680 | 679 | .Float => blk: { |
| 681 | | const bits = ty.floatBits(self.target); |
| 680 | const bits = ty.floatBits(target); |
| 682 | 681 | if (bits == 16 or bits == 32) break :blk wasm.Valtype.f32; |
| 683 | 682 | if (bits == 64) break :blk wasm.Valtype.f64; |
| 684 | | return self.fail("Float bit size not supported by wasm: '{d}'", .{bits}); |
| 683 | return wasm.Valtype.i32; // represented as pointer to stack |
| 685 | 684 | }, |
| 686 | 685 | .Int => blk: { |
| 687 | | const info = ty.intInfo(self.target); |
| 686 | const info = ty.intInfo(target); |
| 688 | 687 | if (info.bits <= 32) break :blk wasm.Valtype.i32; |
| 689 | 688 | if (info.bits > 32 and info.bits <= 64) break :blk wasm.Valtype.i64; |
| 690 | 689 | break :blk wasm.Valtype.i32; // represented as pointer to stack |
| 691 | 690 | }, |
| 692 | 691 | .Enum => switch (ty.tag()) { |
| 693 | 692 | .enum_simple => wasm.Valtype.i32, |
| 694 | | else => self.typeToValtype(ty.cast(Type.Payload.EnumFull).?.data.tag_ty), |
| 693 | else => typeToValtype(ty.cast(Type.Payload.EnumFull).?.data.tag_ty, target), |
| 695 | 694 | }, |
| 696 | | .Bool, |
| 697 | | .Pointer, |
| 698 | | .ErrorSet, |
| 699 | | .Struct, |
| 700 | | .ErrorUnion, |
| 701 | | .Optional, |
| 702 | | .Fn, |
| 703 | | .Array, |
| 704 | | => wasm.Valtype.i32, |
| 705 | | else => self.fail("TODO - Wasm typeToValtype for type '{}'", .{ty}), |
| 695 | else => wasm.Valtype.i32, // all represented as reference/immediate |
| 706 | 696 | }; |
| 707 | 697 | } |
| 708 | 698 | |
| 709 | 699 | /// Using a given `Type`, returns the byte representation of its wasm value type |
| 710 | | fn genValtype(self: *Self, ty: Type) InnerError!u8 { |
| 711 | | return wasm.valtype(try self.typeToValtype(ty)); |
| 700 | fn genValtype(ty: Type, target: std.Target) u8 { |
| 701 | return wasm.valtype(typeToValtype(ty, target)); |
| 712 | 702 | } |
| 713 | 703 | |
| 714 | 704 | /// Using a given `Type`, returns the corresponding wasm value type |
| 715 | 705 | /// Differently from `genValtype` this also allows `void` to create a block |
| 716 | 706 | /// with no return type |
| 717 | | fn genBlockType(self: *Self, ty: Type) InnerError!u8 { |
| 707 | fn genBlockType(ty: Type, target: std.Target) u8 { |
| 718 | 708 | return switch (ty.tag()) { |
| 719 | 709 | .void, .noreturn => wasm.block_empty, |
| 720 | | else => self.genValtype(ty), |
| 710 | else => genValtype(ty, target), |
| 721 | 711 | }; |
| 722 | 712 | } |
| 723 | 713 | |
| ... | ... | @@ -739,7 +729,7 @@ fn emitWValue(self: *Self, value: WValue) InnerError!void { |
| 739 | 729 | /// Returns a corresponding `Wvalue` with `local` as active tag |
| 740 | 730 | fn allocLocal(self: *Self, ty: Type) InnerError!WValue { |
| 741 | 731 | const initial_index = self.local_index; |
| 742 | | const valtype = try self.genValtype(ty); |
| 732 | const valtype = genValtype(ty, self.target); |
| 743 | 733 | try self.locals.append(self.gpa, valtype); |
| 744 | 734 | self.local_index += 1; |
| 745 | 735 | return WValue{ .local = initial_index }; |
| ... | ... | @@ -747,33 +737,33 @@ fn allocLocal(self: *Self, ty: Type) InnerError!WValue { |
| 747 | 737 | |
| 748 | 738 | /// Generates a `wasm.Type` from a given function type. |
| 749 | 739 | /// Memory is owned by the caller. |
| 750 | | fn genFunctype(self: *Self, fn_ty: Type) !wasm.Type { |
| 751 | | var params = std.ArrayList(wasm.Valtype).init(self.gpa); |
| 740 | fn genFunctype(gpa: Allocator, fn_ty: Type, target: std.Target) !wasm.Type { |
| 741 | var params = std.ArrayList(wasm.Valtype).init(gpa); |
| 752 | 742 | defer params.deinit(); |
| 753 | | var returns = std.ArrayList(wasm.Valtype).init(self.gpa); |
| 743 | var returns = std.ArrayList(wasm.Valtype).init(gpa); |
| 754 | 744 | defer returns.deinit(); |
| 755 | 745 | const return_type = fn_ty.fnReturnType(); |
| 756 | 746 | |
| 757 | | const want_sret = self.isByRef(return_type); |
| 747 | const want_sret = isByRef(return_type, target); |
| 758 | 748 | |
| 759 | 749 | if (want_sret) { |
| 760 | | try params.append(try self.typeToValtype(Type.usize)); |
| 750 | try params.append(typeToValtype(return_type, target)); |
| 761 | 751 | } |
| 762 | 752 | |
| 763 | 753 | // param types |
| 764 | 754 | if (fn_ty.fnParamLen() != 0) { |
| 765 | | const fn_params = try self.gpa.alloc(Type, fn_ty.fnParamLen()); |
| 766 | | defer self.gpa.free(fn_params); |
| 755 | const fn_params = try gpa.alloc(Type, fn_ty.fnParamLen()); |
| 756 | defer gpa.free(fn_params); |
| 767 | 757 | fn_ty.fnParamTypes(fn_params); |
| 768 | 758 | for (fn_params) |param_type| { |
| 769 | 759 | if (!param_type.hasCodeGenBits()) continue; |
| 770 | | try params.append(try self.typeToValtype(param_type)); |
| 760 | try params.append(typeToValtype(param_type, target)); |
| 771 | 761 | } |
| 772 | 762 | } |
| 773 | 763 | |
| 774 | 764 | // return type |
| 775 | 765 | if (!want_sret and return_type.hasCodeGenBits()) { |
| 776 | | try returns.append(try self.typeToValtype(return_type)); |
| 766 | try returns.append(typeToValtype(return_type, target)); |
| 777 | 767 | } |
| 778 | 768 | |
| 779 | 769 | return wasm.Type{ |
| ... | ... | @@ -782,8 +772,8 @@ fn genFunctype(self: *Self, fn_ty: Type) !wasm.Type { |
| 782 | 772 | }; |
| 783 | 773 | } |
| 784 | 774 | |
| 785 | | pub fn genFunc(self: *Self) InnerError!Result { |
| 786 | | var func_type = try self.genFunctype(self.decl.ty); |
| 775 | pub fn genFunc(self: *Self) InnerError!void { |
| 776 | var func_type = try genFunctype(self.gpa, self.decl.ty, self.target); |
| 787 | 777 | defer func_type.deinit(self.gpa); |
| 788 | 778 | self.decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type); |
| 789 | 779 | |
| ... | ... | @@ -828,240 +818,260 @@ pub fn genFunc(self: *Self) InnerError!Result { |
| 828 | 818 | }, |
| 829 | 819 | else => |e| return e, |
| 830 | 820 | }; |
| 831 | | |
| 832 | | // codegen data has been appended to `code` |
| 833 | | return Result.appended; |
| 834 | 821 | } |
| 835 | 822 | |
| 836 | | pub fn genDecl(self: *Self) InnerError!Result { |
| 837 | | const decl = self.decl; |
| 838 | | assert(decl.has_tv); |
| 839 | | |
| 840 | | log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val }); |
| 841 | | |
| 842 | | if (decl.val.castTag(.function)) |func_payload| { |
| 843 | | _ = func_payload; |
| 844 | | return self.fail("TODO wasm backend genDecl function pointer", .{}); |
| 845 | | } else if (decl.val.castTag(.extern_fn)) |extern_fn| { |
| 846 | | const ext_decl = extern_fn.data; |
| 847 | | var func_type = try self.genFunctype(ext_decl.ty); |
| 848 | | func_type.deinit(self.gpa); |
| 849 | | ext_decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type); |
| 850 | | return Result.appended; |
| 851 | | } else { |
| 852 | | const init_val = if (decl.val.castTag(.variable)) |payload| init_val: { |
| 853 | | break :init_val payload.data.init; |
| 854 | | } else decl.val; |
| 855 | | if (init_val.tag() != .unreachable_value) { |
| 856 | | return try self.genTypedValue(decl.ty, init_val); |
| 823 | pub const DeclGen = struct { |
| 824 | /// The decl we are generating code for. |
| 825 | decl: *Decl, |
| 826 | /// The symbol we're generating code for. |
| 827 | /// This can either be the symbol of the Decl itself, |
| 828 | /// or one of its locals. |
| 829 | symbol_index: u32, |
| 830 | gpa: Allocator, |
| 831 | /// A reference to the linker, that will process the decl's |
| 832 | /// code and create any relocations it deems neccesary. |
| 833 | bin_file: *link.File.Wasm, |
| 834 | /// This will be set when `InnerError` has been returned. |
| 835 | /// In any other case, this will be 'undefined'. |
| 836 | err_msg: *Module.ErrorMsg, |
| 837 | /// Reference to the Module that is being compiled. |
| 838 | /// Used to find the error value of an error. |
| 839 | module: *Module, |
| 840 | /// The list of bytes that have been generated so far, |
| 841 | /// can be used to calculate the offset into a section. |
| 842 | code: *std.ArrayList(u8), |
| 843 | |
| 844 | /// Sets `err_msg` on `DeclGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig |
| 845 | fn fail(self: *DeclGen, comptime fmt: []const u8, args: anytype) InnerError { |
| 846 | const src: LazySrcLoc = .{ .node_offset = 0 }; |
| 847 | const src_loc = src.toSrcLoc(self.decl); |
| 848 | self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, fmt, args); |
| 849 | return error.CodegenFail; |
| 850 | } |
| 851 | |
| 852 | fn target(self: *const DeclGen) std.Target { |
| 853 | return self.bin_file.base.options.target; |
| 854 | } |
| 855 | |
| 856 | pub fn genDecl(self: *DeclGen) InnerError!Result { |
| 857 | const decl = self.decl; |
| 858 | assert(decl.has_tv); |
| 859 | |
| 860 | log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val }); |
| 861 | |
| 862 | if (decl.val.castTag(.function)) |func_payload| { |
| 863 | _ = func_payload; |
| 864 | return self.fail("TODO wasm backend genDecl function pointer", .{}); |
| 865 | } else if (decl.val.castTag(.extern_fn)) |extern_fn| { |
| 866 | const ext_decl = extern_fn.data; |
| 867 | var func_type = try genFunctype(self.gpa, ext_decl.ty, self.target()); |
| 868 | func_type.deinit(self.gpa); |
| 869 | ext_decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type); |
| 870 | return Result.appended; |
| 871 | } else { |
| 872 | const init_val = if (decl.val.castTag(.variable)) |payload| init_val: { |
| 873 | break :init_val payload.data.init; |
| 874 | } else decl.val; |
| 875 | if (init_val.tag() != .unreachable_value) { |
| 876 | return try self.genTypedValue(decl.ty, init_val, self.code.writer()); |
| 877 | } |
| 878 | return Result.appended; |
| 857 | 879 | } |
| 858 | | return Result.appended; |
| 859 | 880 | } |
| 860 | | } |
| 861 | 881 | |
| 862 | | /// Generates the wasm bytecode for the declaration belonging to `Context` |
| 863 | | fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result { |
| 864 | | if (val.isUndef()) { |
| 865 | | try self.code.appendNTimes(0xaa, @intCast(usize, ty.abiSize(self.target))); |
| 866 | | return Result.appended; |
| 867 | | } |
| 868 | | switch (ty.zigTypeTag()) { |
| 869 | | .Fn => { |
| 870 | | const fn_decl = switch (val.tag()) { |
| 871 | | .extern_fn => val.castTag(.extern_fn).?.data, |
| 872 | | .function => val.castTag(.function).?.data.owner_decl, |
| 873 | | else => unreachable, |
| 874 | | }; |
| 875 | | return try self.lowerDeclRef(ty, val, fn_decl); |
| 876 | | }, |
| 877 | | .Optional => { |
| 878 | | var opt_buf: Type.Payload.ElemType = undefined; |
| 879 | | const payload_type = ty.optionalChild(&opt_buf); |
| 880 | | if (ty.isPtrLikeOptional()) { |
| 881 | | if (val.castTag(.opt_payload)) |payload| { |
| 882 | | return try self.genTypedValue(payload_type, payload.data); |
| 883 | | } else if (!val.isNull()) { |
| 884 | | return try self.genTypedValue(payload_type, val); |
| 885 | | } else { |
| 886 | | try self.code.appendNTimes(0, @intCast(usize, ty.abiSize(self.target))); |
| 882 | /// Generates the wasm bytecode for the declaration belonging to `Context` |
| 883 | fn genTypedValue(self: *DeclGen, ty: Type, val: Value, writer: anytype) InnerError!Result { |
| 884 | if (val.isUndef()) { |
| 885 | try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target()))); |
| 886 | return Result.appended; |
| 887 | } |
| 888 | switch (ty.zigTypeTag()) { |
| 889 | .Fn => { |
| 890 | const fn_decl = switch (val.tag()) { |
| 891 | .extern_fn => val.castTag(.extern_fn).?.data, |
| 892 | .function => val.castTag(.function).?.data.owner_decl, |
| 893 | else => unreachable, |
| 894 | }; |
| 895 | return try self.lowerDeclRef(ty, val, fn_decl, writer); |
| 896 | }, |
| 897 | .Optional => { |
| 898 | var opt_buf: Type.Payload.ElemType = undefined; |
| 899 | const payload_type = ty.optionalChild(&opt_buf); |
| 900 | const is_pl = !val.isNull(); |
| 901 | |
| 902 | if (!payload_type.hasCodeGenBits()) { |
| 903 | try writer.writeByteNTimes(@boolToInt(is_pl), 4); |
| 887 | 904 | return Result.appended; |
| 888 | 905 | } |
| 889 | | } |
| 890 | | // `null-tag` byte |
| 891 | | try self.code.appendNTimes(@boolToInt(!val.isNull()), 4); |
| 892 | | const pl_result = try self.genTypedValue( |
| 893 | | payload_type, |
| 894 | | if (val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef), |
| 895 | | ); |
| 896 | | switch (pl_result) { |
| 897 | | .appended => {}, |
| 898 | | .externally_managed => |payload| try self.code.appendSlice(payload), |
| 899 | | } |
| 900 | | return Result.appended; |
| 901 | | }, |
| 902 | | .Array => switch (val.tag()) { |
| 903 | | .bytes => { |
| 904 | | const payload = val.castTag(.bytes).?; |
| 905 | | return Result{ .externally_managed = payload.data }; |
| 906 | |
| 907 | if (ty.isPtrLikeOptional()) { |
| 908 | if (val.castTag(.opt_payload)) |payload| { |
| 909 | return try self.genTypedValue(payload_type, payload.data, writer); |
| 910 | } else if (!val.isNull()) { |
| 911 | return try self.genTypedValue(payload_type, val, writer); |
| 912 | } else { |
| 913 | try writer.writeByteNTimes(0, @intCast(usize, ty.abiSize(self.target()))); |
| 914 | return Result.appended; |
| 915 | } |
| 916 | } |
| 917 | |
| 918 | // `null-tag` bytes |
| 919 | try writer.writeByteNTimes(@boolToInt(is_pl), 4); |
| 920 | const pl_result = try self.genTypedValue( |
| 921 | payload_type, |
| 922 | if (val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef), |
| 923 | writer, |
| 924 | ); |
| 925 | switch (pl_result) { |
| 926 | .appended => {}, |
| 927 | .externally_managed => |payload| try writer.writeAll(payload), |
| 928 | } |
| 929 | return Result.appended; |
| 906 | 930 | }, |
| 907 | | .array => { |
| 908 | | const elem_vals = val.castTag(.array).?.data; |
| 909 | | const elem_ty = ty.childType(); |
| 910 | | for (elem_vals) |elem_val| { |
| 911 | | switch (try self.genTypedValue(elem_ty, elem_val)) { |
| 931 | .Array => switch (val.tag()) { |
| 932 | .bytes => { |
| 933 | const payload = val.castTag(.bytes).?; |
| 934 | return Result{ .externally_managed = payload.data }; |
| 935 | }, |
| 936 | .array => { |
| 937 | const elem_vals = val.castTag(.array).?.data; |
| 938 | const elem_ty = ty.childType(); |
| 939 | for (elem_vals) |elem_val| { |
| 940 | switch (try self.genTypedValue(elem_ty, elem_val, writer)) { |
| 941 | .appended => {}, |
| 942 | .externally_managed => |data| try writer.writeAll(data), |
| 943 | } |
| 944 | } |
| 945 | return Result.appended; |
| 946 | }, |
| 947 | else => return self.fail("TODO implement genTypedValue for array type value: {s}", .{@tagName(val.tag())}), |
| 948 | }, |
| 949 | .Int => { |
| 950 | const info = ty.intInfo(self.target()); |
| 951 | const abi_size = @intCast(usize, ty.abiSize(self.target())); |
| 952 | // todo: Implement integer sizes larger than 64bits |
| 953 | if (info.bits > 64) return self.fail("TODO: Implement genTypedValue for integer bit size: {d}", .{info.bits}); |
| 954 | var buf: [8]u8 = undefined; |
| 955 | if (info.signedness == .unsigned) { |
| 956 | std.mem.writeIntLittle(u64, &buf, val.toUnsignedInt()); |
| 957 | } else std.mem.writeIntLittle(i64, &buf, val.toSignedInt()); |
| 958 | try writer.writeAll(buf[0..abi_size]); |
| 959 | return Result.appended; |
| 960 | }, |
| 961 | .Enum => { |
| 962 | try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target()))); |
| 963 | return Result.appended; |
| 964 | }, |
| 965 | .Bool => { |
| 966 | try writer.writeByte(@boolToInt(val.toBool())); |
| 967 | return Result.appended; |
| 968 | }, |
| 969 | .Struct => { |
| 970 | const field_vals = val.castTag(.@"struct").?.data; |
| 971 | for (field_vals) |field_val, index| { |
| 972 | const field_ty = ty.structFieldType(index); |
| 973 | if (!field_ty.hasCodeGenBits()) continue; |
| 974 | switch (try self.genTypedValue(field_ty, field_val, writer)) { |
| 912 | 975 | .appended => {}, |
| 913 | | .externally_managed => |data| try self.code.appendSlice(data), |
| 976 | .externally_managed => |payload| try writer.writeAll(payload), |
| 914 | 977 | } |
| 915 | 978 | } |
| 916 | 979 | return Result.appended; |
| 917 | 980 | }, |
| 918 | | else => return self.fail("TODO implement genTypedValue for array type value: {s}", .{@tagName(val.tag())}), |
| 919 | | }, |
| 920 | | .Int => { |
| 921 | | const info = ty.intInfo(self.target); |
| 922 | | const abi_size = @intCast(usize, ty.abiSize(self.target)); |
| 923 | | // todo: Implement integer sizes larger than 64bits |
| 924 | | if (info.bits > 64) return self.fail("TODO: Implement genTypedValue for integer bit size: {d}", .{info.bits}); |
| 925 | | var buf: [8]u8 = undefined; |
| 926 | | if (info.signedness == .unsigned) { |
| 927 | | std.mem.writeIntLittle(u64, &buf, val.toUnsignedInt()); |
| 928 | | } else std.mem.writeIntLittle(i64, &buf, val.toSignedInt()); |
| 929 | | try self.code.appendSlice(buf[0..abi_size]); |
| 930 | | return Result.appended; |
| 931 | | }, |
| 932 | | .Enum => { |
| 933 | | const size = @intCast(usize, ty.abiSize(self.target)); |
| 934 | | try self.code.appendNTimes(0xaa, size); |
| 935 | | return Result.appended; |
| 936 | | }, |
| 937 | | .Bool => { |
| 938 | | const int_byte: u8 = @boolToInt(val.toBool()); |
| 939 | | try self.code.append(int_byte); |
| 940 | | return Result.appended; |
| 941 | | }, |
| 942 | | .Struct => { |
| 943 | | const field_vals = val.castTag(.@"struct").?.data; |
| 944 | | for (field_vals) |field_val, index| { |
| 945 | | const field_ty = ty.structFieldType(index); |
| 946 | | if (!field_ty.hasCodeGenBits()) continue; |
| 947 | | switch (try self.genTypedValue(field_ty, field_val)) { |
| 948 | | .appended => {}, |
| 949 | | .externally_managed => |payload| try self.code.appendSlice(payload), |
| 950 | | } |
| 951 | | } |
| 952 | | return Result.appended; |
| 953 | | }, |
| 954 | | .Union => { |
| 955 | | // TODO: Implement Union declarations |
| 956 | | const abi_size = @intCast(usize, ty.abiSize(self.target)); |
| 957 | | try self.code.appendNTimes(0xaa, abi_size); |
| 958 | | return Result.appended; |
| 959 | | }, |
| 960 | | .Pointer => switch (val.tag()) { |
| 961 | | .variable => { |
| 962 | | const decl = val.castTag(.variable).?.data.owner_decl; |
| 963 | | return try self.lowerDeclRef(ty, val, decl); |
| 981 | .Union => { |
| 982 | // TODO: Implement Union declarations |
| 983 | try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target()))); |
| 984 | return Result.appended; |
| 964 | 985 | }, |
| 965 | | .decl_ref => { |
| 966 | | const decl = val.castTag(.decl_ref).?.data; |
| 967 | | return try self.lowerDeclRef(ty, val, decl); |
| 986 | .Pointer => switch (val.tag()) { |
| 987 | .variable => { |
| 988 | const decl = val.castTag(.variable).?.data.owner_decl; |
| 989 | return try self.lowerDeclRef(ty, val, decl, writer); |
| 990 | }, |
| 991 | .decl_ref => { |
| 992 | const decl = val.castTag(.decl_ref).?.data; |
| 993 | return try self.lowerDeclRef(ty, val, decl, writer); |
| 994 | }, |
| 995 | .slice => { |
| 996 | const slice = val.castTag(.slice).?.data; |
| 997 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 998 | const ptr_ty = ty.slicePtrFieldType(&buf); |
| 999 | switch (try self.genTypedValue(ptr_ty, slice.ptr, writer)) { |
| 1000 | .externally_managed => |data| try writer.writeAll(data), |
| 1001 | .appended => {}, |
| 1002 | } |
| 1003 | switch (try self.genTypedValue(Type.usize, slice.len, writer)) { |
| 1004 | .externally_managed => |data| try writer.writeAll(data), |
| 1005 | .appended => {}, |
| 1006 | } |
| 1007 | return Result.appended; |
| 1008 | }, |
| 1009 | else => return self.fail("TODO: Implement zig decl gen for pointer type value: '{s}'", .{@tagName(val.tag())}), |
| 968 | 1010 | }, |
| 969 | | .slice => { |
| 970 | | const slice = val.castTag(.slice).?.data; |
| 971 | | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 972 | | const ptr_ty = ty.slicePtrFieldType(&buf); |
| 973 | | switch (try self.genTypedValue(ptr_ty, slice.ptr)) { |
| 974 | | .externally_managed => |data| try self.code.appendSlice(data), |
| 1011 | .ErrorUnion => { |
| 1012 | const error_ty = ty.errorUnionSet(); |
| 1013 | const payload_ty = ty.errorUnionPayload(); |
| 1014 | const is_pl = val.errorUnionIsPayload(); |
| 1015 | |
| 1016 | const err_val = if (!is_pl) val else Value.initTag(.zero); |
| 1017 | switch (try self.genTypedValue(error_ty, err_val, writer)) { |
| 1018 | .externally_managed => |data| try writer.writeAll(data), |
| 975 | 1019 | .appended => {}, |
| 976 | 1020 | } |
| 977 | | switch (try self.genTypedValue(Type.usize, slice.len)) { |
| 978 | | .externally_managed => |data| try self.code.appendSlice(data), |
| 979 | | .appended => {}, |
| 1021 | |
| 1022 | if (payload_ty.hasCodeGenBits()) { |
| 1023 | const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); |
| 1024 | switch (try self.genTypedValue(payload_ty, pl_val, writer)) { |
| 1025 | .externally_managed => |data| try writer.writeAll(data), |
| 1026 | .appended => {}, |
| 1027 | } |
| 980 | 1028 | } |
| 1029 | |
| 981 | 1030 | return Result.appended; |
| 982 | 1031 | }, |
| 983 | | else => return self.fail("TODO: Implement zig decl gen for pointer type value: '{s}'", .{@tagName(val.tag())}), |
| 984 | | }, |
| 985 | | .ErrorUnion => { |
| 986 | | const error_ty = ty.errorUnionSet(); |
| 987 | | const payload_ty = ty.errorUnionPayload(); |
| 988 | | const is_pl = val.errorUnionIsPayload(); |
| 989 | | |
| 990 | | const err_val = if (!is_pl) val else Value.initTag(.zero); |
| 991 | | switch (try self.genTypedValue(error_ty, err_val)) { |
| 992 | | .externally_managed => |data| try self.code.appendSlice(data), |
| 993 | | .appended => {}, |
| 994 | | } |
| 995 | | |
| 996 | | if (payload_ty.hasCodeGenBits()) { |
| 997 | | const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); |
| 998 | | switch (try self.genTypedValue(payload_ty, pl_val)) { |
| 999 | | .externally_managed => |data| try self.code.appendSlice(data), |
| 1000 | | .appended => {}, |
| 1032 | .ErrorSet => { |
| 1033 | switch (val.tag()) { |
| 1034 | .@"error" => { |
| 1035 | const name = val.castTag(.@"error").?.data.name; |
| 1036 | const kv = try self.module.getErrorValue(name); |
| 1037 | try writer.writeIntLittle(u32, kv.value); |
| 1038 | }, |
| 1039 | else => { |
| 1040 | try writer.writeByteNTimes(0, @intCast(usize, ty.abiSize(self.target()))); |
| 1041 | }, |
| 1001 | 1042 | } |
| 1002 | | } |
| 1003 | | |
| 1004 | | return Result.appended; |
| 1005 | | }, |
| 1006 | | .ErrorSet => { |
| 1007 | | switch (val.tag()) { |
| 1008 | | .@"error" => { |
| 1009 | | const name = val.castTag(.@"error").?.data.name; |
| 1010 | | const value = self.global_error_set.get(name).?; |
| 1011 | | try self.code.writer().writeIntLittle(u32, value); |
| 1012 | | }, |
| 1013 | | else => { |
| 1014 | | const abi_size = @intCast(usize, ty.abiSize(self.target)); |
| 1015 | | try self.code.appendNTimes(0, abi_size); |
| 1016 | | }, |
| 1017 | | } |
| 1018 | | return Result.appended; |
| 1019 | | }, |
| 1020 | | else => |tag| return self.fail("TODO: Implement zig type codegen for type: '{s}'", .{tag}), |
| 1043 | return Result.appended; |
| 1044 | }, |
| 1045 | else => |tag| return self.fail("TODO: Implement zig type codegen for type: '{s}'", .{tag}), |
| 1046 | } |
| 1021 | 1047 | } |
| 1022 | | } |
| 1023 | 1048 | |
| 1024 | | fn lowerDeclRef(self: *Self, ty: Type, val: Value, decl: *Module.Decl) InnerError!Result { |
| 1025 | | if (ty.isSlice()) { |
| 1026 | | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1027 | | const slice_ty = ty.slicePtrFieldType(&buf); |
| 1028 | | switch (try self.genTypedValue(slice_ty, val)) { |
| 1029 | | .appended => {}, |
| 1030 | | .externally_managed => |payload| try self.code.appendSlice(payload), |
| 1049 | fn lowerDeclRef(self: *DeclGen, ty: Type, val: Value, decl: *Module.Decl, writer: anytype) InnerError!Result { |
| 1050 | if (ty.isSlice()) { |
| 1051 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1052 | const slice_ty = ty.slicePtrFieldType(&buf); |
| 1053 | switch (try self.genTypedValue(slice_ty, val, writer)) { |
| 1054 | .appended => {}, |
| 1055 | .externally_managed => |payload| try writer.writeAll(payload), |
| 1056 | } |
| 1057 | var slice_len: Value.Payload.U64 = .{ |
| 1058 | .base = .{ .tag = .int_u64 }, |
| 1059 | .data = val.sliceLen(), |
| 1060 | }; |
| 1061 | return try self.genTypedValue(Type.usize, Value.initPayload(&slice_len.base), writer); |
| 1031 | 1062 | } |
| 1032 | | var slice_len: Value.Payload.U64 = .{ |
| 1033 | | .base = .{ .tag = .int_u64 }, |
| 1034 | | .data = val.sliceLen(), |
| 1035 | | }; |
| 1036 | | return try self.genTypedValue(Type.usize, Value.initPayload(&slice_len.base)); |
| 1037 | | } |
| 1038 | | |
| 1039 | | const offset = @intCast(u32, self.code.items.len); |
| 1040 | | const atom = &self.decl.link.wasm; |
| 1041 | | const target_sym_index = decl.link.wasm.sym_index; |
| 1042 | | decl.markAlive(); |
| 1043 | | if (decl.ty.zigTypeTag() == .Fn) { |
| 1044 | | // We found a function pointer, so add it to our table, |
| 1045 | | // as function pointers are not allowed to be stored inside the data section, |
| 1046 | | // but rather in a function table which are called by index |
| 1047 | | try self.bin_file.addTableFunction(target_sym_index); |
| 1048 | | try atom.relocs.append(self.gpa, .{ |
| 1049 | | .index = target_sym_index, |
| 1050 | | .offset = offset, |
| 1051 | | .relocation_type = .R_WASM_TABLE_INDEX_I32, |
| 1052 | | }); |
| 1053 | | } else { |
| 1054 | | try atom.relocs.append(self.gpa, .{ |
| 1055 | | .index = target_sym_index, |
| 1056 | | .offset = offset, |
| 1057 | | .relocation_type = .R_WASM_MEMORY_ADDR_I32, |
| 1058 | | }); |
| 1059 | | } |
| 1060 | | const ptr_width = @intCast(usize, self.target.cpu.arch.ptrBitWidth() / 8); |
| 1061 | | try self.code.appendNTimes(0xaa, ptr_width); |
| 1062 | 1063 | |
| 1063 | | return Result.appended; |
| 1064 | | } |
| 1064 | decl.markAlive(); |
| 1065 | try writer.writeIntLittle(u32, try self.bin_file.getDeclVAddr( |
| 1066 | self.decl, // The decl containing the source symbol index |
| 1067 | decl.ty, // type we generate the address of |
| 1068 | self.symbol_index, // source symbol index |
| 1069 | decl.link.wasm.sym_index, // target symbol index |
| 1070 | @intCast(u32, self.code.items.len), // offset |
| 1071 | )); |
| 1072 | return Result.appended; |
| 1073 | } |
| 1074 | }; |
| 1065 | 1075 | |
| 1066 | 1076 | const CallWValues = struct { |
| 1067 | 1077 | args: []WValue, |
| ... | ... | @@ -1086,7 +1096,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) InnerError!CallWValu |
| 1086 | 1096 | const ret_ty = fn_ty.fnReturnType(); |
| 1087 | 1097 | // Check if we store the result as a pointer to the stack rather than |
| 1088 | 1098 | // by value |
| 1089 | | if (self.isByRef(ret_ty)) { |
| 1099 | if (isByRef(ret_ty, self.target)) { |
| 1090 | 1100 | // the sret arg will be passed as first argument, therefore we |
| 1091 | 1101 | // set the `return_value` before allocating locals for regular args. |
| 1092 | 1102 | result.return_value = .{ .local = self.local_index }; |
| ... | ... | @@ -1213,8 +1223,8 @@ fn arch(self: *const Self) std.Target.Cpu.Arch { |
| 1213 | 1223 | } |
| 1214 | 1224 | |
| 1215 | 1225 | /// For a given `Type`, will return true when the type will be passed |
| 1216 | | /// by reference, rather than by value. |
| 1217 | | fn isByRef(self: Self, ty: Type) bool { |
| 1226 | /// by reference, rather than by value |
| 1227 | fn isByRef(ty: Type, target: std.Target) bool { |
| 1218 | 1228 | switch (ty.zigTypeTag()) { |
| 1219 | 1229 | .Type, |
| 1220 | 1230 | .ComptimeInt, |
| ... | ... | @@ -1242,7 +1252,7 @@ fn isByRef(self: Self, ty: Type) bool { |
| 1242 | 1252 | .Frame, |
| 1243 | 1253 | .Union, |
| 1244 | 1254 | => return ty.hasCodeGenBits(), |
| 1245 | | .Int => return if (ty.intInfo(self.target).bits > 64) true else false, |
| 1255 | .Int => return if (ty.intInfo(target).bits > 64) true else false, |
| 1246 | 1256 | .ErrorUnion => { |
| 1247 | 1257 | const has_tag = ty.errorUnionSet().hasCodeGenBits(); |
| 1248 | 1258 | const has_pl = ty.errorUnionPayload().hasCodeGenBits(); |
| ... | ... | @@ -1470,7 +1480,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1470 | 1480 | const child_type = self.air.typeOfIndex(inst).childType(); |
| 1471 | 1481 | if (child_type.abiSize(self.target) == 0) return WValue{ .none = {} }; |
| 1472 | 1482 | |
| 1473 | | if (self.isByRef(child_type)) { |
| 1483 | if (isByRef(child_type, self.target)) { |
| 1474 | 1484 | return self.return_value; |
| 1475 | 1485 | } |
| 1476 | 1486 | |
| ... | ... | @@ -1487,7 +1497,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1487 | 1497 | const ret_ty = self.air.typeOf(un_op).childType(); |
| 1488 | 1498 | if (!ret_ty.hasCodeGenBits()) return WValue.none; |
| 1489 | 1499 | |
| 1490 | | if (!self.isByRef(ret_ty)) { |
| 1500 | if (!isByRef(ret_ty, self.target)) { |
| 1491 | 1501 | const result = try self.load(operand, ret_ty, 0); |
| 1492 | 1502 | try self.emitWValue(result); |
| 1493 | 1503 | } |
| ... | ... | @@ -1509,7 +1519,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1509 | 1519 | else => unreachable, |
| 1510 | 1520 | }; |
| 1511 | 1521 | const ret_ty = fn_ty.fnReturnType(); |
| 1512 | | const first_param_sret = self.isByRef(ret_ty); |
| 1522 | const first_param_sret = isByRef(ret_ty, self.target); |
| 1513 | 1523 | |
| 1514 | 1524 | const target: ?*Decl = blk: { |
| 1515 | 1525 | const func_val = self.air.value(pl_op.operand) orelse break :blk null; |
| ... | ... | @@ -1546,7 +1556,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1546 | 1556 | const operand = try self.resolveInst(pl_op.operand); |
| 1547 | 1557 | try self.emitWValue(operand); |
| 1548 | 1558 | |
| 1549 | | var fn_type = try self.genFunctype(fn_ty); |
| 1559 | var fn_type = try genFunctype(self.gpa, fn_ty, self.target); |
| 1550 | 1560 | defer fn_type.deinit(self.gpa); |
| 1551 | 1561 | |
| 1552 | 1562 | const fn_type_index = try self.bin_file.putOrGetFuncType(fn_type); |
| ... | ... | @@ -1642,7 +1652,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro |
| 1642 | 1652 | } |
| 1643 | 1653 | try self.emitWValue(lhs); |
| 1644 | 1654 | try self.emitWValue(rhs); |
| 1645 | | const valtype = try self.typeToValtype(ty); |
| 1655 | const valtype = typeToValtype(ty, self.target); |
| 1646 | 1656 | // check if we should pass by pointer or value based on ABI size |
| 1647 | 1657 | // TODO: Implement a way to get ABI values from a given type, |
| 1648 | 1658 | // that is portable across the backend, rather than copying logic. |
| ... | ... | @@ -1675,7 +1685,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1675 | 1685 | |
| 1676 | 1686 | if (!ty.hasCodeGenBits()) return WValue{ .none = {} }; |
| 1677 | 1687 | |
| 1678 | | if (self.isByRef(ty)) { |
| 1688 | if (isByRef(ty, self.target)) { |
| 1679 | 1689 | const new_local = try self.allocStack(ty); |
| 1680 | 1690 | try self.store(new_local, operand, ty, 0); |
| 1681 | 1691 | return new_local; |
| ... | ... | @@ -1712,7 +1722,7 @@ fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue { |
| 1712 | 1722 | }; |
| 1713 | 1723 | |
| 1714 | 1724 | const opcode = buildOpcode(.{ |
| 1715 | | .valtype1 = try self.typeToValtype(ty), |
| 1725 | .valtype1 = typeToValtype(ty, self.target), |
| 1716 | 1726 | .width = abi_size * 8, // use bitsize instead of byte size |
| 1717 | 1727 | .op = .load, |
| 1718 | 1728 | .signedness = signedness, |
| ... | ... | @@ -1743,7 +1753,7 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue { |
| 1743 | 1753 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1744 | 1754 | const operand_ty = self.air.typeOfIndex(inst); |
| 1745 | 1755 | |
| 1746 | | if (self.isByRef(operand_ty)) { |
| 1756 | if (isByRef(operand_ty, self.target)) { |
| 1747 | 1757 | return self.fail("TODO: Implement binary operation for type: {}", .{operand_ty}); |
| 1748 | 1758 | } |
| 1749 | 1759 | |
| ... | ... | @@ -1753,7 +1763,7 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue { |
| 1753 | 1763 | const bin_ty = self.air.typeOf(bin_op.lhs); |
| 1754 | 1764 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 1755 | 1765 | .op = op, |
| 1756 | | .valtype1 = try self.typeToValtype(bin_ty), |
| 1766 | .valtype1 = typeToValtype(bin_ty, self.target), |
| 1757 | 1767 | .signedness = if (bin_ty.isSignedInt()) .signed else .unsigned, |
| 1758 | 1768 | }); |
| 1759 | 1769 | try self.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| ... | ... | @@ -1775,7 +1785,7 @@ fn airWrapBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue { |
| 1775 | 1785 | const bin_ty = self.air.typeOf(bin_op.lhs); |
| 1776 | 1786 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 1777 | 1787 | .op = op, |
| 1778 | | .valtype1 = try self.typeToValtype(bin_ty), |
| 1788 | .valtype1 = typeToValtype(bin_ty, self.target), |
| 1779 | 1789 | .signedness = if (bin_ty.isSignedInt()) .signed else .unsigned, |
| 1780 | 1790 | }); |
| 1781 | 1791 | try self.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| ... | ... | @@ -1924,8 +1934,8 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue { |
| 1924 | 1934 | }, |
| 1925 | 1935 | .ErrorSet => switch (val.tag()) { |
| 1926 | 1936 | .@"error" => { |
| 1927 | | const error_index = self.global_error_set.get(val.getError().?).?; |
| 1928 | | return WValue{ .imm32 = error_index }; |
| 1937 | const kv = try self.module.getErrorValue(val.getError().?); |
| 1938 | return WValue{ .imm32 = kv.value }; |
| 1929 | 1939 | }, |
| 1930 | 1940 | else => return WValue{ .imm32 = 0 }, |
| 1931 | 1941 | }, |
| ... | ... | @@ -1945,7 +1955,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue { |
| 1945 | 1955 | if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef), |
| 1946 | 1956 | payload_type, |
| 1947 | 1957 | ); |
| 1948 | | const pl_ptr = if (self.isByRef(payload_type)) |
| 1958 | const pl_ptr = if (isByRef(payload_type, self.target)) |
| 1949 | 1959 | try self.buildPointerOffset(result, error_type.abiSize(self.target), .new) |
| 1950 | 1960 | else |
| 1951 | 1961 | result; |
| ... | ... | @@ -2159,8 +2169,8 @@ fn valueAsI32(self: Self, val: Value, ty: Type) i32 { |
| 2159 | 2169 | .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt())), |
| 2160 | 2170 | }, |
| 2161 | 2171 | .ErrorSet => { |
| 2162 | | const error_index = self.global_error_set.get(val.getError().?).?; |
| 2163 | | return @bitCast(i32, error_index); |
| 2172 | const kv = self.module.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function |
| 2173 | return @bitCast(i32, kv.value); |
| 2164 | 2174 | }, |
| 2165 | 2175 | else => unreachable, // Programmer called this function for an illegal type |
| 2166 | 2176 | } |
| ... | ... | @@ -2168,7 +2178,7 @@ fn valueAsI32(self: Self, val: Value, ty: Type) i32 { |
| 2168 | 2178 | |
| 2169 | 2179 | fn airBlock(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2170 | 2180 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2171 | | const block_ty = try self.genBlockType(self.air.getRefType(ty_pl.ty)); |
| 2181 | const block_ty = genBlockType(self.air.getRefType(ty_pl.ty), self.target); |
| 2172 | 2182 | const extra = self.air.extraData(Air.Block, ty_pl.payload); |
| 2173 | 2183 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 2174 | 2184 | |
| ... | ... | @@ -2265,7 +2275,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) Inner |
| 2265 | 2275 | // both lhs and rhs, as well as checking the payload are matching of lhs and rhs |
| 2266 | 2276 | return self.cmpOptionals(lhs, rhs, operand_ty, op); |
| 2267 | 2277 | } |
| 2268 | | } else if (self.isByRef(operand_ty)) { |
| 2278 | } else if (isByRef(operand_ty, self.target)) { |
| 2269 | 2279 | return self.cmpBigInt(lhs, rhs, operand_ty, op); |
| 2270 | 2280 | } |
| 2271 | 2281 | |
| ... | ... | @@ -2280,7 +2290,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) Inner |
| 2280 | 2290 | break :blk operand_ty.intInfo(self.target).signedness; |
| 2281 | 2291 | }; |
| 2282 | 2292 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 2283 | | .valtype1 = try self.typeToValtype(operand_ty), |
| 2293 | .valtype1 = typeToValtype(operand_ty, self.target), |
| 2284 | 2294 | .op = switch (op) { |
| 2285 | 2295 | .lt => .lt, |
| 2286 | 2296 | .lte => .le, |
| ... | ... | @@ -2353,13 +2363,6 @@ fn airUnreachable(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2353 | 2363 | fn airBitcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2354 | 2364 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2355 | 2365 | const operand = try self.resolveInst(ty_op.operand); |
| 2356 | | // if (operand == .constant) { |
| 2357 | | // std.debug.print("Let's take a look at this!!!!!!\n--------------------\n", .{}); |
| 2358 | | // const result = try self.allocLocal(self.air.typeOfIndex(inst)); |
| 2359 | | // try self.emitWValue(operand); |
| 2360 | | // try self.addLabel(.local_set, result.local); |
| 2361 | | // return result; |
| 2362 | | // } |
| 2363 | 2366 | return operand; |
| 2364 | 2367 | } |
| 2365 | 2368 | |
| ... | ... | @@ -2407,7 +2410,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2407 | 2410 | return self.fail("Field type '{}' too big to fit into stack frame", .{field_ty}); |
| 2408 | 2411 | }; |
| 2409 | 2412 | |
| 2410 | | if (self.isByRef(field_ty)) { |
| 2413 | if (isByRef(field_ty, self.target)) { |
| 2411 | 2414 | return self.buildPointerOffset(operand, offset, .new); |
| 2412 | 2415 | } |
| 2413 | 2416 | |
| ... | ... | @@ -2527,7 +2530,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2527 | 2530 | const val = try self.lowerConstant(case.values[0].value, target_ty); |
| 2528 | 2531 | try self.emitWValue(val); |
| 2529 | 2532 | const opcode = buildOpcode(.{ |
| 2530 | | .valtype1 = try self.typeToValtype(target_ty), |
| 2533 | .valtype1 = typeToValtype(target_ty, self.target), |
| 2531 | 2534 | .op = .ne, // not equal, because we want to jump out of this block if it does not match the condition. |
| 2532 | 2535 | .signedness = signedness, |
| 2533 | 2536 | }); |
| ... | ... | @@ -2541,7 +2544,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2541 | 2544 | const val = try self.lowerConstant(value.value, target_ty); |
| 2542 | 2545 | try self.emitWValue(val); |
| 2543 | 2546 | const opcode = buildOpcode(.{ |
| 2544 | | .valtype1 = try self.typeToValtype(target_ty), |
| 2547 | .valtype1 = typeToValtype(target_ty, self.target), |
| 2545 | 2548 | .op = .eq, |
| 2546 | 2549 | .signedness = signedness, |
| 2547 | 2550 | }); |
| ... | ... | @@ -2596,7 +2599,7 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue |
| 2596 | 2599 | const payload_ty = err_ty.errorUnionPayload(); |
| 2597 | 2600 | if (!payload_ty.hasCodeGenBits()) return WValue{ .none = {} }; |
| 2598 | 2601 | const offset = @intCast(u32, err_ty.errorUnionSet().abiSize(self.target)); |
| 2599 | | if (self.isByRef(payload_ty)) { |
| 2602 | if (isByRef(payload_ty, self.target)) { |
| 2600 | 2603 | return self.buildPointerOffset(operand, offset, .new); |
| 2601 | 2604 | } |
| 2602 | 2605 | return try self.load(operand, payload_ty, offset); |
| ... | ... | @@ -2725,7 +2728,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2725 | 2728 | |
| 2726 | 2729 | const offset = opt_ty.abiSize(self.target) - payload_ty.abiSize(self.target); |
| 2727 | 2730 | |
| 2728 | | if (self.isByRef(payload_ty)) { |
| 2731 | if (isByRef(payload_ty, self.target)) { |
| 2729 | 2732 | return self.buildPointerOffset(operand, offset, .new); |
| 2730 | 2733 | } |
| 2731 | 2734 | |
| ... | ... | @@ -2856,7 +2859,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2856 | 2859 | const result = try self.allocLocal(elem_ty); |
| 2857 | 2860 | try self.addLabel(.local_set, result.local); |
| 2858 | 2861 | |
| 2859 | | if (self.isByRef(elem_ty)) { |
| 2862 | if (isByRef(elem_ty, self.target)) { |
| 2860 | 2863 | return result; |
| 2861 | 2864 | } |
| 2862 | 2865 | return try self.load(result, elem_ty, 0); |
| ... | ... | @@ -3017,7 +3020,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3017 | 3020 | |
| 3018 | 3021 | const result = try self.allocLocal(elem_ty); |
| 3019 | 3022 | try self.addLabel(.local_set, result.local); |
| 3020 | | if (self.isByRef(elem_ty)) { |
| 3023 | if (isByRef(elem_ty, self.target)) { |
| 3021 | 3024 | return result; |
| 3022 | 3025 | } |
| 3023 | 3026 | return try self.load(result, elem_ty, 0); |
| ... | ... | @@ -3064,7 +3067,7 @@ fn airPtrBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue { |
| 3064 | 3067 | else => ptr_ty.childType(), |
| 3065 | 3068 | }; |
| 3066 | 3069 | |
| 3067 | | const valtype = try self.typeToValtype(Type.usize); |
| 3070 | const valtype = typeToValtype(Type.usize, self.target); |
| 3068 | 3071 | const mul_opcode = buildOpcode(.{ .valtype1 = valtype, .op = .mul }); |
| 3069 | 3072 | const bin_opcode = buildOpcode(.{ .valtype1 = valtype, .op = op }); |
| 3070 | 3073 | |
| ... | ... | @@ -3167,7 +3170,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3167 | 3170 | const result = try self.allocLocal(elem_ty); |
| 3168 | 3171 | try self.addLabel(.local_set, result.local); |
| 3169 | 3172 | |
| 3170 | | if (self.isByRef(elem_ty)) { |
| 3173 | if (isByRef(elem_ty, self.target)) { |
| 3171 | 3174 | return result; |
| 3172 | 3175 | } |
| 3173 | 3176 | return try self.load(result, elem_ty, 0); |
| ... | ... | @@ -3184,8 +3187,8 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3184 | 3187 | try self.emitWValue(operand); |
| 3185 | 3188 | const op = buildOpcode(.{ |
| 3186 | 3189 | .op = .trunc, |
| 3187 | | .valtype1 = try self.typeToValtype(dest_ty), |
| 3188 | | .valtype2 = try self.typeToValtype(op_ty), |
| 3190 | .valtype1 = typeToValtype(dest_ty, self.target), |
| 3191 | .valtype2 = typeToValtype(op_ty, self.target), |
| 3189 | 3192 | .signedness = if (dest_ty.isSignedInt()) .signed else .unsigned, |
| 3190 | 3193 | }); |
| 3191 | 3194 | try self.addTag(Mir.Inst.Tag.fromOpcode(op)); |
| ... | ... | @@ -3249,7 +3252,7 @@ fn cmpOptionals(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std |
| 3249 | 3252 | |
| 3250 | 3253 | try self.emitWValue(lhs_pl); |
| 3251 | 3254 | try self.emitWValue(rhs_pl); |
| 3252 | | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = try self.typeToValtype(payload_ty) }); |
| 3255 | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, self.target) }); |
| 3253 | 3256 | try self.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| 3254 | 3257 | try self.addLabel(.br_if, 0); |
| 3255 | 3258 | |