authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-04 21:55:50-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-04 21:55:50-07:00
logf7cbd92e6ca531fc19dce1f233b5c8ca0479eeb5
tree345e9325e58e5992b32a7bc6b5aeeb08ade3e2ae
parent117c0460d3f5ff05d5e2c51c2aa376b56be13096

Revert "Merge pull request #10270 from Luukdegram/behaviour-tests"

This reverts commit 725267f7c20f0ba588b472048a8c1fe1a328c714, reversing changes made to 2dae860de3494f97c9477af9282fe0131ff5c4cb. This test is failing: ```zig pub fn main() u8 { var e = foo(); const i = e catch 69; return i; } fn foo() anyerror!u8 { return 5; } ``` It's returning 69 instead of the expected value 5.

7 files changed, 287 insertions(+), 504 deletions(-)

ci/zinc/linux_test.sh-1
...@@ -6,7 +6,6 @@ ZIG=$DEBUG_STAGING/bin/zig...@@ -6,7 +6,6 @@ ZIG=$DEBUG_STAGING/bin/zig
66
7$ZIG test test/behavior.zig -fno-stage1 -fLLVM -I test7$ZIG test test/behavior.zig -fno-stage1 -fLLVM -I test
8$ZIG test test/behavior.zig -fno-stage1 -ofmt=c -I test8$ZIG test test/behavior.zig -fno-stage1 -ofmt=c -I test
9$ZIG test test/behavior.zig -fno-stage1 -target wasm32-wasi --test-cmd wasmtime --test-cmd-bin
109
11$ZIG build test-behavior -fqemu -fwasmtime10$ZIG build test-behavior -fqemu -fwasmtime
12$ZIG build test-compiler-rt -fqemu -fwasmtime11$ZIG build test-compiler-rt -fqemu -fwasmtime
src/Module.zig+4-8
...@@ -1226,20 +1226,19 @@ pub const Fn = struct {...@@ -1226,20 +1226,19 @@ pub const Fn = struct {
1226 };1226 };
12271227
1228 pub fn deinit(func: *Fn, gpa: Allocator) void {1228 pub fn deinit(func: *Fn, gpa: Allocator) void {
1229 if (func.getInferredErrorSet()) |error_set_data| {1229 if (func.getInferredErrorSet()) |map| {
1230 error_set_data.map.deinit(gpa);1230 map.deinit(gpa);
1231 error_set_data.functions.deinit(gpa);
1232 }1231 }
1233 }1232 }
12341233
1235 pub fn getInferredErrorSet(func: *Fn) ?*Type.Payload.ErrorSetInferred.Data {1234 pub fn getInferredErrorSet(func: *Fn) ?*std.StringHashMapUnmanaged(void) {
1236 const ret_ty = func.owner_decl.ty.fnReturnType();1235 const ret_ty = func.owner_decl.ty.fnReturnType();
1237 if (ret_ty.tag() == .generic_poison) {1236 if (ret_ty.tag() == .generic_poison) {
1238 return null;1237 return null;
1239 }1238 }
1240 if (ret_ty.zigTypeTag() == .ErrorUnion) {1239 if (ret_ty.zigTypeTag() == .ErrorUnion) {
1241 if (ret_ty.errorUnionSet().castTag(.error_set_inferred)) |payload| {1240 if (ret_ty.errorUnionSet().castTag(.error_set_inferred)) |payload| {
1242 return &payload.data;1241 return &payload.data.map;
1243 }1242 }
1244 }1243 }
1245 return null;1244 return null;
...@@ -1302,7 +1301,6 @@ pub const Namespace = struct {...@@ -1302,7 +1301,6 @@ pub const Namespace = struct {
1302 key.destroy(mod);1301 key.destroy(mod);
1303 }1302 }
1304 anon_decls.deinit(gpa);1303 anon_decls.deinit(gpa);
1305 ns.usingnamespace_set.deinit(gpa);
1306 }1304 }
13071305
1308 pub fn deleteAllDecls(1306 pub fn deleteAllDecls(
...@@ -1334,8 +1332,6 @@ pub const Namespace = struct {...@@ -1334,8 +1332,6 @@ pub const Namespace = struct {
1334 child_decl.destroy(mod);1332 child_decl.destroy(mod);
1335 }1333 }
1336 anon_decls.deinit(gpa);1334 anon_decls.deinit(gpa);
1337
1338 ns.usingnamespace_set.deinit(gpa);
1339 }1335 }
13401336
1341 // This renders e.g. "std.fs.Dir.OpenOptions"1337 // This renders e.g. "std.fs.Dir.OpenOptions"
src/arch/wasm/CodeGen.zig+102-270
...@@ -6,7 +6,6 @@ const testing = std.testing;...@@ -6,7 +6,6 @@ const testing = std.testing;
6const leb = std.leb;6const leb = std.leb;
7const mem = std.mem;7const mem = std.mem;
8const wasm = std.wasm;8const wasm = std.wasm;
9const log = std.log.scoped(.codegen);
109
11const Module = @import("../../Module.zig");10const Module = @import("../../Module.zig");
12const Decl = Module.Decl;11const Decl = Module.Decl;
...@@ -551,7 +550,7 @@ mir_extra: std.ArrayListUnmanaged(u32) = .{},...@@ -551,7 +550,7 @@ mir_extra: std.ArrayListUnmanaged(u32) = .{},
551initial_stack_value: WValue = .none,550initial_stack_value: WValue = .none,
552/// Arguments of this function declaration551/// Arguments of this function declaration
553/// This will be set after `resolveCallingConventionValues`552/// This will be set after `resolveCallingConventionValues`
554args: []WValue = &.{},553args: []WValue = undefined,
555/// This will only be `.none` if the function returns void, or returns an immediate.554/// This will only be `.none` if the function returns void, or returns an immediate.
556/// When it returns a pointer to the stack, the `.local` tag will be active and must be populated555/// When it returns a pointer to the stack, the `.local` tag will be active and must be populated
557/// before this function returns its execution to the caller.556/// before this function returns its execution to the caller.
...@@ -563,6 +562,8 @@ const InnerError = error{...@@ -563,6 +562,8 @@ const InnerError = error{
563 CodegenFail,562 CodegenFail,
564 /// Can occur when dereferencing a pointer that points to a `Decl` of which the analysis has failed563 /// Can occur when dereferencing a pointer that points to a `Decl` of which the analysis has failed
565 AnalysisFail,564 AnalysisFail,
565 /// Failed to emit MIR instructions to binary/textual representation.
566 EmitFail,
566 /// Compiler implementation could not handle a large integer.567 /// Compiler implementation could not handle a large integer.
567 Overflow,568 Overflow,
568};569};
...@@ -799,7 +800,7 @@ pub fn genFunc(self: *Self) InnerError!Result {...@@ -799,7 +800,7 @@ pub fn genFunc(self: *Self) InnerError!Result {
799 emit.emitMir() catch |err| switch (err) {800 emit.emitMir() catch |err| switch (err) {
800 error.EmitFail => {801 error.EmitFail => {
801 self.err_msg = emit.error_msg.?;802 self.err_msg = emit.error_msg.?;
802 return error.CodegenFail;803 return error.EmitFail;
803 },804 },
804 else => |e| return e,805 else => |e| return e,
805 };806 };
...@@ -808,34 +809,8 @@ pub fn genFunc(self: *Self) InnerError!Result {...@@ -808,34 +809,8 @@ pub fn genFunc(self: *Self) InnerError!Result {
808 return Result.appended;809 return Result.appended;
809}810}
810811
811pub fn genDecl(self: *Self) InnerError!Result {
812 const decl = self.decl;
813 assert(decl.has_tv);
814
815 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val });
816
817 if (decl.val.castTag(.function)) |func_payload| {
818 _ = func_payload;
819 return self.fail("TODO wasm backend genDecl function pointer", .{});
820 } else if (decl.val.castTag(.extern_fn)) |extern_fn| {
821 const ext_decl = extern_fn.data;
822 var func_type = try self.genFunctype(ext_decl.ty);
823 func_type.deinit(self.gpa);
824 ext_decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type);
825 return Result.appended;
826 } else {
827 const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
828 break :init_val payload.data.init;
829 } else decl.val;
830 if (init_val.tag() != .unreachable_value) {
831 return try self.genTypedValue(decl.ty, init_val);
832 }
833 return Result.appended;
834 }
835}
836
837/// Generates the wasm bytecode for the declaration belonging to `Context`812/// Generates the wasm bytecode for the declaration belonging to `Context`
838fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {813pub fn genDecl(self: *Self, ty: Type, val: Value) InnerError!Result {
839 if (val.isUndef()) {814 if (val.isUndef()) {
840 try self.code.appendNTimes(0xaa, @intCast(usize, ty.abiSize(self.target)));815 try self.code.appendNTimes(0xaa, @intCast(usize, ty.abiSize(self.target)));
841 return Result.appended;816 return Result.appended;
...@@ -847,16 +822,16 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {...@@ -847,16 +822,16 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {
847 .function => val.castTag(.function).?.data.owner_decl,822 .function => val.castTag(.function).?.data.owner_decl,
848 else => unreachable,823 else => unreachable,
849 };824 };
850 return try self.lowerDeclRef(ty, val, fn_decl);825 return try self.lowerDeclRef(fn_decl);
851 },826 },
852 .Optional => {827 .Optional => {
853 var opt_buf: Type.Payload.ElemType = undefined;828 var opt_buf: Type.Payload.ElemType = undefined;
854 const payload_type = ty.optionalChild(&opt_buf);829 const payload_type = ty.optionalChild(&opt_buf);
855 if (ty.isPtrLikeOptional()) {830 if (ty.isPtrLikeOptional()) {
856 if (val.castTag(.opt_payload)) |payload| {831 if (val.castTag(.opt_payload)) |payload| {
857 return try self.genTypedValue(payload_type, payload.data);832 return try self.genDecl(payload_type, payload.data);
858 } else if (!val.isNull()) {833 } else if (!val.isNull()) {
859 return try self.genTypedValue(payload_type, val);834 return try self.genDecl(payload_type, val);
860 } else {835 } else {
861 try self.code.appendNTimes(0, @intCast(usize, ty.abiSize(self.target)));836 try self.code.appendNTimes(0, @intCast(usize, ty.abiSize(self.target)));
862 return Result.appended;837 return Result.appended;
...@@ -864,7 +839,7 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {...@@ -864,7 +839,7 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {
864 }839 }
865 // `null-tag` byte840 // `null-tag` byte
866 try self.code.appendNTimes(@boolToInt(!val.isNull()), 4);841 try self.code.appendNTimes(@boolToInt(!val.isNull()), 4);
867 const pl_result = try self.genTypedValue(842 const pl_result = try self.genDecl(
868 payload_type,843 payload_type,
869 if (val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef),844 if (val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef),
870 );845 );
...@@ -880,7 +855,7 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {...@@ -880,7 +855,7 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {
880 if (ty.sentinel()) |sentinel| {855 if (ty.sentinel()) |sentinel| {
881 try self.code.appendSlice(payload.data);856 try self.code.appendSlice(payload.data);
882857
883 switch (try self.genTypedValue(ty.childType(), sentinel)) {858 switch (try self.genDecl(ty.childType(), sentinel)) {
884 .appended => return Result.appended,859 .appended => return Result.appended,
885 .externally_managed => |data| {860 .externally_managed => |data| {
886 try self.code.appendSlice(data);861 try self.code.appendSlice(data);
...@@ -894,20 +869,22 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {...@@ -894,20 +869,22 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {
894 const elem_vals = val.castTag(.array).?.data;869 const elem_vals = val.castTag(.array).?.data;
895 const elem_ty = ty.elemType();870 const elem_ty = ty.elemType();
896 for (elem_vals) |elem_val| {871 for (elem_vals) |elem_val| {
897 switch (try self.genTypedValue(elem_ty, elem_val)) {872 switch (try self.genDecl(elem_ty, elem_val)) {
898 .appended => {},873 .appended => {},
899 .externally_managed => |data| try self.code.appendSlice(data),874 .externally_managed => |data| {
875 try self.code.appendSlice(data);
876 },
900 }877 }
901 }878 }
902 return Result.appended;879 return Result.appended;
903 },880 },
904 else => return self.fail("TODO implement genTypedValue for array type value: {s}", .{@tagName(val.tag())}),881 else => return self.fail("TODO implement genDecl for array type value: {s}", .{@tagName(val.tag())}),
905 },882 },
906 .Int => {883 .Int => {
907 const info = ty.intInfo(self.target);884 const info = ty.intInfo(self.target);
908 const abi_size = @intCast(usize, ty.abiSize(self.target));885 const abi_size = @intCast(usize, ty.abiSize(self.target));
909 // todo: Implement integer sizes larger than 64bits886 // todo: Implement integer sizes larger than 64bits
910 if (info.bits > 64) return self.fail("TODO: Implement genTypedValue for integer bit size: {d}", .{info.bits});887 if (info.bits > 64) return self.fail("TODO: Implement genDecl for integer bit size: {d}", .{info.bits});
911 var buf: [8]u8 = undefined;888 var buf: [8]u8 = undefined;
912 if (info.signedness == .unsigned) {889 if (info.signedness == .unsigned) {
913 std.mem.writeIntLittle(u64, &buf, val.toUnsignedInt());890 std.mem.writeIntLittle(u64, &buf, val.toUnsignedInt());
...@@ -929,7 +906,8 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {...@@ -929,7 +906,8 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {
929 for (field_vals) |field_val, index| {906 for (field_vals) |field_val, index| {
930 const field_ty = ty.structFieldType(index);907 const field_ty = ty.structFieldType(index);
931 if (!field_ty.hasCodeGenBits()) continue;908 if (!field_ty.hasCodeGenBits()) continue;
932 switch (try self.genTypedValue(field_ty, field_val)) {909
910 switch (try self.genDecl(field_ty, field_val)) {
933 .appended => {},911 .appended => {},
934 .externally_managed => |payload| try self.code.appendSlice(payload),912 .externally_managed => |payload| try self.code.appendSlice(payload),
935 }913 }
...@@ -945,21 +923,21 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {...@@ -945,21 +923,21 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {
945 .Pointer => switch (val.tag()) {923 .Pointer => switch (val.tag()) {
946 .variable => {924 .variable => {
947 const decl = val.castTag(.variable).?.data.owner_decl;925 const decl = val.castTag(.variable).?.data.owner_decl;
948 return try self.lowerDeclRef(ty, val, decl);926 return try self.lowerDeclRef(decl);
949 },927 },
950 .decl_ref => {928 .decl_ref => {
951 const decl = val.castTag(.decl_ref).?.data;929 const decl = val.castTag(.decl_ref).?.data;
952 return try self.lowerDeclRef(ty, val, decl);930 return try self.lowerDeclRef(decl);
953 },931 },
954 .slice => {932 .slice => {
955 const slice = val.castTag(.slice).?.data;933 const slice = val.castTag(.slice).?.data;
956 var buf: Type.SlicePtrFieldTypeBuffer = undefined;934 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
957 const ptr_ty = ty.slicePtrFieldType(&buf);935 const ptr_ty = ty.slicePtrFieldType(&buf);
958 switch (try self.genTypedValue(ptr_ty, slice.ptr)) {936 switch (try self.genDecl(ptr_ty, slice.ptr)) {
959 .externally_managed => |data| try self.code.appendSlice(data),937 .externally_managed => |data| try self.code.appendSlice(data),
960 .appended => {},938 .appended => {},
961 }939 }
962 switch (try self.genTypedValue(Type.usize, slice.len)) {940 switch (try self.genDecl(Type.usize, slice.len)) {
963 .externally_managed => |data| try self.code.appendSlice(data),941 .externally_managed => |data| try self.code.appendSlice(data),
964 .appended => {},942 .appended => {},
965 }943 }
...@@ -971,25 +949,13 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {...@@ -971,25 +949,13 @@ fn genTypedValue(self: *Self, ty: Type, val: Value) InnerError!Result {
971 }949 }
972}950}
973951
974fn lowerDeclRef(self: *Self, ty: Type, val: Value, decl: *Module.Decl) InnerError!Result {952fn lowerDeclRef(self: *Self, decl: *Module.Decl) InnerError!Result {
975 if (ty.isSlice()) {953 decl.alive = true;
976 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
977 const slice_ty = ty.slicePtrFieldType(&buf);
978 switch (try self.genTypedValue(slice_ty, val)) {
979 .appended => {},
980 .externally_managed => |payload| try self.code.appendSlice(payload),
981 }
982 var slice_len: Value.Payload.U64 = .{
983 .base = .{ .tag = .int_u64 },
984 .data = val.sliceLen(),
985 };
986 return try self.genTypedValue(Type.usize, Value.initPayload(&slice_len.base));
987 }
988954
989 const offset = @intCast(u32, self.code.items.len);955 const offset = @intCast(u32, self.code.items.len);
990 const atom = &self.decl.link.wasm;956 const atom = &self.decl.link.wasm;
991 const target_sym_index = decl.link.wasm.sym_index;957 const target_sym_index = decl.link.wasm.sym_index;
992 decl.alive = true;958
993 if (decl.ty.zigTypeTag() == .Fn) {959 if (decl.ty.zigTypeTag() == .Fn) {
994 // We found a function pointer, so add it to our table,960 // We found a function pointer, so add it to our table,
995 // as function pointers are not allowed to be stored inside the data section,961 // as function pointers are not allowed to be stored inside the data section,
...@@ -1048,7 +1014,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) InnerError!CallWValu...@@ -1048,7 +1014,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) InnerError!CallWValu
10481014
1049 const ret_ty = fn_ty.fnReturnType();1015 const ret_ty = fn_ty.fnReturnType();
1050 switch (ret_ty.zigTypeTag()) {1016 switch (ret_ty.zigTypeTag()) {
1051 .ErrorUnion, .Optional, .Pointer => result.return_value = try self.allocLocal(Type.initTag(.i32)),1017 .ErrorUnion, .Optional => result.return_value = try self.allocLocal(Type.initTag(.i32)),
1052 .Int, .Float, .Bool, .Void, .NoReturn => {},1018 .Int, .Float, .Bool, .Void, .NoReturn => {},
1053 else => return self.fail("TODO: Implement function return type {}", .{ret_ty}),1019 else => return self.fail("TODO: Implement function return type {}", .{ret_ty}),
1054 }1020 }
...@@ -1062,11 +1028,6 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) InnerError!CallWValu...@@ -1062,11 +1028,6 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) InnerError!CallWValu
1062 };1028 };
10631029
1064 try self.moveStack(offset, result.return_value.local);1030 try self.moveStack(offset, result.return_value.local);
1065
1066 // We want to make sure the return value's stack value doesn't get overwritten,
1067 // so set initial stack value to current's position instead.
1068 try self.addLabel(.global_get, 0);
1069 try self.addLabel(.local_set, self.initial_stack_value.local);
1070 }1031 }
1071 },1032 },
1072 else => return self.fail("TODO implement function parameters for cc '{}' on wasm", .{cc}),1033 else => return self.fail("TODO implement function parameters for cc '{}' on wasm", .{cc}),
...@@ -1081,6 +1042,10 @@ fn initializeStack(self: *Self) !void {...@@ -1081,6 +1042,10 @@ fn initializeStack(self: *Self) !void {
1081 assert(self.initial_stack_value == .none);1042 assert(self.initial_stack_value == .none);
1082 // reserve space for immediate value1043 // reserve space for immediate value
1083 // get stack pointer global1044 // get stack pointer global
1045 // TODO: For now, we hardcode the stack pointer to index '0',
1046 // once the linker is further implemented, we can replace this by inserting
1047 // a relocation and have the linker resolve the correct index to the stack pointer global.
1048 // NOTE: relocations of the type GLOBAL_INDEX_LEB are 5-bytes big
1084 try self.addLabel(.global_get, 0);1049 try self.addLabel(.global_get, 0);
10851050
1086 // Reserve a local to store the current stack pointer1051 // Reserve a local to store the current stack pointer
...@@ -1109,6 +1074,8 @@ fn restoreStackPointer(self: *Self) !void {...@@ -1109,6 +1074,8 @@ fn restoreStackPointer(self: *Self) !void {
1109/// the result back into the stack pointer.1074/// the result back into the stack pointer.
1110fn moveStack(self: *Self, offset: u32, local: u32) !void {1075fn moveStack(self: *Self, offset: u32, local: u32) !void {
1111 if (offset == 0) return;1076 if (offset == 0) return;
1077 // TODO: Rather than hardcode the stack pointer to position 0,
1078 // have the linker resolve its relocation
1112 try self.addLabel(.global_get, 0);1079 try self.addLabel(.global_get, 0);
1113 try self.addImm32(@bitCast(i32, offset));1080 try self.addImm32(@bitCast(i32, offset));
1114 try self.addTag(.i32_sub);1081 try self.addTag(.i32_sub);
...@@ -1116,13 +1083,6 @@ fn moveStack(self: *Self, offset: u32, local: u32) !void {...@@ -1116,13 +1083,6 @@ fn moveStack(self: *Self, offset: u32, local: u32) !void {
1116 try self.addLabel(.global_set, 0);1083 try self.addLabel(.global_set, 0);
1117}1084}
11181085
1119/// From given zig bitsize, returns the wasm bitsize
1120fn toWasmIntBits(bits: u16) ?u16 {
1121 return for ([_]u16{ 32, 64 }) |wasm_bits| {
1122 if (bits <= wasm_bits) return wasm_bits;
1123 } else null;
1124}
1125
1126fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {1086fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1127 const air_tags = self.air.instructions.items(.tag);1087 const air_tags = self.air.instructions.items(.tag);
1128 return switch (air_tags[inst]) {1088 return switch (air_tags[inst]) {
...@@ -1169,15 +1129,11 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -1169,15 +1129,11 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1169 .load => self.airLoad(inst),1129 .load => self.airLoad(inst),
1170 .loop => self.airLoop(inst),1130 .loop => self.airLoop(inst),
1171 .not => self.airNot(inst),1131 .not => self.airNot(inst),
1172 .optional_payload => self.airOptionalPayload(inst),
1173 .optional_payload_ptr => self.airOptionalPayload(inst),
1174 .optional_payload_ptr_set => self.airOptionalPayloadPtrSet(inst),
1175 .ret => self.airRet(inst),1132 .ret => self.airRet(inst),
1176 .ret_ptr => self.airRetPtr(inst),1133 .ret_ptr => self.airRetPtr(inst),
1177 .ret_load => self.airRetLoad(inst),1134 .ret_load => self.airRetLoad(inst),
1178 .slice_len => self.airSliceLen(inst),1135 .slice_len => self.airSliceLen(inst),
1179 .slice_elem_val => self.airSliceElemVal(inst),1136 .slice_elem_val => self.airSliceElemVal(inst),
1180 .slice_ptr => self.airSlicePtr(inst),
1181 .store => self.airStore(inst),1137 .store => self.airStore(inst),
1182 .struct_field_ptr => self.airStructFieldPtr(inst),1138 .struct_field_ptr => self.airStructFieldPtr(inst),
1183 .struct_field_ptr_index_0 => self.airStructFieldPtrIndex(inst, 0),1139 .struct_field_ptr_index_0 => self.airStructFieldPtrIndex(inst, 0),
...@@ -1186,14 +1142,16 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -1186,14 +1142,16 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1186 .struct_field_ptr_index_3 => self.airStructFieldPtrIndex(inst, 3),1142 .struct_field_ptr_index_3 => self.airStructFieldPtrIndex(inst, 3),
1187 .struct_field_val => self.airStructFieldVal(inst),1143 .struct_field_val => self.airStructFieldVal(inst),
1188 .switch_br => self.airSwitchBr(inst),1144 .switch_br => self.airSwitchBr(inst),
1189 .trunc => self.airTrunc(inst),
1190 .unreach => self.airUnreachable(inst),1145 .unreach => self.airUnreachable(inst),
1191
1192 .wrap_optional => self.airWrapOptional(inst),1146 .wrap_optional => self.airWrapOptional(inst),
1147
1193 .unwrap_errunion_payload => self.airUnwrapErrUnionPayload(inst),1148 .unwrap_errunion_payload => self.airUnwrapErrUnionPayload(inst),
1194 .unwrap_errunion_err => self.airUnwrapErrUnionError(inst),1149 .unwrap_errunion_err => self.airUnwrapErrUnionError(inst),
1195 .wrap_errunion_payload => self.airWrapErrUnionPayload(inst),1150 .wrap_errunion_payload => self.airWrapErrUnionPayload(inst),
1196 .wrap_errunion_err => self.airWrapErrUnionErr(inst),1151
1152 .optional_payload => self.airOptionalPayload(inst),
1153 .optional_payload_ptr => self.airOptionalPayload(inst),
1154 .optional_payload_ptr_set => self.airOptionalPayloadPtrSet(inst),
1197 else => |tag| self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),1155 else => |tag| self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
1198 };1156 };
1199}1157}
...@@ -1235,15 +1193,15 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -1235,15 +1193,15 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1235 // local, containing the offset to the stack position1193 // local, containing the offset to the stack position
1236 const local = try self.allocLocal(Type.initTag(.i32)); // always pointer therefore i321194 const local = try self.allocLocal(Type.initTag(.i32)); // always pointer therefore i32
1237 try self.moveStack(@intCast(u32, abi_size), local.local);1195 try self.moveStack(@intCast(u32, abi_size), local.local);
1196
1238 return local;1197 return local;
1239}1198}
12401199
1241fn airRetLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {1200fn airRetLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1242 const un_op = self.air.instructions.items(.data)[inst].un_op;1201 const un_op = self.air.instructions.items(.data)[inst].un_op;
1243 const operand = self.resolveInst(un_op);1202 const operand = self.resolveInst(un_op);
12441203 const result = try self.load(operand, self.air.typeOf(un_op), 0);
1245 const result = try self.load(operand, self.air.typeOf(un_op).childType(), 0);1204 try self.addLabel(.local_get, result.local);
1246 try self.emitWValue(result);
1247 try self.restoreStackPointer();1205 try self.restoreStackPointer();
1248 try self.addTag(.@"return");1206 try self.addTag(.@"return");
1249 return .none;1207 return .none;
...@@ -1273,25 +1231,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -1273,25 +1231,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1273 };1231 };
12741232
1275 for (args) |arg| {1233 for (args) |arg| {
1276 const arg_ref = @intToEnum(Air.Inst.Ref, arg);1234 const arg_val = self.resolveInst(@intToEnum(Air.Inst.Ref, arg));
1277 const arg_val = self.resolveInst(arg_ref);1235 try self.emitWValue(arg_val);
1278
1279 const arg_ty = self.air.typeOf(arg_ref);
1280 switch (arg_ty.zigTypeTag()) {
1281 .Struct, .Pointer, .Optional, .ErrorUnion => {
1282 // single pointer can be passed directly
1283 if (arg_ty.isSinglePointer() or arg_val != .constant) {
1284 try self.emitWValue(arg_val);
1285 continue;
1286 }
1287 const abi_size = arg_ty.abiSize(self.target);
1288 const arg_local = try self.allocLocal(Type.initTag(.i32));
1289 try self.moveStack(@intCast(u32, abi_size), arg_local.local);
1290 try self.store(arg_local, arg_val, arg_ty, 0);
1291 try self.emitWValue(arg_local);
1292 },
1293 else => try self.emitWValue(arg_val),
1294 }
1295 }1236 }
12961237
1297 if (target) |direct| {1238 if (target) |direct| {
...@@ -1301,11 +1242,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -1301,11 +1242,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1301 // so load its value onto the stack1242 // so load its value onto the stack
1302 std.debug.assert(ty.zigTypeTag() == .Pointer);1243 std.debug.assert(ty.zigTypeTag() == .Pointer);
1303 const operand = self.resolveInst(pl_op.operand);1244 const operand = self.resolveInst(pl_op.operand);
1304 const offset = switch (operand) {1245 try self.emitWValue(operand);
1305 .local_with_offset => |with_offset| with_offset.offset,1246 const result = try self.load(operand, fn_ty, operand.local_with_offset.offset);
1306 else => @as(u32, 0),
1307 };
1308 const result = try self.load(operand, fn_ty, offset);
1309 try self.addLabel(.local_get, result.local);1247 try self.addLabel(.local_get, result.local);
13101248
1311 var fn_type = try self.genFunctype(fn_ty);1249 var fn_type = try self.genFunctype(fn_ty);
...@@ -1316,12 +1254,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -1316,12 +1254,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1316 }1254 }
13171255
1318 const ret_ty = fn_ty.fnReturnType();1256 const ret_ty = fn_ty.fnReturnType();
1319 if (!ret_ty.hasCodeGenBits()) return WValue.none;1257 switch (ret_ty.zigTypeTag()) {
13201258 .Void, .NoReturn => return WValue.none,
1321 const result_local = try self.allocLocal(ret_ty);1259 else => {
1322 try self.addLabel(.local_set, result_local.local);1260 const result_local = try self.allocLocal(ret_ty);
1323 // if the result was allocated on the virtual stack, we must load1261 try self.addLabel(.local_set, result_local.local);
1324 return result_local;1262 return result_local;
1263 },
1264 }
1325}1265}
13261266
1327fn airAlloc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {1267fn airAlloc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
...@@ -1338,6 +1278,7 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -1338,6 +1278,7 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1338 // local, containing the offset to the stack position1278 // local, containing the offset to the stack position
1339 const local = try self.allocLocal(Type.initTag(.i32)); // always pointer therefore i321279 const local = try self.allocLocal(Type.initTag(.i32)); // always pointer therefore i32
1340 try self.moveStack(@intCast(u32, abi_size), local.local);1280 try self.moveStack(@intCast(u32, abi_size), local.local);
1281
1341 return local;1282 return local;
1342}1283}
13431284
...@@ -1387,15 +1328,16 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro...@@ -1387,15 +1328,16 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro
1387 return;1328 return;
1388 },1329 },
1389 .local => {1330 .local => {
1390 if (payload_ty.hasCodeGenBits()) {1331 // Load values from `rhs` stack position and store in `lhs` instead
1391 try self.store(lhs, rhs, payload_ty, payload_offset);1332 const tag_local = try self.load(rhs, tag_ty, 0);
1392 }1333 const payload_local = try self.load(rhs, payload_ty, payload_offset);
1393 return try self.store(lhs, rhs, tag_ty, 0);1334
1335 try self.store(lhs, tag_local, tag_ty, 0);
1336 return try self.store(lhs, payload_local, payload_ty, payload_offset);
1394 },1337 },
1395 .local_with_offset => |with_offset| {1338 .local_with_offset => |with_offset| {
1396 const tag_local = try self.allocLocal(tag_ty);1339 const tag_local = try self.allocLocal(tag_ty);
1397 try self.addImm32(0);1340 try self.addImm32(0);
1398 try self.addLabel(.local_set, tag_local.local);
1399 try self.store(lhs, tag_local, tag_ty, 0);1341 try self.store(lhs, tag_local, tag_ty, 0);
14001342
1401 return try self.store(1343 return try self.store(
...@@ -1424,18 +1366,6 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro...@@ -1424,18 +1366,6 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro
1424 }1366 }
1425 return;1367 return;
1426 },1368 },
1427 .Pointer => {
1428 if (ty.isSlice() and rhs == .constant) {
1429 try self.emitWValue(rhs);
1430 const len_local = try self.allocLocal(Type.usize);
1431 const ptr_local = try self.allocLocal(Type.usize);
1432 try self.addLabel(.local_set, len_local.local);
1433 try self.addLabel(.local_set, ptr_local.local);
1434 try self.store(lhs, ptr_local, Type.usize, 0);
1435 try self.store(lhs, len_local, Type.usize, self.target.cpu.arch.ptrBitWidth() / 8);
1436 return;
1437 }
1438 },
1439 else => {},1369 else => {},
1440 }1370 }
1441 try self.emitWValue(lhs);1371 try self.emitWValue(lhs);
...@@ -1472,8 +1402,6 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -1472,8 +1402,6 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1472 const operand = self.resolveInst(ty_op.operand);1402 const operand = self.resolveInst(ty_op.operand);
1473 const ty = self.air.getRefType(ty_op.ty);1403 const ty = self.air.getRefType(ty_op.ty);
14741404
1475 if (!ty.hasCodeGenBits()) return WValue{ .none = {} };
1476
1477 return switch (ty.zigTypeTag()) {1405 return switch (ty.zigTypeTag()) {
1478 .Struct, .ErrorUnion, .Optional, .Pointer => operand, // pass as pointer1406 .Struct, .ErrorUnion, .Optional, .Pointer => operand, // pass as pointer
1479 else => switch (operand) {1407 else => switch (operand) {
...@@ -1487,10 +1415,7 @@ fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue {...@@ -1487,10 +1415,7 @@ fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue {
1487 // load local's value from memory by its stack position1415 // load local's value from memory by its stack position
1488 try self.emitWValue(operand);1416 try self.emitWValue(operand);
1489 // Build the opcode with the right bitsize1417 // Build the opcode with the right bitsize
1490 const signedness: std.builtin.Signedness = if (ty.isUnsignedInt() or ty.zigTypeTag() == .ErrorSet)1418 const signedness: std.builtin.Signedness = if (ty.isUnsignedInt()) .unsigned else .signed;
1491 .unsigned
1492 else
1493 .signed;
1494 // check if we should pass by pointer or value based on ABI size1419 // check if we should pass by pointer or value based on ABI size
1495 // TODO: Implement a way to get ABI values from a given type,1420 // TODO: Implement a way to get ABI values from a given type,
1496 // that is portable across the backend, rather than copying logic.1421 // that is portable across the backend, rather than copying logic.
...@@ -1601,7 +1526,6 @@ fn airWrapBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue {...@@ -1601,7 +1526,6 @@ fn airWrapBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue {
1601}1526}
16021527
1603fn emitConstant(self: *Self, val: Value, ty: Type) InnerError!void {1528fn emitConstant(self: *Self, val: Value, ty: Type) InnerError!void {
1604 if (val.isUndefDeep()) return self.emitUndefined(ty);
1605 switch (ty.zigTypeTag()) {1529 switch (ty.zigTypeTag()) {
1606 .Int => {1530 .Int => {
1607 const int_info = ty.intInfo(self.target);1531 const int_info = ty.intInfo(self.target);
...@@ -1629,21 +1553,10 @@ fn emitConstant(self: *Self, val: Value, ty: Type) InnerError!void {...@@ -1629,21 +1553,10 @@ fn emitConstant(self: *Self, val: Value, ty: Type) InnerError!void {
1629 }1553 }
1630 },1554 },
1631 .Pointer => {1555 .Pointer => {
1632 if (val.castTag(.slice)) |slice| {1556 if (val.castTag(.decl_ref)) |payload| {
1633 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1634 try self.emitConstant(slice.data.ptr, ty.slicePtrFieldType(&buf));
1635 try self.emitConstant(slice.data.len, Type.usize);
1636 } else if (val.castTag(.decl_ref)) |payload| {
1637 const decl = payload.data;1557 const decl = payload.data;
1638 decl.alive = true;1558 decl.alive = true;
1639 // Function pointers use a table index, rather than a memory address1559 try self.addLabel(.memory_address, decl.link.wasm.sym_index);
1640 if (decl.ty.zigTypeTag() == .Fn) {
1641 const target_sym_index = decl.link.wasm.sym_index;
1642 try self.bin_file.addTableFunction(target_sym_index);
1643 try self.addLabel(.function_index, target_sym_index);
1644 } else {
1645 try self.addLabel(.memory_address, decl.link.wasm.sym_index);
1646 }
1647 } else return self.fail("Wasm TODO: emitConstant for other const pointer tag {s}", .{val.tag()});1560 } else return self.fail("Wasm TODO: emitConstant for other const pointer tag {s}", .{val.tag()});
1648 },1561 },
1649 .Void => {},1562 .Void => {},
...@@ -1718,22 +1631,6 @@ fn emitConstant(self: *Self, val: Value, ty: Type) InnerError!void {...@@ -1718,22 +1631,6 @@ fn emitConstant(self: *Self, val: Value, ty: Type) InnerError!void {
1718 }1631 }
1719}1632}
17201633
1721fn emitUndefined(self: *Self, ty: Type) InnerError!void {
1722 switch (ty.zigTypeTag()) {
1723 .Int => switch (ty.intInfo(self.target).bits) {
1724 0...32 => try self.addImm32(@bitCast(i32, @as(u32, 0xaaaaaaaa))),
1725 33...64 => try self.addImm64(0xaaaaaaaaaaaaaaaa),
1726 else => |bits| return self.fail("Wasm TODO: emitUndefined for integer bitsize: {d}", .{bits}),
1727 },
1728 .Float => switch (ty.floatBits(self.target)) {
1729 0...32 => try self.addInst(.{ .tag = .f32_const, .data = .{ .float32 = @bitCast(f32, @as(u32, 0xaaaaaaaa)) } }),
1730 33...64 => try self.addFloat64(@bitCast(f64, @as(u64, 0xaaaaaaaaaaaaaaaa))),
1731 else => |bits| return self.fail("Wasm TODO: emitUndefined for float bitsize: {d}", .{bits}),
1732 },
1733 else => return self.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty}),
1734 }
1735}
1736
1737/// Returns a `Value` as a signed 32 bit value.1634/// Returns a `Value` as a signed 32 bit value.
1738/// It's illegal to provide a value with a type that cannot be represented1635/// It's illegal to provide a value with a type that cannot be represented
1739/// as an integer value.1636/// as an integer value.
...@@ -1884,7 +1781,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) Inner...@@ -1884,7 +1781,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) Inner
1884 });1781 });
1885 try self.addTag(Mir.Inst.Tag.fromOpcode(opcode));1782 try self.addTag(Mir.Inst.Tag.fromOpcode(opcode));
18861783
1887 const cmp_tmp = try self.allocLocal(Type.initTag(.i32)); // bool is always i321784 const cmp_tmp = try self.allocLocal(lhs_ty);
1888 try self.addLabel(.local_set, cmp_tmp.local);1785 try self.addLabel(.local_set, cmp_tmp.local);
1889 return cmp_tmp;1786 return cmp_tmp;
1890}1787}
...@@ -2184,25 +2081,9 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -2184,25 +2081,9 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2184}2081}
21852082
2186fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {2083fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2187 if (self.liveness.isUnused(inst)) return WValue.none;
2188 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2189 const operand = self.resolveInst(ty_op.operand);
2190
2191 const op_ty = self.air.typeOf(ty_op.operand);
2192 if (!op_ty.hasCodeGenBits()) return WValue.none;
2193 const err_ty = self.air.getRefType(ty_op.ty);
2194 const offset = err_ty.errorUnionSet().abiSize(self.target);
2195
2196 return WValue{ .local_with_offset = .{
2197 .local = operand.local,
2198 .offset = @intCast(u32, offset),
2199 } };
2200}
2201
2202fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2203 if (self.liveness.isUnused(inst)) return WValue.none;
2204 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2084 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2205 return self.resolveInst(ty_op.operand);2085 _ = ty_op;
2086 return self.fail("TODO: wasm airWrapErrUnionPayload", .{});
2206}2087}
22072088
2208fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue {2089fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
...@@ -2211,26 +2092,20 @@ fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -2211,26 +2092,20 @@ fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2211 const operand = self.resolveInst(ty_op.operand);2092 const operand = self.resolveInst(ty_op.operand);
2212 const ref_ty = self.air.typeOf(ty_op.operand);2093 const ref_ty = self.air.typeOf(ty_op.operand);
2213 const ref_info = ref_ty.intInfo(self.target);2094 const ref_info = ref_ty.intInfo(self.target);
2214 const wanted_info = ty.intInfo(self.target);2095 const op_bits = ref_info.bits;
2096 const wanted_bits = ty.intInfo(self.target).bits;
22152097
2216 const op_bits = toWasmIntBits(ref_info.bits) orelse2098 if (op_bits > 32 and wanted_bits <= 32) {
2217 return self.fail("TODO: Wasm intcast integer types of bitsize: {d}", .{ref_info.bits});
2218 const wanted_bits = toWasmIntBits(wanted_info.bits) orelse
2219 return self.fail("TODO: Wasm intcast integer types of bitsize: {d}", .{wanted_info.bits});
2220
2221 // hot path
2222 if (op_bits == wanted_bits) return operand;
2223
2224 if (op_bits > 32 and wanted_bits == 32) {
2225 try self.emitWValue(operand);2099 try self.emitWValue(operand);
2226 try self.addTag(.i32_wrap_i64);2100 try self.addTag(.i32_wrap_i64);
2227 } else if (op_bits == 32 and wanted_bits > 32) {2101 } else if (op_bits <= 32 and wanted_bits > 32) {
2228 try self.emitWValue(operand);2102 try self.emitWValue(operand);
2229 try self.addTag(switch (ref_info.signedness) {2103 try self.addTag(switch (ref_info.signedness) {
2230 .signed => .i64_extend_i32_s,2104 .signed => .i64_extend_i32_s,
2231 .unsigned => .i64_extend_i32_u,2105 .unsigned => .i64_extend_i32_u,
2232 });2106 });
2233 }2107 } else return operand;
2108
2234 const result = try self.allocLocal(ty);2109 const result = try self.allocLocal(ty);
2235 try self.addLabel(.local_set, result.local);2110 try self.addLabel(.local_set, result.local);
2236 return result;2111 return result;
...@@ -2305,7 +2180,19 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -2305,7 +2180,19 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2305 const operand = self.resolveInst(ty_op.operand);2180 const operand = self.resolveInst(ty_op.operand);
2306 const pointer_width = self.target.cpu.arch.ptrBitWidth() / 8;2181 const pointer_width = self.target.cpu.arch.ptrBitWidth() / 8;
23072182
2308 return try self.load(operand, Type.usize, pointer_width);2183 // Get pointer to slice
2184 try self.emitWValue(operand);
2185 // length of slice is stored after the pointer of the slice
2186 const extra_index = try self.addExtra(Mir.MemArg{
2187 .offset = pointer_width,
2188 .alignment = pointer_width,
2189 });
2190 try self.addInst(.{ .tag = .i32_load, .data = .{ .payload = extra_index } });
2191
2192 const result = try self.allocLocal(Type.initTag(.i32)); // pointer is always i32
2193 // store slice length in local
2194 try self.addLabel(.local_set, result.local);
2195 return result;
2309}2196}
23102197
2311fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {2198fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
...@@ -2319,8 +2206,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -2319,8 +2206,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2319 const elem_size = elem_ty.abiSize(self.target);2206 const elem_size = elem_ty.abiSize(self.target);
23202207
2321 // load pointer onto stack2208 // load pointer onto stack
2322 const slice_ptr = try self.load(slice, slice_ty, 0);2209 try self.emitWValue(slice);
2323 try self.addLabel(.local_get, slice_ptr.local);
23242210
2325 // calculate index into slice2211 // calculate index into slice
2326 try self.emitWValue(index);2212 try self.emitWValue(index);
...@@ -2328,79 +2214,25 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -2328,79 +2214,25 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2328 try self.addTag(.i32_mul);2214 try self.addTag(.i32_mul);
2329 try self.addTag(.i32_add);2215 try self.addTag(.i32_add);
23302216
2331 const result = try self.allocLocal(elem_ty);2217 const abi_size = if (elem_size < 8)
2332 try self.addLabel(.local_set, result.local);2218 @intCast(u8, elem_size)
2333 return switch (elem_ty.zigTypeTag()) {2219 else
2334 // pass as pointer2220 @as(u8, 4); // elements larger than 8 bytes will be passed by pointer
2335 .Pointer, .Struct, .Optional => result,
2336 // pass by value
2337 else => try self.load(result, elem_ty, 0),
2338 };
2339}
2340
2341fn airSlicePtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2342 if (self.liveness.isUnused(inst)) return WValue.none;
2343 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2344 const operand = self.resolveInst(ty_op.operand);
2345 return try self.load(operand, Type.usize, 0);
2346}
2347
2348fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2349 if (self.liveness.isUnused(inst)) return WValue.none;
2350 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2351 const operand = self.resolveInst(ty_op.operand);
2352 const op_ty = self.air.typeOf(ty_op.operand);
2353 const int_info = self.air.getRefType(ty_op.ty).intInfo(self.target);
2354 const wanted_bits = int_info.bits;
2355 const result = try self.allocLocal(self.air.getRefType(ty_op.ty));
2356 const op_bits = op_ty.intInfo(self.target).bits;
2357
2358 const wasm_bits = toWasmIntBits(wanted_bits) orelse
2359 return self.fail("TODO: Implement wasm integer truncation for integer bitsize: {d}", .{wanted_bits});
2360
2361 // Use wasm's instruction to wrap from 64bit to 32bit integer when possible
2362 if (op_bits == 64 and wanted_bits == 32) {
2363 try self.emitWValue(operand);
2364 try self.addTag(.i32_wrap_i64);
2365 try self.addLabel(.local_set, result.local);
2366 return result;
2367 }
23682221
2369 // Any other truncation must be done manually2222 const extra_index = try self.addExtra(Mir.MemArg{
2370 if (int_info.signedness == .unsigned) {2223 .offset = 0,
2371 const mask = (@as(u65, 1) << @intCast(u7, wanted_bits)) - 1;2224 .alignment = elem_ty.abiAlignment(self.target),
2372 try self.emitWValue(operand);2225 });
2373 switch (wasm_bits) {2226 const signedness: std.builtin.Signedness = if (elem_ty.isUnsignedInt()) .unsigned else .signed;
2374 32 => {2227 const opcode = buildOpcode(.{
2375 try self.addImm32(@bitCast(i32, @intCast(u32, mask)));2228 .valtype1 = try self.typeToValtype(elem_ty),
2376 try self.addTag(.i32_and);2229 .width = abi_size * 8,
2377 },2230 .op = .load,
2378 64 => {2231 .signedness = signedness,
2379 try self.addImm64(@intCast(u64, mask));2232 });
2380 try self.addTag(.i64_and);2233 try self.addInst(.{ .tag = Mir.Inst.Tag.fromOpcode(opcode), .data = .{ .payload = extra_index } });
2381 },
2382 else => unreachable,
2383 }
2384 } else {
2385 const shift_bits = wasm_bits - wanted_bits;
2386 try self.emitWValue(operand);
2387 switch (wasm_bits) {
2388 32 => {
2389 try self.addImm32(@bitCast(i16, shift_bits));
2390 try self.addTag(.i32_shl);
2391 try self.addImm32(@bitCast(i16, shift_bits));
2392 try self.addTag(.i32_shr_s);
2393 },
2394 64 => {
2395 try self.addImm64(shift_bits);
2396 try self.addTag(.i64_shl);
2397 try self.addImm64(shift_bits);
2398 try self.addTag(.i64_shr_s);
2399 },
2400 else => unreachable,
2401 }
2402 }
24032234
2235 const result = try self.allocLocal(elem_ty);
2404 try self.addLabel(.local_set, result.local);2236 try self.addLabel(.local_set, result.local);
2405 return result;2237 return result;
2406}2238}
src/arch/wasm/Emit.zig+1-22
...@@ -50,7 +50,6 @@ pub fn emitMir(emit: *Emit) InnerError!void {...@@ -50,7 +50,6 @@ pub fn emitMir(emit: *Emit) InnerError!void {
50 .call_indirect => try emit.emitCallIndirect(inst),50 .call_indirect => try emit.emitCallIndirect(inst),
51 .global_get => try emit.emitGlobal(tag, inst),51 .global_get => try emit.emitGlobal(tag, inst),
52 .global_set => try emit.emitGlobal(tag, inst),52 .global_set => try emit.emitGlobal(tag, inst),
53 .function_index => try emit.emitFunctionIndex(inst),
54 .memory_address => try emit.emitMemAddress(inst),53 .memory_address => try emit.emitMemAddress(inst),
5554
56 // immediates55 // immediates
...@@ -148,11 +147,6 @@ pub fn emitMir(emit: *Emit) InnerError!void {...@@ -148,11 +147,6 @@ pub fn emitMir(emit: *Emit) InnerError!void {
148 .i64_div_s => try emit.emitTag(tag),147 .i64_div_s => try emit.emitTag(tag),
149 .i64_div_u => try emit.emitTag(tag),148 .i64_div_u => try emit.emitTag(tag),
150 .i64_and => try emit.emitTag(tag),149 .i64_and => try emit.emitTag(tag),
151 .i64_or => try emit.emitTag(tag),
152 .i64_xor => try emit.emitTag(tag),
153 .i64_shl => try emit.emitTag(tag),
154 .i64_shr_s => try emit.emitTag(tag),
155 .i64_shr_u => try emit.emitTag(tag),
156 .i32_wrap_i64 => try emit.emitTag(tag),150 .i32_wrap_i64 => try emit.emitTag(tag),
157 .i64_extend_i32_s => try emit.emitTag(tag),151 .i64_extend_i32_s => try emit.emitTag(tag),
158 .i64_extend_i32_u => try emit.emitTag(tag),152 .i64_extend_i32_u => try emit.emitTag(tag),
...@@ -241,7 +235,7 @@ fn emitImm64(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -241,7 +235,7 @@ fn emitImm64(emit: *Emit, inst: Mir.Inst.Index) !void {
241 const extra_index = emit.mir.instructions.items(.data)[inst].payload;235 const extra_index = emit.mir.instructions.items(.data)[inst].payload;
242 const value = emit.mir.extraData(Mir.Imm64, extra_index);236 const value = emit.mir.extraData(Mir.Imm64, extra_index);
243 try emit.code.append(std.wasm.opcode(.i64_const));237 try emit.code.append(std.wasm.opcode(.i64_const));
244 try leb128.writeILEB128(emit.code.writer(), @bitCast(i64, value.data.toU64()));238 try leb128.writeULEB128(emit.code.writer(), value.data.toU64());
245}239}
246240
247fn emitFloat32(emit: *Emit, inst: Mir.Inst.Index) !void {241fn emitFloat32(emit: *Emit, inst: Mir.Inst.Index) !void {
...@@ -290,21 +284,6 @@ fn emitCallIndirect(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -290,21 +284,6 @@ fn emitCallIndirect(emit: *Emit, inst: Mir.Inst.Index) !void {
290 try leb128.writeULEB128(emit.code.writer(), label);284 try leb128.writeULEB128(emit.code.writer(), label);
291}285}
292286
293fn emitFunctionIndex(emit: *Emit, inst: Mir.Inst.Index) !void {
294 const symbol_index = emit.mir.instructions.items(.data)[inst].label;
295 try emit.code.append(std.wasm.opcode(.i32_const));
296 const index_offset = emit.offset();
297 var buf: [5]u8 = undefined;
298 leb128.writeUnsignedFixed(5, &buf, symbol_index);
299 try emit.code.appendSlice(&buf);
300
301 try emit.decl.link.wasm.relocs.append(emit.bin_file.allocator, .{
302 .offset = index_offset,
303 .index = symbol_index,
304 .relocation_type = .R_WASM_TABLE_INDEX_SLEB,
305 });
306}
307
308fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void {287fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void {
309 const symbol_index = emit.mir.instructions.items(.data)[inst].label;288 const symbol_index = emit.mir.instructions.items(.data)[inst].label;
310 try emit.code.append(std.wasm.opcode(.i32_const));289 try emit.code.append(std.wasm.opcode(.i32_const));
src/arch/wasm/Mir.zig+2-18
...@@ -348,16 +348,6 @@ pub const Inst = struct {...@@ -348,16 +348,6 @@ pub const Inst = struct {
348 /// Uses `tag`348 /// Uses `tag`
349 i64_and = 0x83,349 i64_and = 0x83,
350 /// Uses `tag`350 /// Uses `tag`
351 i64_or = 0x84,
352 /// Uses `tag`
353 i64_xor = 0x85,
354 /// Uses `tag`
355 i64_shl = 0x86,
356 /// Uses `tag`
357 i64_shr_s = 0x87,
358 /// Uses `tag`
359 i64_shr_u = 0x88,
360 /// Uses `tag`
361 i32_wrap_i64 = 0xA7,351 i32_wrap_i64 = 0xA7,
362 /// Uses `tag`352 /// Uses `tag`
363 i64_extend_i32_s = 0xAC,353 i64_extend_i32_s = 0xAC,
...@@ -373,17 +363,11 @@ pub const Inst = struct {...@@ -373,17 +363,11 @@ pub const Inst = struct {
373 i64_extend16_s = 0xC3,363 i64_extend16_s = 0xC3,
374 /// Uses `tag`364 /// Uses `tag`
375 i64_extend32_s = 0xC4,365 i64_extend32_s = 0xC4,
376 /// Contains a symbol to a function pointer
377 /// uses `label`
378 ///
379 /// Note: This uses `0xFE` as value as it is unused and not reserved
380 /// by the wasm specification, making it safe to use.
381 function_index = 0xFE,
382 /// Contains a symbol to a memory address366 /// Contains a symbol to a memory address
383 /// Uses `label`367 /// Uses `label`
384 ///368 ///
385 /// Note: This uses `0xFF` as value as it is unused and not reserved369 /// Note: This uses `0xFF` as value as it is unused and not-reserved
386 /// by the wasm specification, making it safe to use.370 /// by the wasm specification, making it safe to use
387 memory_address = 0xFF,371 memory_address = 0xFF,
388372
389 /// From a given wasm opcode, returns a MIR tag.373 /// From a given wasm opcode, returns a MIR tag.
src/link/Wasm.zig+6-9
...@@ -162,8 +162,9 @@ pub fn deinit(self: *Wasm) void {...@@ -162,8 +162,9 @@ pub fn deinit(self: *Wasm) void {
162 decl.link.wasm.deinit(self.base.allocator);162 decl.link.wasm.deinit(self.base.allocator);
163 }163 }
164164
165 for (self.func_types.items) |*func_type| {165 for (self.func_types.items) |func_type| {
166 func_type.deinit(self.base.allocator);166 self.base.allocator.free(func_type.params);
167 self.base.allocator.free(func_type.returns);
167 }168 }
168 for (self.segment_info.items) |segment_info| {169 for (self.segment_info.items) |segment_info| {
169 self.base.allocator.free(segment_info.name);170 self.base.allocator.free(segment_info.name);
...@@ -277,7 +278,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {...@@ -277,7 +278,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
277 defer codegen.deinit();278 defer codegen.deinit();
278279
279 // generate the 'code' section for the function declaration280 // generate the 'code' section for the function declaration
280 const result = codegen.genDecl() catch |err| switch (err) {281 const result = codegen.genDecl(decl.ty, decl.val) catch |err| switch (err) {
281 error.CodegenFail => {282 error.CodegenFail => {
282 decl.analysis = .codegen_failure;283 decl.analysis = .codegen_failure;
283 try module.failed_decls.put(module.gpa, decl, codegen.err_msg);284 try module.failed_decls.put(module.gpa, decl, codegen.err_msg);
...@@ -297,7 +298,6 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, result: CodeGen.Result, cod...@@ -297,7 +298,6 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, result: CodeGen.Result, cod
297298
298 if (decl.isExtern()) {299 if (decl.isExtern()) {
299 try self.addOrUpdateImport(decl);300 try self.addOrUpdateImport(decl);
300 return;
301 }301 }
302302
303 if (code.len == 0) return;303 if (code.len == 0) return;
...@@ -574,6 +574,7 @@ fn resetState(self: *Wasm) void {...@@ -574,6 +574,7 @@ fn resetState(self: *Wasm) void {
574 self.segments.clearRetainingCapacity();574 self.segments.clearRetainingCapacity();
575 self.segment_info.clearRetainingCapacity();575 self.segment_info.clearRetainingCapacity();
576 self.data_segments.clearRetainingCapacity();576 self.data_segments.clearRetainingCapacity();
577 self.function_table.clearRetainingCapacity();
577 self.atoms.clearRetainingCapacity();578 self.atoms.clearRetainingCapacity();
578 self.code_section_index = null;579 self.code_section_index = null;
579}580}
...@@ -683,16 +684,12 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {...@@ -683,16 +684,12 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
683 );684 );
684 }685 }
685686
686 // Table section
687 if (self.function_table.count() > 0) {687 if (self.function_table.count() > 0) {
688 const header_offset = try reserveVecSectionHeader(file);688 const header_offset = try reserveVecSectionHeader(file);
689 const writer = file.writer();689 const writer = file.writer();
690690
691 try leb.writeULEB128(writer, wasm.reftype(.funcref));691 try leb.writeULEB128(writer, wasm.reftype(.funcref));
692 try emitLimits(writer, .{692 try emitLimits(writer, .{ .min = 1, .max = null });
693 .min = @intCast(u32, self.function_table.count()),
694 .max = null,
695 });
696693
697 try writeVecSectionHeader(694 try writeVecSectionHeader(
698 file,695 file,
test/behavior.zig+172-176
...@@ -1,202 +1,198 @@...@@ -1,202 +1,198 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
22
3test {3test {
4 // Tests that pass for stage1, stage2, the C -and wasm backend.4 // Tests that pass for stage1, stage2, and the C backend.
5 _ = @import("behavior/align.zig");
5 _ = @import("behavior/basic.zig");6 _ = @import("behavior/basic.zig");
6 _ = @import("behavior/bitcast.zig");7 _ = @import("behavior/bitcast.zig");
8 _ = @import("behavior/bool.zig");
7 _ = @import("behavior/bugs/624.zig");9 _ = @import("behavior/bugs/624.zig");
8 _ = @import("behavior/bugs/655.zig");10 _ = @import("behavior/bugs/655.zig");
9 _ = @import("behavior/bugs/679.zig");11 _ = @import("behavior/bugs/679.zig");
12 _ = @import("behavior/bugs/704.zig");
10 _ = @import("behavior/bugs/1111.zig");13 _ = @import("behavior/bugs/1111.zig");
11 _ = @import("behavior/bugs/1486.zig");14 _ = @import("behavior/bugs/1486.zig");
12 _ = @import("behavior/bugs/2346.zig");15 _ = @import("behavior/bugs/2346.zig");
16 _ = @import("behavior/bugs/2692.zig");
17 _ = @import("behavior/bugs/2889.zig");
18 _ = @import("behavior/bugs/3046.zig");
19 _ = @import("behavior/bugs/3586.zig");
20 _ = @import("behavior/bugs/4560.zig");
21 _ = @import("behavior/bugs/4769_a.zig");
22 _ = @import("behavior/bugs/4769_b.zig");
23 _ = @import("behavior/bugs/4954.zig");
13 _ = @import("behavior/bugs/6850.zig");24 _ = @import("behavior/bugs/6850.zig");
25 _ = @import("behavior/byval_arg_var.zig");
26 _ = @import("behavior/call.zig");
27 _ = @import("behavior/cast.zig");
28 _ = @import("behavior/defer.zig");
14 _ = @import("behavior/enum.zig");29 _ = @import("behavior/enum.zig");
30 _ = @import("behavior/error.zig");
31 _ = @import("behavior/fn_in_struct_in_comptime.zig");
32 _ = @import("behavior/generics.zig");
15 _ = @import("behavior/hasdecl.zig");33 _ = @import("behavior/hasdecl.zig");
16 _ = @import("behavior/hasfield.zig");34 _ = @import("behavior/hasfield.zig");
35 _ = @import("behavior/if.zig");
17 _ = @import("behavior/import.zig");36 _ = @import("behavior/import.zig");
37 _ = @import("behavior/incomplete_struct_param_tld.zig");
38 _ = @import("behavior/int128.zig");
39 _ = @import("behavior/inttoptr.zig");
40 _ = @import("behavior/member_func.zig");
41 _ = @import("behavior/null.zig");
42 _ = @import("behavior/optional.zig");
43 _ = @import("behavior/pointers.zig");
44 _ = @import("behavior/ptrcast.zig");
18 _ = @import("behavior/pub_enum.zig");45 _ = @import("behavior/pub_enum.zig");
46 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
19 _ = @import("behavior/slice_sentinel_comptime.zig");47 _ = @import("behavior/slice_sentinel_comptime.zig");
48 _ = @import("behavior/struct.zig");
49 _ = @import("behavior/this.zig");
50 _ = @import("behavior/translate_c_macros.zig");
20 _ = @import("behavior/truncate.zig");51 _ = @import("behavior/truncate.zig");
52 _ = @import("behavior/underscore.zig");
21 _ = @import("behavior/usingnamespace.zig");53 _ = @import("behavior/usingnamespace.zig");
54 _ = @import("behavior/while.zig");
2255
23 // Tests that pass for stage1, stage2 and the C backend, but not for the wasm backend56 if (builtin.object_format != .c) {
24 if (!builtin.zig_is_stage2 or (builtin.zig_is_stage2 and builtin.stage2_arch != .wasm32)) {57 // Tests that pass for stage1 and stage2 but not the C backend.
25 _ = @import("behavior/align.zig");58 _ = @import("behavior/align_llvm.zig");
26 _ = @import("behavior/bool.zig");59 _ = @import("behavior/alignof.zig");
27 _ = @import("behavior/bugs/704.zig");60 _ = @import("behavior/array.zig");
28 _ = @import("behavior/bugs/2692.zig");61 _ = @import("behavior/atomics.zig");
29 _ = @import("behavior/bugs/2889.zig");62 _ = @import("behavior/basic_llvm.zig");
30 _ = @import("behavior/bugs/3046.zig");63 _ = @import("behavior/bugs/394.zig");
31 _ = @import("behavior/bugs/3586.zig");64 _ = @import("behavior/bugs/656.zig");
32 _ = @import("behavior/bugs/4560.zig");65 _ = @import("behavior/bugs/1277.zig");
33 _ = @import("behavior/bugs/4769_a.zig");66 _ = @import("behavior/bugs/1381.zig");
34 _ = @import("behavior/bugs/4769_b.zig");67 _ = @import("behavior/bugs/1500.zig");
35 _ = @import("behavior/bugs/4954.zig");68 _ = @import("behavior/bugs/1741.zig");
36 _ = @import("behavior/byval_arg_var.zig");69 _ = @import("behavior/bugs/2006.zig");
37 _ = @import("behavior/call.zig");70 _ = @import("behavior/bugs/2578.zig");
38 _ = @import("behavior/cast.zig");71 _ = @import("behavior/bugs/3007.zig");
39 _ = @import("behavior/defer.zig");72 _ = @import("behavior/bugs/3112.zig");
40 _ = @import("behavior/error.zig");73 _ = @import("behavior/bugs/7250.zig");
41 _ = @import("behavior/fn_in_struct_in_comptime.zig");74 _ = @import("behavior/cast_llvm.zig");
42 _ = @import("behavior/generics.zig");75 _ = @import("behavior/eval.zig");
43 _ = @import("behavior/if.zig");76 _ = @import("behavior/floatop.zig");
44 _ = @import("behavior/incomplete_struct_param_tld.zig");77 _ = @import("behavior/fn.zig");
45 _ = @import("behavior/int128.zig");78 _ = @import("behavior/for.zig");
46 _ = @import("behavior/inttoptr.zig");79 _ = @import("behavior/generics_llvm.zig");
47 _ = @import("behavior/member_func.zig");80 _ = @import("behavior/math.zig");
48 _ = @import("behavior/null.zig");81 _ = @import("behavior/maximum_minimum.zig");
49 _ = @import("behavior/optional.zig");82 _ = @import("behavior/namespace_depends_on_compile_var.zig");
50 _ = @import("behavior/pointers.zig");83 _ = @import("behavior/null_llvm.zig");
51 _ = @import("behavior/ptrcast.zig");84 _ = @import("behavior/optional_llvm.zig");
52 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");85 _ = @import("behavior/popcount.zig");
53 _ = @import("behavior/struct.zig");86 _ = @import("behavior/saturating_arithmetic.zig");
54 _ = @import("behavior/this.zig");87 _ = @import("behavior/sizeof_and_typeof.zig");
55 _ = @import("behavior/translate_c_macros.zig");88 _ = @import("behavior/slice.zig");
56 _ = @import("behavior/underscore.zig");89 _ = @import("behavior/struct_llvm.zig");
57 _ = @import("behavior/while.zig");90 _ = @import("behavior/switch.zig");
91 _ = @import("behavior/undefined.zig");
92 _ = @import("behavior/union.zig");
93 _ = @import("behavior/void.zig");
94 _ = @import("behavior/widening.zig");
5895
59 if (builtin.object_format != .c) {96 if (builtin.zig_is_stage2) {
60 // Tests that pass for stage1 and stage2 but not the C backend and wasm backend.97 // When all comptime_memory.zig tests pass, #9646 can be closed.
61 _ = @import("behavior/align_llvm.zig");98 // _ = @import("behavior/comptime_memory.zig");
62 _ = @import("behavior/alignof.zig");99 _ = @import("behavior/slice_stage2.zig");
63 _ = @import("behavior/array.zig");100 } else {
64 _ = @import("behavior/atomics.zig");101 _ = @import("behavior/align_stage1.zig");
65 _ = @import("behavior/basic_llvm.zig");102 _ = @import("behavior/array_stage1.zig");
66 _ = @import("behavior/bugs/394.zig");103 if (builtin.os.tag != .wasi) {
67 _ = @import("behavior/bugs/656.zig");104 _ = @import("behavior/asm.zig");
68 _ = @import("behavior/bugs/1277.zig");105 _ = @import("behavior/async_fn.zig");
69 _ = @import("behavior/bugs/1381.zig");106 }
70 _ = @import("behavior/bugs/1500.zig");107 _ = @import("behavior/await_struct.zig");
71 _ = @import("behavior/bugs/1741.zig");108 _ = @import("behavior/bit_shifting.zig");
72 _ = @import("behavior/bugs/2006.zig");109 _ = @import("behavior/bitcast_stage1.zig");
73 _ = @import("behavior/bugs/2578.zig");110 _ = @import("behavior/bitreverse.zig");
74 _ = @import("behavior/bugs/3007.zig");111 _ = @import("behavior/bugs/421.zig");
75 _ = @import("behavior/bugs/3112.zig");112 _ = @import("behavior/bugs/529.zig");
76 _ = @import("behavior/bugs/7250.zig");113 _ = @import("behavior/bugs/718.zig");
77 _ = @import("behavior/cast_llvm.zig");114 _ = @import("behavior/bugs/726.zig");
78 _ = @import("behavior/eval.zig");115 _ = @import("behavior/bugs/828.zig");
79 _ = @import("behavior/floatop.zig");116 _ = @import("behavior/bugs/920.zig");
80 _ = @import("behavior/fn.zig");117 _ = @import("behavior/bugs/1025.zig");
81 _ = @import("behavior/for.zig");118 _ = @import("behavior/bugs/1076.zig");
82 _ = @import("behavior/generics_llvm.zig");119 _ = @import("behavior/bugs/1120.zig");
83 _ = @import("behavior/math.zig");120 _ = @import("behavior/bugs/1310.zig");
84 _ = @import("behavior/maximum_minimum.zig");121 _ = @import("behavior/bugs/1322.zig");
85 _ = @import("behavior/namespace_depends_on_compile_var.zig");122 _ = @import("behavior/bugs/1421.zig");
86 _ = @import("behavior/null_llvm.zig");123 _ = @import("behavior/bugs/1442.zig");
87 _ = @import("behavior/optional_llvm.zig");124 _ = @import("behavior/bugs/1607.zig");
88 _ = @import("behavior/popcount.zig");125 _ = @import("behavior/bugs/1735.zig");
89 _ = @import("behavior/saturating_arithmetic.zig");126 _ = @import("behavior/bugs/1851.zig");
90 _ = @import("behavior/sizeof_and_typeof.zig");127 _ = @import("behavior/bugs/1914.zig");
91 _ = @import("behavior/slice.zig");128 _ = @import("behavior/bugs/2114.zig");
92 _ = @import("behavior/struct_llvm.zig");129 _ = @import("behavior/bugs/3367.zig");
93 _ = @import("behavior/switch.zig");130 _ = @import("behavior/bugs/3384.zig");
94 _ = @import("behavior/undefined.zig");131 _ = @import("behavior/bugs/3742.zig");
95 _ = @import("behavior/union.zig");132 _ = @import("behavior/bugs/3779.zig");
96 _ = @import("behavior/void.zig");133 _ = @import("behavior/bugs/4328.zig");
97 _ = @import("behavior/widening.zig");134 _ = @import("behavior/bugs/5398.zig");
98135 _ = @import("behavior/bugs/5413.zig");
99 if (builtin.zig_is_stage2) {136 _ = @import("behavior/bugs/5474.zig");
100 // When all comptime_memory.zig tests pass, #9646 can be closed.137 _ = @import("behavior/bugs/5487.zig");
101 // _ = @import("behavior/comptime_memory.zig");138 _ = @import("behavior/bugs/6456.zig");
102 _ = @import("behavior/slice_stage2.zig");139 _ = @import("behavior/bugs/6781.zig");
103 } else {140 _ = @import("behavior/bugs/7003.zig");
104 _ = @import("behavior/align_stage1.zig");141 _ = @import("behavior/bugs/7027.zig");
105 _ = @import("behavior/array_stage1.zig");142 _ = @import("behavior/bugs/7047.zig");
106 if (builtin.os.tag != .wasi) {143 _ = @import("behavior/bugs/9584.zig");
107 _ = @import("behavior/asm.zig");144 _ = @import("behavior/bugs/9967.zig");
108 _ = @import("behavior/async_fn.zig");145 _ = @import("behavior/bugs/10147.zig");
109 }146 _ = @import("behavior/byteswap.zig");
110 _ = @import("behavior/await_struct.zig");147 _ = @import("behavior/call_stage1.zig");
111 _ = @import("behavior/bit_shifting.zig");148 _ = @import("behavior/cast_stage1.zig");
112 _ = @import("behavior/bitcast_stage1.zig");149 _ = @import("behavior/const_slice_child.zig");
113 _ = @import("behavior/bitreverse.zig");150 _ = @import("behavior/defer_stage1.zig");
114 _ = @import("behavior/bugs/421.zig");151 _ = @import("behavior/enum_stage1.zig");
115 _ = @import("behavior/bugs/529.zig");152 _ = @import("behavior/error_stage1.zig");
116 _ = @import("behavior/bugs/718.zig");153 _ = @import("behavior/eval_stage1.zig");
117 _ = @import("behavior/bugs/726.zig");154 _ = @import("behavior/field_parent_ptr.zig");
118 _ = @import("behavior/bugs/828.zig");155 _ = @import("behavior/floatop_stage1.zig");
119 _ = @import("behavior/bugs/920.zig");156 _ = @import("behavior/fn_stage1.zig");
120 _ = @import("behavior/bugs/1025.zig");157 _ = @import("behavior/fn_delegation.zig");
121 _ = @import("behavior/bugs/1076.zig");158 _ = @import("behavior/for_stage1.zig");
122 _ = @import("behavior/bugs/1120.zig");159 _ = @import("behavior/if_stage1.zig");
123 _ = @import("behavior/bugs/1310.zig");160 _ = @import("behavior/ir_block_deps.zig");
124 _ = @import("behavior/bugs/1322.zig");161 _ = @import("behavior/math_stage1.zig");
125 _ = @import("behavior/bugs/1421.zig");162 _ = @import("behavior/merge_error_sets.zig");
126 _ = @import("behavior/bugs/1442.zig");163 _ = @import("behavior/misc.zig");
127 _ = @import("behavior/bugs/1607.zig");164 _ = @import("behavior/muladd.zig");
128 _ = @import("behavior/bugs/1735.zig");165 _ = @import("behavior/null_stage1.zig");
129 _ = @import("behavior/bugs/1851.zig");166 _ = @import("behavior/optional_stage1.zig");
130 _ = @import("behavior/bugs/1914.zig");167 _ = @import("behavior/pointers_stage1.zig");
131 _ = @import("behavior/bugs/2114.zig");168 _ = @import("behavior/popcount_stage1.zig");
132 _ = @import("behavior/bugs/3367.zig");169 _ = @import("behavior/ptrcast_stage1.zig");
133 _ = @import("behavior/bugs/3384.zig");170 _ = @import("behavior/reflection.zig");
134 _ = @import("behavior/bugs/3742.zig");171 _ = @import("behavior/select.zig");
135 _ = @import("behavior/bugs/3779.zig");172 _ = @import("behavior/shuffle.zig");
136 _ = @import("behavior/bugs/4328.zig");173 _ = @import("behavior/sizeof_and_typeof_stage1.zig");
137 _ = @import("behavior/bugs/5398.zig");174 _ = @import("behavior/slice_stage1.zig");
138 _ = @import("behavior/bugs/5413.zig");175 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
139 _ = @import("behavior/bugs/5474.zig");176 _ = @import("behavior/struct_contains_slice_of_itself.zig");
140 _ = @import("behavior/bugs/5487.zig");177 _ = @import("behavior/struct_stage1.zig");
141 _ = @import("behavior/bugs/6456.zig");178 _ = @import("behavior/switch_prong_err_enum.zig");
142 _ = @import("behavior/bugs/6781.zig");179 _ = @import("behavior/switch_prong_implicit_cast.zig");
143 _ = @import("behavior/bugs/7003.zig");180 _ = @import("behavior/switch_stage1.zig");
144 _ = @import("behavior/bugs/7027.zig");181 _ = @import("behavior/try.zig");
145 _ = @import("behavior/bugs/7047.zig");182 _ = @import("behavior/tuple.zig");
146 _ = @import("behavior/bugs/9584.zig");183 _ = @import("behavior/type.zig");
147 _ = @import("behavior/bugs/9967.zig");184 _ = @import("behavior/type_info.zig");
148 _ = @import("behavior/bugs/10147.zig");185 _ = @import("behavior/typename.zig");
149 _ = @import("behavior/byteswap.zig");186 _ = @import("behavior/union_stage1.zig");
150 _ = @import("behavior/call_stage1.zig");187 _ = @import("behavior/union_with_members.zig");
151 _ = @import("behavior/cast_stage1.zig");188 _ = @import("behavior/var_args.zig");
152 _ = @import("behavior/const_slice_child.zig");189 _ = @import("behavior/vector.zig");
153 _ = @import("behavior/defer_stage1.zig");190 if (builtin.target.cpu.arch == .wasm32) {
154 _ = @import("behavior/enum_stage1.zig");191 _ = @import("behavior/wasm.zig");
155 _ = @import("behavior/error_stage1.zig");
156 _ = @import("behavior/eval_stage1.zig");
157 _ = @import("behavior/field_parent_ptr.zig");
158 _ = @import("behavior/floatop_stage1.zig");
159 _ = @import("behavior/fn_stage1.zig");
160 _ = @import("behavior/fn_delegation.zig");
161 _ = @import("behavior/for_stage1.zig");
162 _ = @import("behavior/if_stage1.zig");
163 _ = @import("behavior/ir_block_deps.zig");
164 _ = @import("behavior/math_stage1.zig");
165 _ = @import("behavior/merge_error_sets.zig");
166 _ = @import("behavior/misc.zig");
167 _ = @import("behavior/muladd.zig");
168 _ = @import("behavior/null_stage1.zig");
169 _ = @import("behavior/optional_stage1.zig");
170 _ = @import("behavior/pointers_stage1.zig");
171 _ = @import("behavior/popcount_stage1.zig");
172 _ = @import("behavior/ptrcast_stage1.zig");
173 _ = @import("behavior/reflection.zig");
174 _ = @import("behavior/select.zig");
175 _ = @import("behavior/shuffle.zig");
176 _ = @import("behavior/sizeof_and_typeof_stage1.zig");
177 _ = @import("behavior/slice_stage1.zig");
178 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
179 _ = @import("behavior/struct_contains_slice_of_itself.zig");
180 _ = @import("behavior/struct_stage1.zig");
181 _ = @import("behavior/switch_prong_err_enum.zig");
182 _ = @import("behavior/switch_prong_implicit_cast.zig");
183 _ = @import("behavior/switch_stage1.zig");
184 _ = @import("behavior/try.zig");
185 _ = @import("behavior/tuple.zig");
186 _ = @import("behavior/type.zig");
187 _ = @import("behavior/type_info.zig");
188 _ = @import("behavior/typename.zig");
189 _ = @import("behavior/union_stage1.zig");
190 _ = @import("behavior/union_with_members.zig");
191 _ = @import("behavior/var_args.zig");
192 _ = @import("behavior/vector.zig");
193 if (builtin.target.cpu.arch == .wasm32) {
194 _ = @import("behavior/wasm.zig");
195 }
196 _ = @import("behavior/while_stage1.zig");
197 _ = @import("behavior/src.zig");
198 _ = @import("behavior/translate_c_macros_stage1.zig");
199 }192 }
193 _ = @import("behavior/while_stage1.zig");
194 _ = @import("behavior/src.zig");
195 _ = @import("behavior/translate_c_macros_stage1.zig");
200 }196 }
201 }197 }
202}198}