authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-28 11:34:23+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-07-28 11:34:23+02:00
log91c17979f10db4fdc6639b176c0563718f060f47
tree7ae29768d6ad64678c389685752f2848ecec76ba
parent1fba9e1280efb935e935f09a196ae35d5391ed48
parentb20007daf74f44cfc86c5f2d2d7e2acde079e127
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20807 from Rexicon226/riscv

riscv: more backend progress

64 files changed, 3516 insertions(+), 3279 deletions(-)

CMakeLists.txt+5-2
...@@ -535,11 +535,14 @@ set(ZIG_STAGE2_SOURCES...@@ -535,11 +535,14 @@ set(ZIG_STAGE2_SOURCES
535 src/arch/arm/Mir.zig535 src/arch/arm/Mir.zig
536 src/arch/arm/abi.zig536 src/arch/arm/abi.zig
537 src/arch/arm/bits.zig537 src/arch/arm/bits.zig
538 src/arch/riscv64/abi.zig
539 src/arch/riscv64/bits.zig
538 src/arch/riscv64/CodeGen.zig540 src/arch/riscv64/CodeGen.zig
539 src/arch/riscv64/Emit.zig541 src/arch/riscv64/Emit.zig
542 src/arch/riscv64/encoding.zig
543 src/arch/riscv64/Lower.zig
540 src/arch/riscv64/Mir.zig544 src/arch/riscv64/Mir.zig
541 src/arch/riscv64/abi.zig545 src/arch/riscv64/mnem.zig
542 src/arch/riscv64/bits.zig
543 src/arch/sparc64/CodeGen.zig546 src/arch/sparc64/CodeGen.zig
544 src/arch/sparc64/Emit.zig547 src/arch/sparc64/Emit.zig
545 src/arch/sparc64/Mir.zig548 src/arch/sparc64/Mir.zig
lib/compiler/test_runner.zig+8-7
...@@ -282,11 +282,13 @@ pub fn mainSimple() anyerror!void {...@@ -282,11 +282,13 @@ pub fn mainSimple() anyerror!void {
282 const stderr = if (comptime enable_print) std.io.getStdErr() else {};282 const stderr = if (comptime enable_print) std.io.getStdErr() else {};
283283
284 for (builtin.test_functions) |test_fn| {284 for (builtin.test_functions) |test_fn| {
285 if (enable_print) {285 if (test_fn.func()) |_| {
286 stderr.writeAll(test_fn.name) catch {};286 if (enable_print) {
287 stderr.writeAll("... ") catch {};287 stderr.writeAll(test_fn.name) catch {};
288 }288 stderr.writeAll("... ") catch {};
289 test_fn.func() catch |err| {289 stderr.writeAll("PASS\n") catch {};
290 }
291 } else |err| if (enable_print) {
290 if (enable_print) {292 if (enable_print) {
291 stderr.writeAll(test_fn.name) catch {};293 stderr.writeAll(test_fn.name) catch {};
292 stderr.writeAll("... ") catch {};294 stderr.writeAll("... ") catch {};
...@@ -300,8 +302,7 @@ pub fn mainSimple() anyerror!void {...@@ -300,8 +302,7 @@ pub fn mainSimple() anyerror!void {
300 if (enable_print) stderr.writeAll("SKIP\n") catch {};302 if (enable_print) stderr.writeAll("SKIP\n") catch {};
301 skipped += 1;303 skipped += 1;
302 continue;304 continue;
303 };305 }
304 if (enable_print) stderr.writeAll("PASS\n") catch {};
305 passed += 1;306 passed += 1;
306 }307 }
307 if (enable_print and print_summary) {308 if (enable_print and print_summary) {
lib/std/Thread.zig+1-1
...@@ -385,7 +385,7 @@ pub fn yield() YieldError!void {...@@ -385,7 +385,7 @@ pub fn yield() YieldError!void {
385}385}
386386
387/// State to synchronize detachment of spawner thread to spawned thread387/// State to synchronize detachment of spawner thread to spawned thread
388const Completion = std.atomic.Value(enum(u8) {388const Completion = std.atomic.Value(enum(if (builtin.zig_backend == .stage2_riscv64) u32 else u8) {
389 running,389 running,
390 detached,390 detached,
391 completed,391 completed,
lib/std/builtin.zig+2-8
...@@ -775,14 +775,8 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr...@@ -775,14 +775,8 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr
775 }775 }
776776
777 if (builtin.zig_backend == .stage2_riscv64) {777 if (builtin.zig_backend == .stage2_riscv64) {
778 asm volatile ("ecall"778 std.debug.print("panic: {s}\n", .{msg});
779 :779 @breakpoint();
780 : [number] "{a7}" (64),
781 [arg1] "{a0}" (1),
782 [arg2] "{a1}" (@intFromPtr(msg.ptr)),
783 [arg3] "{a2}" (msg.len),
784 : "memory"
785 );
786 std.posix.exit(127);780 std.posix.exit(127);
787 }781 }
788782
lib/std/start.zig+5-42
...@@ -20,8 +20,7 @@ pub const simplified_logic =...@@ -20,8 +20,7 @@ pub const simplified_logic =
20 builtin.zig_backend == .stage2_arm or20 builtin.zig_backend == .stage2_arm or
21 builtin.zig_backend == .stage2_sparc64 or21 builtin.zig_backend == .stage2_sparc64 or
22 builtin.cpu.arch == .spirv32 or22 builtin.cpu.arch == .spirv32 or
23 builtin.cpu.arch == .spirv64 or23 builtin.cpu.arch == .spirv64;
24 builtin.zig_backend == .stage2_riscv64;
2524
26comptime {25comptime {
27 // No matter what, we import the root file, so that any export, test, comptime26 // No matter what, we import the root file, so that any export, test, comptime
...@@ -41,10 +40,6 @@ comptime {...@@ -41,10 +40,6 @@ comptime {
41 } else if (builtin.os.tag == .opencl) {40 } else if (builtin.os.tag == .opencl) {
42 if (@hasDecl(root, "main"))41 if (@hasDecl(root, "main"))
43 @export(spirvMain2, .{ .name = "main" });42 @export(spirvMain2, .{ .name = "main" });
44 } else if (native_arch.isRISCV()) {
45 if (!@hasDecl(root, "_start")) {
46 @export(riscv_start, .{ .name = "_start" });
47 }
48 } else {43 } else {
49 if (!@hasDecl(root, "_start")) {44 if (!@hasDecl(root, "_start")) {
50 @export(_start2, .{ .name = "_start" });45 @export(_start2, .{ .name = "_start" });
...@@ -206,42 +201,6 @@ fn wasi_start() callconv(.C) void {...@@ -206,42 +201,6 @@ fn wasi_start() callconv(.C) void {
206 }201 }
207}202}
208203
209fn riscv_start() callconv(.C) noreturn {
210 std.process.exit(switch (@typeInfo(@typeInfo(@TypeOf(root.main)).Fn.return_type.?)) {
211 .NoReturn => root.main(),
212 .Void => ret: {
213 root.main();
214 break :ret 0;
215 },
216 .Int => |info| ret: {
217 if (info.bits != 8 or info.signedness == .signed) {
218 @compileError(bad_main_ret);
219 }
220 break :ret root.main();
221 },
222 .ErrorUnion => ret: {
223 const result = root.main() catch {
224 const stderr = std.io.getStdErr().writer();
225 stderr.writeAll("failed with error\n") catch {
226 @panic("failed to print when main returned error");
227 };
228 break :ret 1;
229 };
230 switch (@typeInfo(@TypeOf(result))) {
231 .Void => break :ret 0,
232 .Int => |info| {
233 if (info.bits != 8 or info.signedness == .signed) {
234 @compileError(bad_main_ret);
235 }
236 return result;
237 },
238 else => @compileError(bad_main_ret),
239 }
240 },
241 else => @compileError(bad_main_ret),
242 });
243}
244
245fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv(.C) usize {204fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv(.C) usize {
246 uefi.handle = handle;205 uefi.handle = handle;
247 uefi.system_table = system_table;206 uefi.system_table = system_table;
...@@ -563,6 +522,10 @@ pub inline fn callMain() u8 {...@@ -563,6 +522,10 @@ pub inline fn callMain() u8 {
563 if (@typeInfo(ReturnType) != .ErrorUnion) @compileError(bad_main_ret);522 if (@typeInfo(ReturnType) != .ErrorUnion) @compileError(bad_main_ret);
564523
565 const result = root.main() catch |err| {524 const result = root.main() catch |err| {
525 if (builtin.zig_backend == .stage2_riscv64) {
526 std.debug.print("error: failed with error\n", .{});
527 return 1;
528 }
566 std.log.err("{s}", .{@errorName(err)});529 std.log.err("{s}", .{@errorName(err)});
567 if (@errorReturnTrace()) |trace| {530 if (@errorReturnTrace()) |trace| {
568 std.debug.dumpStackTrace(trace.*);531 std.debug.dumpStackTrace(trace.*);
src/Compilation.zig+1
...@@ -6334,6 +6334,7 @@ fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool {...@@ -6334,6 +6334,7 @@ fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool {
6334 }6334 }
6335 return switch (target_util.zigBackend(target, use_llvm)) {6335 return switch (target_util.zigBackend(target, use_llvm)) {
6336 .stage2_llvm => true,6336 .stage2_llvm => true,
6337 .stage2_riscv64 => true,
6337 .stage2_x86_64 => if (target.ofmt == .elf or target.ofmt == .macho) true else build_options.have_llvm,6338 .stage2_x86_64 => if (target.ofmt == .elf or target.ofmt == .macho) true else build_options.have_llvm,
6338 else => build_options.have_llvm,6339 else => build_options.have_llvm,
6339 };6340 };
src/arch/riscv64/CodeGen.zig+1914-894
...@@ -37,6 +37,10 @@ const DebugInfoOutput = codegen.DebugInfoOutput;...@@ -37,6 +37,10 @@ const DebugInfoOutput = codegen.DebugInfoOutput;
37const bits = @import("bits.zig");37const bits = @import("bits.zig");
38const abi = @import("abi.zig");38const abi = @import("abi.zig");
39const Lower = @import("Lower.zig");39const Lower = @import("Lower.zig");
40const mnem_import = @import("mnem.zig");
41const Mnemonic = mnem_import.Mnemonic;
42const Pseudo = mnem_import.Pseudo;
43const encoding = @import("encoding.zig");
4044
41const Register = bits.Register;45const Register = bits.Register;
42const CSR = bits.CSR;46const CSR = bits.CSR;
...@@ -45,19 +49,18 @@ const Memory = bits.Memory;...@@ -45,19 +49,18 @@ const Memory = bits.Memory;
45const FrameIndex = bits.FrameIndex;49const FrameIndex = bits.FrameIndex;
46const RegisterManager = abi.RegisterManager;50const RegisterManager = abi.RegisterManager;
47const RegisterLock = RegisterManager.RegisterLock;51const RegisterLock = RegisterManager.RegisterLock;
52const Instruction = encoding.Instruction;
4853
49const InnerError = CodeGenError || error{OutOfRegisters};54const InnerError = CodeGenError || error{OutOfRegisters};
5055
51pt: Zcu.PerThread,56pt: Zcu.PerThread,
52air: Air,57air: Air,
53liveness: Liveness,58liveness: Liveness,
54zcu: *Zcu,
55bin_file: *link.File,59bin_file: *link.File,
56gpa: Allocator,60gpa: Allocator,
5761
58mod: *Package.Module,62mod: *Package.Module,
59target: *const std.Target,63target: *const std.Target,
60func_index: InternPool.Index,
61debug_output: DebugInfoOutput,64debug_output: DebugInfoOutput,
62err_msg: ?*ErrorMsg,65err_msg: ?*ErrorMsg,
63args: []MCValue,66args: []MCValue,
...@@ -67,7 +70,8 @@ arg_index: usize,...@@ -67,7 +70,8 @@ arg_index: usize,
67src_loc: Zcu.LazySrcLoc,70src_loc: Zcu.LazySrcLoc,
6871
69mir_instructions: std.MultiArrayList(Mir.Inst) = .{},72mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
70mir_extra: std.ArrayListUnmanaged(u32) = .{},73
74owner: Owner,
7175
72/// Byte offset within the source file of the ending curly.76/// Byte offset within the source file of the ending curly.
73end_di_line: u32,77end_di_line: u32,
...@@ -113,6 +117,34 @@ const SymbolOffset = struct { sym: u32, off: i32 = 0 };...@@ -113,6 +117,34 @@ const SymbolOffset = struct { sym: u32, off: i32 = 0 };
113const RegisterOffset = struct { reg: Register, off: i32 = 0 };117const RegisterOffset = struct { reg: Register, off: i32 = 0 };
114pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };118pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
115119
120const Owner = union(enum) {
121 func_index: InternPool.Index,
122 lazy_sym: link.File.LazySymbol,
123
124 fn getDecl(owner: Owner, zcu: *Zcu) InternPool.DeclIndex {
125 return switch (owner) {
126 .func_index => |func_index| zcu.funcOwnerDeclIndex(func_index),
127 .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(zcu),
128 };
129 }
130
131 fn getSymbolIndex(owner: Owner, func: *Func) !u32 {
132 const pt = func.pt;
133 switch (owner) {
134 .func_index => |func_index| {
135 const decl_index = func.pt.zcu.funcOwnerDeclIndex(func_index);
136 const elf_file = func.bin_file.cast(link.File.Elf).?;
137 return elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
138 },
139 .lazy_sym => |lazy_sym| {
140 const elf_file = func.bin_file.cast(link.File.Elf).?;
141 return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
142 func.fail("{s} creating lazy symbol", .{@errorName(err)});
143 },
144 }
145 }
146};
147
116const MCValue = union(enum) {148const MCValue = union(enum) {
117 /// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc.149 /// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc.
118 /// TODO Look into deleting this tag and using `dead` instead, since every use150 /// TODO Look into deleting this tag and using `dead` instead, since every use
...@@ -131,8 +163,12 @@ const MCValue = union(enum) {...@@ -131,8 +163,12 @@ const MCValue = union(enum) {
131 immediate: u64,163 immediate: u64,
132 /// The value doesn't exist in memory yet.164 /// The value doesn't exist in memory yet.
133 load_symbol: SymbolOffset,165 load_symbol: SymbolOffset,
166 /// A TLV value.
167 load_tlv: u32,
134 /// The address of the memory location not-yet-allocated by the linker.168 /// The address of the memory location not-yet-allocated by the linker.
135 lea_symbol: SymbolOffset,169 lea_symbol: SymbolOffset,
170 /// The address of a TLV value.
171 lea_tlv: u32,
136 /// The value is in a target-specific register.172 /// The value is in a target-specific register.
137 register: Register,173 register: Register,
138 /// The value is split across two registers174 /// The value is split across two registers
...@@ -189,6 +225,7 @@ const MCValue = union(enum) {...@@ -189,6 +225,7 @@ const MCValue = union(enum) {
189 .lea_frame,225 .lea_frame,
190 .undef,226 .undef,
191 .lea_symbol,227 .lea_symbol,
228 .lea_tlv,
192 .air_ref,229 .air_ref,
193 .reserved_frame,230 .reserved_frame,
194 => false,231 => false,
...@@ -198,6 +235,7 @@ const MCValue = union(enum) {...@@ -198,6 +235,7 @@ const MCValue = union(enum) {
198 .register_offset,235 .register_offset,
199 .load_frame,236 .load_frame,
200 .load_symbol,237 .load_symbol,
238 .load_tlv,
201 .indirect,239 .indirect,
202 => true,240 => true,
203 };241 };
...@@ -216,10 +254,12 @@ const MCValue = union(enum) {...@@ -216,10 +254,12 @@ const MCValue = union(enum) {
216 .undef,254 .undef,
217 .air_ref,255 .air_ref,
218 .lea_symbol,256 .lea_symbol,
257 .lea_tlv,
219 .reserved_frame,258 .reserved_frame,
220 => unreachable, // not in memory259 => unreachable, // not in memory
221260
222 .load_symbol => |sym_off| .{ .lea_symbol = sym_off },261 .load_symbol => |sym_off| .{ .lea_symbol = sym_off },
262 .load_tlv => |sym| .{ .lea_tlv = sym },
223 .memory => |addr| .{ .immediate = addr },263 .memory => |addr| .{ .immediate = addr },
224 .load_frame => |off| .{ .lea_frame = off },264 .load_frame => |off| .{ .lea_frame = off },
225 .indirect => |reg_off| switch (reg_off.off) {265 .indirect => |reg_off| switch (reg_off.off) {
...@@ -238,17 +278,19 @@ const MCValue = union(enum) {...@@ -238,17 +278,19 @@ const MCValue = union(enum) {
238 .indirect,278 .indirect,
239 .undef,279 .undef,
240 .air_ref,280 .air_ref,
241 .load_frame,
242 .register_pair,281 .register_pair,
282 .load_frame,
243 .load_symbol,283 .load_symbol,
284 .load_tlv,
244 .reserved_frame,285 .reserved_frame,
245 => unreachable, // not a pointer286 => unreachable, // not a pointer
246287
247 .immediate => |addr| .{ .memory = addr },288 .immediate => |addr| .{ .memory = addr },
248 .lea_frame => |off| .{ .load_frame = off },
249 .register => |reg| .{ .indirect = .{ .reg = reg } },289 .register => |reg| .{ .indirect = .{ .reg = reg } },
250 .register_offset => |reg_off| .{ .indirect = reg_off },290 .register_offset => |reg_off| .{ .indirect = reg_off },
291 .lea_frame => |off| .{ .load_frame = off },
251 .lea_symbol => |sym_off| .{ .load_symbol = sym_off },292 .lea_symbol => |sym_off| .{ .load_symbol = sym_off },
293 .lea_tlv => |sym| .{ .load_tlv = sym },
252 };294 };
253 }295 }
254296
...@@ -264,13 +306,15 @@ const MCValue = union(enum) {...@@ -264,13 +306,15 @@ const MCValue = union(enum) {
264 .register_pair,306 .register_pair,
265 .memory,307 .memory,
266 .indirect,308 .indirect,
267 .load_frame,
268 .load_symbol,309 .load_symbol,
269 .lea_symbol,310 .lea_symbol,
311 .lea_tlv,
312 .load_tlv,
270 => switch (off) {313 => switch (off) {
271 0 => mcv,314 0 => mcv,
272 else => unreachable, // not offsettable315 else => unreachable,
273 },316 },
317 .load_frame => |frame| .{ .load_frame = .{ .index = frame.index, .off = frame.off + off } },
274 .immediate => |imm| .{ .immediate = @bitCast(@as(i64, @bitCast(imm)) +% off) },318 .immediate => |imm| .{ .immediate = @bitCast(@as(i64, @bitCast(imm)) +% off) },
275 .register => |reg| .{ .register_offset = .{ .reg = reg, .off = off } },319 .register => |reg| .{ .register_offset = .{ .reg = reg, .off = off } },
276 .register_offset => |reg_off| .{ .register_offset = .{ .reg = reg_off.reg, .off = reg_off.off + off } },320 .register_offset => |reg_off| .{ .register_offset = .{ .reg = reg_off.reg, .off = reg_off.off + off } },
...@@ -323,6 +367,8 @@ const InstTracking = struct {...@@ -323,6 +367,8 @@ const InstTracking = struct {
323 .memory,367 .memory,
324 .load_frame,368 .load_frame,
325 .lea_frame,369 .lea_frame,
370 .load_tlv,
371 .lea_tlv,
326 .load_symbol,372 .load_symbol,
327 .lea_symbol,373 .lea_symbol,
328 => result,374 => result,
...@@ -378,6 +424,8 @@ const InstTracking = struct {...@@ -378,6 +424,8 @@ const InstTracking = struct {
378 .lea_frame,424 .lea_frame,
379 .load_symbol,425 .load_symbol,
380 .lea_symbol,426 .lea_symbol,
427 .load_tlv,
428 .lea_tlv,
381 => inst_tracking.long,429 => inst_tracking.long,
382 .dead,430 .dead,
383 .register,431 .register,
...@@ -406,6 +454,8 @@ const InstTracking = struct {...@@ -406,6 +454,8 @@ const InstTracking = struct {
406 .lea_frame,454 .lea_frame,
407 .load_symbol,455 .load_symbol,
408 .lea_symbol,456 .lea_symbol,
457 .load_tlv,
458 .lea_tlv,
409 => assert(std.meta.eql(inst_tracking.long, target.long)),459 => assert(std.meta.eql(inst_tracking.long, target.long)),
410 .load_frame,460 .load_frame,
411 .reserved_frame,461 .reserved_frame,
...@@ -737,12 +787,11 @@ pub fn generate(...@@ -737,12 +787,11 @@ pub fn generate(
737 .air = air,787 .air = air,
738 .pt = pt,788 .pt = pt,
739 .mod = mod,789 .mod = mod,
740 .zcu = zcu,
741 .bin_file = bin_file,790 .bin_file = bin_file,
742 .liveness = liveness,791 .liveness = liveness,
743 .target = target,792 .target = target,
744 .func_index = func_index,
745 .debug_output = debug_output,793 .debug_output = debug_output,
794 .owner = .{ .func_index = func_index },
746 .err_msg = null,795 .err_msg = null,
747 .args = undefined, // populated after `resolveCallingConventionValues`796 .args = undefined, // populated after `resolveCallingConventionValues`
748 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`797 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
...@@ -767,7 +816,6 @@ pub fn generate(...@@ -767,7 +816,6 @@ pub fn generate(
767 function.const_tracking.deinit(gpa);816 function.const_tracking.deinit(gpa);
768 function.exitlude_jump_relocs.deinit(gpa);817 function.exitlude_jump_relocs.deinit(gpa);
769 function.mir_instructions.deinit(gpa);818 function.mir_instructions.deinit(gpa);
770 function.mir_extra.deinit(gpa);
771 }819 }
772820
773 wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)});821 wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)});
...@@ -799,11 +847,11 @@ pub fn generate(...@@ -799,11 +847,11 @@ pub fn generate(
799 function.args = call_info.args;847 function.args = call_info.args;
800 function.ret_mcv = call_info.return_value;848 function.ret_mcv = call_info.return_value;
801 function.frame_allocs.set(@intFromEnum(FrameIndex.ret_addr), FrameAlloc.init(.{849 function.frame_allocs.set(@intFromEnum(FrameIndex.ret_addr), FrameAlloc.init(.{
802 .size = Type.usize.abiSize(pt),850 .size = Type.u64.abiSize(pt),
803 .alignment = Type.usize.abiAlignment(pt).min(call_info.stack_align),851 .alignment = Type.u64.abiAlignment(pt).min(call_info.stack_align),
804 }));852 }));
805 function.frame_allocs.set(@intFromEnum(FrameIndex.base_ptr), FrameAlloc.init(.{853 function.frame_allocs.set(@intFromEnum(FrameIndex.base_ptr), FrameAlloc.init(.{
806 .size = Type.usize.abiSize(pt),854 .size = Type.u64.abiSize(pt),
807 .alignment = Alignment.min(855 .alignment = Alignment.min(
808 call_info.stack_align,856 call_info.stack_align,
809 Alignment.fromNonzeroByteUnits(function.target.stackAlignment()),857 Alignment.fromNonzeroByteUnits(function.target.stackAlignment()),
...@@ -815,7 +863,7 @@ pub fn generate(...@@ -815,7 +863,7 @@ pub fn generate(
815 }));863 }));
816 function.frame_allocs.set(@intFromEnum(FrameIndex.spill_frame), FrameAlloc.init(.{864 function.frame_allocs.set(@intFromEnum(FrameIndex.spill_frame), FrameAlloc.init(.{
817 .size = 0,865 .size = 0,
818 .alignment = Type.usize.abiAlignment(pt),866 .alignment = Type.u64.abiAlignment(pt),
819 }));867 }));
820868
821 function.gen() catch |err| switch (err) {869 function.gen() catch |err| switch (err) {
...@@ -828,7 +876,6 @@ pub fn generate(...@@ -828,7 +876,6 @@ pub fn generate(
828876
829 var mir: Mir = .{877 var mir: Mir = .{
830 .instructions = function.mir_instructions.toOwnedSlice(),878 .instructions = function.mir_instructions.toOwnedSlice(),
831 .extra = try function.mir_extra.toOwnedSlice(gpa),
832 .frame_locs = function.frame_locs.toOwnedSlice(),879 .frame_locs = function.frame_locs.toOwnedSlice(),
833 };880 };
834 defer mir.deinit(gpa);881 defer mir.deinit(gpa);
...@@ -878,6 +925,102 @@ pub fn generate(...@@ -878,6 +925,102 @@ pub fn generate(
878 }925 }
879}926}
880927
928pub fn generateLazy(
929 bin_file: *link.File,
930 pt: Zcu.PerThread,
931 src_loc: Zcu.LazySrcLoc,
932 lazy_sym: link.File.LazySymbol,
933 code: *std.ArrayList(u8),
934 debug_output: DebugInfoOutput,
935) CodeGenError!Result {
936 const comp = bin_file.comp;
937 const gpa = comp.gpa;
938 const mod = comp.root_mod;
939
940 var function: Func = .{
941 .gpa = gpa,
942 .air = undefined,
943 .pt = pt,
944 .mod = mod,
945 .bin_file = bin_file,
946 .liveness = undefined,
947 .target = &mod.resolved_target.result,
948 .debug_output = debug_output,
949 .owner = .{ .lazy_sym = lazy_sym },
950 .err_msg = null,
951 .args = undefined, // populated after `resolveCallingConventionValues`
952 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
953 .fn_type = undefined,
954 .arg_index = 0,
955 .branch_stack = undefined,
956 .src_loc = src_loc,
957 .end_di_line = undefined,
958 .end_di_column = undefined,
959 .scope_generation = 0,
960 .avl = null,
961 .vtype = null,
962 };
963 defer function.mir_instructions.deinit(gpa);
964
965 function.genLazy(lazy_sym) catch |err| switch (err) {
966 error.CodegenFail => return Result{ .fail = function.err_msg.? },
967 error.OutOfRegisters => return Result{
968 .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
969 },
970 else => |e| return e,
971 };
972
973 var mir: Mir = .{
974 .instructions = function.mir_instructions.toOwnedSlice(),
975 .frame_locs = function.frame_locs.toOwnedSlice(),
976 };
977 defer mir.deinit(gpa);
978
979 var emit: Emit = .{
980 .lower = .{
981 .pt = pt,
982 .allocator = gpa,
983 .mir = mir,
984 .cc = .Unspecified,
985 .src_loc = src_loc,
986 .output_mode = comp.config.output_mode,
987 .link_mode = comp.config.link_mode,
988 .pic = mod.pic,
989 },
990 .bin_file = bin_file,
991 .debug_output = debug_output,
992 .code = code,
993 .prev_di_pc = undefined, // no debug info yet
994 .prev_di_line = undefined, // no debug info yet
995 .prev_di_column = undefined, // no debug info yet
996 };
997 defer emit.deinit();
998
999 emit.emitMir() catch |err| switch (err) {
1000 error.LowerFail, error.EmitFail => return Result{ .fail = emit.lower.err_msg.? },
1001 error.InvalidInstruction => |e| {
1002 const msg = switch (e) {
1003 error.InvalidInstruction => "CodeGen failed to find a viable instruction.",
1004 };
1005 return Result{
1006 .fail = try ErrorMsg.create(
1007 gpa,
1008 src_loc,
1009 "{s} This is a bug in the Zig compiler.",
1010 .{msg},
1011 ),
1012 };
1013 },
1014 else => |e| return e,
1015 };
1016
1017 if (function.err_msg) |em| {
1018 return Result{ .fail = em };
1019 } else {
1020 return Result.ok;
1021 }
1022}
1023
881const FormatWipMirData = struct {1024const FormatWipMirData = struct {
882 func: *Func,1025 func: *Func,
883 inst: Mir.Inst.Index,1026 inst: Mir.Inst.Index,
...@@ -895,7 +1038,6 @@ fn formatWipMir(...@@ -895,7 +1038,6 @@ fn formatWipMir(
895 .allocator = data.func.gpa,1038 .allocator = data.func.gpa,
896 .mir = .{1039 .mir = .{
897 .instructions = data.func.mir_instructions.slice(),1040 .instructions = data.func.mir_instructions.slice(),
898 .extra = data.func.mir_extra.items,
899 .frame_locs = data.func.frame_locs.slice(),1041 .frame_locs = data.func.frame_locs.slice(),
900 },1042 },
901 .cc = .Unspecified,1043 .cc = .Unspecified,
...@@ -946,7 +1088,7 @@ fn formatDecl(...@@ -946,7 +1088,7 @@ fn formatDecl(
946}1088}
947fn fmtDecl(func: *Func, decl_index: InternPool.DeclIndex) std.fmt.Formatter(formatDecl) {1089fn fmtDecl(func: *Func, decl_index: InternPool.DeclIndex) std.fmt.Formatter(formatDecl) {
948 return .{ .data = .{1090 return .{ .data = .{
949 .zcu = func.zcu,1091 .zcu = func.pt.zcu,
950 .decl_index = decl_index,1092 .decl_index = decl_index,
951 } };1093 } };
952}1094}
...@@ -993,7 +1135,7 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {...@@ -993,7 +1135,7 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
993 try func.mir_instructions.ensureUnusedCapacity(gpa, 1);1135 try func.mir_instructions.ensureUnusedCapacity(gpa, 1);
994 const result_index: Mir.Inst.Index = @intCast(func.mir_instructions.len);1136 const result_index: Mir.Inst.Index = @intCast(func.mir_instructions.len);
995 func.mir_instructions.appendAssumeCapacity(inst);1137 func.mir_instructions.appendAssumeCapacity(inst);
996 if (inst.tag != .pseudo or switch (inst.ops) {1138 if (switch (inst.tag) {
997 else => true,1139 else => true,
998 .pseudo_dbg_prologue_end,1140 .pseudo_dbg_prologue_end,
999 .pseudo_dbg_line_column,1141 .pseudo_dbg_line_column,
...@@ -1004,65 +1146,26 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {...@@ -1004,65 +1146,26 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
1004 return result_index;1146 return result_index;
1005}1147}
10061148
1007fn addNop(func: *Func) error{OutOfMemory}!Mir.Inst.Index {1149fn addPseudo(func: *Func, mnem: Mnemonic) error{OutOfMemory}!Mir.Inst.Index {
1008 return func.addInst(.{1150 return func.addInst(.{
1009 .tag = .nop,1151 .tag = mnem,
1010 .ops = .none,1152 .data = .none,
1011 .data = undefined,
1012 });1153 });
1013}1154}
10141155
1015fn addPseudoNone(func: *Func, ops: Mir.Inst.Ops) !void {
1016 _ = try func.addInst(.{
1017 .tag = .pseudo,
1018 .ops = ops,
1019 .data = undefined,
1020 });
1021}
1022
1023fn addPseudo(func: *Func, ops: Mir.Inst.Ops) !Mir.Inst.Index {
1024 return func.addInst(.{
1025 .tag = .pseudo,
1026 .ops = ops,
1027 .data = undefined,
1028 });
1029}
1030
1031pub fn addExtra(func: *Func, extra: anytype) Allocator.Error!u32 {
1032 const fields = std.meta.fields(@TypeOf(extra));
1033 try func.mir_extra.ensureUnusedCapacity(func.gpa, fields.len);
1034 return func.addExtraAssumeCapacity(extra);
1035}
1036
1037pub fn addExtraAssumeCapacity(func: *Func, extra: anytype) u32 {
1038 const fields = std.meta.fields(@TypeOf(extra));
1039 const result: u32 = @intCast(func.mir_extra.items.len);
1040 inline for (fields) |field| {
1041 func.mir_extra.appendAssumeCapacity(switch (field.type) {
1042 u32 => @field(extra, field.name),
1043 i32 => @bitCast(@field(extra, field.name)),
1044 else => @compileError("bad field type"),
1045 });
1046 }
1047 return result;
1048}
1049
1050/// Returns a temporary register that contains the value of the `reg` csr.1156/// Returns a temporary register that contains the value of the `reg` csr.
1051///1157///
1052/// Caller's duty to lock the return register is needed.1158/// Caller's duty to lock the return register is needed.
1053fn getCsr(func: *Func, csr: CSR) !Register {1159fn getCsr(func: *Func, csr: CSR) !Register {
1054 assert(func.hasFeature(.zicsr));1160 assert(func.hasFeature(.zicsr));
1055 const dst_reg = try func.register_manager.allocReg(null, func.regTempClassForType(Type.usize));1161 const dst_reg = try func.register_manager.allocReg(null, func.regTempClassForType(Type.u64));
1056 _ = try func.addInst(.{1162 _ = try func.addInst(.{
1057 .tag = .csrrs,1163 .tag = .csrrs,
1058 .ops = .csr,1164 .data = .{ .csr = .{
1059 .data = .{1165 .csr = csr,
1060 .csr = .{1166 .rd = dst_reg,
1061 .csr = csr,1167 .rs1 = .x0,
1062 .rd = dst_reg,1168 } },
1063 .rs1 = .x0,
1064 },
1065 },
1066 });1169 });
1067 return dst_reg;1170 return dst_reg;
1068}1171}
...@@ -1081,7 +1184,6 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void {...@@ -1081,7 +1184,6 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void {
1081 const options_int: u12 = @as(u12, 0) | @as(u8, @bitCast(options));1184 const options_int: u12 = @as(u12, 0) | @as(u8, @bitCast(options));
1082 _ = try func.addInst(.{1185 _ = try func.addInst(.{
1083 .tag = .vsetvli,1186 .tag = .vsetvli,
1084 .ops = .rri,
1085 .data = .{ .i_type = .{1187 .data = .{ .i_type = .{
1086 .rd = dst_reg,1188 .rd = dst_reg,
1087 .rs1 = .zero,1189 .rs1 = .zero,
...@@ -1094,7 +1196,6 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void {...@@ -1094,7 +1196,6 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void {
1094 const options_int: u12 = (~@as(u12, 0) << 10) | @as(u8, @bitCast(options));1196 const options_int: u12 = (~@as(u12, 0) << 10) | @as(u8, @bitCast(options));
1095 _ = try func.addInst(.{1197 _ = try func.addInst(.{
1096 .tag = .vsetivli,1198 .tag = .vsetivli,
1097 .ops = .rri,
1098 .data = .{1199 .data = .{
1099 .i_type = .{1200 .i_type = .{
1100 .rd = dst_reg,1201 .rd = dst_reg,
...@@ -1105,10 +1206,9 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void {...@@ -1105,10 +1206,9 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void {
1105 });1206 });
1106 } else {1207 } else {
1107 const options_int: u12 = @as(u12, 0) | @as(u8, @bitCast(options));1208 const options_int: u12 = @as(u12, 0) | @as(u8, @bitCast(options));
1108 const temp_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = avl });1209 const temp_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = avl });
1109 _ = try func.addInst(.{1210 _ = try func.addInst(.{
1110 .tag = .vsetvli,1211 .tag = .vsetvli,
1111 .ops = .rri,
1112 .data = .{ .i_type = .{1212 .data = .{ .i_type = .{
1113 .rd = dst_reg,1213 .rd = dst_reg,
1114 .rs1 = temp_reg,1214 .rs1 = temp_reg,
...@@ -1125,6 +1225,7 @@ const required_features = [_]Target.riscv.Feature{...@@ -1125,6 +1225,7 @@ const required_features = [_]Target.riscv.Feature{
1125 .a,1225 .a,
1126 .zicsr,1226 .zicsr,
1127 .v,1227 .v,
1228 .zbb,
1128};1229};
11291230
1130fn gen(func: *Func) !void {1231fn gen(func: *Func) !void {
...@@ -1142,7 +1243,7 @@ fn gen(func: *Func) !void {...@@ -1142,7 +1243,7 @@ fn gen(func: *Func) !void {
1142 }1243 }
11431244
1144 if (fn_info.cc != .Naked) {1245 if (fn_info.cc != .Naked) {
1145 try func.addPseudoNone(.pseudo_dbg_prologue_end);1246 _ = try func.addPseudo(.pseudo_dbg_prologue_end);
11461247
1147 const backpatch_stack_alloc = try func.addPseudo(.pseudo_dead);1248 const backpatch_stack_alloc = try func.addPseudo(.pseudo_dead);
1148 const backpatch_ra_spill = try func.addPseudo(.pseudo_dead);1249 const backpatch_ra_spill = try func.addPseudo(.pseudo_dead);
...@@ -1156,11 +1257,11 @@ fn gen(func: *Func) !void {...@@ -1156,11 +1257,11 @@ fn gen(func: *Func) !void {
1156 // The address where to store the return value for the caller is in a1257 // The address where to store the return value for the caller is in a
1157 // register which the callee is free to clobber. Therefore, we purposely1258 // register which the callee is free to clobber. Therefore, we purposely
1158 // spill it to stack immediately.1259 // spill it to stack immediately.
1159 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(Type.usize, pt));1260 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(Type.u64, pt));
1160 try func.genSetMem(1261 try func.genSetMem(
1161 .{ .frame = frame_index },1262 .{ .frame = frame_index },
1162 0,1263 0,
1163 Type.usize,1264 Type.u64,
1164 func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off),1265 func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off),
1165 );1266 );
1166 func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };1267 func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
...@@ -1172,11 +1273,11 @@ fn gen(func: *Func) !void {...@@ -1172,11 +1273,11 @@ fn gen(func: *Func) !void {
1172 try func.genBody(func.air.getMainBody());1273 try func.genBody(func.air.getMainBody());
11731274
1174 for (func.exitlude_jump_relocs.items) |jmp_reloc| {1275 for (func.exitlude_jump_relocs.items) |jmp_reloc| {
1175 func.mir_instructions.items(.data)[jmp_reloc].inst =1276 func.mir_instructions.items(.data)[jmp_reloc].j_type.inst =
1176 @intCast(func.mir_instructions.len);1277 @intCast(func.mir_instructions.len);
1177 }1278 }
11781279
1179 try func.addPseudoNone(.pseudo_dbg_epilogue_begin);1280 _ = try func.addPseudo(.pseudo_dbg_epilogue_begin);
11801281
1181 const backpatch_restore_callee_preserved_regs = try func.addPseudo(.pseudo_dead);1282 const backpatch_restore_callee_preserved_regs = try func.addPseudo(.pseudo_dead);
1182 const backpatch_ra_restore = try func.addPseudo(.pseudo_dead);1283 const backpatch_ra_restore = try func.addPseudo(.pseudo_dead);
...@@ -1186,14 +1287,11 @@ fn gen(func: *Func) !void {...@@ -1186,14 +1287,11 @@ fn gen(func: *Func) !void {
1186 // ret1287 // ret
1187 _ = try func.addInst(.{1288 _ = try func.addInst(.{
1188 .tag = .jalr,1289 .tag = .jalr,
1189 .ops = .rri,1290 .data = .{ .i_type = .{
1190 .data = .{1291 .rd = .zero,
1191 .i_type = .{1292 .rs1 = .ra,
1192 .rd = .zero,1293 .imm12 = Immediate.s(0),
1193 .rs1 = .ra,1294 } },
1194 .imm12 = Immediate.s(0),
1195 },
1196 },
1197 });1295 });
11981296
1199 const frame_layout = try func.computeFrameLayout();1297 const frame_layout = try func.computeFrameLayout();
...@@ -1201,7 +1299,6 @@ fn gen(func: *Func) !void {...@@ -1201,7 +1299,6 @@ fn gen(func: *Func) !void {
12011299
1202 func.mir_instructions.set(backpatch_stack_alloc, .{1300 func.mir_instructions.set(backpatch_stack_alloc, .{
1203 .tag = .addi,1301 .tag = .addi,
1204 .ops = .rri,
1205 .data = .{ .i_type = .{1302 .data = .{ .i_type = .{
1206 .rd = .sp,1303 .rd = .sp,
1207 .rs1 = .sp,1304 .rs1 = .sp,
...@@ -1209,8 +1306,7 @@ fn gen(func: *Func) !void {...@@ -1209,8 +1306,7 @@ fn gen(func: *Func) !void {
1209 } },1306 } },
1210 });1307 });
1211 func.mir_instructions.set(backpatch_ra_spill, .{1308 func.mir_instructions.set(backpatch_ra_spill, .{
1212 .tag = .pseudo,1309 .tag = .pseudo_store_rm,
1213 .ops = .pseudo_store_rm,
1214 .data = .{ .rm = .{1310 .data = .{ .rm = .{
1215 .r = .ra,1311 .r = .ra,
1216 .m = .{1312 .m = .{
...@@ -1220,8 +1316,7 @@ fn gen(func: *Func) !void {...@@ -1220,8 +1316,7 @@ fn gen(func: *Func) !void {
1220 } },1316 } },
1221 });1317 });
1222 func.mir_instructions.set(backpatch_ra_restore, .{1318 func.mir_instructions.set(backpatch_ra_restore, .{
1223 .tag = .pseudo,1319 .tag = .pseudo_load_rm,
1224 .ops = .pseudo_load_rm,
1225 .data = .{ .rm = .{1320 .data = .{ .rm = .{
1226 .r = .ra,1321 .r = .ra,
1227 .m = .{1322 .m = .{
...@@ -1231,8 +1326,7 @@ fn gen(func: *Func) !void {...@@ -1231,8 +1326,7 @@ fn gen(func: *Func) !void {
1231 } },1326 } },
1232 });1327 });
1233 func.mir_instructions.set(backpatch_fp_spill, .{1328 func.mir_instructions.set(backpatch_fp_spill, .{
1234 .tag = .pseudo,1329 .tag = .pseudo_store_rm,
1235 .ops = .pseudo_store_rm,
1236 .data = .{ .rm = .{1330 .data = .{ .rm = .{
1237 .r = .s0,1331 .r = .s0,
1238 .m = .{1332 .m = .{
...@@ -1242,8 +1336,7 @@ fn gen(func: *Func) !void {...@@ -1242,8 +1336,7 @@ fn gen(func: *Func) !void {
1242 } },1336 } },
1243 });1337 });
1244 func.mir_instructions.set(backpatch_fp_restore, .{1338 func.mir_instructions.set(backpatch_fp_restore, .{
1245 .tag = .pseudo,1339 .tag = .pseudo_load_rm,
1246 .ops = .pseudo_load_rm,
1247 .data = .{ .rm = .{1340 .data = .{ .rm = .{
1248 .r = .s0,1341 .r = .s0,
1249 .m = .{1342 .m = .{
...@@ -1254,7 +1347,6 @@ fn gen(func: *Func) !void {...@@ -1254,7 +1347,6 @@ fn gen(func: *Func) !void {
1254 });1347 });
1255 func.mir_instructions.set(backpatch_fp_add, .{1348 func.mir_instructions.set(backpatch_fp_add, .{
1256 .tag = .addi,1349 .tag = .addi,
1257 .ops = .rri,
1258 .data = .{ .i_type = .{1350 .data = .{ .i_type = .{
1259 .rd = .s0,1351 .rd = .s0,
1260 .rs1 = .sp,1352 .rs1 = .sp,
...@@ -1263,7 +1355,6 @@ fn gen(func: *Func) !void {...@@ -1263,7 +1355,6 @@ fn gen(func: *Func) !void {
1263 });1355 });
1264 func.mir_instructions.set(backpatch_stack_alloc_restore, .{1356 func.mir_instructions.set(backpatch_stack_alloc_restore, .{
1265 .tag = .addi,1357 .tag = .addi,
1266 .ops = .rri,
1267 .data = .{ .i_type = .{1358 .data = .{ .i_type = .{
1268 .rd = .sp,1359 .rd = .sp,
1269 .rs1 = .sp,1360 .rs1 = .sp,
...@@ -1273,27 +1364,24 @@ fn gen(func: *Func) !void {...@@ -1273,27 +1364,24 @@ fn gen(func: *Func) !void {
12731364
1274 if (need_save_reg) {1365 if (need_save_reg) {
1275 func.mir_instructions.set(backpatch_spill_callee_preserved_regs, .{1366 func.mir_instructions.set(backpatch_spill_callee_preserved_regs, .{
1276 .tag = .pseudo,1367 .tag = .pseudo_spill_regs,
1277 .ops = .pseudo_spill_regs,
1278 .data = .{ .reg_list = frame_layout.save_reg_list },1368 .data = .{ .reg_list = frame_layout.save_reg_list },
1279 });1369 });
12801370
1281 func.mir_instructions.set(backpatch_restore_callee_preserved_regs, .{1371 func.mir_instructions.set(backpatch_restore_callee_preserved_regs, .{
1282 .tag = .pseudo,1372 .tag = .pseudo_restore_regs,
1283 .ops = .pseudo_restore_regs,
1284 .data = .{ .reg_list = frame_layout.save_reg_list },1373 .data = .{ .reg_list = frame_layout.save_reg_list },
1285 });1374 });
1286 }1375 }
1287 } else {1376 } else {
1288 try func.addPseudoNone(.pseudo_dbg_prologue_end);1377 _ = try func.addPseudo(.pseudo_dbg_prologue_end);
1289 try func.genBody(func.air.getMainBody());1378 try func.genBody(func.air.getMainBody());
1290 try func.addPseudoNone(.pseudo_dbg_epilogue_begin);1379 _ = try func.addPseudo(.pseudo_dbg_epilogue_begin);
1291 }1380 }
12921381
1293 // Drop them off at the rbrace.1382 // Drop them off at the rbrace.
1294 _ = try func.addInst(.{1383 _ = try func.addInst(.{
1295 .tag = .pseudo,1384 .tag = .pseudo_dbg_line_column,
1296 .ops = .pseudo_dbg_line_column,
1297 .data = .{ .pseudo_dbg_line_column = .{1385 .data = .{ .pseudo_dbg_line_column = .{
1298 .line = func.end_di_line,1386 .line = func.end_di_line,
1299 .column = func.end_di_column,1387 .column = func.end_di_column,
...@@ -1301,6 +1389,101 @@ fn gen(func: *Func) !void {...@@ -1301,6 +1389,101 @@ fn gen(func: *Func) !void {
1301 });1389 });
1302}1390}
13031391
1392fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
1393 const pt = func.pt;
1394 const mod = pt.zcu;
1395 const ip = &mod.intern_pool;
1396 switch (lazy_sym.ty.zigTypeTag(mod)) {
1397 .Enum => {
1398 const enum_ty = lazy_sym.ty;
1399 wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)});
1400
1401 const param_regs = abi.Registers.Integer.function_arg_regs;
1402 const ret_reg = param_regs[0];
1403 const enum_mcv: MCValue = .{ .register = param_regs[1] };
1404
1405 const exitlude_jump_relocs = try func.gpa.alloc(Mir.Inst.Index, enum_ty.enumFieldCount(mod));
1406 defer func.gpa.free(exitlude_jump_relocs);
1407
1408 const data_reg, const data_lock = try func.allocReg(.int);
1409 defer func.register_manager.unlockReg(data_lock);
1410
1411 const elf_file = func.bin_file.cast(link.File.Elf).?;
1412 const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, .{
1413 .kind = .const_data,
1414 .ty = enum_ty,
1415 }) catch |err|
1416 return func.fail("{s} creating lazy symbol", .{@errorName(err)});
1417 const sym = elf_file.symbol(sym_index);
1418
1419 try func.genSetReg(Type.u64, data_reg, .{ .lea_symbol = .{ .sym = sym.esym_index } });
1420
1421 const cmp_reg, const cmp_lock = try func.allocReg(.int);
1422 defer func.register_manager.unlockReg(cmp_lock);
1423
1424 var data_off: i32 = 0;
1425 const tag_names = enum_ty.enumFields(mod);
1426 for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, tag_index| {
1427 const tag_name_len = tag_names.get(ip)[tag_index].length(ip);
1428 const tag_val = try pt.enumValueFieldIndex(enum_ty, @intCast(tag_index));
1429 const tag_mcv = try func.genTypedValue(tag_val);
1430
1431 _ = try func.genBinOp(
1432 .cmp_neq,
1433 enum_mcv,
1434 enum_ty,
1435 tag_mcv,
1436 enum_ty,
1437 cmp_reg,
1438 );
1439 const skip_reloc = try func.condBr(Type.bool, .{ .register = cmp_reg });
1440
1441 try func.genSetMem(
1442 .{ .reg = ret_reg },
1443 0,
1444 Type.u64,
1445 .{ .register_offset = .{ .reg = data_reg, .off = data_off } },
1446 );
1447
1448 try func.genSetMem(
1449 .{ .reg = ret_reg },
1450 8,
1451 Type.u64,
1452 .{ .immediate = tag_name_len },
1453 );
1454
1455 exitlude_jump_reloc.* = try func.addInst(.{
1456 .tag = .pseudo_j,
1457 .data = .{ .j_type = .{
1458 .rd = .zero,
1459 .inst = undefined,
1460 } },
1461 });
1462 func.performReloc(skip_reloc);
1463
1464 data_off += @intCast(tag_name_len + 1);
1465 }
1466
1467 try func.airTrap();
1468
1469 for (exitlude_jump_relocs) |reloc| func.performReloc(reloc);
1470
1471 _ = try func.addInst(.{
1472 .tag = .jalr,
1473 .data = .{ .i_type = .{
1474 .rd = .zero,
1475 .rs1 = .ra,
1476 .imm12 = Immediate.s(0),
1477 } },
1478 });
1479 },
1480 else => return func.fail(
1481 "TODO implement {s} for {}",
1482 .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(pt) },
1483 ),
1484 }
1485}
1486
1304fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {1487fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1305 const pt = func.pt;1488 const pt = func.pt;
1306 const zcu = pt.zcu;1489 const zcu = pt.zcu;
...@@ -1322,9 +1505,12 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1322,9 +1505,12 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1322 .sub,1505 .sub,
1323 .sub_wrap,1506 .sub_wrap,
13241507
1508 .add_sat,
1509
1325 .mul,1510 .mul,
1326 .mul_wrap,1511 .mul_wrap,
1327 .div_trunc, 1512 .div_trunc,
1513 .rem,
13281514
1329 .shl, .shl_exact,1515 .shl, .shl_exact,
1330 .shr, .shr_exact,1516 .shr, .shr_exact,
...@@ -1344,7 +1530,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1344,7 +1530,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1344 .ptr_add,1530 .ptr_add,
1345 .ptr_sub => try func.airPtrArithmetic(inst, tag),1531 .ptr_sub => try func.airPtrArithmetic(inst, tag),
13461532
1347 .rem,
1348 .mod,1533 .mod,
1349 .div_float, 1534 .div_float,
1350 .div_floor, 1535 .div_floor,
...@@ -1373,7 +1558,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1373,7 +1558,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1373 .shl_with_overflow => try func.airShlWithOverflow(inst),1558 .shl_with_overflow => try func.airShlWithOverflow(inst),
13741559
13751560
1376 .add_sat => try func.airAddSat(inst),
1377 .sub_sat => try func.airSubSat(inst),1561 .sub_sat => try func.airSubSat(inst),
1378 .mul_sat => try func.airMulSat(inst),1562 .mul_sat => try func.airMulSat(inst),
1379 .shl_sat => try func.airShlSat(inst),1563 .shl_sat => try func.airShlSat(inst),
...@@ -1440,8 +1624,8 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1440,8 +1624,8 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1440 .struct_field_val=> try func.airStructFieldVal(inst),1624 .struct_field_val=> try func.airStructFieldVal(inst),
1441 .float_from_int => try func.airFloatFromInt(inst),1625 .float_from_int => try func.airFloatFromInt(inst),
1442 .int_from_float => try func.airIntFromFloat(inst),1626 .int_from_float => try func.airIntFromFloat(inst),
1443 .cmpxchg_strong => try func.airCmpxchg(inst),1627 .cmpxchg_strong => try func.airCmpxchg(inst, .strong),
1444 .cmpxchg_weak => try func.airCmpxchg(inst),1628 .cmpxchg_weak => try func.airCmpxchg(inst, .weak),
1445 .atomic_rmw => try func.airAtomicRmw(inst),1629 .atomic_rmw => try func.airAtomicRmw(inst),
1446 .atomic_load => try func.airAtomicLoad(inst),1630 .atomic_load => try func.airAtomicLoad(inst),
1447 .memcpy => try func.airMemcpy(inst),1631 .memcpy => try func.airMemcpy(inst),
...@@ -1579,7 +1763,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1579,7 +1763,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1579 for (tracking.getRegs()) |reg| {1763 for (tracking.getRegs()) |reg| {
1580 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;1764 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
1581 } else return std.debug.panic(1765 } else return std.debug.panic(
1582 \\%{} takes up these regs: {any}, however these regs {any}, don't use it1766 \\%{} takes up these regs: {any}, however this regs {any}, don't use it
1583 , .{ tracked_inst, tracking.getRegs(), RegisterManager.regAtTrackedIndex(@intCast(index)) });1767 , .{ tracked_inst, tracking.getRegs(), RegisterManager.regAtTrackedIndex(@intCast(index)) });
1584 }1768 }
1585 }1769 }
...@@ -1657,7 +1841,7 @@ fn finishAir(...@@ -1657,7 +1841,7 @@ fn finishAir(
1657}1841}
16581842
1659const FrameLayout = struct {1843const FrameLayout = struct {
1660 stack_adjust: u32,1844 stack_adjust: i12,
1661 save_reg_list: Mir.RegisterList,1845 save_reg_list: Mir.RegisterList,
1662};1846};
16631847
...@@ -1671,10 +1855,7 @@ fn setFrameLoc(...@@ -1671,10 +1855,7 @@ fn setFrameLoc(
1671 const frame_i = @intFromEnum(frame_index);1855 const frame_i = @intFromEnum(frame_index);
1672 if (aligned) {1856 if (aligned) {
1673 const alignment: InternPool.Alignment = func.frame_allocs.items(.abi_align)[frame_i];1857 const alignment: InternPool.Alignment = func.frame_allocs.items(.abi_align)[frame_i];
1674 offset.* = if (math.sign(offset.*) < 0)1858 offset.* = math.sign(offset.*) * @as(i32, @intCast(alignment.backward(@intCast(@abs(offset.*)))));
1675 -1 * @as(i32, @intCast(alignment.backward(@intCast(@abs(offset.*)))))
1676 else
1677 @intCast(alignment.forward(@intCast(@abs(offset.*))));
1678 }1859 }
1679 func.frame_locs.set(frame_i, .{ .base = base, .disp = offset.* });1860 func.frame_locs.set(frame_i, .{ .base = base, .disp = offset.* });
1680 offset.* += func.frame_allocs.items(.abi_size)[frame_i];1861 offset.* += func.frame_allocs.items(.abi_size)[frame_i];
...@@ -1717,8 +1898,8 @@ fn computeFrameLayout(func: *Func) !FrameLayout {...@@ -1717,8 +1898,8 @@ fn computeFrameLayout(func: *Func) !FrameLayout {
1717 }1898 }
1718 break :blk i;1899 break :blk i;
1719 };1900 };
1720 const saved_reg_size = save_reg_list.size();
17211901
1902 const saved_reg_size = save_reg_list.size();
1722 frame_size[@intFromEnum(FrameIndex.spill_frame)] = @intCast(saved_reg_size);1903 frame_size[@intFromEnum(FrameIndex.spill_frame)] = @intCast(saved_reg_size);
17231904
1724 // The total frame size is calculated by the amount of s registers you need to save * 8, as each1905 // The total frame size is calculated by the amount of s registers you need to save * 8, as each
...@@ -1811,12 +1992,14 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {...@@ -1811,12 +1992,14 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {
1811 .signedness = .unsigned,1992 .signedness = .unsigned,
1812 .bits = @intCast(ty.bitSize(pt)),1993 .bits = @intCast(ty.bitSize(pt)),
1813 };1994 };
1995 assert(reg.class() == .int);
1996
1814 const shift = math.cast(u6, 64 - int_info.bits % 64) orelse return;1997 const shift = math.cast(u6, 64 - int_info.bits % 64) orelse return;
1815 switch (int_info.signedness) {1998 switch (int_info.signedness) {
1816 .signed => {1999 .signed => {
1817 _ = try func.addInst(.{2000 _ = try func.addInst(.{
1818 .tag = .slli,2001 .tag = .slli,
1819 .ops = .rri,2002
1820 .data = .{2003 .data = .{
1821 .i_type = .{2004 .i_type = .{
1822 .rd = reg,2005 .rd = reg,
...@@ -1827,7 +2010,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {...@@ -1827,7 +2010,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {
1827 });2010 });
1828 _ = try func.addInst(.{2011 _ = try func.addInst(.{
1829 .tag = .srai,2012 .tag = .srai,
1830 .ops = .rri,2013
1831 .data = .{2014 .data = .{
1832 .i_type = .{2015 .i_type = .{
1833 .rd = reg,2016 .rd = reg,
...@@ -1842,7 +2025,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {...@@ -1842,7 +2025,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {
1842 if (mask < 256) {2025 if (mask < 256) {
1843 _ = try func.addInst(.{2026 _ = try func.addInst(.{
1844 .tag = .andi,2027 .tag = .andi,
1845 .ops = .rri,2028
1846 .data = .{2029 .data = .{
1847 .i_type = .{2030 .i_type = .{
1848 .rd = reg,2031 .rd = reg,
...@@ -1854,7 +2037,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {...@@ -1854,7 +2037,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {
1854 } else {2037 } else {
1855 _ = try func.addInst(.{2038 _ = try func.addInst(.{
1856 .tag = .slli,2039 .tag = .slli,
1857 .ops = .rri,2040
1858 .data = .{2041 .data = .{
1859 .i_type = .{2042 .i_type = .{
1860 .rd = reg,2043 .rd = reg,
...@@ -1865,7 +2048,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {...@@ -1865,7 +2048,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {
1865 });2048 });
1866 _ = try func.addInst(.{2049 _ = try func.addInst(.{
1867 .tag = .srli,2050 .tag = .srli,
1868 .ops = .rri,2051
1869 .data = .{2052 .data = .{
1870 .i_type = .{2053 .i_type = .{
1871 .rd = reg,2054 .rd = reg,
...@@ -1879,15 +2062,6 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {...@@ -1879,15 +2062,6 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {
1879 }2062 }
1880}2063}
18812064
1882fn symbolIndex(func: *Func) !u32 {
1883 const pt = func.pt;
1884 const zcu = pt.zcu;
1885 const decl_index = zcu.funcOwnerDeclIndex(func.func_index);
1886 const elf_file = func.bin_file.cast(link.File.Elf).?;
1887 const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
1888 return atom_index;
1889}
1890
1891fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex {2065fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex {
1892 const frame_allocs_slice = func.frame_allocs.slice();2066 const frame_allocs_slice = func.frame_allocs.slice();
1893 const frame_size = frame_allocs_slice.items(.abi_size);2067 const frame_size = frame_allocs_slice.items(.abi_size);
...@@ -2051,6 +2225,10 @@ pub fn spillInstruction(func: *Func, reg: Register, inst: Air.Inst.Index) !void...@@ -2051,6 +2225,10 @@ pub fn spillInstruction(func: *Func, reg: Register, inst: Air.Inst.Index) !void
2051 try tracking.trackSpill(func, inst);2225 try tracking.trackSpill(func, inst);
2052}2226}
20532227
2228pub fn spillRegisters(func: *Func, comptime registers: []const Register) !void {
2229 inline for (registers) |reg| try func.register_manager.getKnownReg(reg, null);
2230}
2231
2054/// Copies a value to a register without tracking the register. The register is not considered2232/// Copies a value to a register without tracking the register. The register is not considered
2055/// allocated. A second call to `copyToTmpRegister` may return the same register.2233/// allocated. A second call to `copyToTmpRegister` may return the same register.
2056/// This can have a side effect of spilling instructions to the stack to free up a register.2234/// This can have a side effect of spilling instructions to the stack to free up a register.
...@@ -2151,11 +2329,16 @@ fn airTrunc(func: *Func, inst: Air.Inst.Index) !void {...@@ -2151,11 +2329,16 @@ fn airTrunc(func: *Func, inst: Air.Inst.Index) !void {
2151 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2329 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2152 if (func.liveness.isUnused(inst))2330 if (func.liveness.isUnused(inst))
2153 return func.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });2331 return func.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });
21542332 // we assume no zeroext in the "Zig ABI", so it's fine to just not truncate it.
2155 const operand = try func.resolveInst(ty_op.operand);2333 const operand = try func.resolveInst(ty_op.operand);
2156 _ = operand;2334
2157 return func.fail("TODO implement trunc for {}", .{func.target.cpu.arch});2335 // we can do it just to be safe, but this shouldn't be needed for no-runtime safety modes
2158 // return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });2336 switch (operand) {
2337 .register => |reg| try func.truncateRegister(func.typeOf(ty_op.operand), reg),
2338 else => {},
2339 }
2340
2341 return func.finishAir(inst, operand, .{ ty_op.operand, .none, .none });
2159}2342}
21602343
2161fn airIntFromBool(func: *Func, inst: Air.Inst.Index) !void {2344fn airIntFromBool(func: *Func, inst: Air.Inst.Index) !void {
...@@ -2186,8 +2369,7 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void {...@@ -2186,8 +2369,7 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void {
2186 switch (ty.zigTypeTag(zcu)) {2369 switch (ty.zigTypeTag(zcu)) {
2187 .Bool => {2370 .Bool => {
2188 _ = try func.addInst(.{2371 _ = try func.addInst(.{
2189 .tag = .pseudo,2372 .tag = .pseudo_not,
2190 .ops = .pseudo_not,
2191 .data = .{2373 .data = .{
2192 .rr = .{2374 .rr = .{
2193 .rs = operand_reg,2375 .rs = operand_reg,
...@@ -2205,7 +2387,6 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void {...@@ -2205,7 +2387,6 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void {
2205 32, 64 => {2387 32, 64 => {
2206 _ = try func.addInst(.{2388 _ = try func.addInst(.{
2207 .tag = .xori,2389 .tag = .xori,
2208 .ops = .rri,
2209 .data = .{2390 .data = .{
2210 .i_type = .{2391 .i_type = .{
2211 .rd = dst_reg,2392 .rd = dst_reg,
...@@ -2305,10 +2486,7 @@ fn binOp(...@@ -2305,10 +2486,7 @@ fn binOp(
2305 80, 128 => true,2486 80, 128 => true,
2306 else => unreachable,2487 else => unreachable,
2307 };2488 };
2308 switch (air_tag) {2489 if (!type_needs_libcall) break :libcall;
2309 .rem, .mod => {},
2310 else => if (!type_needs_libcall) break :libcall,
2311 }
2312 return func.fail("binOp libcall runtime-float ops", .{});2490 return func.fail("binOp libcall runtime-float ops", .{});
2313 }2491 }
23142492
...@@ -2367,7 +2545,6 @@ fn genBinOp(...@@ -2367,7 +2545,6 @@ fn genBinOp(
2367 const pt = func.pt;2545 const pt = func.pt;
2368 const zcu = pt.zcu;2546 const zcu = pt.zcu;
2369 const bit_size = lhs_ty.bitSize(pt);2547 const bit_size = lhs_ty.bitSize(pt);
2370 assert(bit_size <= 64);
23712548
2372 const is_unsigned = lhs_ty.isUnsignedInt(zcu);2549 const is_unsigned = lhs_ty.isUnsignedInt(zcu);
23732550
...@@ -2384,16 +2561,30 @@ fn genBinOp(...@@ -2384,16 +2561,30 @@ fn genBinOp(
2384 .sub_wrap,2561 .sub_wrap,
2385 .mul,2562 .mul,
2386 .mul_wrap,2563 .mul_wrap,
2564 .rem,
2565 .div_trunc,
2387 => {2566 => {
2388 if (!math.isPowerOfTwo(bit_size))2567 switch (tag) {
2389 return func.fail(2568 .rem,
2390 "TODO: genBinOp {s} non-pow 2, found {}",2569 .div_trunc,
2391 .{ @tagName(tag), bit_size },2570 => {
2392 );2571 if (!math.isPowerOfTwo(bit_size)) {
2572 try func.truncateRegister(lhs_ty, lhs_reg);
2573 try func.truncateRegister(rhs_ty, rhs_reg);
2574 }
2575 },
2576 else => {
2577 if (!math.isPowerOfTwo(bit_size))
2578 return func.fail(
2579 "TODO: genBinOp verify {s} non-pow 2, found {}",
2580 .{ @tagName(tag), bit_size },
2581 );
2582 },
2583 }
23932584
2394 switch (lhs_ty.zigTypeTag(zcu)) {2585 switch (lhs_ty.zigTypeTag(zcu)) {
2395 .Int => {2586 .Int => {
2396 const mir_tag: Mir.Inst.Tag = switch (tag) {2587 const mnem: Mnemonic = switch (tag) {
2397 .add, .add_wrap => switch (bit_size) {2588 .add, .add_wrap => switch (bit_size) {
2398 8, 16, 64 => .add,2589 8, 16, 64 => .add,
2399 32 => .addw,2590 32 => .addw,
...@@ -2409,12 +2600,19 @@ fn genBinOp(...@@ -2409,12 +2600,19 @@ fn genBinOp(
2409 32 => .mulw,2600 32 => .mulw,
2410 else => unreachable,2601 else => unreachable,
2411 },2602 },
2603 .rem => switch (bit_size) {
2604 8, 16, 32 => if (is_unsigned) .remuw else .remw,
2605 else => if (is_unsigned) .remu else .rem,
2606 },
2607 .div_trunc => switch (bit_size) {
2608 8, 16, 32 => if (is_unsigned) .divuw else .divw,
2609 else => if (is_unsigned) .divu else .div,
2610 },
2412 else => unreachable,2611 else => unreachable,
2413 };2612 };
24142613
2415 _ = try func.addInst(.{2614 _ = try func.addInst(.{
2416 .tag = mir_tag,2615 .tag = mnem,
2417 .ops = .rrr,
2418 .data = .{2616 .data = .{
2419 .r_type = .{2617 .r_type = .{
2420 .rd = dst_reg,2618 .rd = dst_reg,
...@@ -2423,17 +2621,9 @@ fn genBinOp(...@@ -2423,17 +2621,9 @@ fn genBinOp(
2423 },2621 },
2424 },2622 },
2425 });2623 });
2426
2427 // truncate when the instruction is larger than the bit size.
2428 switch (bit_size) {
2429 8, 16 => try func.truncateRegister(lhs_ty, dst_reg),
2430 32 => {}, // addw/subw affects the first 32-bits
2431 64 => {}, // add/sub affects the entire register
2432 else => unreachable,
2433 }
2434 },2624 },
2435 .Float => {2625 .Float => {
2436 const mir_tag: Mir.Inst.Tag = switch (tag) {2626 const mir_tag: Mnemonic = switch (tag) {
2437 .add => switch (bit_size) {2627 .add => switch (bit_size) {
2438 32 => .fadds,2628 32 => .fadds,
2439 64 => .faddd,2629 64 => .faddd,
...@@ -2449,12 +2639,11 @@ fn genBinOp(...@@ -2449,12 +2639,11 @@ fn genBinOp(
2449 64 => .fmuld,2639 64 => .fmuld,
2450 else => unreachable,2640 else => unreachable,
2451 },2641 },
2452 else => unreachable,2642 else => return func.fail("TODO: genBinOp {s} Float", .{@tagName(tag)}),
2453 };2643 };
24542644
2455 _ = try func.addInst(.{2645 _ = try func.addInst(.{
2456 .tag = mir_tag,2646 .tag = mir_tag,
2457 .ops = .rrr,
2458 .data = .{2647 .data = .{
2459 .r_type = .{2648 .r_type = .{
2460 .rd = dst_reg,2649 .rd = dst_reg,
...@@ -2470,7 +2659,7 @@ fn genBinOp(...@@ -2470,7 +2659,7 @@ fn genBinOp(
24702659
2471 const child_ty = lhs_ty.childType(zcu);2660 const child_ty = lhs_ty.childType(zcu);
24722661
2473 const mir_tag: Mir.Inst.Tag = switch (tag) {2662 const mir_tag: Mnemonic = switch (tag) {
2474 .add => switch (child_ty.zigTypeTag(zcu)) {2663 .add => switch (child_ty.zigTypeTag(zcu)) {
2475 .Int => .vaddvv,2664 .Int => .vaddvv,
2476 .Float => .vfaddvv,2665 .Float => .vfaddvv,
...@@ -2481,6 +2670,11 @@ fn genBinOp(...@@ -2481,6 +2670,11 @@ fn genBinOp(
2481 .Float => .vfsubvv,2670 .Float => .vfsubvv,
2482 else => unreachable,2671 else => unreachable,
2483 },2672 },
2673 .mul => switch (child_ty.zigTypeTag(zcu)) {
2674 .Int => .vmulvv,
2675 .Float => .vfmulvv,
2676 else => unreachable,
2677 },
2484 else => return func.fail("TODO: genBinOp {s} Vector", .{@tagName(tag)}),2678 else => return func.fail("TODO: genBinOp {s} Vector", .{@tagName(tag)}),
2485 };2679 };
24862680
...@@ -2490,7 +2684,7 @@ fn genBinOp(...@@ -2490,7 +2684,7 @@ fn genBinOp(
2490 16 => .@"16",2684 16 => .@"16",
2491 32 => .@"32",2685 32 => .@"32",
2492 64 => .@"64",2686 64 => .@"64",
2493 else => unreachable,2687 else => return func.fail("TODO: genBinOp > 64 bit elements, found {d}", .{elem_size}),
2494 },2688 },
2495 .vlmul = .m1,2689 .vlmul = .m1,
2496 .vma = true,2690 .vma = true,
...@@ -2499,7 +2693,6 @@ fn genBinOp(...@@ -2499,7 +2693,6 @@ fn genBinOp(
24992693
2500 _ = try func.addInst(.{2694 _ = try func.addInst(.{
2501 .tag = mir_tag,2695 .tag = mir_tag,
2502 .ops = .rrr,
2503 .data = .{2696 .data = .{
2504 .r_type = .{2697 .r_type = .{
2505 .rd = dst_reg,2698 .rd = dst_reg,
...@@ -2513,6 +2706,53 @@ fn genBinOp(...@@ -2513,6 +2706,53 @@ fn genBinOp(
2513 }2706 }
2514 },2707 },
25152708
2709 .add_sat,
2710 => {
2711 if (bit_size != 64 or !is_unsigned)
2712 return func.fail("TODO: genBinOp ty: {}", .{lhs_ty.fmt(pt)});
2713
2714 const tmp_reg = try func.copyToTmpRegister(rhs_ty, .{ .register = rhs_reg });
2715 const tmp_lock = func.register_manager.lockRegAssumeUnused(tmp_reg);
2716 defer func.register_manager.unlockReg(tmp_lock);
2717
2718 _ = try func.addInst(.{
2719 .tag = .add,
2720 .data = .{ .r_type = .{
2721 .rd = tmp_reg,
2722 .rs1 = rhs_reg,
2723 .rs2 = lhs_reg,
2724 } },
2725 });
2726
2727 _ = try func.addInst(.{
2728 .tag = .sltu,
2729 .data = .{ .r_type = .{
2730 .rd = dst_reg,
2731 .rs1 = tmp_reg,
2732 .rs2 = lhs_reg,
2733 } },
2734 });
2735
2736 // neg dst_reg, dst_reg
2737 _ = try func.addInst(.{
2738 .tag = .sub,
2739 .data = .{ .r_type = .{
2740 .rd = dst_reg,
2741 .rs1 = .zero,
2742 .rs2 = dst_reg,
2743 } },
2744 });
2745
2746 _ = try func.addInst(.{
2747 .tag = .@"or",
2748 .data = .{ .r_type = .{
2749 .rd = dst_reg,
2750 .rs1 = dst_reg,
2751 .rs2 = tmp_reg,
2752 } },
2753 });
2754 },
2755
2516 .ptr_add,2756 .ptr_add,
2517 .ptr_sub,2757 .ptr_sub,
2518 => {2758 => {
...@@ -2523,14 +2763,14 @@ fn genBinOp(...@@ -2523,14 +2763,14 @@ fn genBinOp(
25232763
2524 // RISC-V has no immediate mul, so we copy the size to a temporary register2764 // RISC-V has no immediate mul, so we copy the size to a temporary register
2525 const elem_size = lhs_ty.elemType2(zcu).abiSize(pt);2765 const elem_size = lhs_ty.elemType2(zcu).abiSize(pt);
2526 const elem_size_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = elem_size });2766 const elem_size_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = elem_size });
25272767
2528 try func.genBinOp(2768 try func.genBinOp(
2529 .mul,2769 .mul,
2530 tmp_mcv,2770 tmp_mcv,
2531 rhs_ty,2771 rhs_ty,
2532 .{ .register = elem_size_reg },2772 .{ .register = elem_size_reg },
2533 Type.usize,2773 Type.u64,
2534 tmp_reg,2774 tmp_reg,
2535 );2775 );
25362776
...@@ -2541,9 +2781,9 @@ fn genBinOp(...@@ -2541,9 +2781,9 @@ fn genBinOp(
2541 else => unreachable,2781 else => unreachable,
2542 },2782 },
2543 lhs_mcv,2783 lhs_mcv,
2544 Type.usize, // we know it's a pointer, so it'll be usize.2784 Type.u64, // we know it's a pointer, so it'll be usize.
2545 tmp_mcv,2785 tmp_mcv,
2546 Type.usize,2786 Type.u64,
2547 dst_reg,2787 dst_reg,
2548 );2788 );
2549 },2789 },
...@@ -2559,7 +2799,6 @@ fn genBinOp(...@@ -2559,7 +2799,6 @@ fn genBinOp(
2559 .bit_or, .bool_or => .@"or",2799 .bit_or, .bool_or => .@"or",
2560 else => unreachable,2800 else => unreachable,
2561 },2801 },
2562 .ops = .rrr,
2563 .data = .{2802 .data = .{
2564 .r_type = .{2803 .r_type = .{
2565 .rd = dst_reg,2804 .rd = dst_reg,
...@@ -2577,18 +2816,23 @@ fn genBinOp(...@@ -2577,18 +2816,23 @@ fn genBinOp(
2577 }2816 }
2578 },2817 },
25792818
2580 .div_trunc,2819 .shr,
2820 .shr_exact,
2821 .shl,
2822 .shl_exact,
2581 => {2823 => {
2582 if (!math.isPowerOfTwo(bit_size))2824 if (bit_size > 64) return func.fail("TODO: genBinOp shift > 64 bits, {}", .{bit_size});
2583 return func.fail(2825 try func.truncateRegister(rhs_ty, rhs_reg);
2584 "TODO: genBinOp {s} non-pow 2, found {}",
2585 .{ @tagName(tag), bit_size },
2586 );
25872826
2588 const mir_tag: Mir.Inst.Tag = switch (tag) {2827 const mir_tag: Mnemonic = switch (tag) {
2589 .div_trunc => switch (bit_size) {2828 .shl, .shl_exact => switch (bit_size) {
2590 8, 16, 32 => if (is_unsigned) .divuw else .divw,2829 1...31, 33...64 => .sll,
2591 64 => if (is_unsigned) .divu else .div,2830 32 => .sllw,
2831 else => unreachable,
2832 },
2833 .shr, .shr_exact => switch (bit_size) {
2834 1...31, 33...64 => .srl,
2835 32 => .srlw,
2592 else => unreachable,2836 else => unreachable,
2593 },2837 },
2594 else => unreachable,2838 else => unreachable,
...@@ -2596,71 +2840,12 @@ fn genBinOp(...@@ -2596,71 +2840,12 @@ fn genBinOp(
25962840
2597 _ = try func.addInst(.{2841 _ = try func.addInst(.{
2598 .tag = mir_tag,2842 .tag = mir_tag,
2599 .ops = .rrr,
2600 .data = .{
2601 .r_type = .{
2602 .rd = dst_reg,
2603 .rs1 = lhs_reg,
2604 .rs2 = rhs_reg,
2605 },
2606 },
2607 });
2608
2609 if (!is_unsigned) {
2610 // truncate when the instruction is larger than the bit size.
2611 switch (bit_size) {
2612 8, 16 => try func.truncateRegister(lhs_ty, dst_reg),
2613 32 => {}, // divw affects the first 32-bits
2614 64 => {}, // div affects the entire register
2615 else => unreachable,
2616 }
2617 }
2618 },
2619
2620 .shr,
2621 .shr_exact,
2622 .shl,
2623 .shl_exact,
2624 => {
2625 if (!math.isPowerOfTwo(bit_size))
2626 return func.fail(
2627 "TODO: genBinOp {s} non-pow 2, found {}",
2628 .{ @tagName(tag), bit_size },
2629 );
2630
2631 // it's important that the shift amount is exact
2632 try func.truncateRegister(rhs_ty, rhs_reg);
2633
2634 const mir_tag: Mir.Inst.Tag = switch (tag) {
2635 .shl, .shl_exact => switch (bit_size) {
2636 8, 16, 64 => .sll,
2637 32 => .sllw,
2638 else => unreachable,
2639 },
2640 .shr, .shr_exact => switch (bit_size) {
2641 8, 16, 64 => .srl,
2642 32 => .srlw,
2643 else => unreachable,
2644 },
2645 else => unreachable,
2646 };
2647
2648 _ = try func.addInst(.{
2649 .tag = mir_tag,
2650 .ops = .rrr,
2651 .data = .{ .r_type = .{2843 .data = .{ .r_type = .{
2652 .rd = dst_reg,2844 .rd = dst_reg,
2653 .rs1 = lhs_reg,2845 .rs1 = lhs_reg,
2654 .rs2 = rhs_reg,2846 .rs2 = rhs_reg,
2655 } },2847 } },
2656 });2848 });
2657
2658 switch (bit_size) {
2659 8, 16 => try func.truncateRegister(lhs_ty, dst_reg),
2660 32 => {},
2661 64 => {},
2662 else => unreachable,
2663 }
2664 },2849 },
26652850
2666 // TODO: move the isel logic out of lower and into here.2851 // TODO: move the isel logic out of lower and into here.
...@@ -2671,9 +2856,14 @@ fn genBinOp(...@@ -2671,9 +2856,14 @@ fn genBinOp(
2671 .cmp_gt,2856 .cmp_gt,
2672 .cmp_gte,2857 .cmp_gte,
2673 => {2858 => {
2859 assert(lhs_reg.class() == rhs_reg.class());
2860 if (lhs_reg.class() == .int) {
2861 try func.truncateRegister(lhs_ty, lhs_reg);
2862 try func.truncateRegister(rhs_ty, rhs_reg);
2863 }
2864
2674 _ = try func.addInst(.{2865 _ = try func.addInst(.{
2675 .tag = .pseudo,2866 .tag = .pseudo_compare,
2676 .ops = .pseudo_compare,
2677 .data = .{2867 .data = .{
2678 .compare = .{2868 .compare = .{
2679 .op = switch (tag) {2869 .op = switch (tag) {
...@@ -2719,60 +2909,60 @@ fn genBinOp(...@@ -2719,60 +2909,60 @@ fn genBinOp(
2719 // a1, s0 was -1, flipping all the bits in a2 and effectively restoring a0. If a0 was greater than or equal to a1,2909 // a1, s0 was -1, flipping all the bits in a2 and effectively restoring a0. If a0 was greater than or equal to a1,
2720 // s0 was 0, leaving a2 unchanged as a0.2910 // s0 was 0, leaving a2 unchanged as a0.
2721 .min, .max => {2911 .min, .max => {
2722 const int_info = lhs_ty.intInfo(zcu);2912 switch (lhs_ty.zigTypeTag(zcu)) {
2913 .Int => {
2914 const int_info = lhs_ty.intInfo(zcu);
27232915
2724 const mask_reg, const mask_lock = try func.allocReg(.int);2916 const mask_reg, const mask_lock = try func.allocReg(.int);
2725 defer func.register_manager.unlockReg(mask_lock);2917 defer func.register_manager.unlockReg(mask_lock);
27262918
2727 _ = try func.addInst(.{2919 _ = try func.addInst(.{
2728 .tag = if (int_info.signedness == .unsigned) .sltu else .slt,2920 .tag = if (int_info.signedness == .unsigned) .sltu else .slt,
2729 .ops = .rrr,2921 .data = .{ .r_type = .{
2730 .data = .{ .r_type = .{2922 .rd = mask_reg,
2731 .rd = mask_reg,2923 .rs1 = lhs_reg,
2732 .rs1 = lhs_reg,2924 .rs2 = rhs_reg,
2733 .rs2 = rhs_reg,2925 } },
2734 } },2926 });
2735 });
27362927
2737 _ = try func.addInst(.{2928 _ = try func.addInst(.{
2738 .tag = .sub,2929 .tag = .sub,
2739 .ops = .rrr,2930 .data = .{ .r_type = .{
2740 .data = .{ .r_type = .{2931 .rd = mask_reg,
2741 .rd = mask_reg,2932 .rs1 = .zero,
2742 .rs1 = .zero,2933 .rs2 = mask_reg,
2743 .rs2 = mask_reg,2934 } },
2744 } },2935 });
2745 });
27462936
2747 _ = try func.addInst(.{2937 _ = try func.addInst(.{
2748 .tag = .xor,2938 .tag = .xor,
2749 .ops = .rrr,2939 .data = .{ .r_type = .{
2750 .data = .{ .r_type = .{2940 .rd = dst_reg,
2751 .rd = dst_reg,2941 .rs1 = lhs_reg,
2752 .rs1 = lhs_reg,2942 .rs2 = rhs_reg,
2753 .rs2 = rhs_reg,2943 } },
2754 } },2944 });
2755 });
27562945
2757 _ = try func.addInst(.{2946 _ = try func.addInst(.{
2758 .tag = .@"and",2947 .tag = .@"and",
2759 .ops = .rrr,2948 .data = .{ .r_type = .{
2760 .data = .{ .r_type = .{2949 .rd = mask_reg,
2761 .rd = mask_reg,2950 .rs1 = dst_reg,
2762 .rs1 = dst_reg,2951 .rs2 = mask_reg,
2763 .rs2 = mask_reg,2952 } },
2764 } },2953 });
2765 });
27662954
2767 _ = try func.addInst(.{2955 _ = try func.addInst(.{
2768 .tag = .xor,2956 .tag = .xor,
2769 .ops = .rrr,2957 .data = .{ .r_type = .{
2770 .data = .{ .r_type = .{2958 .rd = dst_reg,
2771 .rd = dst_reg,2959 .rs1 = if (tag == .min) rhs_reg else lhs_reg,
2772 .rs1 = if (tag == .min) rhs_reg else lhs_reg,2960 .rs2 = mask_reg,
2773 .rs2 = mask_reg,2961 } },
2774 } },2962 });
2775 });2963 },
2964 else => |t| return func.fail("TODO: genBinOp min/max for {s}", .{@tagName(t)}),
2965 }
2776 },2966 },
2777 else => return func.fail("TODO: genBinOp {}", .{tag}),2967 else => return func.fail("TODO: genBinOp {}", .{tag}),
2778 }2968 }
...@@ -2791,12 +2981,14 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2791,12 +2981,14 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2791 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2981 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2792 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;2982 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
27932983
2984 const rhs_ty = func.typeOf(extra.rhs);
2985 const lhs_ty = func.typeOf(extra.lhs);
2986
2794 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {2987 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2795 const ty = func.typeOf(extra.lhs);2988 switch (lhs_ty.zigTypeTag(zcu)) {
2796 switch (ty.zigTypeTag(zcu)) {
2797 .Vector => return func.fail("TODO implement add with overflow for Vector type", .{}),2989 .Vector => return func.fail("TODO implement add with overflow for Vector type", .{}),
2798 .Int => {2990 .Int => {
2799 const int_info = ty.intInfo(zcu);2991 const int_info = lhs_ty.intInfo(zcu);
28002992
2801 const tuple_ty = func.typeOfIndex(inst);2993 const tuple_ty = func.typeOfIndex(inst);
2802 const result_mcv = try func.allocRegOrMem(tuple_ty, inst, false);2994 const result_mcv = try func.allocRegOrMem(tuple_ty, inst, false);
...@@ -2805,26 +2997,29 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2805,26 +2997,29 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2805 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {2997 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
2806 const add_result = try func.binOp(null, .add, extra.lhs, extra.rhs);2998 const add_result = try func.binOp(null, .add, extra.lhs, extra.rhs);
28072999
2808 const add_result_reg = try func.copyToTmpRegister(ty, add_result);
2809 const add_result_reg_lock = func.register_manager.lockRegAssumeUnused(add_result_reg);
2810 defer func.register_manager.unlockReg(add_result_reg_lock);
2811
2812 try func.genSetMem(3000 try func.genSetMem(
2813 .{ .frame = offset.index },3001 .{ .frame = offset.index },
2814 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, pt))),3002 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, pt))),
2815 ty,3003 lhs_ty,
2816 add_result,3004 add_result,
2817 );3005 );
28183006
3007 const trunc_reg = try func.copyToTmpRegister(lhs_ty, add_result);
3008 const trunc_reg_lock = func.register_manager.lockRegAssumeUnused(trunc_reg);
3009 defer func.register_manager.unlockReg(trunc_reg_lock);
3010
2819 const overflow_reg, const overflow_lock = try func.allocReg(.int);3011 const overflow_reg, const overflow_lock = try func.allocReg(.int);
2820 defer func.register_manager.unlockReg(overflow_lock);3012 defer func.register_manager.unlockReg(overflow_lock);
28213013
3014 // if the result isn't equal after truncating it to the given type,
3015 // an overflow must have happened.
3016 try func.truncateRegister(lhs_ty, trunc_reg);
2822 try func.genBinOp(3017 try func.genBinOp(
2823 .cmp_neq,3018 .cmp_neq,
2824 .{ .register = add_result_reg },3019 add_result,
2825 ty,3020 lhs_ty,
2826 .{ .register = add_result_reg },3021 .{ .register = trunc_reg },
2827 ty,3022 rhs_ty,
2828 overflow_reg,3023 overflow_reg,
2829 );3024 );
28303025
...@@ -2837,7 +3032,68 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2837,7 +3032,68 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
28373032
2838 break :result result_mcv;3033 break :result result_mcv;
2839 } else {3034 } else {
2840 return func.fail("TODO: less than 8 bit or non-pow 2 addition", .{});3035 const rhs_mcv = try func.resolveInst(extra.rhs);
3036 const lhs_mcv = try func.resolveInst(extra.lhs);
3037
3038 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs_mcv);
3039 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs_mcv);
3040 defer {
3041 if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
3042 if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
3043 }
3044
3045 try func.truncateRegister(rhs_ty, rhs_reg);
3046 try func.truncateRegister(lhs_ty, lhs_reg);
3047
3048 const dest_reg, const dest_lock = try func.allocReg(.int);
3049 defer func.register_manager.unlockReg(dest_lock);
3050
3051 _ = try func.addInst(.{
3052 .tag = .add,
3053 .data = .{ .r_type = .{
3054 .rs1 = rhs_reg,
3055 .rs2 = lhs_reg,
3056 .rd = dest_reg,
3057 } },
3058 });
3059
3060 try func.truncateRegister(func.typeOfIndex(inst), dest_reg);
3061 const add_result: MCValue = .{ .register = dest_reg };
3062
3063 try func.genSetMem(
3064 .{ .frame = offset.index },
3065 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, pt))),
3066 lhs_ty,
3067 add_result,
3068 );
3069
3070 const trunc_reg = try func.copyToTmpRegister(lhs_ty, add_result);
3071 const trunc_reg_lock = func.register_manager.lockRegAssumeUnused(trunc_reg);
3072 defer func.register_manager.unlockReg(trunc_reg_lock);
3073
3074 const overflow_reg, const overflow_lock = try func.allocReg(.int);
3075 defer func.register_manager.unlockReg(overflow_lock);
3076
3077 // if the result isn't equal after truncating it to the given type,
3078 // an overflow must have happened.
3079 try func.truncateRegister(lhs_ty, trunc_reg);
3080 try func.genBinOp(
3081 .cmp_neq,
3082 add_result,
3083 lhs_ty,
3084 .{ .register = trunc_reg },
3085 rhs_ty,
3086 overflow_reg,
3087 );
3088
3089 try func.genSetMem(
3090 .{ .frame = offset.index },
3091 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, pt))),
3092 Type.u1,
3093 .{ .register = overflow_reg },
3094 );
3095
3096 break :result result_mcv;
2841 }3097 }
2842 },3098 },
2843 else => unreachable,3099 else => unreachable,
...@@ -2890,7 +3146,7 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2890,7 +3146,7 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2890 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs);3146 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs);
2891 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);3147 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
28923148
2893 const overflow_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = 0 });3149 const overflow_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = 0 });
28943150
2895 const overflow_lock = func.register_manager.lockRegAssumeUnused(overflow_reg);3151 const overflow_lock = func.register_manager.lockRegAssumeUnused(overflow_reg);
2896 defer func.register_manager.unlockReg(overflow_lock);3152 defer func.register_manager.unlockReg(overflow_lock);
...@@ -2899,7 +3155,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2899,7 +3155,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2899 .unsigned => {3155 .unsigned => {
2900 _ = try func.addInst(.{3156 _ = try func.addInst(.{
2901 .tag = .sltu,3157 .tag = .sltu,
2902 .ops = .rrr,
2903 .data = .{ .r_type = .{3158 .data = .{ .r_type = .{
2904 .rd = overflow_reg,3159 .rd = overflow_reg,
2905 .rs1 = lhs_reg,3160 .rs1 = lhs_reg,
...@@ -2921,7 +3176,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2921,7 +3176,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2921 64 => {3176 64 => {
2922 _ = try func.addInst(.{3177 _ = try func.addInst(.{
2923 .tag = .slt,3178 .tag = .slt,
2924 .ops = .rrr,
2925 .data = .{ .r_type = .{3179 .data = .{ .r_type = .{
2926 .rd = overflow_reg,3180 .rd = overflow_reg,
2927 .rs1 = overflow_reg,3181 .rs1 = overflow_reg,
...@@ -2931,7 +3185,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2931,7 +3185,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
29313185
2932 _ = try func.addInst(.{3186 _ = try func.addInst(.{
2933 .tag = .slt,3187 .tag = .slt,
2934 .ops = .rrr,
2935 .data = .{ .r_type = .{3188 .data = .{ .r_type = .{
2936 .rd = rhs_reg,3189 .rd = rhs_reg,
2937 .rs1 = rhs_reg,3190 .rs1 = rhs_reg,
...@@ -2941,7 +3194,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2941,7 +3194,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
29413194
2942 _ = try func.addInst(.{3195 _ = try func.addInst(.{
2943 .tag = .xor,3196 .tag = .xor,
2944 .ops = .rrr,
2945 .data = .{ .r_type = .{3197 .data = .{ .r_type = .{
2946 .rd = lhs_reg,3198 .rd = lhs_reg,
2947 .rs1 = overflow_reg,3199 .rs1 = overflow_reg,
...@@ -2952,9 +3204,9 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2952,9 +3204,9 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2952 try func.genBinOp(3204 try func.genBinOp(
2953 .cmp_neq,3205 .cmp_neq,
2954 .{ .register = overflow_reg },3206 .{ .register = overflow_reg },
2955 Type.usize,3207 Type.u64,
2956 .{ .register = rhs_reg },3208 .{ .register = rhs_reg },
2957 Type.usize,3209 Type.u64,
2958 overflow_reg,3210 overflow_reg,
2959 );3211 );
29603212
...@@ -3017,61 +3269,34 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -3017,61 +3269,34 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
3017 switch (lhs_ty.zigTypeTag(zcu)) {3269 switch (lhs_ty.zigTypeTag(zcu)) {
3018 else => |x| return func.fail("TODO: airMulWithOverflow {s}", .{@tagName(x)}),3270 else => |x| return func.fail("TODO: airMulWithOverflow {s}", .{@tagName(x)}),
3019 .Int => {3271 .Int => {
3020 assert(lhs_ty.eql(rhs_ty, zcu));3272 if (std.debug.runtime_safety) assert(lhs_ty.eql(rhs_ty, zcu));
3021 const int_info = lhs_ty.intInfo(zcu);3273
3022 switch (int_info.bits) {3274 const trunc_reg = try func.copyToTmpRegister(lhs_ty, .{ .register = dest_reg });
3023 1...32 => {3275 const trunc_reg_lock = func.register_manager.lockRegAssumeUnused(trunc_reg);
3024 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {3276 defer func.register_manager.unlockReg(trunc_reg_lock);
3025 if (int_info.signedness == .unsigned) {3277
3026 switch (int_info.bits) {3278 const overflow_reg, const overflow_lock = try func.allocReg(.int);
3027 1...8 => {3279 defer func.register_manager.unlockReg(overflow_lock);
3028 const max_val = std.math.pow(u16, 2, int_info.bits) - 1;3280
30293281 // if the result isn't equal after truncating it to the given type,
3030 const add_reg, const add_lock = try func.promoteReg(lhs_ty, lhs);3282 // an overflow must have happened.
3031 defer if (add_lock) |lock| func.register_manager.unlockReg(lock);3283 try func.truncateRegister(func.typeOf(extra.lhs), trunc_reg);
30323284 try func.genBinOp(
3033 const overflow_reg, const overflow_lock = try func.allocReg(.int);3285 .cmp_neq,
3034 defer func.register_manager.unlockReg(overflow_lock);3286 .{ .register = dest_reg },
30353287 lhs_ty,
3036 _ = try func.addInst(.{3288 .{ .register = trunc_reg },
3037 .tag = .andi,3289 rhs_ty,
3038 .ops = .rri,3290 overflow_reg,
3039 .data = .{ .i_type = .{3291 );
3040 .rd = overflow_reg,3292
3041 .rs1 = add_reg,3293 try func.genCopy(
3042 .imm12 = Immediate.s(max_val),3294 lhs_ty,
3043 } },3295 result_mcv.offset(overflow_off),
3044 });3296 .{ .register = overflow_reg },
30453297 );
3046 try func.genBinOp(3298
3047 .cmp_neq,3299 break :result result_mcv;
3048 .{ .register = overflow_reg },
3049 lhs_ty,
3050 .{ .register = add_reg },
3051 lhs_ty,
3052 overflow_reg,
3053 );
3054
3055 try func.genCopy(
3056 lhs_ty,
3057 result_mcv.offset(overflow_off),
3058 .{ .register = overflow_reg },
3059 );
3060
3061 break :result result_mcv;
3062 },
3063
3064 else => return func.fail("TODO: airMulWithOverflow check for size {d}", .{int_info.bits}),
3065 }
3066 } else {
3067 return func.fail("TODO: airMulWithOverflow calculate carry for signed addition", .{});
3068 }
3069 } else {
3070 return func.fail("TODO: airMulWithOverflow with < 8 bits or non-pow of 2", .{});
3071 }
3072 },
3073 else => return func.fail("TODO: airMulWithOverflow larger than 32-bit mul", .{}),
3074 }
3075 },3300 },
3076 }3301 }
3077 };3302 };
...@@ -3085,12 +3310,6 @@ fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -3085,12 +3310,6 @@ fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
3085 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3310 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3086}3311}
30873312
3088fn airAddSat(func: *Func, inst: Air.Inst.Index) !void {
3089 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3090 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airAddSat", .{});
3091 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3092}
3093
3094fn airSubSat(func: *Func, inst: Air.Inst.Index) !void {3313fn airSubSat(func: *Func, inst: Air.Inst.Index) !void {
3095 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3314 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3096 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airSubSat", .{});3315 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airSubSat", .{});
...@@ -3300,19 +3519,21 @@ fn airWrapOptional(func: *Func, inst: Air.Inst.Index) !void {...@@ -3300,19 +3519,21 @@ fn airWrapOptional(func: *Func, inst: Air.Inst.Index) !void {
3300 };3519 };
3301 defer if (pl_lock) |lock| func.register_manager.unlockReg(lock);3520 defer if (pl_lock) |lock| func.register_manager.unlockReg(lock);
33023521
3303 const opt_mcv = try func.allocRegOrMem(opt_ty, inst, true);3522 const opt_mcv = try func.allocRegOrMem(opt_ty, inst, false);
3304 try func.genCopy(pl_ty, opt_mcv, pl_mcv);3523 try func.genCopy(pl_ty, opt_mcv, pl_mcv);
33053524
3306 if (!same_repr) {3525 if (!same_repr) {
3307 const pl_abi_size: i32 = @intCast(pl_ty.abiSize(pt));3526 const pl_abi_size: i32 = @intCast(pl_ty.abiSize(pt));
3308 switch (opt_mcv) {3527 switch (opt_mcv) {
3309 .load_frame => |frame_addr| try func.genSetMem(3528 .load_frame => |frame_addr| {
3310 .{ .frame = frame_addr.index },3529 try func.genCopy(pl_ty, opt_mcv, pl_mcv);
3311 frame_addr.off + pl_abi_size,3530 try func.genSetMem(
3312 Type.u8,3531 .{ .frame = frame_addr.index },
3313 .{ .immediate = 1 },3532 frame_addr.off + pl_abi_size,
3314 ),3533 Type.u8,
3315 .register => return func.fail("TODO: airWrapOption opt_mcv register", .{}),3534 .{ .immediate = 1 },
3535 );
3536 },
3316 else => unreachable,3537 else => unreachable,
3317 }3538 }
3318 }3539 }
...@@ -3454,7 +3675,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {...@@ -3454,7 +3675,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
3454 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;3675 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
34553676
3456 const dst_mcv = try func.allocRegOrMem(ty, inst, true);3677 const dst_mcv = try func.allocRegOrMem(ty, inst, true);
3457 try func.genCopy(Type.usize, dst_mcv, len_mcv);3678 try func.genCopy(Type.u64, dst_mcv, len_mcv);
3458 break :result dst_mcv;3679 break :result dst_mcv;
3459 },3680 },
3460 .register_pair => |pair| {3681 .register_pair => |pair| {
...@@ -3463,7 +3684,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {...@@ -3463,7 +3684,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
3463 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;3684 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
34643685
3465 const dst_mcv = try func.allocRegOrMem(ty, inst, true);3686 const dst_mcv = try func.allocRegOrMem(ty, inst, true);
3466 try func.genCopy(Type.usize, dst_mcv, len_mcv);3687 try func.genCopy(Type.u64, dst_mcv, len_mcv);
3467 break :result dst_mcv;3688 break :result dst_mcv;
3468 },3689 },
3469 else => return func.fail("TODO airSliceLen for {}", .{src_mcv}),3690 else => return func.fail("TODO airSliceLen for {}", .{src_mcv}),
...@@ -3474,14 +3695,28 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {...@@ -3474,14 +3695,28 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
34743695
3475fn airPtrSliceLenPtr(func: *Func, inst: Air.Inst.Index) !void {3696fn airPtrSliceLenPtr(func: *Func, inst: Air.Inst.Index) !void {
3476 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3697 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3477 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement ptr_slice_len_ptr for {}", .{func.target.cpu.arch});3698 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3699 const src_mcv = try func.resolveInst(ty_op.operand);
3700
3701 const dst_reg, const dst_lock = try func.allocReg(.int);
3702 defer func.register_manager.unlockReg(dst_lock);
3703 const dst_mcv: MCValue = .{ .register = dst_reg };
3704
3705 try func.genCopy(Type.u64, dst_mcv, src_mcv.offset(8));
3706 break :result dst_mcv;
3707 };
3478 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });3708 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3479}3709}
34803710
3481fn airPtrSlicePtrPtr(func: *Func, inst: Air.Inst.Index) !void {3711fn airPtrSlicePtrPtr(func: *Func, inst: Air.Inst.Index) !void {
3482 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3712 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3483 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement ptr_slice_ptr_ptr for {}", .{func.target.cpu.arch});3713
3484 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });3714 const opt_mcv = try func.resolveInst(ty_op.operand);
3715 const dst_mcv = if (func.reuseOperand(inst, ty_op.operand, 0, opt_mcv))
3716 opt_mcv
3717 else
3718 try func.copyToNewRegister(inst, opt_mcv);
3719 return func.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
3485}3720}
34863721
3487fn airSliceElemVal(func: *Func, inst: Air.Inst.Index) !void {3722fn airSliceElemVal(func: *Func, inst: Air.Inst.Index) !void {
...@@ -3538,11 +3773,10 @@ fn genSliceElemPtr(func: *Func, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {...@@ -3538,11 +3773,10 @@ fn genSliceElemPtr(func: *Func, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
35383773
3539 const addr_reg, const addr_lock = try func.allocReg(.int);3774 const addr_reg, const addr_lock = try func.allocReg(.int);
3540 defer func.register_manager.unlockReg(addr_lock);3775 defer func.register_manager.unlockReg(addr_lock);
3541 try func.genSetReg(Type.usize, addr_reg, slice_mcv);3776 try func.genSetReg(Type.u64, addr_reg, slice_mcv);
35423777
3543 _ = try func.addInst(.{3778 _ = try func.addInst(.{
3544 .tag = .add,3779 .tag = .add,
3545 .ops = .rrr,
3546 .data = .{ .r_type = .{3780 .data = .{ .r_type = .{
3547 .rd = addr_reg,3781 .rd = addr_reg,
3548 .rs1 = addr_reg,3782 .rs1 = addr_reg,
...@@ -3576,12 +3810,12 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -3576,12 +3810,12 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
3576 .register => {3810 .register => {
3577 const frame_index = try func.allocFrameIndex(FrameAlloc.initType(array_ty, pt));3811 const frame_index = try func.allocFrameIndex(FrameAlloc.initType(array_ty, pt));
3578 try func.genSetMem(.{ .frame = frame_index }, 0, array_ty, array_mcv);3812 try func.genSetMem(.{ .frame = frame_index }, 0, array_ty, array_mcv);
3579 try func.genSetReg(Type.usize, addr_reg, .{ .lea_frame = .{ .index = frame_index } });3813 try func.genSetReg(Type.u64, addr_reg, .{ .lea_frame = .{ .index = frame_index } });
3580 },3814 },
3581 .load_frame => |frame_addr| {3815 .load_frame => |frame_addr| {
3582 try func.genSetReg(Type.usize, addr_reg, .{ .lea_frame = frame_addr });3816 try func.genSetReg(Type.u64, addr_reg, .{ .lea_frame = frame_addr });
3583 },3817 },
3584 else => try func.genSetReg(Type.usize, addr_reg, array_mcv.address()),3818 else => try func.genSetReg(Type.u64, addr_reg, array_mcv.address()),
3585 }3819 }
35863820
3587 const dst_mcv = try func.allocRegOrMem(result_ty, inst, false);3821 const dst_mcv = try func.allocRegOrMem(result_ty, inst, false);
...@@ -3602,11 +3836,10 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -3602,11 +3836,10 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
3602 // we can do a shortcut here where we don't need a vslicedown3836 // we can do a shortcut here where we don't need a vslicedown
3603 // and can just copy to the frame index.3837 // and can just copy to the frame index.
3604 if (!(index_mcv == .immediate and index_mcv.immediate == 0)) {3838 if (!(index_mcv == .immediate and index_mcv.immediate == 0)) {
3605 const index_reg = try func.copyToTmpRegister(Type.usize, index_mcv);3839 const index_reg = try func.copyToTmpRegister(Type.u64, index_mcv);
36063840
3607 _ = try func.addInst(.{3841 _ = try func.addInst(.{
3608 .tag = .vslidedownvx,3842 .tag = .vslidedownvx,
3609 .ops = .rrr,
3610 .data = .{ .r_type = .{3843 .data = .{ .r_type = .{
3611 .rd = src_reg,3844 .rd = src_reg,
3612 .rs1 = index_reg,3845 .rs1 = index_reg,
...@@ -3624,7 +3857,6 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -3624,7 +3857,6 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
3624 defer func.register_manager.unlockReg(offset_lock);3857 defer func.register_manager.unlockReg(offset_lock);
3625 _ = try func.addInst(.{3858 _ = try func.addInst(.{
3626 .tag = .add,3859 .tag = .add,
3627 .ops = .rrr,
3628 .data = .{ .r_type = .{3860 .data = .{ .r_type = .{
3629 .rd = addr_reg,3861 .rd = addr_reg,
3630 .rs1 = addr_reg,3862 .rs1 = addr_reg,
...@@ -3640,8 +3872,55 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -3640,8 +3872,55 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
36403872
3641fn airPtrElemVal(func: *Func, inst: Air.Inst.Index) !void {3873fn airPtrElemVal(func: *Func, inst: Air.Inst.Index) !void {
3642 const is_volatile = false; // TODO3874 const is_volatile = false; // TODO
3875 const pt = func.pt;
3876 const zcu = pt.zcu;
3643 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3877 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3644 const result: MCValue = if (!is_volatile and func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement ptr_elem_val for {}", .{func.target.cpu.arch});3878 const base_ptr_ty = func.typeOf(bin_op.lhs);
3879
3880 const result: MCValue = if (!is_volatile and func.liveness.isUnused(inst)) .unreach else result: {
3881 const elem_ty = base_ptr_ty.elemType2(zcu);
3882 if (!elem_ty.hasRuntimeBitsIgnoreComptime(pt)) break :result .none;
3883
3884 const base_ptr_mcv = try func.resolveInst(bin_op.lhs);
3885 const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) {
3886 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
3887 else => null,
3888 };
3889 defer if (base_ptr_lock) |lock| func.register_manager.unlockReg(lock);
3890
3891 const index_mcv = try func.resolveInst(bin_op.rhs);
3892 const index_lock: ?RegisterLock = switch (index_mcv) {
3893 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
3894 else => null,
3895 };
3896 defer if (index_lock) |lock| func.register_manager.unlockReg(lock);
3897
3898 const elem_ptr_reg = if (base_ptr_mcv.isRegister() and func.liveness.operandDies(inst, 0))
3899 base_ptr_mcv.register
3900 else
3901 try func.copyToTmpRegister(base_ptr_ty, base_ptr_mcv);
3902 const elem_ptr_lock = func.register_manager.lockRegAssumeUnused(elem_ptr_reg);
3903 defer func.register_manager.unlockReg(elem_ptr_lock);
3904
3905 try func.genBinOp(
3906 .ptr_add,
3907 base_ptr_mcv,
3908 base_ptr_ty,
3909 index_mcv,
3910 Type.u64,
3911 elem_ptr_reg,
3912 );
3913
3914 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
3915 const dst_lock = switch (dst_mcv) {
3916 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
3917 else => null,
3918 };
3919 defer if (dst_lock) |lock| func.register_manager.unlockReg(lock);
3920
3921 try func.load(dst_mcv, .{ .register = elem_ptr_reg }, base_ptr_ty);
3922 break :result dst_mcv;
3923 };
3645 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3924 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3646}3925}
36473926
...@@ -3651,10 +3930,14 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -3651,10 +3930,14 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {
3651 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3930 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
3652 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;3931 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
36533932
3654 const result = result: {3933 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3655 const elem_ptr_ty = func.typeOfIndex(inst);3934 const elem_ptr_ty = func.typeOfIndex(inst);
3656 const base_ptr_ty = func.typeOf(extra.lhs);3935 const base_ptr_ty = func.typeOf(extra.lhs);
36573936
3937 if (elem_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) {
3938 @panic("audit");
3939 }
3940
3658 const base_ptr_mcv = try func.resolveInst(extra.lhs);3941 const base_ptr_mcv = try func.resolveInst(extra.lhs);
3659 const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) {3942 const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) {
3660 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),3943 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
...@@ -3662,16 +3945,6 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -3662,16 +3945,6 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {
3662 };3945 };
3663 defer if (base_ptr_lock) |lock| func.register_manager.unlockReg(lock);3946 defer if (base_ptr_lock) |lock| func.register_manager.unlockReg(lock);
36643947
3665 if (elem_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) {
3666 break :result if (func.reuseOperand(inst, extra.lhs, 0, base_ptr_mcv))
3667 base_ptr_mcv
3668 else
3669 try func.copyToNewRegister(inst, base_ptr_mcv);
3670 }
3671
3672 const elem_ty = base_ptr_ty.elemType2(zcu);
3673 const elem_abi_size = elem_ty.abiSize(pt);
3674 const index_ty = func.typeOf(extra.rhs);
3675 const index_mcv = try func.resolveInst(extra.rhs);3948 const index_mcv = try func.resolveInst(extra.rhs);
3676 const index_lock: ?RegisterLock = switch (index_mcv) {3949 const index_lock: ?RegisterLock = switch (index_mcv) {
3677 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),3950 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
...@@ -3679,10 +3952,6 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -3679,10 +3952,6 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {
3679 };3952 };
3680 defer if (index_lock) |lock| func.register_manager.unlockReg(lock);3953 defer if (index_lock) |lock| func.register_manager.unlockReg(lock);
36813954
3682 const offset_reg = try func.elemOffset(index_ty, index_mcv, elem_abi_size);
3683 const offset_reg_lock = func.register_manager.lockRegAssumeUnused(offset_reg);
3684 defer func.register_manager.unlockReg(offset_reg_lock);
3685
3686 const result_reg, const result_lock = try func.allocReg(.int);3955 const result_reg, const result_lock = try func.allocReg(.int);
3687 defer func.register_manager.unlockReg(result_lock);3956 defer func.register_manager.unlockReg(result_lock);
36883957
...@@ -3690,13 +3959,14 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -3690,13 +3959,14 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {
3690 .ptr_add,3959 .ptr_add,
3691 base_ptr_mcv,3960 base_ptr_mcv,
3692 base_ptr_ty,3961 base_ptr_ty,
3693 .{ .register = offset_reg },3962 index_mcv,
3694 Type.usize,3963 Type.u64,
3695 result_reg,3964 result_reg,
3696 );3965 );
36973966
3698 break :result MCValue{ .register = result_reg };3967 break :result MCValue{ .register = result_reg };
3699 };3968 };
3969
3700 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });3970 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
3701}3971}
37023972
...@@ -3729,7 +3999,7 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {...@@ -3729,7 +3999,7 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {
3729 defer func.register_manager.unlockReg(result_lock);3999 defer func.register_manager.unlockReg(result_lock);
37304000
3731 switch (frame_mcv) {4001 switch (frame_mcv) {
3732 .load_frame => |frame_addr| {4002 .load_frame => {
3733 if (tag_abi_size <= 8) {4003 if (tag_abi_size <= 8) {
3734 const off: i32 = if (layout.tag_align.compare(.lt, layout.payload_align))4004 const off: i32 = if (layout.tag_align.compare(.lt, layout.payload_align))
3735 @intCast(layout.payload_size)4005 @intCast(layout.payload_size)
...@@ -3739,7 +4009,7 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {...@@ -3739,7 +4009,7 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {
3739 try func.genCopy(4009 try func.genCopy(
3740 tag_ty,4010 tag_ty,
3741 .{ .register = result_reg },4011 .{ .register = result_reg },
3742 .{ .load_frame = .{ .index = frame_addr.index, .off = frame_addr.off + off } },4012 frame_mcv.offset(off),
3743 );4013 );
3744 } else {4014 } else {
3745 return func.fail(4015 return func.fail(
...@@ -3756,7 +4026,57 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {...@@ -3756,7 +4026,57 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {
37564026
3757fn airClz(func: *Func, inst: Air.Inst.Index) !void {4027fn airClz(func: *Func, inst: Air.Inst.Index) !void {
3758 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;4028 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3759 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airClz for {}", .{func.target.cpu.arch});4029 const operand = try func.resolveInst(ty_op.operand);
4030 const ty = func.typeOf(ty_op.operand);
4031
4032 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4033 const src_reg, const src_lock = try func.promoteReg(ty, operand);
4034 defer if (src_lock) |lock| func.register_manager.unlockReg(lock);
4035
4036 const dst_reg: Register = if (func.reuseOperand(
4037 inst,
4038 ty_op.operand,
4039 0,
4040 operand,
4041 ) and operand == .register)
4042 operand.register
4043 else
4044 (try func.allocRegOrMem(func.typeOfIndex(inst), inst, true)).register;
4045
4046 const bit_size = ty.bitSize(func.pt);
4047 if (!math.isPowerOfTwo(bit_size)) try func.truncateRegister(ty, src_reg);
4048
4049 if (bit_size > 64) {
4050 return func.fail("TODO: airClz > 64 bits, found {d}", .{bit_size});
4051 }
4052
4053 _ = try func.addInst(.{
4054 .tag = switch (bit_size) {
4055 32 => .clzw,
4056 else => .clz,
4057 },
4058 .data = .{
4059 .r_type = .{
4060 .rs2 = .zero, // rs2 is 0 filled in the spec
4061 .rs1 = src_reg,
4062 .rd = dst_reg,
4063 },
4064 },
4065 });
4066
4067 if (!(bit_size == 32 or bit_size == 64)) {
4068 _ = try func.addInst(.{
4069 .tag = .addi,
4070 .data = .{ .i_type = .{
4071 .rd = dst_reg,
4072 .rs1 = dst_reg,
4073 .imm12 = Immediate.s(-@as(i12, @intCast(64 - bit_size % 64))),
4074 } },
4075 });
4076 }
4077
4078 break :result .{ .register = dst_reg };
4079 };
3760 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });4080 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3761}4081}
37624082
...@@ -3767,14 +4087,44 @@ fn airCtz(func: *Func, inst: Air.Inst.Index) !void {...@@ -3767,14 +4087,44 @@ fn airCtz(func: *Func, inst: Air.Inst.Index) !void {
3767}4087}
37684088
3769fn airPopcount(func: *Func, inst: Air.Inst.Index) !void {4089fn airPopcount(func: *Func, inst: Air.Inst.Index) !void {
3770 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;4090 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3771 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airPopcount for {}", .{func.target.cpu.arch});4091 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3772 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });4092 const pt = func.pt;
3773}4093
37744094 const operand = try func.resolveInst(ty_op.operand);
3775fn airAbs(func: *Func, inst: Air.Inst.Index) !void {4095 const src_ty = func.typeOf(ty_op.operand);
3776 const pt = func.pt;4096 const operand_reg, const operand_lock = try func.promoteReg(src_ty, operand);
3777 const zcu = pt.zcu;4097 defer if (operand_lock) |lock| func.register_manager.unlockReg(lock);
4098
4099 const dst_reg, const dst_lock = try func.allocReg(.int);
4100 defer func.register_manager.unlockReg(dst_lock);
4101
4102 const bit_size = src_ty.bitSize(pt);
4103 switch (bit_size) {
4104 32, 64 => {},
4105 1...31, 33...63 => try func.truncateRegister(src_ty, operand_reg),
4106 else => return func.fail("TODO: airPopcount > 64 bits", .{}),
4107 }
4108
4109 _ = try func.addInst(.{
4110 .tag = if (bit_size <= 32) .cpopw else .cpop,
4111 .data = .{
4112 .r_type = .{
4113 .rd = dst_reg,
4114 .rs1 = operand_reg,
4115 .rs2 = @enumFromInt(0b00010), // this is the cpop funct5
4116 },
4117 },
4118 });
4119
4120 break :result .{ .register = dst_reg };
4121 };
4122 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
4123}
4124
4125fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
4126 const pt = func.pt;
4127 const zcu = pt.zcu;
3778 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;4128 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3779 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {4129 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3780 const ty = func.typeOf(ty_op.operand);4130 const ty = func.typeOf(ty_op.operand);
...@@ -3785,6 +4135,13 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {...@@ -3785,6 +4135,13 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
3785 .Int => if (ty.zigTypeTag(zcu) == .Vector) {4135 .Int => if (ty.zigTypeTag(zcu) == .Vector) {
3786 return func.fail("TODO implement airAbs for {}", .{ty.fmt(pt)});4136 return func.fail("TODO implement airAbs for {}", .{ty.fmt(pt)});
3787 } else {4137 } else {
4138 const int_info = scalar_ty.intInfo(zcu);
4139 const int_bits = int_info.bits;
4140 switch (int_bits) {
4141 32, 64 => {},
4142 else => return func.fail("TODO: airAbs Int size {d}", .{int_bits}),
4143 }
4144
3788 const return_mcv = try func.copyToNewRegister(inst, operand);4145 const return_mcv = try func.copyToNewRegister(inst, operand);
3789 const operand_reg = return_mcv.register;4146 const operand_reg = return_mcv.register;
37904147
...@@ -3792,18 +4149,20 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {...@@ -3792,18 +4149,20 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
3792 defer func.register_manager.unlockReg(temp_lock);4149 defer func.register_manager.unlockReg(temp_lock);
37934150
3794 _ = try func.addInst(.{4151 _ = try func.addInst(.{
3795 .tag = .srai,4152 .tag = switch (int_bits) {
3796 .ops = .rri,4153 32 => .sraiw,
4154 64 => .srai,
4155 else => unreachable,
4156 },
3797 .data = .{ .i_type = .{4157 .data = .{ .i_type = .{
3798 .rd = temp_reg,4158 .rd = temp_reg,
3799 .rs1 = operand_reg,4159 .rs1 = operand_reg,
3800 .imm12 = Immediate.u(63),4160 .imm12 = Immediate.u(int_bits - 1),
3801 } },4161 } },
3802 });4162 });
38034163
3804 _ = try func.addInst(.{4164 _ = try func.addInst(.{
3805 .tag = .xor,4165 .tag = .xor,
3806 .ops = .rrr,
3807 .data = .{ .r_type = .{4166 .data = .{ .r_type = .{
3808 .rd = operand_reg,4167 .rd = operand_reg,
3809 .rs1 = operand_reg,4168 .rs1 = operand_reg,
...@@ -3812,8 +4171,11 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {...@@ -3812,8 +4171,11 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
3812 });4171 });
38134172
3814 _ = try func.addInst(.{4173 _ = try func.addInst(.{
3815 .tag = .sub,4174 .tag = switch (int_bits) {
3816 .ops = .rrr,4175 32 => .subw,
4176 64 => .sub,
4177 else => unreachable,
4178 },
3817 .data = .{ .r_type = .{4179 .data = .{ .r_type = .{
3818 .rd = operand_reg,4180 .rd = operand_reg,
3819 .rs1 = operand_reg,4181 .rs1 = operand_reg,
...@@ -3825,14 +4187,14 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {...@@ -3825,14 +4187,14 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
3825 },4187 },
3826 .Float => {4188 .Float => {
3827 const float_bits = scalar_ty.floatBits(zcu.getTarget());4189 const float_bits = scalar_ty.floatBits(zcu.getTarget());
3828 switch (float_bits) {4190 const mnem: Mnemonic = switch (float_bits) {
3829 16 => return func.fail("TODO: airAbs 16-bit float", .{}),4191 16 => return func.fail("TODO: airAbs 16-bit float", .{}),
3830 32 => {},4192 32 => .fsgnjxs,
3831 64 => {},4193 64 => .fsgnjxd,
3832 80 => return func.fail("TODO: airAbs 80-bit float", .{}),4194 80 => return func.fail("TODO: airAbs 80-bit float", .{}),
3833 128 => return func.fail("TODO: airAbs 128-bit float", .{}),4195 128 => return func.fail("TODO: airAbs 128-bit float", .{}),
3834 else => unreachable,4196 else => unreachable,
3835 }4197 };
38364198
3837 const return_mcv = try func.copyToNewRegister(inst, operand);4199 const return_mcv = try func.copyToNewRegister(inst, operand);
3838 const operand_reg = return_mcv.register;4200 const operand_reg = return_mcv.register;
...@@ -3840,13 +4202,12 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {...@@ -3840,13 +4202,12 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
3840 assert(operand_reg.class() == .float);4202 assert(operand_reg.class() == .float);
38414203
3842 _ = try func.addInst(.{4204 _ = try func.addInst(.{
3843 .tag = .pseudo,4205 .tag = mnem,
3844 .ops = .pseudo_fabs,
3845 .data = .{4206 .data = .{
3846 .fabs = .{4207 .r_type = .{
3847 .rd = operand_reg,4208 .rd = operand_reg,
3848 .rs = operand_reg,4209 .rs1 = operand_reg,
3849 .bits = float_bits,4210 .rs2 = operand_reg,
3850 },4211 },
3851 },4212 },
3852 });4213 });
...@@ -3869,54 +4230,56 @@ fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void {...@@ -3869,54 +4230,56 @@ fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void {
3869 const ty = func.typeOf(ty_op.operand);4230 const ty = func.typeOf(ty_op.operand);
3870 const operand = try func.resolveInst(ty_op.operand);4231 const operand = try func.resolveInst(ty_op.operand);
38714232
3872 const int_bits = ty.intInfo(zcu).bits;4233 switch (ty.zigTypeTag(zcu)) {
4234 .Int => {
4235 const int_bits = ty.intInfo(zcu).bits;
38734236
3874 // bytes are no-op4237 // bytes are no-op
3875 if (int_bits == 8 and func.reuseOperand(inst, ty_op.operand, 0, operand)) {4238 if (int_bits == 8 and func.reuseOperand(inst, ty_op.operand, 0, operand)) {
3876 return func.finishAir(inst, operand, .{ ty_op.operand, .none, .none });4239 return func.finishAir(inst, operand, .{ ty_op.operand, .none, .none });
3877 }4240 }
38784241
3879 const dest_mcv = try func.copyToNewRegister(inst, operand);4242 const dest_mcv = try func.copyToNewRegister(inst, operand);
3880 const dest_reg = dest_mcv.register;4243 const dest_reg = dest_mcv.register;
38814244
3882 switch (int_bits) {4245 switch (int_bits) {
3883 16 => {4246 16 => {
3884 const temp_reg, const temp_lock = try func.allocReg(.int);4247 const temp_reg, const temp_lock = try func.allocReg(.int);
3885 defer func.register_manager.unlockReg(temp_lock);4248 defer func.register_manager.unlockReg(temp_lock);
38864249
3887 _ = try func.addInst(.{4250 _ = try func.addInst(.{
3888 .tag = .srli,4251 .tag = .srli,
3889 .ops = .rri,4252 .data = .{ .i_type = .{
3890 .data = .{ .i_type = .{4253 .imm12 = Immediate.s(8),
3891 .imm12 = Immediate.s(8),4254 .rd = temp_reg,
3892 .rd = temp_reg,4255 .rs1 = dest_reg,
3893 .rs1 = dest_reg,4256 } },
3894 } },4257 });
3895 });
38964258
3897 _ = try func.addInst(.{4259 _ = try func.addInst(.{
3898 .tag = .slli,4260 .tag = .slli,
3899 .ops = .rri,4261 .data = .{ .i_type = .{
3900 .data = .{ .i_type = .{4262 .imm12 = Immediate.s(8),
3901 .imm12 = Immediate.s(8),4263 .rd = dest_reg,
3902 .rd = dest_reg,4264 .rs1 = dest_reg,
3903 .rs1 = dest_reg,4265 } },
3904 } },4266 });
3905 });4267 _ = try func.addInst(.{
3906 _ = try func.addInst(.{4268 .tag = .@"or",
3907 .tag = .@"or",4269 .data = .{ .r_type = .{
3908 .ops = .rri,4270 .rd = dest_reg,
3909 .data = .{ .r_type = .{4271 .rs1 = dest_reg,
3910 .rd = dest_reg,4272 .rs2 = temp_reg,
3911 .rs1 = dest_reg,4273 } },
3912 .rs2 = temp_reg,4274 });
3913 } },4275 },
3914 });4276 else => return func.fail("TODO: {d} bits for airByteSwap", .{int_bits}),
4277 }
4278
4279 break :result dest_mcv;
3915 },4280 },
3916 else => return func.fail("TODO: {d} bits for airByteSwap", .{int_bits}),4281 else => return func.fail("TODO: airByteSwap {}", .{ty.fmt(pt)}),
3917 }4282 }
3918
3919 break :result dest_mcv;
3920 };4283 };
3921 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });4284 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3922}4285}
...@@ -3960,7 +4323,6 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {...@@ -3960,7 +4323,6 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
3960 .sqrt => {4323 .sqrt => {
3961 _ = try func.addInst(.{4324 _ = try func.addInst(.{
3962 .tag = if (operand_bit_size == 64) .fsqrtd else .fsqrts,4325 .tag = if (operand_bit_size == 64) .fsqrtd else .fsqrts,
3963 .ops = .rrr,
3964 .data = .{4326 .data = .{
3965 .r_type = .{4327 .r_type = .{
3966 .rd = dst_reg,4328 .rd = dst_reg,
...@@ -3970,6 +4332,7 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {...@@ -3970,6 +4332,7 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
3970 },4332 },
3971 });4333 });
3972 },4334 },
4335
3973 else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}),4336 else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}),
3974 }4337 }
3975 },4338 },
...@@ -4054,9 +4417,15 @@ fn airLoad(func: *Func, inst: Air.Inst.Index) !void {...@@ -4054,9 +4417,15 @@ fn airLoad(func: *Func, inst: Air.Inst.Index) !void {
4054 const elem_size = elem_ty.abiSize(pt);4417 const elem_size = elem_ty.abiSize(pt);
40554418
4056 const dst_mcv: MCValue = blk: {4419 const dst_mcv: MCValue = blk: {
4057 // Pointer is 8 bytes, and if the element is more than that, we cannot reuse it.4420 // The MCValue that holds the pointer can be re-used as the value.
4058 if (elem_size <= 8 and func.reuseOperand(inst, ty_op.operand, 0, ptr)) {4421 // - "ptr" is 8 bytes, and if the element is more than that, we cannot reuse it.
4059 // The MCValue that holds the pointer can be re-used as the value.4422 //
4423 // - "ptr" will be stored in an integer register, so the type that we're gonna
4424 // load into it must also be a type that can be inside of an integer register
4425 if (elem_size <= 8 and
4426 (if (ptr == .register) func.typeRegClass(elem_ty) == ptr.register.class() else true) and
4427 func.reuseOperand(inst, ty_op.operand, 0, ptr))
4428 {
4060 break :blk ptr;4429 break :blk ptr;
4061 } else {4430 } else {
4062 break :blk try func.allocRegOrMem(elem_ty, inst, true);4431 break :blk try func.allocRegOrMem(elem_ty, inst, true);
...@@ -4090,12 +4459,14 @@ fn load(func: *Func, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro...@@ -4090,12 +4459,14 @@ fn load(func: *Func, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro
4090 .register_offset,4459 .register_offset,
4091 .lea_frame,4460 .lea_frame,
4092 .lea_symbol,4461 .lea_symbol,
4462 .lea_tlv,
4093 => try func.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()),4463 => try func.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()),
40944464
4095 .memory,4465 .memory,
4096 .indirect,4466 .indirect,
4097 .load_symbol,4467 .load_symbol,
4098 .load_frame,4468 .load_frame,
4469 .load_tlv,
4099 => {4470 => {
4100 const addr_reg = try func.copyToTmpRegister(ptr_ty, ptr_mcv);4471 const addr_reg = try func.copyToTmpRegister(ptr_ty, ptr_mcv);
4101 const addr_lock = func.register_manager.lockRegAssumeUnused(addr_reg);4472 const addr_lock = func.register_manager.lockRegAssumeUnused(addr_reg);
...@@ -4117,15 +4488,16 @@ fn airStore(func: *Func, inst: Air.Inst.Index, safety: bool) !void {...@@ -4117,15 +4488,16 @@ fn airStore(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
4117 const ptr = try func.resolveInst(bin_op.lhs);4488 const ptr = try func.resolveInst(bin_op.lhs);
4118 const value = try func.resolveInst(bin_op.rhs);4489 const value = try func.resolveInst(bin_op.rhs);
4119 const ptr_ty = func.typeOf(bin_op.lhs);4490 const ptr_ty = func.typeOf(bin_op.lhs);
4120 const value_ty = func.typeOf(bin_op.rhs);
41214491
4122 try func.store(ptr, value, ptr_ty, value_ty);4492 try func.store(ptr, value, ptr_ty);
41234493
4124 return func.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });4494 return func.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });
4125}4495}
41264496
4127/// Loads `value` into the "payload" of `pointer`.4497/// Loads `value` into the "payload" of `pointer`.
4128fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty: Type) !void {4498fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type) !void {
4499 const zcu = func.pt.zcu;
4500 const src_ty = ptr_ty.childType(zcu);
4129 log.debug("storing {}:{} in {}:{}", .{ src_mcv, src_ty.fmt(func.pt), ptr_mcv, ptr_ty.fmt(func.pt) });4501 log.debug("storing {}:{} in {}:{}", .{ src_mcv, src_ty.fmt(func.pt), ptr_mcv, ptr_ty.fmt(func.pt) });
41304502
4131 switch (ptr_mcv) {4503 switch (ptr_mcv) {
...@@ -4141,12 +4513,14 @@ fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty:...@@ -4141,12 +4513,14 @@ fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty:
4141 .register_offset,4513 .register_offset,
4142 .lea_symbol,4514 .lea_symbol,
4143 .lea_frame,4515 .lea_frame,
4516 .lea_tlv,
4144 => try func.genCopy(src_ty, ptr_mcv.deref(), src_mcv),4517 => try func.genCopy(src_ty, ptr_mcv.deref(), src_mcv),
41454518
4146 .memory,4519 .memory,
4147 .indirect,4520 .indirect,
4148 .load_symbol,4521 .load_symbol,
4149 .load_frame,4522 .load_frame,
4523 .load_tlv,
4150 => {4524 => {
4151 const addr_reg = try func.copyToTmpRegister(ptr_ty, ptr_mcv);4525 const addr_reg = try func.copyToTmpRegister(ptr_ty, ptr_mcv);
4152 const addr_lock = func.register_manager.lockRegAssumeUnused(addr_reg);4526 const addr_lock = func.register_manager.lockRegAssumeUnused(addr_reg);
...@@ -4154,7 +4528,7 @@ fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty:...@@ -4154,7 +4528,7 @@ fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty:
41544528
4155 try func.genCopy(src_ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv);4529 try func.genCopy(src_ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv);
4156 },4530 },
4157 .air_ref => |ptr_ref| try func.store(try func.resolveInst(ptr_ref), src_mcv, ptr_ty, src_ty),4531 .air_ref => |ptr_ref| try func.store(try func.resolveInst(ptr_ref), src_mcv, ptr_ty),
4158 }4532 }
4159}4533}
41604534
...@@ -4176,17 +4550,14 @@ fn structFieldPtr(func: *Func, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -4176,17 +4550,14 @@ fn structFieldPtr(func: *Func, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
4176 const zcu = pt.zcu;4550 const zcu = pt.zcu;
4177 const ptr_field_ty = func.typeOfIndex(inst);4551 const ptr_field_ty = func.typeOfIndex(inst);
4178 const ptr_container_ty = func.typeOf(operand);4552 const ptr_container_ty = func.typeOf(operand);
4179 const ptr_container_ty_info = ptr_container_ty.ptrInfo(zcu);
4180 const container_ty = ptr_container_ty.childType(zcu);4553 const container_ty = ptr_container_ty.childType(zcu);
41814554
4182 const field_offset: i32 = if (zcu.typeToPackedStruct(container_ty)) |struct_obj|4555 const field_offset: i32 = switch (container_ty.containerLayout(zcu)) {
4183 if (ptr_field_ty.ptrInfo(zcu).packed_offset.host_size == 0)4556 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, pt)),
4184 @divExact(pt.structPackedFieldBitOffset(struct_obj, index) +4557 .@"packed" => @divExact(@as(i32, ptr_container_ty.ptrInfo(zcu).packed_offset.bit_offset) +
4185 ptr_container_ty_info.packed_offset.bit_offset, 8)4558 (if (zcu.typeToStruct(container_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, index) else 0) -
4186 else4559 ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),
4187 04560 };
4188 else
4189 @intCast(container_ty.structFieldOffset(index, pt));
41904561
4191 const src_mcv = try func.resolveInst(operand);4562 const src_mcv = try func.resolveInst(operand);
4192 const dst_mcv = if (switch (src_mcv) {4563 const dst_mcv = if (switch (src_mcv) {
...@@ -4229,7 +4600,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -4229,7 +4600,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
4229 const dst_reg = if (field_off == 0)4600 const dst_reg = if (field_off == 0)
4230 (try func.copyToNewRegister(inst, src_mcv)).register4601 (try func.copyToNewRegister(inst, src_mcv)).register
4231 else4602 else
4232 try func.copyToTmpRegister(Type.usize, .{ .register = src_reg });4603 try func.copyToTmpRegister(Type.u64, .{ .register = src_reg });
42334604
4234 const dst_mcv: MCValue = .{ .register = dst_reg };4605 const dst_mcv: MCValue = .{ .register = dst_reg };
4235 const dst_lock = func.register_manager.lockReg(dst_reg);4606 const dst_lock = func.register_manager.lockReg(dst_reg);
...@@ -4238,7 +4609,6 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -4238,7 +4609,6 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
4238 if (field_off > 0) {4609 if (field_off > 0) {
4239 _ = try func.addInst(.{4610 _ = try func.addInst(.{
4240 .tag = .srli,4611 .tag = .srli,
4241 .ops = .rri,
4242 .data = .{ .i_type = .{4612 .data = .{ .i_type = .{
4243 .imm12 = Immediate.u(@intCast(field_off)),4613 .imm12 = Immediate.u(@intCast(field_off)),
4244 .rd = dst_reg,4614 .rd = dst_reg,
...@@ -4289,8 +4659,8 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -4289,8 +4659,8 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
42894659
4290 const hi_mcv =4660 const hi_mcv =
4291 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();4661 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();
4292 try func.genSetReg(Type.usize, tmp_reg, hi_mcv);4662 try func.genSetReg(Type.u64, tmp_reg, hi_mcv);
4293 try func.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });4663 try func.genCopy(Type.u64, hi_mcv, .{ .register = tmp_reg });
4294 }4664 }
4295 break :result dst_mcv;4665 break :result dst_mcv;
4296 }4666 }
...@@ -4314,7 +4684,7 @@ fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void {...@@ -4314,7 +4684,7 @@ fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void {
4314 const zcu = pt.zcu;4684 const zcu = pt.zcu;
4315 const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;4685 const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
4316 const ty = arg.ty.toType();4686 const ty = arg.ty.toType();
4317 const owner_decl = zcu.funcOwnerDeclIndex(func.func_index);4687 const owner_decl = func.owner.getDecl(zcu);
4318 if (arg.name == .none) return;4688 if (arg.name == .none) return;
4319 const name = func.air.nullTerminatedString(@intFromEnum(arg.name));4689 const name = func.air.nullTerminatedString(@intFromEnum(arg.name));
43204690
...@@ -4358,8 +4728,7 @@ fn airArg(func: *Func, inst: Air.Inst.Index) !void {...@@ -4358,8 +4728,7 @@ fn airArg(func: *Func, inst: Air.Inst.Index) !void {
4358fn airTrap(func: *Func) !void {4728fn airTrap(func: *Func) !void {
4359 _ = try func.addInst(.{4729 _ = try func.addInst(.{
4360 .tag = .unimp,4730 .tag = .unimp,
4361 .ops = .none,4731 .data = .none,
4362 .data = undefined,
4363 });4732 });
4364 return func.finishAirBookkeeping();4733 return func.finishAirBookkeeping();
4365}4734}
...@@ -4367,21 +4736,20 @@ fn airTrap(func: *Func) !void {...@@ -4367,21 +4736,20 @@ fn airTrap(func: *Func) !void {
4367fn airBreakpoint(func: *Func) !void {4736fn airBreakpoint(func: *Func) !void {
4368 _ = try func.addInst(.{4737 _ = try func.addInst(.{
4369 .tag = .ebreak,4738 .tag = .ebreak,
4370 .ops = .none,4739 .data = .none,
4371 .data = undefined,
4372 });4740 });
4373 return func.finishAirBookkeeping();4741 return func.finishAirBookkeeping();
4374}4742}
43754743
4376fn airRetAddr(func: *Func, inst: Air.Inst.Index) !void {4744fn airRetAddr(func: *Func, inst: Air.Inst.Index) !void {
4377 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);4745 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
4378 try func.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } });4746 try func.genCopy(Type.u64, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } });
4379 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });4747 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
4380}4748}
43814749
4382fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void {4750fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void {
4383 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);4751 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
4384 try func.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } });4752 try func.genCopy(Type.u64, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } });
4385 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });4753 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
4386}4754}
43874755
...@@ -4396,15 +4764,11 @@ fn airFence(func: *Func, inst: Air.Inst.Index) !void {...@@ -4396,15 +4764,11 @@ fn airFence(func: *Func, inst: Air.Inst.Index) !void {
4396 };4764 };
43974765
4398 _ = try func.addInst(.{4766 _ = try func.addInst(.{
4399 .tag = .pseudo,4767 .tag = if (order == .acq_rel) .fencetso else .fence,
4400 .ops = .pseudo_fence,4768 .data = .{ .fence = .{
4401 .data = .{4769 .pred = pred,
4402 .fence = .{4770 .succ = succ,
4403 .pred = pred,4771 } },
4404 .succ = succ,
4405 .fm = if (order == .acq_rel) .tso else .none,
4406 },
4407 },
4408 });4772 });
4409 return func.finishAirBookkeeping();4773 return func.finishAirBookkeeping();
4410}4774}
...@@ -4540,7 +4904,7 @@ fn genCall(...@@ -4540,7 +4904,7 @@ fn genCall(
4540 .indirect => |reg_off| {4904 .indirect => |reg_off| {
4541 const ret_ty = Type.fromInterned(fn_info.return_type);4905 const ret_ty = Type.fromInterned(fn_info.return_type);
4542 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(ret_ty, pt));4906 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(ret_ty, pt));
4543 try func.genSetReg(Type.usize, reg_off.reg, .{4907 try func.genSetReg(Type.u64, reg_off.reg, .{
4544 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },4908 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
4545 });4909 });
4546 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };4910 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
...@@ -4558,7 +4922,7 @@ fn genCall(...@@ -4558,7 +4922,7 @@ fn genCall(
4558 dst_reg,4922 dst_reg,
4559 src_arg,4923 src_arg,
4560 ),4924 ),
4561 .indirect => |reg_off| try func.genSetReg(Type.usize, reg_off.reg, .{4925 .indirect => |reg_off| try func.genSetReg(Type.u64, reg_off.reg, .{
4562 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },4926 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
4563 }),4927 }),
4564 else => return func.fail("TODO: genCall actual set {s}", .{@tagName(dst_arg)}),4928 else => return func.fail("TODO: genCall actual set {s}", .{@tagName(dst_arg)}),
...@@ -4586,10 +4950,9 @@ fn genCall(...@@ -4586,10 +4950,9 @@ fn genCall(
4586 if (func.mod.pic) {4950 if (func.mod.pic) {
4587 return func.fail("TODO: genCall pic", .{});4951 return func.fail("TODO: genCall pic", .{});
4588 } else {4952 } else {
4589 try func.genSetReg(Type.usize, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } });4953 try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } });
4590 _ = try func.addInst(.{4954 _ = try func.addInst(.{
4591 .tag = .jalr,4955 .tag = .jalr,
4592 .ops = .rri,
4593 .data = .{ .i_type = .{4956 .data = .{ .i_type = .{
4594 .rd = .ra,4957 .rd = .ra,
4595 .rs1 = .ra,4958 .rs1 = .ra,
...@@ -4603,18 +4966,17 @@ fn genCall(...@@ -4603,18 +4966,17 @@ fn genCall(
4603 const owner_decl = zcu.declPtr(extern_func.decl);4966 const owner_decl = zcu.declPtr(extern_func.decl);
4604 const lib_name = extern_func.lib_name.toSlice(&zcu.intern_pool);4967 const lib_name = extern_func.lib_name.toSlice(&zcu.intern_pool);
4605 const decl_name = owner_decl.name.toSlice(&zcu.intern_pool);4968 const decl_name = owner_decl.name.toSlice(&zcu.intern_pool);
4606 const atom_index = try func.symbolIndex();4969 const atom_index = try func.owner.getSymbolIndex(func);
46074970
4608 if (func.bin_file.cast(link.File.Elf)) |elf_file| {4971 const elf_file = func.bin_file.cast(link.File.Elf).?;
4609 _ = try func.addInst(.{4972 _ = try func.addInst(.{
4610 .tag = .pseudo,4973 .tag = .pseudo_extern_fn_reloc,
4611 .ops = .pseudo_extern_fn_reloc,4974 .data = .{ .reloc = .{
4612 .data = .{ .reloc = .{4975 .register = .ra,
4613 .atom_index = atom_index,4976 .atom_index = atom_index,
4614 .sym_index = try elf_file.getGlobalSymbol(decl_name, lib_name),4977 .sym_index = try elf_file.getGlobalSymbol(decl_name, lib_name),
4615 } },4978 } },
4616 });4979 });
4617 } else unreachable; // not a valid riscv64 format
4618 },4980 },
4619 else => return func.fail("TODO implement calling bitcasted functions", .{}),4981 else => return func.fail("TODO implement calling bitcasted functions", .{}),
4620 }4982 }
...@@ -4622,11 +4984,10 @@ fn genCall(...@@ -4622,11 +4984,10 @@ fn genCall(
4622 assert(func.typeOf(callee).zigTypeTag(zcu) == .Pointer);4984 assert(func.typeOf(callee).zigTypeTag(zcu) == .Pointer);
4623 const addr_reg, const addr_lock = try func.allocReg(.int);4985 const addr_reg, const addr_lock = try func.allocReg(.int);
4624 defer func.register_manager.unlockReg(addr_lock);4986 defer func.register_manager.unlockReg(addr_lock);
4625 try func.genSetReg(Type.usize, addr_reg, .{ .air_ref = callee });4987 try func.genSetReg(Type.u64, addr_reg, .{ .air_ref = callee });
46264988
4627 _ = try func.addInst(.{4989 _ = try func.addInst(.{
4628 .tag = .jalr,4990 .tag = .jalr,
4629 .ops = .rri,
4630 .data = .{ .i_type = .{4991 .data = .{ .i_type = .{
4631 .rd = .ra,4992 .rd = .ra,
4632 .rs1 = addr_reg,4993 .rs1 = addr_reg,
...@@ -4638,6 +4999,10 @@ fn genCall(...@@ -4638,6 +4999,10 @@ fn genCall(
4638 .lib => return func.fail("TODO: lib func calls", .{}),4999 .lib => return func.fail("TODO: lib func calls", .{}),
4639 }5000 }
46405001
5002 // reset the vector settings as they might have changed in the function
5003 func.avl = null;
5004 func.vtype = null;
5005
4641 return call_info.return_value.short;5006 return call_info.return_value.short;
4642}5007}
46435008
...@@ -4683,7 +5048,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {...@@ -4683,7 +5048,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
4683 const lock = func.register_manager.lockRegAssumeUnused(reg_off.reg);5048 const lock = func.register_manager.lockRegAssumeUnused(reg_off.reg);
4684 defer func.register_manager.unlockReg(lock);5049 defer func.register_manager.unlockReg(lock);
46855050
4686 try func.genSetReg(Type.usize, reg_off.reg, func.ret_mcv.long);5051 try func.genSetReg(Type.u64, reg_off.reg, func.ret_mcv.long);
4687 try func.genSetMem(5052 try func.genSetMem(
4688 .{ .reg = reg_off.reg },5053 .{ .reg = reg_off.reg },
4689 reg_off.off,5054 reg_off.off,
...@@ -4699,9 +5064,11 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {...@@ -4699,9 +5064,11 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
46995064
4700 // Just add space for an instruction, reloced this later5065 // Just add space for an instruction, reloced this later
4701 const index = try func.addInst(.{5066 const index = try func.addInst(.{
4702 .tag = .pseudo,5067 .tag = .pseudo_j,
4703 .ops = .pseudo_j,5068 .data = .{ .j_type = .{
4704 .data = .{ .inst = undefined },5069 .rd = .zero,
5070 .inst = undefined,
5071 } },
4705 });5072 });
47065073
4707 try func.exitlude_jump_relocs.append(func.gpa, index);5074 try func.exitlude_jump_relocs.append(func.gpa, index);
...@@ -4723,9 +5090,11 @@ fn airRetLoad(func: *Func, inst: Air.Inst.Index) !void {...@@ -4723,9 +5090,11 @@ fn airRetLoad(func: *Func, inst: Air.Inst.Index) !void {
47235090
4724 // Just add space for an instruction, reloced this later5091 // Just add space for an instruction, reloced this later
4725 const index = try func.addInst(.{5092 const index = try func.addInst(.{
4726 .tag = .pseudo,5093 .tag = .pseudo_j,
4727 .ops = .pseudo_j,5094 .data = .{ .j_type = .{
4728 .data = .{ .inst = undefined },5095 .rd = .zero,
5096 .inst = undefined,
5097 } },
4729 });5098 });
47305099
4731 try func.exitlude_jump_relocs.append(func.gpa, index);5100 try func.exitlude_jump_relocs.append(func.gpa, index);
...@@ -4751,14 +5120,14 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {...@@ -4751,14 +5120,14 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
4751 .Enum => lhs_ty.intTagType(zcu),5120 .Enum => lhs_ty.intTagType(zcu),
4752 .Int => lhs_ty,5121 .Int => lhs_ty,
4753 .Bool => Type.u1,5122 .Bool => Type.u1,
4754 .Pointer => Type.usize,5123 .Pointer => Type.u64,
4755 .ErrorSet => Type.anyerror,5124 .ErrorSet => Type.anyerror,
4756 .Optional => blk: {5125 .Optional => blk: {
4757 const payload_ty = lhs_ty.optionalChild(zcu);5126 const payload_ty = lhs_ty.optionalChild(zcu);
4758 if (!payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {5127 if (!payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {
4759 break :blk Type.u1;5128 break :blk Type.u1;
4760 } else if (lhs_ty.isPtrLikeOptional(zcu)) {5129 } else if (lhs_ty.isPtrLikeOptional(zcu)) {
4761 break :blk Type.usize;5130 break :blk Type.u64;
4762 } else {5131 } else {
4763 return func.fail("TODO riscv cmp non-pointer optionals", .{});5132 return func.fail("TODO riscv cmp non-pointer optionals", .{});
4764 }5133 }
...@@ -4805,8 +5174,7 @@ fn airDbgStmt(func: *Func, inst: Air.Inst.Index) !void {...@@ -4805,8 +5174,7 @@ fn airDbgStmt(func: *Func, inst: Air.Inst.Index) !void {
4805 const dbg_stmt = func.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;5174 const dbg_stmt = func.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
48065175
4807 _ = try func.addInst(.{5176 _ = try func.addInst(.{
4808 .tag = .pseudo,5177 .tag = .pseudo_dbg_line_column,
4809 .ops = .pseudo_dbg_line_column,
4810 .data = .{ .pseudo_dbg_line_column = .{5178 .data = .{ .pseudo_dbg_line_column = .{
4811 .line = dbg_stmt.line,5179 .line = dbg_stmt.line,
4812 .column = dbg_stmt.column,5180 .column = dbg_stmt.column,
...@@ -4868,7 +5236,7 @@ fn genVarDbgInfo(...@@ -4868,7 +5236,7 @@ fn genVarDbgInfo(
4868 break :blk .nop;5236 break :blk .nop;
4869 },5237 },
4870 };5238 };
4871 try dw.genVarDbgInfo(name, ty, zcu.funcOwnerDeclIndex(func.func_index), is_ptr, loc);5239 try dw.genVarDbgInfo(name, ty, func.owner.getDecl(zcu), is_ptr, loc);
4872 },5240 },
4873 .plan9 => {},5241 .plan9 => {},
4874 .none => {},5242 .none => {},
...@@ -4924,7 +5292,6 @@ fn condBr(func: *Func, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {...@@ -4924,7 +5292,6 @@ fn condBr(func: *Func, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {
49245292
4925 return try func.addInst(.{5293 return try func.addInst(.{
4926 .tag = .beq,5294 .tag = .beq,
4927 .ops = .rr_inst,
4928 .data = .{5295 .data = .{
4929 .b_type = .{5296 .b_type = .{
4930 .rs1 = cond_reg,5297 .rs1 = cond_reg,
...@@ -4955,19 +5322,18 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -4955,19 +5322,18 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
4955 .dead,5322 .dead,
4956 .undef,5323 .undef,
4957 .immediate,5324 .immediate,
4958 .register_pair,
4959 .register_offset,5325 .register_offset,
4960 .lea_frame,5326 .lea_frame,
4961 .lea_symbol,5327 .lea_symbol,
4962 .reserved_frame,5328 .reserved_frame,
4963 .air_ref,5329 .air_ref,
4964 => return func.fail("TODO: hmm {}", .{opt_mcv}),5330 .register_pair,
5331 => unreachable,
49655332
4966 .register => |opt_reg| {5333 .register => |opt_reg| {
4967 if (some_info.off == 0) {5334 if (some_info.off == 0) {
4968 _ = try func.addInst(.{5335 _ = try func.addInst(.{
4969 .tag = .pseudo,5336 .tag = .pseudo_compare,
4970 .ops = .pseudo_compare,
4971 .data = .{5337 .data = .{
4972 .compare = .{5338 .compare = .{
4973 .op = .eq,5339 .op = .eq,
...@@ -4984,9 +5350,27 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -4984,9 +5350,27 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
4984 return return_mcv;5350 return return_mcv;
4985 }5351 }
4986 assert(some_info.ty.ip_index == .bool_type);5352 assert(some_info.ty.ip_index == .bool_type);
4987 const opt_abi_size: u32 = @intCast(opt_ty.abiSize(pt));5353 const bit_offset: u7 = @intCast(some_info.off * 8);
4988 _ = opt_abi_size;5354
4989 return func.fail("TODO: isNull some_info.off != 0 register", .{});5355 try func.genBinOp(
5356 .shr,
5357 .{ .register = opt_reg },
5358 Type.u64,
5359 .{ .immediate = bit_offset },
5360 Type.u8,
5361 return_reg,
5362 );
5363 try func.truncateRegister(Type.u8, return_reg);
5364 try func.genBinOp(
5365 .cmp_eq,
5366 .{ .register = return_reg },
5367 Type.u64,
5368 .{ .immediate = 0 },
5369 Type.u8,
5370 return_reg,
5371 );
5372
5373 return return_mcv;
4990 },5374 },
49915375
4992 .load_frame => {5376 .load_frame => {
...@@ -4998,8 +5382,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -4998,8 +5382,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
4998 defer func.register_manager.unlockReg(opt_reg_lock);5382 defer func.register_manager.unlockReg(opt_reg_lock);
49995383
5000 _ = try func.addInst(.{5384 _ = try func.addInst(.{
5001 .tag = .pseudo,5385 .tag = .pseudo_compare,
5002 .ops = .pseudo_compare,
5003 .data = .{5386 .data = .{
5004 .compare = .{5387 .compare = .{
5005 .op = .eq,5388 .op = .eq,
...@@ -5048,8 +5431,7 @@ fn airIsNonNull(func: *Func, inst: Air.Inst.Index) !void {...@@ -5048,8 +5431,7 @@ fn airIsNonNull(func: *Func, inst: Air.Inst.Index) !void {
5048 assert(result == .register);5431 assert(result == .register);
50495432
5050 _ = try func.addInst(.{5433 _ = try func.addInst(.{
5051 .tag = .pseudo,5434 .tag = .pseudo_not,
5052 .ops = .pseudo_not,
5053 .data = .{5435 .data = .{
5054 .rr = .{5436 .rr = .{
5055 .rd = result.register,5437 .rd = result.register,
...@@ -5181,8 +5563,7 @@ fn isNonErr(func: *Func, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MC...@@ -5181,8 +5563,7 @@ fn isNonErr(func: *Func, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MC
5181 switch (is_err_res) {5563 switch (is_err_res) {
5182 .register => |reg| {5564 .register => |reg| {
5183 _ = try func.addInst(.{5565 _ = try func.addInst(.{
5184 .tag = .pseudo,5566 .tag = .pseudo_not,
5185 .ops = .pseudo_not,
5186 .data = .{5567 .data = .{
5187 .rr = .{5568 .rr = .{
5188 .rd = reg,5569 .rd = reg,
...@@ -5249,11 +5630,11 @@ fn airLoop(func: *Func, inst: Air.Inst.Index) !void {...@@ -5249,11 +5630,11 @@ fn airLoop(func: *Func, inst: Air.Inst.Index) !void {
5249/// Send control flow to the `index` of `func.code`.5630/// Send control flow to the `index` of `func.code`.
5250fn jump(func: *Func, index: Mir.Inst.Index) !Mir.Inst.Index {5631fn jump(func: *Func, index: Mir.Inst.Index) !Mir.Inst.Index {
5251 return func.addInst(.{5632 return func.addInst(.{
5252 .tag = .pseudo,5633 .tag = .pseudo_j,
5253 .ops = .pseudo_j,5634 .data = .{ .j_type = .{
5254 .data = .{5635 .rd = .zero,
5255 .inst = index,5636 .inst = index,
5256 },5637 } },
5257 });5638 });
5258}5639}
52595640
...@@ -5296,7 +5677,6 @@ fn lowerBlock(func: *Func, inst: Air.Inst.Index, body: []const Air.Inst.Index) !...@@ -5296,7 +5677,6 @@ fn lowerBlock(func: *Func, inst: Air.Inst.Index, body: []const Air.Inst.Index) !
52965677
5297fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {5678fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {
5298 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;5679 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
5299 const condition = try func.resolveInst(pl_op.operand);
5300 const condition_ty = func.typeOf(pl_op.operand);5680 const condition_ty = func.typeOf(pl_op.operand);
5301 const switch_br = func.air.extraData(Air.SwitchBr, pl_op.payload);5681 const switch_br = func.air.extraData(Air.SwitchBr, pl_op.payload);
5302 var extra_index: usize = switch_br.end;5682 var extra_index: usize = switch_br.end;
...@@ -5304,6 +5684,8 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {...@@ -5304,6 +5684,8 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {
5304 const liveness = try func.liveness.getSwitchBr(func.gpa, inst, switch_br.data.cases_len + 1);5684 const liveness = try func.liveness.getSwitchBr(func.gpa, inst, switch_br.data.cases_len + 1);
5305 defer func.gpa.free(liveness.deaths);5685 defer func.gpa.free(liveness.deaths);
53065686
5687 const condition = try func.resolveInst(pl_op.operand);
5688
5307 // If the condition dies here in this switch instruction, process5689 // If the condition dies here in this switch instruction, process
5308 // that death now instead of later as this has an effect on5690 // that death now instead of later as this has an effect on
5309 // whether it needs to be spilled in the branches5691 // whether it needs to be spilled in the branches
...@@ -5326,9 +5708,14 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {...@@ -5326,9 +5708,14 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {
5326 defer func.gpa.free(relocs);5708 defer func.gpa.free(relocs);
53275709
5328 for (items, relocs, 0..) |item, *reloc, i| {5710 for (items, relocs, 0..) |item, *reloc, i| {
5329 // switch branches must be comptime-known, so this is stored in an immediate
5330 const item_mcv = try func.resolveInst(item);5711 const item_mcv = try func.resolveInst(item);
53315712
5713 const cond_lock = switch (condition) {
5714 .register => func.register_manager.lockRegAssumeUnused(condition.register),
5715 else => null,
5716 };
5717 defer if (cond_lock) |lock| func.register_manager.unlockReg(lock);
5718
5332 const cmp_reg, const cmp_lock = try func.allocReg(.int);5719 const cmp_reg, const cmp_lock = try func.allocReg(.int);
5333 defer func.register_manager.unlockReg(cmp_lock);5720 defer func.register_manager.unlockReg(cmp_lock);
53345721
...@@ -5343,8 +5730,7 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {...@@ -5343,8 +5730,7 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {
53435730
5344 if (!(i < relocs.len - 1)) {5731 if (!(i < relocs.len - 1)) {
5345 _ = try func.addInst(.{5732 _ = try func.addInst(.{
5346 .tag = .pseudo,5733 .tag = .pseudo_not,
5347 .ops = .pseudo_not,
5348 .data = .{ .rr = .{5734 .data = .{ .rr = .{
5349 .rd = cmp_reg,5735 .rd = cmp_reg,
5350 .rs = cmp_reg,5736 .rs = cmp_reg,
...@@ -5391,18 +5777,14 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {...@@ -5391,18 +5777,14 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {
53915777
5392fn performReloc(func: *Func, inst: Mir.Inst.Index) void {5778fn performReloc(func: *Func, inst: Mir.Inst.Index) void {
5393 const tag = func.mir_instructions.items(.tag)[inst];5779 const tag = func.mir_instructions.items(.tag)[inst];
5394 const ops = func.mir_instructions.items(.ops)[inst];
5395 const target: Mir.Inst.Index = @intCast(func.mir_instructions.len);5780 const target: Mir.Inst.Index = @intCast(func.mir_instructions.len);
53965781
5397 switch (tag) {5782 switch (tag) {
5398 .bne,
5399 .beq,5783 .beq,
5784 .bne,
5400 => func.mir_instructions.items(.data)[inst].b_type.inst = target,5785 => func.mir_instructions.items(.data)[inst].b_type.inst = target,
5401 .jal => func.mir_instructions.items(.data)[inst].j_type.inst = target,5786 .jal => func.mir_instructions.items(.data)[inst].j_type.inst = target,
5402 .pseudo => switch (ops) {5787 .pseudo_j => func.mir_instructions.items(.data)[inst].j_type.inst = target,
5403 .pseudo_j => func.mir_instructions.items(.data)[inst].inst = target,
5404 else => std.debug.panic("TODO: performReloc {s}", .{@tagName(ops)}),
5405 },
5406 else => std.debug.panic("TODO: performReloc {s}", .{@tagName(tag)}),5788 else => std.debug.panic("TODO: performReloc {s}", .{@tagName(tag)}),
5407 }5789 }
5408}5790}
...@@ -5489,7 +5871,6 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void {...@@ -5489,7 +5871,6 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void {
54895871
5490 _ = try func.addInst(.{5872 _ = try func.addInst(.{
5491 .tag = if (tag == .bool_or) .@"or" else .@"and",5873 .tag = if (tag == .bool_or) .@"or" else .@"and",
5492 .ops = .rrr,
5493 .data = .{ .r_type = .{5874 .data = .{ .r_type = .{
5494 .rd = result_reg,5875 .rd = result_reg,
5495 .rs1 = lhs_reg,5876 .rs1 = lhs_reg,
...@@ -5501,7 +5882,6 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void {...@@ -5501,7 +5882,6 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void {
5501 if (func.wantSafety()) {5882 if (func.wantSafety()) {
5502 _ = try func.addInst(.{5883 _ = try func.addInst(.{
5503 .tag = .andi,5884 .tag = .andi,
5504 .ops = .rri,
5505 .data = .{ .i_type = .{5885 .data = .{ .i_type = .{
5506 .rd = result_reg,5886 .rd = result_reg,
5507 .rs1 = result_reg,5887 .rs1 = result_reg,
...@@ -5518,7 +5898,6 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void {...@@ -5518,7 +5898,6 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void {
5518fn airAsm(func: *Func, inst: Air.Inst.Index) !void {5898fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
5519 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;5899 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
5520 const extra = func.air.extraData(Air.Asm, ty_pl.payload);5900 const extra = func.air.extraData(Air.Asm, ty_pl.payload);
5521 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
5522 const clobbers_len: u31 = @truncate(extra.data.flags);5901 const clobbers_len: u31 = @truncate(extra.data.flags);
5523 var extra_i: usize = extra.end;5902 var extra_i: usize = extra.end;
5524 const outputs: []const Air.Inst.Ref =5903 const outputs: []const Air.Inst.Ref =
...@@ -5527,87 +5906,444 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {...@@ -5527,87 +5906,444 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
5527 const inputs: []const Air.Inst.Ref = @ptrCast(func.air.extra[extra_i..][0..extra.data.inputs_len]);5906 const inputs: []const Air.Inst.Ref = @ptrCast(func.air.extra[extra_i..][0..extra.data.inputs_len]);
5528 extra_i += inputs.len;5907 extra_i += inputs.len;
55295908
5530 const dead = !is_volatile and func.liveness.isUnused(inst);5909 var result: MCValue = .none;
5531 const result: MCValue = if (dead) .unreach else result: {5910 var args = std.ArrayList(MCValue).init(func.gpa);
5532 if (outputs.len > 1) {5911 try args.ensureTotalCapacity(outputs.len + inputs.len);
5533 return func.fail("TODO implement codegen for asm with more than 1 output", .{});5912 defer {
5534 }5913 for (args.items) |arg| if (arg.getReg()) |reg| func.register_manager.unlockReg(.{
5914 .tracked_index = RegisterManager.indexOfRegIntoTracked(reg) orelse continue,
5915 });
5916 args.deinit();
5917 }
5918 var arg_map = std.StringHashMap(u8).init(func.gpa);
5919 try arg_map.ensureTotalCapacity(@intCast(outputs.len + inputs.len));
5920 defer arg_map.deinit();
5921
5922 var outputs_extra_i = extra_i;
5923 for (outputs) |output| {
5924 const extra_bytes = mem.sliceAsBytes(func.air.extra[extra_i..]);
5925 const constraint = mem.sliceTo(mem.sliceAsBytes(func.air.extra[extra_i..]), 0);
5926 const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
5927 // This equation accounts for the fact that even if we have exactly 4 bytes
5928 // for the string, we still use the next u32 for the null terminator.
5929 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
5930
5931 const is_read = switch (constraint[0]) {
5932 '=' => false,
5933 '+' => read: {
5934 if (output == .none) return func.fail(
5935 "read-write constraint unsupported for asm result: '{s}'",
5936 .{constraint},
5937 );
5938 break :read true;
5939 },
5940 else => return func.fail("invalid constraint: '{s}'", .{constraint}),
5941 };
5942 const is_early_clobber = constraint[1] == '&';
5943 const rest = constraint[@as(usize, 1) + @intFromBool(is_early_clobber) ..];
5944 const arg_mcv: MCValue = arg_mcv: {
5945 const arg_maybe_reg: ?Register = if (mem.eql(u8, rest, "m"))
5946 if (output != .none) null else return func.fail(
5947 "memory constraint unsupported for asm result: '{s}'",
5948 .{constraint},
5949 )
5950 else if (mem.startsWith(u8, rest, "{") and mem.endsWith(u8, rest, "}"))
5951 parseRegName(rest["{".len .. rest.len - "}".len]) orelse
5952 return func.fail("invalid register constraint: '{s}'", .{constraint})
5953 else if (rest.len == 1 and std.ascii.isDigit(rest[0])) {
5954 const index = std.fmt.charToDigit(rest[0], 10) catch unreachable;
5955 if (index >= args.items.len) return func.fail("constraint out of bounds: '{s}'", .{
5956 constraint,
5957 });
5958 break :arg_mcv args.items[index];
5959 } else return func.fail("invalid constraint: '{s}'", .{constraint});
5960 break :arg_mcv if (arg_maybe_reg) |reg| .{ .register = reg } else arg: {
5961 const ptr_mcv = try func.resolveInst(output);
5962 switch (ptr_mcv) {
5963 .immediate => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
5964 break :arg ptr_mcv.deref(),
5965 .register, .register_offset, .lea_frame => break :arg ptr_mcv.deref(),
5966 else => {},
5967 }
5968 break :arg .{ .indirect = .{ .reg = try func.copyToTmpRegister(Type.usize, ptr_mcv) } };
5969 };
5970 };
5971 if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
5972 _ = func.register_manager.lockReg(reg);
5973 };
5974 if (!mem.eql(u8, name, "_"))
5975 arg_map.putAssumeCapacityNoClobber(name, @intCast(args.items.len));
5976 args.appendAssumeCapacity(arg_mcv);
5977 if (output == .none) result = arg_mcv;
5978 if (is_read) try func.load(arg_mcv, .{ .air_ref = output }, func.typeOf(output));
5979 }
55355980
5536 const output_constraint: ?[]const u8 = for (outputs) |output| {5981 for (inputs) |input| {
5537 if (output != .none) {5982 const input_bytes = mem.sliceAsBytes(func.air.extra[extra_i..]);
5538 return func.fail("TODO implement codegen for non-expr asm", .{});5983 const constraint = mem.sliceTo(input_bytes, 0);
5984 const name = mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
5985 // This equation accounts for the fact that even if we have exactly 4 bytes
5986 // for the string, we still use the next u32 for the null terminator.
5987 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
5988
5989 const ty = func.typeOf(input);
5990 const input_mcv = try func.resolveInst(input);
5991 const arg_mcv: MCValue = if (mem.eql(u8, constraint, "X"))
5992 input_mcv
5993 else if (mem.startsWith(u8, constraint, "{") and mem.endsWith(u8, constraint, "}")) arg: {
5994 const reg = parseRegName(constraint["{".len .. constraint.len - "}".len]) orelse
5995 return func.fail("invalid register constraint: '{s}'", .{constraint});
5996 try func.register_manager.getReg(reg, null);
5997 try func.genSetReg(ty, reg, input_mcv);
5998 break :arg .{ .register = reg };
5999 } else if (mem.eql(u8, constraint, "r")) arg: {
6000 switch (input_mcv) {
6001 .register => break :arg input_mcv,
6002 else => {},
5539 }6003 }
5540 const extra_bytes = std.mem.sliceAsBytes(func.air.extra[extra_i..]);6004 const temp_reg = try func.copyToTmpRegister(ty, input_mcv);
5541 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(func.air.extra[extra_i..]), 0);6005 break :arg .{ .register = temp_reg };
5542 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);6006 } else return func.fail("invalid input constraint: '{s}'", .{constraint});
5543 // This equation accounts for the fact that even if we have exactly 4 bytes6007 if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
5544 // for the string, we still use the next u32 for the null terminator.6008 _ = func.register_manager.lockReg(reg);
5545 extra_i += (constraint.len + name.len + (2 + 3)) / 4;6009 };
55466010 if (!mem.eql(u8, name, "_"))
5547 break constraint;6011 arg_map.putAssumeCapacityNoClobber(name, @intCast(args.items.len));
5548 } else null;6012 args.appendAssumeCapacity(arg_mcv);
6013 }
55496014
5550 for (inputs) |input| {6015 {
5551 const input_bytes = std.mem.sliceAsBytes(func.air.extra[extra_i..]);6016 var clobber_i: u32 = 0;
5552 const constraint = std.mem.sliceTo(input_bytes, 0);6017 while (clobber_i < clobbers_len) : (clobber_i += 1) {
5553 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);6018 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(func.air.extra[extra_i..]), 0);
5554 // This equation accounts for the fact that even if we have exactly 4 bytes6019 // This equation accounts for the fact that even if we have exactly 4 bytes
5555 // for the string, we still use the next u32 for the null terminator.6020 // for the string, we still use the next u32 for the null terminator.
5556 extra_i += (constraint.len + name.len + (2 + 3)) / 4;6021 extra_i += clobber.len / 4 + 1;
55576022
5558 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {6023 if (std.mem.eql(u8, clobber, "") or std.mem.eql(u8, clobber, "memory")) {
5559 return func.fail("unrecognized asm input constraint: '{s}'", .{constraint});6024 // nothing really to do
6025 } else {
6026 try func.register_manager.getReg(parseRegName(clobber) orelse
6027 return func.fail("invalid clobber: '{s}'", .{clobber}), null);
5560 }6028 }
5561 const reg_name = constraint[1 .. constraint.len - 1];
5562 const reg = parseRegName(reg_name) orelse
5563 return func.fail("unrecognized register: '{s}'", .{reg_name});
5564
5565 const arg_mcv = try func.resolveInst(input);
5566 try func.register_manager.getReg(reg, null);
5567 try func.genSetReg(func.typeOf(input), reg, arg_mcv);
5568 }6029 }
6030 }
55696031
5570 {6032 const Label = struct {
5571 var clobber_i: u32 = 0;6033 target: Mir.Inst.Index = undefined,
5572 while (clobber_i < clobbers_len) : (clobber_i += 1) {6034 pending_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .{},
5573 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(func.air.extra[extra_i..]), 0);6035
5574 // This equation accounts for the fact that even if we have exactly 4 bytes6036 const Kind = enum { definition, reference };
5575 // for the string, we still use the next u32 for the null terminator.6037
5576 extra_i += clobber.len / 4 + 1;6038 fn isValid(kind: Kind, name: []const u8) bool {
6039 for (name, 0..) |c, i| switch (c) {
6040 else => return false,
6041 '$' => if (i == 0) return false,
6042 '.' => {},
6043 '0'...'9' => if (i == 0) switch (kind) {
6044 .definition => if (name.len != 1) return false,
6045 .reference => {
6046 if (name.len != 2) return false;
6047 switch (name[1]) {
6048 else => return false,
6049 'B', 'F', 'b', 'f' => {},
6050 }
6051 },
6052 },
6053 '@', 'A'...'Z', '_', 'a'...'z' => {},
6054 };
6055 return name.len > 0;
6056 }
6057 };
6058 var labels: std.StringHashMapUnmanaged(Label) = .{};
6059 defer {
6060 var label_it = labels.valueIterator();
6061 while (label_it.next()) |label| label.pending_relocs.deinit(func.gpa);
6062 labels.deinit(func.gpa);
6063 }
55776064
5578 if (std.mem.eql(u8, clobber, "") or std.mem.eql(u8, clobber, "memory")) {6065 const asm_source = std.mem.sliceAsBytes(func.air.extra[extra_i..])[0..extra.data.source_len];
5579 // nothing really to do6066 var line_it = mem.tokenizeAny(u8, asm_source, "\n\r;");
5580 } else {6067 next_line: while (line_it.next()) |line| {
5581 try func.register_manager.getReg(parseRegName(clobber) orelse6068 var mnem_it = mem.tokenizeAny(u8, line, " \t");
5582 return func.fail("invalid clobber: '{s}'", .{clobber}), null);6069 const mnem_str = while (mnem_it.next()) |mnem_str| {
5583 }6070 if (mem.startsWith(u8, mnem_str, "#")) continue :next_line;
6071 if (mem.startsWith(u8, mnem_str, "//")) continue :next_line;
6072 if (!mem.endsWith(u8, mnem_str, ":")) break mnem_str;
6073 const label_name = mnem_str[0 .. mnem_str.len - ":".len];
6074 if (!Label.isValid(.definition, label_name))
6075 return func.fail("invalid label: '{s}'", .{label_name});
6076
6077 const label_gop = try labels.getOrPut(func.gpa, label_name);
6078 if (!label_gop.found_existing) label_gop.value_ptr.* = .{} else {
6079 const anon = std.ascii.isDigit(label_name[0]);
6080 if (!anon and label_gop.value_ptr.pending_relocs.items.len == 0)
6081 return func.fail("redefined label: '{s}'", .{label_name});
6082 for (label_gop.value_ptr.pending_relocs.items) |pending_reloc|
6083 func.performReloc(pending_reloc);
6084 if (anon)
6085 label_gop.value_ptr.pending_relocs.clearRetainingCapacity()
6086 else
6087 label_gop.value_ptr.pending_relocs.clearAndFree(func.gpa);
5584 }6088 }
5585 }6089 label_gop.value_ptr.target = @intCast(func.mir_instructions.len);
6090 } else continue;
6091
6092 const instruction: union(enum) { mnem: Mnemonic, pseudo: Pseudo } =
6093 if (std.meta.stringToEnum(Mnemonic, mnem_str)) |mnem|
6094 .{ .mnem = mnem }
6095 else if (std.meta.stringToEnum(Pseudo, mnem_str)) |pseudo|
6096 .{ .pseudo = pseudo }
6097 else
6098 return func.fail("invalid mnem str '{s}'", .{mnem_str});
6099
6100 const Operand = union(enum) {
6101 none,
6102 reg: Register,
6103 imm: Immediate,
6104 inst: Mir.Inst.Index,
6105 sym: SymbolOffset,
6106 };
55866107
5587 const asm_source = std.mem.sliceAsBytes(func.air.extra[extra_i..])[0..extra.data.source_len];6108 var ops: [4]Operand = .{.none} ** 4;
6109 var last_op = false;
6110 var op_it = mem.splitAny(u8, mnem_it.rest(), ",(");
6111 next_op: for (&ops) |*op| {
6112 const op_str = while (!last_op) {
6113 const full_str = op_it.next() orelse break :next_op;
6114 const code_str = if (mem.indexOfScalar(u8, full_str, '#') orelse
6115 mem.indexOf(u8, full_str, "//")) |comment|
6116 code: {
6117 last_op = true;
6118 break :code full_str[0..comment];
6119 } else full_str;
6120 const trim_str = mem.trim(u8, code_str, " \t*");
6121 if (trim_str.len > 0) break trim_str;
6122 } else break;
6123
6124 if (parseRegName(op_str)) |reg| {
6125 op.* = .{ .reg = reg };
6126 } else if (std.fmt.parseInt(i12, op_str, 10)) |int| {
6127 op.* = .{ .imm = Immediate.s(int) };
6128 } else |_| if (mem.startsWith(u8, op_str, "%[")) {
6129 const mod_index = mem.indexOf(u8, op_str, "]@");
6130 const modifier = if (mod_index) |index|
6131 op_str[index + "]@".len ..]
6132 else
6133 "";
6134
6135 op.* = switch (args.items[
6136 arg_map.get(op_str["%[".len .. mod_index orelse op_str.len - "]".len]) orelse
6137 return func.fail("no matching constraint: '{s}'", .{op_str})
6138 ]) {
6139 .load_symbol => |sym_off| if (mem.eql(u8, modifier, "plt")) blk: {
6140 assert(sym_off.off == 0);
6141 break :blk .{ .sym = sym_off };
6142 } else return func.fail("invalid modifier: '{s}'", .{modifier}),
6143 .register => |reg| if (modifier.len == 0)
6144 .{ .reg = reg }
6145 else
6146 return func.fail("invalid modified '{s}'", .{modifier}),
6147 else => return func.fail("invalid constraint: '{s}'", .{op_str}),
6148 };
6149 } else if (mem.endsWith(u8, op_str, ")")) {
6150 const reg = op_str[0 .. op_str.len - ")".len];
6151 const addr_reg = parseRegName(reg) orelse
6152 return func.fail("expected valid register, found '{s}'", .{reg});
6153
6154 op.* = .{ .reg = addr_reg };
6155 } else if (Label.isValid(.reference, op_str)) {
6156 const anon = std.ascii.isDigit(op_str[0]);
6157 const label_gop = try labels.getOrPut(func.gpa, op_str[0..if (anon) 1 else op_str.len]);
6158 if (!label_gop.found_existing) label_gop.value_ptr.* = .{};
6159 if (anon and (op_str[1] == 'b' or op_str[1] == 'B') and !label_gop.found_existing)
6160 return func.fail("undefined label: '{s}'", .{op_str});
6161 const pending_relocs = &label_gop.value_ptr.pending_relocs;
6162 if (if (anon)
6163 op_str[1] == 'f' or op_str[1] == 'F'
6164 else
6165 !label_gop.found_existing or pending_relocs.items.len > 0)
6166 try pending_relocs.append(func.gpa, @intCast(func.mir_instructions.len));
6167 op.* = .{ .inst = label_gop.value_ptr.target };
6168 } else return func.fail("invalid operand: '{s}'", .{op_str});
6169 } else if (op_it.next()) |op_str| return func.fail("extra operand: '{s}'", .{op_str});
6170
6171 switch (instruction) {
6172 .mnem => |mnem| {
6173 _ = (switch (ops[0]) {
6174 .none => try func.addInst(.{
6175 .tag = mnem,
6176 .data = .none,
6177 }),
6178 .reg => |reg1| switch (ops[1]) {
6179 .reg => |reg2| switch (ops[2]) {
6180 .imm => |imm1| try func.addInst(.{
6181 .tag = mnem,
6182 .data = .{ .i_type = .{
6183 .rd = reg1,
6184 .rs1 = reg2,
6185 .imm12 = imm1,
6186 } },
6187 }),
6188 else => error.InvalidInstruction,
6189 },
6190 .imm => |imm1| switch (ops[2]) {
6191 .reg => |reg2| switch (mnem) {
6192 .sd => try func.addInst(.{
6193 .tag = mnem,
6194 .data = .{ .i_type = .{
6195 .rd = reg2,
6196 .rs1 = reg1,
6197 .imm12 = imm1,
6198 } },
6199 }),
6200 .ld => try func.addInst(.{
6201 .tag = mnem,
6202 .data = .{ .i_type = .{
6203 .rd = reg1,
6204 .rs1 = reg2,
6205 .imm12 = imm1,
6206 } },
6207 }),
6208 else => error.InvalidInstruction,
6209 },
6210 else => error.InvalidInstruction,
6211 },
6212 .none => switch (mnem) {
6213 .jalr => try func.addInst(.{
6214 .tag = mnem,
6215 .data = .{ .i_type = .{
6216 .rd = .ra,
6217 .rs1 = reg1,
6218 .imm12 = Immediate.s(0),
6219 } },
6220 }),
6221 else => error.InvalidInstruction,
6222 },
6223 else => error.InvalidInstruction,
6224 },
6225 else => error.InvalidInstruction,
6226 }) catch |err| {
6227 switch (err) {
6228 error.InvalidInstruction => return func.fail(
6229 "invalid instruction: {s} {s} {s} {s} {s}",
6230 .{
6231 @tagName(mnem),
6232 @tagName(ops[0]),
6233 @tagName(ops[1]),
6234 @tagName(ops[2]),
6235 @tagName(ops[3]),
6236 },
6237 ),
6238 else => |e| return e,
6239 }
6240 };
6241 },
6242 .pseudo => |pseudo| {
6243 (@as(error{InvalidInstruction}!void, switch (pseudo) {
6244 .li => blk: {
6245 if (ops[0] != .reg or ops[1] != .imm) {
6246 break :blk error.InvalidInstruction;
6247 }
55886248
5589 if (std.meta.stringToEnum(Mir.Inst.Tag, asm_source)) |tag| {6249 const reg = ops[0].reg;
5590 _ = try func.addInst(.{6250 const imm = ops[1].imm;
5591 .tag = tag,
5592 .ops = .none,
5593 .data = undefined,
5594 });
5595 } else {
5596 return func.fail("TODO: asm_source {s}", .{asm_source});
5597 }
55986251
5599 if (output_constraint) |output| {6252 try func.genSetReg(Type.usize, reg, .{ .immediate = imm.asBits(u64) });
5600 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {6253 },
5601 return func.fail("unrecognized asm output constraint: '{s}'", .{output});6254 .mv => blk: {
5602 }6255 if (ops[0] != .reg or ops[1] != .reg) {
5603 const reg_name = output[2 .. output.len - 1];6256 break :blk error.InvalidInstruction;
5604 const reg = parseRegName(reg_name) orelse6257 }
5605 return func.fail("unrecognized register: '{s}'", .{reg_name});6258
5606 break :result .{ .register = reg };6259 const dst = ops[0].reg;
5607 } else {6260 const src = ops[1].reg;
5608 break :result .{ .none = {} };6261
6262 if (dst.class() != .int or src.class() != .int) {
6263 return func.fail("pseudo instruction 'mv' only works on integer registers", .{});
6264 }
6265
6266 try func.genSetReg(Type.usize, dst, .{ .register = src });
6267 },
6268 .tail => blk: {
6269 if (ops[0] != .sym) {
6270 break :blk error.InvalidInstruction;
6271 }
6272
6273 const sym_offset = ops[0].sym;
6274 assert(sym_offset.off == 0);
6275
6276 const random_link_reg, const lock = try func.allocReg(.int);
6277 defer func.register_manager.unlockReg(lock);
6278
6279 _ = try func.addInst(.{
6280 .tag = .pseudo_extern_fn_reloc,
6281 .data = .{ .reloc = .{
6282 .register = random_link_reg,
6283 .atom_index = try func.owner.getSymbolIndex(func),
6284 .sym_index = sym_offset.sym,
6285 } },
6286 });
6287 },
6288 .ret => _ = try func.addInst(.{
6289 .tag = .jalr,
6290 .data = .{ .i_type = .{
6291 .rd = .zero,
6292 .rs1 = .ra,
6293 .imm12 = Immediate.s(0),
6294 } },
6295 }),
6296 .beqz => blk: {
6297 if (ops[0] != .reg or ops[1] != .inst) {
6298 break :blk error.InvalidInstruction;
6299 }
6300
6301 _ = try func.addInst(.{
6302 .tag = .beq,
6303 .data = .{ .b_type = .{
6304 .rs1 = ops[0].reg,
6305 .rs2 = .zero,
6306 .inst = ops[1].inst,
6307 } },
6308 });
6309 },
6310 })) catch |err| {
6311 switch (err) {
6312 error.InvalidInstruction => return func.fail(
6313 "invalid instruction: {s} {s} {s} {s} {s}",
6314 .{
6315 @tagName(pseudo),
6316 @tagName(ops[0]),
6317 @tagName(ops[1]),
6318 @tagName(ops[2]),
6319 @tagName(ops[3]),
6320 },
6321 ),
6322 else => |e| return e,
6323 }
6324 };
6325 },
5609 }6326 }
5610 };6327 }
6328
6329 var label_it = labels.iterator();
6330 while (label_it.next()) |label| if (label.value_ptr.pending_relocs.items.len > 0)
6331 return func.fail("undefined label: '{s}'", .{label.key_ptr.*});
6332
6333 for (outputs, args.items[0..outputs.len]) |output, arg_mcv| {
6334 const extra_bytes = mem.sliceAsBytes(func.air.extra[outputs_extra_i..]);
6335 const constraint =
6336 mem.sliceTo(mem.sliceAsBytes(func.air.extra[outputs_extra_i..]), 0);
6337 const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
6338 // This equation accounts for the fact that even if we have exactly 4 bytes
6339 // for the string, we still use the next u32 for the null terminator.
6340 outputs_extra_i += (constraint.len + name.len + (2 + 3)) / 4;
6341
6342 if (output == .none) continue;
6343 if (arg_mcv != .register) continue;
6344 if (constraint.len == 2 and std.ascii.isDigit(constraint[1])) continue;
6345 try func.store(.{ .air_ref = output }, arg_mcv, func.typeOf(output));
6346 }
56116347
5612 simple: {6348 simple: {
5613 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);6349 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);
...@@ -5668,12 +6404,19 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {...@@ -5668,12 +6404,19 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
5668 ty,6404 ty,
5669 src_mcv,6405 src_mcv,
5670 ),6406 ),
6407 .load_tlv => {
6408 const addr_reg, const addr_lock = try func.allocReg(.int);
6409 defer func.register_manager.unlockReg(addr_lock);
6410
6411 try func.genSetReg(ty, addr_reg, dst_mcv.address());
6412 try func.genCopy(ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv);
6413 },
5671 .memory => return func.fail("TODO: genCopy memory", .{}),6414 .memory => return func.fail("TODO: genCopy memory", .{}),
5672 .register_pair => |dst_regs| {6415 .register_pair => |dst_regs| {
5673 const src_info: ?struct { addr_reg: Register, addr_lock: ?RegisterLock } = switch (src_mcv) {6416 const src_info: ?struct { addr_reg: Register, addr_lock: ?RegisterLock } = switch (src_mcv) {
5674 .register_pair, .memory, .indirect, .load_frame => null,6417 .register_pair, .memory, .indirect, .load_frame => null,
5675 .load_symbol => src: {6418 .load_symbol => src: {
5676 const src_addr_reg, const src_addr_lock = try func.promoteReg(Type.usize, src_mcv.address());6419 const src_addr_reg, const src_addr_lock = try func.promoteReg(Type.u64, src_mcv.address());
5677 errdefer func.register_manager.unlockReg(src_addr_lock);6420 errdefer func.register_manager.unlockReg(src_addr_lock);
56786421
5679 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };6422 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
...@@ -5725,14 +6468,23 @@ fn genInlineMemcpy(...@@ -5725,14 +6468,23 @@ fn genInlineMemcpy(
5725 const src = regs[2];6468 const src = regs[2];
5726 const dst = regs[3];6469 const dst = regs[3];
57276470
5728 try func.genSetReg(Type.usize, count, len);6471 try func.genSetReg(Type.u64, count, len);
5729 try func.genSetReg(Type.usize, src, src_ptr);6472 try func.genSetReg(Type.u64, src, src_ptr);
5730 try func.genSetReg(Type.usize, dst, dst_ptr);6473 try func.genSetReg(Type.u64, dst, dst_ptr);
6474
6475 // if count is 0, there's nothing to copy
6476 _ = try func.addInst(.{
6477 .tag = .beq,
6478 .data = .{ .b_type = .{
6479 .rs1 = count,
6480 .rs2 = .zero,
6481 .inst = @intCast(func.mir_instructions.len + 9),
6482 } },
6483 });
57316484
5732 // lb tmp, 0(src)6485 // lb tmp, 0(src)
5733 const first_inst = try func.addInst(.{6486 const first_inst = try func.addInst(.{
5734 .tag = .lb,6487 .tag = .lb,
5735 .ops = .rri,
5736 .data = .{6488 .data = .{
5737 .i_type = .{6489 .i_type = .{
5738 .rd = tmp,6490 .rd = tmp,
...@@ -5745,7 +6497,6 @@ fn genInlineMemcpy(...@@ -5745,7 +6497,6 @@ fn genInlineMemcpy(
5745 // sb tmp, 0(dst)6497 // sb tmp, 0(dst)
5746 _ = try func.addInst(.{6498 _ = try func.addInst(.{
5747 .tag = .sb,6499 .tag = .sb,
5748 .ops = .rri,
5749 .data = .{6500 .data = .{
5750 .i_type = .{6501 .i_type = .{
5751 .rd = dst,6502 .rd = dst,
...@@ -5758,7 +6509,6 @@ fn genInlineMemcpy(...@@ -5758,7 +6509,6 @@ fn genInlineMemcpy(
5758 // dec count by 16509 // dec count by 1
5759 _ = try func.addInst(.{6510 _ = try func.addInst(.{
5760 .tag = .addi,6511 .tag = .addi,
5761 .ops = .rri,
5762 .data = .{6512 .data = .{
5763 .i_type = .{6513 .i_type = .{
5764 .rd = count,6514 .rd = count,
...@@ -5771,7 +6521,6 @@ fn genInlineMemcpy(...@@ -5771,7 +6521,6 @@ fn genInlineMemcpy(
5771 // branch if count is 06521 // branch if count is 0
5772 _ = try func.addInst(.{6522 _ = try func.addInst(.{
5773 .tag = .beq,6523 .tag = .beq,
5774 .ops = .rr_inst,
5775 .data = .{6524 .data = .{
5776 .b_type = .{6525 .b_type = .{
5777 .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst6526 .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst
...@@ -5784,7 +6533,6 @@ fn genInlineMemcpy(...@@ -5784,7 +6533,6 @@ fn genInlineMemcpy(
5784 // increment the pointers6533 // increment the pointers
5785 _ = try func.addInst(.{6534 _ = try func.addInst(.{
5786 .tag = .addi,6535 .tag = .addi,
5787 .ops = .rri,
5788 .data = .{6536 .data = .{
5789 .i_type = .{6537 .i_type = .{
5790 .rd = src,6538 .rd = src,
...@@ -5796,7 +6544,6 @@ fn genInlineMemcpy(...@@ -5796,7 +6544,6 @@ fn genInlineMemcpy(
57966544
5797 _ = try func.addInst(.{6545 _ = try func.addInst(.{
5798 .tag = .addi,6546 .tag = .addi,
5799 .ops = .rri,
5800 .data = .{6547 .data = .{
5801 .i_type = .{6548 .i_type = .{
5802 .rd = dst,6549 .rd = dst,
...@@ -5808,9 +6555,11 @@ fn genInlineMemcpy(...@@ -5808,9 +6555,11 @@ fn genInlineMemcpy(
58086555
5809 // jump back to start of loop6556 // jump back to start of loop
5810 _ = try func.addInst(.{6557 _ = try func.addInst(.{
5811 .tag = .pseudo,6558 .tag = .pseudo_j,
5812 .ops = .pseudo_j,6559 .data = .{ .j_type = .{
5813 .data = .{ .inst = first_inst },6560 .rd = .zero,
6561 .inst = first_inst,
6562 } },
5814 });6563 });
5815}6564}
58166565
...@@ -5828,14 +6577,13 @@ fn genInlineMemset(...@@ -5828,14 +6577,13 @@ fn genInlineMemset(
5828 const src = regs[1];6577 const src = regs[1];
5829 const dst = regs[2];6578 const dst = regs[2];
58306579
5831 try func.genSetReg(Type.usize, count, len);6580 try func.genSetReg(Type.u64, count, len);
5832 try func.genSetReg(Type.usize, src, src_value);6581 try func.genSetReg(Type.u64, src, src_value);
5833 try func.genSetReg(Type.usize, dst, dst_ptr);6582 try func.genSetReg(Type.u64, dst, dst_ptr);
58346583
5835 // sb src, 0(dst)6584 // sb src, 0(dst)
5836 const first_inst = try func.addInst(.{6585 const first_inst = try func.addInst(.{
5837 .tag = .sb,6586 .tag = .sb,
5838 .ops = .rri,
5839 .data = .{6587 .data = .{
5840 .i_type = .{6588 .i_type = .{
5841 .rd = dst,6589 .rd = dst,
...@@ -5848,7 +6596,6 @@ fn genInlineMemset(...@@ -5848,7 +6596,6 @@ fn genInlineMemset(
5848 // dec count by 16596 // dec count by 1
5849 _ = try func.addInst(.{6597 _ = try func.addInst(.{
5850 .tag = .addi,6598 .tag = .addi,
5851 .ops = .rri,
5852 .data = .{6599 .data = .{
5853 .i_type = .{6600 .i_type = .{
5854 .rd = count,6601 .rd = count,
...@@ -5861,7 +6608,6 @@ fn genInlineMemset(...@@ -5861,7 +6608,6 @@ fn genInlineMemset(
5861 // branch if count is 06608 // branch if count is 0
5862 _ = try func.addInst(.{6609 _ = try func.addInst(.{
5863 .tag = .beq,6610 .tag = .beq,
5864 .ops = .rr_inst,
5865 .data = .{6611 .data = .{
5866 .b_type = .{6612 .b_type = .{
5867 .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst6613 .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst
...@@ -5874,7 +6620,6 @@ fn genInlineMemset(...@@ -5874,7 +6620,6 @@ fn genInlineMemset(
5874 // increment the pointers6620 // increment the pointers
5875 _ = try func.addInst(.{6621 _ = try func.addInst(.{
5876 .tag = .addi,6622 .tag = .addi,
5877 .ops = .rri,
5878 .data = .{6623 .data = .{
5879 .i_type = .{6624 .i_type = .{
5880 .rd = dst,6625 .rd = dst,
...@@ -5886,11 +6631,11 @@ fn genInlineMemset(...@@ -5886,11 +6631,11 @@ fn genInlineMemset(
58866631
5887 // jump back to start of loop6632 // jump back to start of loop
5888 _ = try func.addInst(.{6633 _ = try func.addInst(.{
5889 .tag = .pseudo,6634 .tag = .pseudo_j,
5890 .ops = .pseudo_j,6635 .data = .{ .j_type = .{
5891 .data = .{6636 .rd = .zero,
5892 .inst = first_inst,6637 .inst = first_inst,
5893 },6638 } },
5894 });6639 });
5895}6640}
58966641
...@@ -5936,7 +6681,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5936,7 +6681,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5936 if (math.minInt(i12) <= x and x <= math.maxInt(i12)) {6681 if (math.minInt(i12) <= x and x <= math.maxInt(i12)) {
5937 _ = try func.addInst(.{6682 _ = try func.addInst(.{
5938 .tag = .addi,6683 .tag = .addi,
5939 .ops = .rri,
5940 .data = .{ .i_type = .{6684 .data = .{ .i_type = .{
5941 .rd = reg,6685 .rd = reg,
5942 .rs1 = .zero,6686 .rs1 = .zero,
...@@ -5950,7 +6694,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5950,7 +6694,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
59506694
5951 _ = try func.addInst(.{6695 _ = try func.addInst(.{
5952 .tag = .lui,6696 .tag = .lui,
5953 .ops = .ri,
5954 .data = .{ .u_type = .{6697 .data = .{ .u_type = .{
5955 .rd = reg,6698 .rd = reg,
5956 .imm20 = Immediate.s(hi20),6699 .imm20 = Immediate.s(hi20),
...@@ -5958,7 +6701,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5958,7 +6701,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5958 });6701 });
5959 _ = try func.addInst(.{6702 _ = try func.addInst(.{
5960 .tag = .addi,6703 .tag = .addi,
5961 .ops = .rri,
5962 .data = .{ .i_type = .{6704 .data = .{ .i_type = .{
5963 .rd = reg,6705 .rd = reg,
5964 .rs1 = reg,6706 .rs1 = reg,
...@@ -5981,7 +6723,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5981,7 +6723,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
59816723
5982 _ = try func.addInst(.{6724 _ = try func.addInst(.{
5983 .tag = .slli,6725 .tag = .slli,
5984 .ops = .rri,
5985 .data = .{ .i_type = .{6726 .data = .{ .i_type = .{
5986 .rd = reg,6727 .rd = reg,
5987 .rs1 = reg,6728 .rs1 = reg,
...@@ -5991,7 +6732,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5991,7 +6732,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
59916732
5992 _ = try func.addInst(.{6733 _ = try func.addInst(.{
5993 .tag = .add,6734 .tag = .add,
5994 .ops = .rrr,
5995 .data = .{ .r_type = .{6735 .data = .{ .r_type = .{
5996 .rd = reg,6736 .rd = reg,
5997 .rs1 = reg,6737 .rs1 = reg,
...@@ -6028,15 +6768,16 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6028,15 +6768,16 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
60286768
6029 // mv reg, src_reg6769 // mv reg, src_reg
6030 _ = try func.addInst(.{6770 _ = try func.addInst(.{
6031 .tag = .pseudo,6771 .tag = .pseudo_mv,
6032 .ops = .pseudo_mv,
6033 .data = .{ .rr = .{6772 .data = .{ .rr = .{
6034 .rd = reg,6773 .rd = reg,
6035 .rs = src_reg,6774 .rs = src_reg,
6036 } },6775 } },
6037 });6776 });
6038 },6777 },
6039 .register_pair => return func.fail("genSetReg should we allow reg -> reg_pair?", .{}),6778 // useful in cases like slice_ptr, which can easily reuse the operand
6779 // but we need to get only the pointer out.
6780 .register_pair => |pair| try func.genSetReg(ty, reg, .{ .register = pair[0] }),
6040 .load_frame => |frame| {6781 .load_frame => |frame| {
6041 if (reg.class() == .vector) {6782 if (reg.class() == .vector) {
6042 // vectors don't support an offset memory load so we need to put the true6783 // vectors don't support an offset memory load so we need to put the true
...@@ -6048,8 +6789,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6048,8 +6789,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
6048 try func.genCopy(ty, .{ .register = reg }, .{ .indirect = .{ .reg = addr_reg } });6789 try func.genCopy(ty, .{ .register = reg }, .{ .indirect = .{ .reg = addr_reg } });
6049 } else {6790 } else {
6050 _ = try func.addInst(.{6791 _ = try func.addInst(.{
6051 .tag = .pseudo,6792 .tag = .pseudo_load_rm,
6052 .ops = .pseudo_load_rm,
6053 .data = .{ .rm = .{6793 .data = .{ .rm = .{
6054 .r = reg,6794 .r = reg,
6055 .m = .{6795 .m = .{
...@@ -6069,7 +6809,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6069,7 +6809,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
60696809
6070 _ = try func.addInst(.{6810 _ = try func.addInst(.{
6071 .tag = .ld,6811 .tag = .ld,
6072 .ops = .rri,
6073 .data = .{ .i_type = .{6812 .data = .{ .i_type = .{
6074 .rd = reg,6813 .rd = reg,
6075 .rs1 = reg,6814 .rs1 = reg,
...@@ -6079,8 +6818,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6079,8 +6818,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
6079 },6818 },
6080 .lea_frame, .register_offset => {6819 .lea_frame, .register_offset => {
6081 _ = try func.addInst(.{6820 _ = try func.addInst(.{
6082 .tag = .pseudo,6821 .tag = .pseudo_lea_rm,
6083 .ops = .pseudo_lea_rm,
6084 .data = .{6822 .data = .{
6085 .rm = .{6823 .rm = .{
6086 .r = reg,6824 .r = reg,
...@@ -6108,7 +6846,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6108,7 +6846,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
6108 });6846 });
6109 },6847 },
6110 .indirect => |reg_off| {6848 .indirect => |reg_off| {
6111 const load_tag: Mir.Inst.Tag = switch (reg.class()) {6849 const load_tag: Mnemonic = switch (reg.class()) {
6112 .float => switch (abi_size) {6850 .float => switch (abi_size) {
6113 1 => unreachable, // Zig does not support 8-bit floats6851 1 => unreachable, // Zig does not support 8-bit floats
6114 2 => return func.fail("TODO: genSetReg indirect 16-bit float", .{}),6852 2 => return func.fail("TODO: genSetReg indirect 16-bit float", .{}),
...@@ -6147,8 +6885,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6147,8 +6885,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
6147 });6885 });
61486886
6149 _ = try func.addInst(.{6887 _ = try func.addInst(.{
6150 .tag = .pseudo,6888 .tag = .pseudo_load_rm,
6151 .ops = .pseudo_load_rm,
6152 .data = .{ .rm = .{6889 .data = .{ .rm = .{
6153 .r = reg,6890 .r = reg,
6154 .m = .{6891 .m = .{
...@@ -6168,7 +6905,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6168,7 +6905,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
61686905
6169 _ = try func.addInst(.{6906 _ = try func.addInst(.{
6170 .tag = load_tag,6907 .tag = load_tag,
6171 .ops = .rri,
6172 .data = .{ .i_type = .{6908 .data = .{ .i_type = .{
6173 .rd = reg,6909 .rd = reg,
6174 .rs1 = reg_off.reg,6910 .rs1 = reg_off.reg,
...@@ -6178,16 +6914,15 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6178,16 +6914,15 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
6178 },6914 },
6179 .lea_symbol => |sym_off| {6915 .lea_symbol => |sym_off| {
6180 assert(sym_off.off == 0);6916 assert(sym_off.off == 0);
6181 const atom_index = try func.symbolIndex();6917 const atom_index = try func.owner.getSymbolIndex(func);
61826918
6183 _ = try func.addInst(.{6919 _ = try func.addInst(.{
6184 .tag = .pseudo,6920 .tag = .pseudo_load_symbol,
6185 .ops = .pseudo_load_symbol,6921 .data = .{ .reloc = .{
6186 .data = .{ .payload = try func.addExtra(Mir.LoadSymbolPayload{6922 .register = reg,
6187 .register = reg.encodeId(),
6188 .atom_index = atom_index,6923 .atom_index = atom_index,
6189 .sym_index = sym_off.sym,6924 .sym_index = sym_off.sym,
6190 }) },6925 } },
6191 });6926 });
6192 },6927 },
6193 .load_symbol => {6928 .load_symbol => {
...@@ -6197,6 +6932,25 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6197,6 +6932,25 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
6197 try func.genSetReg(ty, addr_reg, src_mcv.address());6932 try func.genSetReg(ty, addr_reg, src_mcv.address());
6198 try func.genSetReg(ty, reg, .{ .indirect = .{ .reg = addr_reg } });6933 try func.genSetReg(ty, reg, .{ .indirect = .{ .reg = addr_reg } });
6199 },6934 },
6935 .lea_tlv => |sym| {
6936 const atom_index = try func.owner.getSymbolIndex(func);
6937
6938 _ = try func.addInst(.{
6939 .tag = .pseudo_load_tlv,
6940 .data = .{ .reloc = .{
6941 .register = reg,
6942 .atom_index = atom_index,
6943 .sym_index = sym,
6944 } },
6945 });
6946 },
6947 .load_tlv => {
6948 const addr_reg, const addr_lock = try func.allocReg(.int);
6949 defer func.register_manager.unlockReg(addr_lock);
6950
6951 try func.genSetReg(ty, addr_reg, src_mcv.address());
6952 try func.genSetReg(ty, reg, .{ .indirect = .{ .reg = addr_reg } });
6953 },
6200 .air_ref => |ref| try func.genSetReg(ty, reg, try func.resolveInst(ref)),6954 .air_ref => |ref| try func.genSetReg(ty, reg, try func.resolveInst(ref)),
6201 else => return func.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),6955 else => return func.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),
6202 }6956 }
...@@ -6216,7 +6970,6 @@ fn genSetMem(...@@ -6216,7 +6970,6 @@ fn genSetMem(
6216 const dst_ptr_mcv: MCValue = switch (base) {6970 const dst_ptr_mcv: MCValue = switch (base) {
6217 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },6971 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
6218 .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },6972 .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },
6219 .reloc => |base_symbol| .{ .lea_symbol = .{ .sym = base_symbol.sym_index, .off = disp } },
6220 };6973 };
6221 switch (src_mcv) {6974 switch (src_mcv) {
6222 .none,6975 .none,
...@@ -6260,7 +7013,7 @@ fn genSetMem(...@@ -6260,7 +7013,7 @@ fn genSetMem(
6260 },7013 },
6261 .register => |reg| {7014 .register => |reg| {
6262 if (reg.class() == .vector) {7015 if (reg.class() == .vector) {
6263 const addr_reg = try func.copyToTmpRegister(Type.usize, dst_ptr_mcv);7016 const addr_reg = try func.copyToTmpRegister(Type.u64, dst_ptr_mcv);
62647017
6265 const num_elem = ty.vectorLen(zcu);7018 const num_elem = ty.vectorLen(zcu);
6266 const elem_size = ty.childType(zcu).bitSize(pt);7019 const elem_size = ty.childType(zcu).bitSize(pt);
...@@ -6279,8 +7032,7 @@ fn genSetMem(...@@ -6279,8 +7032,7 @@ fn genSetMem(
6279 });7032 });
62807033
6281 _ = try func.addInst(.{7034 _ = try func.addInst(.{
6282 .tag = .pseudo,7035 .tag = .pseudo_store_rm,
6283 .ops = .pseudo_store_rm,
6284 .data = .{ .rm = .{7036 .data = .{ .rm = .{
6285 .r = reg,7037 .r = reg,
6286 .m = .{7038 .m = .{
...@@ -6319,8 +7071,7 @@ fn genSetMem(...@@ -6319,8 +7071,7 @@ fn genSetMem(
6319 }));7071 }));
6320 const frame_mcv: MCValue = .{ .load_frame = .{ .index = frame_index } };7072 const frame_mcv: MCValue = .{ .load_frame = .{ .index = frame_index } };
6321 _ = try func.addInst(.{7073 _ = try func.addInst(.{
6322 .tag = .pseudo,7074 .tag = .pseudo_store_rm,
6323 .ops = .pseudo_store_rm,
6324 .data = .{ .rm = .{7075 .data = .{ .rm = .{
6325 .r = reg,7076 .r = reg,
6326 .m = .{7077 .m = .{
...@@ -6335,8 +7086,7 @@ fn genSetMem(...@@ -6335,8 +7086,7 @@ fn genSetMem(
6335 try func.genSetMem(base, disp, ty, frame_mcv);7086 try func.genSetMem(base, disp, ty, frame_mcv);
6336 try func.freeValue(frame_mcv);7087 try func.freeValue(frame_mcv);
6337 } else _ = try func.addInst(.{7088 } else _ = try func.addInst(.{
6338 .tag = .pseudo,7089 .tag = .pseudo_store_rm,
6339 .ops = .pseudo_store_rm,
6340 .data = .{ .rm = .{7090 .data = .{ .rm = .{
6341 .r = reg,7091 .r = reg,
6342 .m = .{7092 .m = .{
...@@ -6366,6 +7116,7 @@ fn genSetMem(...@@ -6366,6 +7116,7 @@ fn genSetMem(
6366 return func.genSetMem(base, disp, ty, .{ .register = reg });7116 return func.genSetMem(base, disp, ty, .{ .register = reg });
6367 },7117 },
6368 .air_ref => |src_ref| try func.genSetMem(base, disp, ty, try func.resolveInst(src_ref)),7118 .air_ref => |src_ref| try func.genSetMem(base, disp, ty, try func.resolveInst(src_ref)),
7119 else => return func.fail("TODO: genSetMem {s}", .{@tagName(src_mcv)}),
6369 }7120 }
6370}7121}
63717122
...@@ -6398,7 +7149,7 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {...@@ -6398,7 +7149,7 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {
6398 const src_lock = if (src_mcv.getReg()) |reg| func.register_manager.lockReg(reg) else null;7149 const src_lock = if (src_mcv.getReg()) |reg| func.register_manager.lockReg(reg) else null;
6399 defer if (src_lock) |lock| func.register_manager.unlockReg(lock);7150 defer if (src_lock) |lock| func.register_manager.unlockReg(lock);
64007151
6401 const dst_mcv = if (dst_ty.abiSize(pt) <= src_ty.abiSize(pt) and7152 const dst_mcv = if (dst_ty.abiSize(pt) <= src_ty.abiSize(pt) and src_mcv != .register_pair and
6402 func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {7153 func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
6403 const dst_mcv = try func.allocRegOrMem(dst_ty, inst, true);7154 const dst_mcv = try func.allocRegOrMem(dst_ty, inst, true);
6404 try func.genCopy(switch (math.order(dst_ty.abiSize(pt), src_ty.abiSize(pt))) {7155 try func.genCopy(switch (math.order(dst_ty.abiSize(pt), src_ty.abiSize(pt))) {
...@@ -6437,7 +7188,7 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {...@@ -6437,7 +7188,7 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {
6437 try func.genSetMem(7188 try func.genSetMem(
6438 .{ .frame = frame_index },7189 .{ .frame = frame_index },
6439 @intCast(ptr_ty.abiSize(pt)),7190 @intCast(ptr_ty.abiSize(pt)),
6440 Type.usize,7191 Type.u64,
6441 .{ .immediate = array_len },7192 .{ .immediate = array_len },
6442 );7193 );
64437194
...@@ -6447,107 +7198,409 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {...@@ -6447,107 +7198,409 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {
64477198
6448fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void {7199fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void {
6449 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;7200 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
6450 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airFloatFromInt for {}", .{7201 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
6451 func.target.cpu.arch,7202 const pt = func.pt;
6452 });7203 const zcu = pt.zcu;
7204
7205 const operand = try func.resolveInst(ty_op.operand);
7206
7207 const src_ty = func.typeOf(ty_op.operand);
7208 const dst_ty = ty_op.ty.toType();
7209
7210 const src_reg, const src_lock = try func.promoteReg(src_ty, operand);
7211 defer if (src_lock) |lock| func.register_manager.unlockReg(lock);
7212
7213 const is_unsigned = dst_ty.isUnsignedInt(zcu);
7214 const src_bits = src_ty.bitSize(pt);
7215 const dst_bits = dst_ty.bitSize(pt);
7216
7217 switch (src_bits) {
7218 32, 64 => {},
7219 else => try func.truncateRegister(src_ty, src_reg),
7220 }
7221
7222 const int_mod: Mir.FcvtOp = switch (src_bits) {
7223 8, 16, 32 => if (is_unsigned) .wu else .w,
7224 64 => if (is_unsigned) .lu else .l,
7225 else => return func.fail("TODO: airFloatFromInt src size: {d}", .{src_bits}),
7226 };
7227
7228 const float_mod: enum { s, d } = switch (dst_bits) {
7229 32 => .s,
7230 64 => .d,
7231 else => return func.fail("TODO: airFloatFromInt dst size {d}", .{dst_bits}),
7232 };
7233
7234 const dst_reg, const dst_lock = try func.allocReg(.int);
7235 defer func.register_manager.unlockReg(dst_lock);
7236
7237 _ = try func.addInst(.{
7238 .tag = switch (float_mod) {
7239 .s => switch (int_mod) {
7240 .l => .fcvtsl,
7241 .lu => .fcvtslu,
7242 .w => .fcvtsw,
7243 .wu => .fcvtswu,
7244 },
7245 .d => switch (int_mod) {
7246 .l => .fcvtdl,
7247 .lu => .fcvtdlu,
7248 .w => .fcvtdw,
7249 .wu => .fcvtdwu,
7250 },
7251 },
7252 .data = .{ .rr = .{
7253 .rd = dst_reg,
7254 .rs = src_reg,
7255 } },
7256 });
7257
7258 break :result .{ .register = dst_reg };
7259 };
6453 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });7260 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
6454}7261}
64557262
6456fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {7263fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {
6457 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;7264 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
6458 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airIntFromFloat for {}", .{7265 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
6459 func.target.cpu.arch,7266 const pt = func.pt;
6460 });7267 const zcu = pt.zcu;
7268
7269 const operand = try func.resolveInst(ty_op.operand);
7270 const src_ty = func.typeOf(ty_op.operand);
7271 const dst_ty = ty_op.ty.toType();
7272
7273 const is_unsigned = dst_ty.isUnsignedInt(zcu);
7274 const src_bits = src_ty.bitSize(pt);
7275 const dst_bits = dst_ty.bitSize(pt);
7276
7277 const float_mod: enum { s, d } = switch (src_bits) {
7278 32 => .s,
7279 64 => .d,
7280 else => return func.fail("TODO: airIntFromFloat src size {d}", .{src_bits}),
7281 };
7282
7283 const int_mod: Mir.FcvtOp = switch (dst_bits) {
7284 32 => if (is_unsigned) .wu else .w,
7285 8, 16, 64 => if (is_unsigned) .lu else .l,
7286 else => return func.fail("TODO: airIntFromFloat dst size: {d}", .{dst_bits}),
7287 };
7288
7289 const src_reg, const src_lock = try func.promoteReg(src_ty, operand);
7290 defer if (src_lock) |lock| func.register_manager.unlockReg(lock);
7291
7292 const dst_reg, const dst_lock = try func.allocReg(.int);
7293 defer func.register_manager.unlockReg(dst_lock);
7294
7295 _ = try func.addInst(.{
7296 .tag = switch (float_mod) {
7297 .s => switch (int_mod) {
7298 .l => .fcvtls,
7299 .lu => .fcvtlus,
7300 .w => .fcvtws,
7301 .wu => .fcvtwus,
7302 },
7303 .d => switch (int_mod) {
7304 .l => .fcvtld,
7305 .lu => .fcvtlud,
7306 .w => .fcvtwd,
7307 .wu => .fcvtwud,
7308 },
7309 },
7310 .data = .{ .rr = .{
7311 .rd = dst_reg,
7312 .rs = src_reg,
7313 } },
7314 });
7315
7316 break :result .{ .register = dst_reg };
7317 };
6461 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });7318 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
6462}7319}
64637320
6464fn airCmpxchg(func: *Func, inst: Air.Inst.Index) !void {7321fn airCmpxchg(func: *Func, inst: Air.Inst.Index, strength: enum { weak, strong }) !void {
7322 _ = strength; // TODO: do something with this
7323
7324 const pt = func.pt;
6465 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;7325 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
6466 const extra = func.air.extraData(Air.Block, ty_pl.payload);7326 const extra = func.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
6467 _ = extra;7327
6468 return func.fail("TODO implement airCmpxchg for {}", .{7328 const ptr_ty = func.typeOf(extra.ptr);
6469 func.target.cpu.arch,7329 const val_ty = func.typeOf(extra.expected_value);
7330 const val_abi_size: u32 = @intCast(val_ty.abiSize(pt));
7331
7332 switch (val_abi_size) {
7333 1, 2, 4, 8 => {},
7334 else => return func.fail("TODO: airCmpxchg Int size {}", .{val_abi_size}),
7335 }
7336
7337 const lr_order: struct { aq: Mir.Barrier, rl: Mir.Barrier } = switch (extra.successOrder()) {
7338 .unordered,
7339 => unreachable,
7340
7341 .monotonic,
7342 .release,
7343 => .{ .aq = .none, .rl = .none },
7344 .acquire,
7345 .acq_rel,
7346 => .{ .aq = .aq, .rl = .none },
7347 .seq_cst => .{ .aq = .aq, .rl = .rl },
7348 };
7349
7350 const sc_order: struct { aq: Mir.Barrier, rl: Mir.Barrier } = switch (extra.failureOrder()) {
7351 .unordered,
7352 .release,
7353 .acq_rel,
7354 => unreachable,
7355
7356 .monotonic,
7357 .acquire,
7358 .seq_cst,
7359 => switch (extra.successOrder()) {
7360 .release,
7361 .seq_cst,
7362 => .{ .aq = .none, .rl = .rl },
7363 else => .{ .aq = .none, .rl = .none },
7364 },
7365 };
7366
7367 const ptr_mcv = try func.resolveInst(extra.ptr);
7368 const ptr_reg, const ptr_lock = try func.promoteReg(ptr_ty, ptr_mcv);
7369 defer if (ptr_lock) |lock| func.register_manager.unlockReg(lock);
7370
7371 const exp_mcv = try func.resolveInst(extra.expected_value);
7372 const exp_reg, const exp_lock = try func.promoteReg(val_ty, exp_mcv);
7373 defer if (exp_lock) |lock| func.register_manager.unlockReg(lock);
7374 try func.truncateRegister(val_ty, exp_reg);
7375
7376 const new_mcv = try func.resolveInst(extra.new_value);
7377 const new_reg, const new_lock = try func.promoteReg(val_ty, new_mcv);
7378 defer if (new_lock) |lock| func.register_manager.unlockReg(lock);
7379 try func.truncateRegister(val_ty, new_reg);
7380
7381 const branch_reg, const branch_lock = try func.allocReg(.int);
7382 defer func.register_manager.unlockReg(branch_lock);
7383
7384 const fallthrough_reg, const fallthrough_lock = try func.allocReg(.int);
7385 defer func.register_manager.unlockReg(fallthrough_lock);
7386
7387 const jump_back = try func.addInst(.{
7388 .tag = if (val_ty.bitSize(pt) <= 32) .lrw else .lrd,
7389 .data = .{ .amo = .{
7390 .aq = lr_order.aq,
7391 .rl = lr_order.rl,
7392 .rd = branch_reg,
7393 .rs1 = ptr_reg,
7394 .rs2 = .zero,
7395 } },
6470 });7396 });
6471 // return func.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });7397 try func.truncateRegister(val_ty, branch_reg);
7398
7399 const jump_forward = try func.addInst(.{
7400 .tag = .bne,
7401 .data = .{ .b_type = .{
7402 .rs1 = branch_reg,
7403 .rs2 = exp_reg,
7404 .inst = undefined,
7405 } },
7406 });
7407
7408 _ = try func.addInst(.{
7409 .tag = if (val_ty.bitSize(pt) <= 32) .scw else .scd,
7410 .data = .{ .amo = .{
7411 .aq = sc_order.aq,
7412 .rl = sc_order.rl,
7413 .rd = fallthrough_reg,
7414 .rs1 = ptr_reg,
7415 .rs2 = new_reg,
7416 } },
7417 });
7418 try func.truncateRegister(Type.bool, fallthrough_reg);
7419
7420 _ = try func.addInst(.{
7421 .tag = .bne,
7422 .data = .{ .b_type = .{
7423 .rs1 = fallthrough_reg,
7424 .rs2 = .zero,
7425 .inst = jump_back,
7426 } },
7427 });
7428
7429 func.performReloc(jump_forward);
7430
7431 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
7432 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, false);
7433
7434 const tmp_reg, const tmp_lock = try func.allocReg(.int);
7435 defer func.register_manager.unlockReg(tmp_lock);
7436
7437 try func.genBinOp(
7438 .cmp_neq,
7439 .{ .register = branch_reg },
7440 val_ty,
7441 .{ .register = exp_reg },
7442 val_ty,
7443 tmp_reg,
7444 );
7445
7446 try func.genCopy(val_ty, dst_mcv, .{ .register = branch_reg });
7447 try func.genCopy(
7448 Type.bool,
7449 dst_mcv.address().offset(@intCast(val_abi_size)).deref(),
7450 .{ .register = tmp_reg },
7451 );
7452
7453 break :result dst_mcv;
7454 };
7455
7456 return func.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });
6472}7457}
64737458
6474fn airAtomicRmw(func: *Func, inst: Air.Inst.Index) !void {7459fn airAtomicRmw(func: *Func, inst: Air.Inst.Index) !void {
6475 const pt = func.pt;7460 const pt = func.pt;
7461 const zcu = pt.zcu;
6476 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;7462 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
6477 const extra = func.air.extraData(Air.AtomicRmw, pl_op.payload).data;7463 const extra = func.air.extraData(Air.AtomicRmw, pl_op.payload).data;
64787464
6479 const op = extra.op();7465 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
6480 const order = extra.ordering();7466 const op = extra.op();
7467 const order = extra.ordering();
64817468
6482 const ptr_ty = func.typeOf(pl_op.operand);7469 const ptr_ty = func.typeOf(pl_op.operand);
6483 const ptr_mcv = try func.resolveInst(pl_op.operand);7470 const ptr_mcv = try func.resolveInst(pl_op.operand);
64847471
6485 const val_ty = func.typeOf(extra.operand);7472 const val_ty = func.typeOf(extra.operand);
6486 const val_size = val_ty.abiSize(pt);7473 const val_size = val_ty.abiSize(pt);
6487 const val_mcv = try func.resolveInst(extra.operand);7474 const val_mcv = try func.resolveInst(extra.operand);
64887475
6489 if (!math.isPowerOfTwo(val_size))7476 if (!math.isPowerOfTwo(val_size))
6490 return func.fail("TODO: airAtomicRmw non-pow 2", .{});7477 return func.fail("TODO: airAtomicRmw non-pow 2", .{});
64917478
6492 switch (val_ty.zigTypeTag(pt.zcu)) {7479 switch (val_ty.zigTypeTag(pt.zcu)) {
6493 .Int => {},7480 .Enum, .Int => {},
6494 inline .Bool, .Float, .Enum, .Pointer => |ty| return func.fail("TODO: airAtomicRmw {s}", .{@tagName(ty)}),7481 inline .Bool, .Float, .Pointer => |ty| return func.fail("TODO: airAtomicRmw {s}", .{@tagName(ty)}),
6495 else => unreachable,7482 else => unreachable,
6496 }7483 }
64977484
6498 switch (val_size) {7485 const method: enum { amo, loop } = switch (val_size) {
6499 1, 2 => return func.fail("TODO: airAtomicRmw Int {}", .{val_size}),7486 1, 2 => .loop,
6500 4, 8 => {},7487 4, 8 => .amo,
6501 else => unreachable,7488 else => unreachable,
6502 }7489 };
65037490
6504 const ptr_register, const ptr_lock = try func.promoteReg(ptr_ty, ptr_mcv);7491 const ptr_register, const ptr_lock = try func.promoteReg(ptr_ty, ptr_mcv);
6505 defer if (ptr_lock) |lock| func.register_manager.unlockReg(lock);7492 defer if (ptr_lock) |lock| func.register_manager.unlockReg(lock);
65067493
6507 const val_register, const val_lock = try func.promoteReg(val_ty, val_mcv);7494 const val_register, const val_lock = try func.promoteReg(val_ty, val_mcv);
6508 defer if (val_lock) |lock| func.register_manager.unlockReg(lock);7495 defer if (val_lock) |lock| func.register_manager.unlockReg(lock);
65097496
6510 const result_mcv = try func.allocRegOrMem(val_ty, inst, true);7497 const result_mcv = try func.allocRegOrMem(val_ty, inst, true);
6511 assert(result_mcv == .register); // should fit into 8 bytes7498 assert(result_mcv == .register); // should fit into 8 bytes
7499 const result_reg = result_mcv.register;
65127500
6513 const aq, const rl = switch (order) {7501 const aq, const rl = switch (order) {
6514 .unordered => unreachable,7502 .unordered => unreachable,
6515 .monotonic => .{ false, false },7503 .monotonic => .{ false, false },
6516 .acquire => .{ true, false },7504 .acquire => .{ true, false },
6517 .release => .{ false, true },7505 .release => .{ false, true },
6518 .acq_rel => .{ true, true },7506 .acq_rel => .{ true, true },
6519 .seq_cst => .{ true, true },7507 .seq_cst => .{ true, true },
6520 };7508 };
65217509
6522 _ = try func.addInst(.{7510 switch (method) {
6523 .tag = .pseudo,7511 .amo => {
6524 .ops = .pseudo_amo,7512 const is_d = val_ty.abiSize(pt) == 8;
6525 .data = .{ .amo = .{7513 const is_un = val_ty.isUnsignedInt(zcu);
6526 .rd = result_mcv.register,7514
6527 .rs1 = ptr_register,7515 const mnem: Mnemonic = switch (op) {
6528 .rs2 = val_register,7516 // zig fmt: off
6529 .aq = if (aq) .aq else .none,7517 .Xchg => if (is_d) .amoswapd else .amoswapw,
6530 .rl = if (rl) .rl else .none,7518 .Add => if (is_d) .amoaddd else .amoaddw,
6531 .op = switch (op) {7519 .And => if (is_d) .amoandd else .amoandw,
6532 .Xchg => .SWAP,7520 .Or => if (is_d) .amoord else .amoorw,
6533 .Add => .ADD,7521 .Xor => if (is_d) .amoxord else .amoxorw,
6534 .Sub => return func.fail("TODO: airAtomicRmw SUB", .{}),7522 .Max => if (is_d) if (is_un) .amomaxud else .amomaxd else if (is_un) .amomaxuw else .amomaxw,
6535 .And => .AND,7523 .Min => if (is_d) if (is_un) .amominud else .amomind else if (is_un) .amominuw else .amominw,
6536 .Nand => return func.fail("TODO: airAtomicRmw NAND", .{}),7524 else => return func.fail("TODO: airAtomicRmw amo {s}", .{@tagName(op)}),
6537 .Or => .OR,7525 // zig fmt: on
6538 .Xor => .XOR,7526 };
6539 .Max => .MAX,7527
6540 .Min => .MIN,7528 _ = try func.addInst(.{
7529 .tag = mnem,
7530 .data = .{ .amo = .{
7531 .rd = result_reg,
7532 .rs1 = ptr_register,
7533 .rs2 = val_register,
7534 .aq = if (aq) .aq else .none,
7535 .rl = if (rl) .rl else .none,
7536 } },
7537 });
6541 },7538 },
6542 .ty = val_ty,7539 .loop => {
6543 } },7540 // where we'll jump back when the sc fails
6544 });7541 const jump_back = try func.addInst(.{
7542 .tag = .lrw,
7543 .data = .{ .amo = .{
7544 .rd = result_reg,
7545 .rs1 = ptr_register,
7546 .rs2 = .zero,
7547 .aq = if (aq) .aq else .none,
7548 .rl = if (rl) .rl else .none,
7549 } },
7550 });
7551
7552 const after_reg, const after_lock = try func.allocReg(.int);
7553 defer func.register_manager.unlockReg(after_lock);
7554
7555 switch (op) {
7556 .Add, .Sub => |tag| {
7557 _ = try func.genBinOp(
7558 switch (tag) {
7559 .Add => .add,
7560 .Sub => .sub,
7561 else => unreachable,
7562 },
7563 .{ .register = result_reg },
7564 val_ty,
7565 .{ .register = val_register },
7566 val_ty,
7567 after_reg,
7568 );
7569 },
7570
7571 else => return func.fail("TODO: airAtomicRmw loop {s}", .{@tagName(op)}),
7572 }
7573
7574 _ = try func.addInst(.{
7575 .tag = .scw,
7576 .data = .{ .amo = .{
7577 .rd = after_reg,
7578 .rs1 = ptr_register,
7579 .rs2 = after_reg,
7580 .aq = if (aq) .aq else .none,
7581 .rl = if (rl) .rl else .none,
7582 } },
7583 });
7584
7585 _ = try func.addInst(.{
7586 .tag = .bne,
7587 .data = .{ .b_type = .{
7588 .inst = jump_back,
7589 .rs1 = after_reg,
7590 .rs2 = .zero,
7591 } },
7592 });
7593 },
7594 }
7595 break :result result_mcv;
7596 };
65457597
6546 return func.finishAir(inst, result_mcv, .{ pl_op.operand, extra.operand, .none });7598 return func.finishAir(inst, result, .{ pl_op.operand, extra.operand, .none });
6547}7599}
65487600
6549fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void {7601fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void {
6550 const zcu = func.pt.zcu;7602 const pt = func.pt;
7603 const zcu = pt.zcu;
6551 const atomic_load = func.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load;7604 const atomic_load = func.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load;
6552 const order: std.builtin.AtomicOrder = atomic_load.order;7605 const order: std.builtin.AtomicOrder = atomic_load.order;
65537606
...@@ -6555,20 +7608,19 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void {...@@ -6555,20 +7608,19 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void {
6555 const elem_ty = ptr_ty.childType(zcu);7608 const elem_ty = ptr_ty.childType(zcu);
6556 const ptr_mcv = try func.resolveInst(atomic_load.ptr);7609 const ptr_mcv = try func.resolveInst(atomic_load.ptr);
65577610
7611 const bit_size = elem_ty.bitSize(pt);
7612 if (bit_size > 64) return func.fail("TODO: airAtomicStore > 64 bits", .{});
7613
6558 const result_mcv = try func.allocRegOrMem(elem_ty, inst, true);7614 const result_mcv = try func.allocRegOrMem(elem_ty, inst, true);
6559 assert(result_mcv == .register); // should be less than 8 bytes7615 assert(result_mcv == .register); // should be less than 8 bytes
65607616
6561 if (order == .seq_cst) {7617 if (order == .seq_cst) {
6562 _ = try func.addInst(.{7618 _ = try func.addInst(.{
6563 .tag = .pseudo,7619 .tag = .fence,
6564 .ops = .pseudo_fence,7620 .data = .{ .fence = .{
6565 .data = .{7621 .pred = .rw,
6566 .fence = .{7622 .succ = .rw,
6567 .pred = .rw,7623 } },
6568 .succ = .rw,
6569 .fm = .none,
6570 },
6571 },
6572 });7624 });
6573 }7625 }
65747626
...@@ -6581,15 +7633,11 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void {...@@ -6581,15 +7633,11 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void {
6581 // Make sure all previous reads happen before any reading or writing accurs.7633 // Make sure all previous reads happen before any reading or writing accurs.
6582 .seq_cst, .acquire => {7634 .seq_cst, .acquire => {
6583 _ = try func.addInst(.{7635 _ = try func.addInst(.{
6584 .tag = .pseudo,7636 .tag = .fence,
6585 .ops = .pseudo_fence,7637 .data = .{ .fence = .{
6586 .data = .{7638 .pred = .r,
6587 .fence = .{7639 .succ = .rw,
6588 .pred = .r,7640 } },
6589 .succ = .rw,
6590 .fm = .none,
6591 },
6592 },
6593 });7641 });
6594 },7642 },
6595 else => unreachable,7643 else => unreachable,
...@@ -6607,25 +7655,24 @@ fn airAtomicStore(func: *Func, inst: Air.Inst.Index, order: std.builtin.AtomicOr...@@ -6607,25 +7655,24 @@ fn airAtomicStore(func: *Func, inst: Air.Inst.Index, order: std.builtin.AtomicOr
6607 const val_ty = func.typeOf(bin_op.rhs);7655 const val_ty = func.typeOf(bin_op.rhs);
6608 const val_mcv = try func.resolveInst(bin_op.rhs);7656 const val_mcv = try func.resolveInst(bin_op.rhs);
66097657
7658 const bit_size = val_ty.bitSize(func.pt);
7659 if (bit_size > 64) return func.fail("TODO: airAtomicStore > 64 bits", .{});
7660
6610 switch (order) {7661 switch (order) {
6611 .unordered, .monotonic => {},7662 .unordered, .monotonic => {},
6612 .release, .seq_cst => {7663 .release, .seq_cst => {
6613 _ = try func.addInst(.{7664 _ = try func.addInst(.{
6614 .tag = .pseudo,7665 .tag = .fence,
6615 .ops = .pseudo_fence,7666 .data = .{ .fence = .{
6616 .data = .{7667 .pred = .rw,
6617 .fence = .{7668 .succ = .w,
6618 .pred = .rw,7669 } },
6619 .succ = .w,
6620 .fm = .none,
6621 },
6622 },
6623 });7670 });
6624 },7671 },
6625 else => unreachable,7672 else => unreachable,
6626 }7673 }
66277674
6628 try func.store(ptr_mcv, val_mcv, ptr_ty, val_ty);7675 try func.store(ptr_mcv, val_mcv, ptr_ty);
6629 return func.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });7676 return func.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
6630}7677}
66317678
...@@ -6689,15 +7736,15 @@ fn airMemset(func: *Func, inst: Air.Inst.Index, safety: bool) !void {...@@ -6689,15 +7736,15 @@ fn airMemset(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
6689 const len = dst_ptr_ty.childType(zcu).arrayLen(zcu);7736 const len = dst_ptr_ty.childType(zcu).arrayLen(zcu);
66907737
6691 assert(len != 0); // prevented by Sema7738 assert(len != 0); // prevented by Sema
6692 try func.store(dst_ptr, src_val, elem_ptr_ty, elem_ty);7739 try func.store(dst_ptr, src_val, elem_ptr_ty);
66937740
6694 const second_elem_ptr_reg, const second_elem_ptr_lock = try func.allocReg(.int);7741 const second_elem_ptr_reg, const second_elem_ptr_lock = try func.allocReg(.int);
6695 defer func.register_manager.unlockReg(second_elem_ptr_lock);7742 defer func.register_manager.unlockReg(second_elem_ptr_lock);
66967743
6697 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };7744 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };
66987745
6699 try func.genSetReg(Type.usize, second_elem_ptr_reg, .{ .register_offset = .{7746 try func.genSetReg(Type.u64, second_elem_ptr_reg, .{ .register_offset = .{
6700 .reg = try func.copyToTmpRegister(Type.usize, dst_ptr),7747 .reg = try func.copyToTmpRegister(Type.u64, dst_ptr),
6701 .off = elem_abi_size,7748 .off = elem_abi_size,
6702 } });7749 } });
67037750
...@@ -6711,123 +7758,94 @@ fn airMemset(func: *Func, inst: Air.Inst.Index, safety: bool) !void {...@@ -6711,123 +7758,94 @@ fn airMemset(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
6711}7758}
67127759
6713fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void {7760fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void {
6714 _ = inst;
6715 return func.fail("TODO implement airMemcpy for {}", .{func.target.cpu.arch});
6716}
6717
6718fn airTagName(func: *Func, inst: Air.Inst.Index) !void {
6719 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
6720 const operand = try func.resolveInst(un_op);
6721 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else {
6722 _ = operand;
6723 return func.fail("TODO implement airTagName for riscv64", .{});
6724 };
6725 return func.finishAir(inst, result, .{ un_op, .none, .none });
6726}
6727
6728fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {
6729 const pt = func.pt;7761 const pt = func.pt;
6730 const zcu = pt.zcu;7762 const zcu = pt.zcu;
6731 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;7763 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
67327764
6733 const err_ty = func.typeOf(un_op);7765 const dst_ptr = try func.resolveInst(bin_op.lhs);
6734 const err_mcv = try func.resolveInst(un_op);7766 const src_ptr = try func.resolveInst(bin_op.rhs);
67357767
6736 const err_reg = try func.copyToTmpRegister(err_ty, err_mcv);7768 const dst_ty = func.typeOf(bin_op.lhs);
6737 const err_lock = func.register_manager.lockRegAssumeUnused(err_reg);
6738 defer func.register_manager.unlockReg(err_lock);
67397769
6740 const addr_reg, const addr_lock = try func.allocReg(.int);7770 const len_mcv: MCValue = switch (dst_ty.ptrSize(zcu)) {
6741 defer func.register_manager.unlockReg(addr_lock);7771 .Slice => len: {
7772 const len_reg, const len_lock = try func.allocReg(.int);
7773 defer func.register_manager.unlockReg(len_lock);
67427774
6743 // this is now the base address of the error name table7775 const elem_size = dst_ty.childType(zcu).abiSize(pt);
6744 const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, zcu);7776 try func.genBinOp(
6745 if (func.bin_file.cast(link.File.Elf)) |elf_file| {7777 .mul,
6746 const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|7778 .{ .immediate = elem_size },
6747 return func.fail("{s} creating lazy symbol", .{@errorName(err)});7779 Type.u64,
6748 const sym = elf_file.symbol(sym_index);7780 dst_ptr.address().offset(8).deref(),
6749 try func.genSetReg(Type.usize, addr_reg, .{ .load_symbol = .{ .sym = sym.esym_index } });7781 Type.u64,
6750 } else {7782 len_reg,
6751 return func.fail("TODO: riscv non-elf", .{});7783 );
6752 }7784 break :len .{ .register = len_reg };
7785 },
7786 .One => len: {
7787 const array_ty = dst_ty.childType(zcu);
7788 break :len .{ .immediate = array_ty.arrayLen(zcu) * array_ty.childType(zcu).abiSize(pt) };
7789 },
7790 else => |size| return func.fail("TODO: airMemcpy size {s}", .{@tagName(size)}),
7791 };
7792 const len_lock: ?RegisterLock = switch (len_mcv) {
7793 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
7794 else => null,
7795 };
7796 defer if (len_lock) |lock| func.register_manager.unlockReg(lock);
67537797
6754 const start_reg, const start_lock = try func.allocReg(.int);7798 try func.genInlineMemcpy(dst_ptr, src_ptr, len_mcv);
6755 defer func.register_manager.unlockReg(start_lock);
67567799
6757 const end_reg, const end_lock = try func.allocReg(.int);7800 return func.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
6758 defer func.register_manager.unlockReg(end_lock);7801}
67597802
6760 // const tmp_reg, const tmp_lock = try func.allocReg(.int);7803fn airTagName(func: *Func, inst: Air.Inst.Index) !void {
6761 // defer func.register_manager.unlockReg(tmp_lock);7804 const pt = func.pt;
7805 const zcu = pt.zcu;
67627806
6763 // we move the base address forward by the following formula: base + (errno * 8)7807 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
7808 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
7809 const enum_ty = func.typeOf(un_op);
67647810
6765 // shifting left by 4 is the same as multiplying by 87811 // TODO: work out the bugs
6766 _ = try func.addInst(.{7812 if (true) return func.fail("TODO: airTagName", .{});
6767 .tag = .slli,
6768 .ops = .rri,
6769 .data = .{ .i_type = .{
6770 .imm12 = Immediate.u(4),
6771 .rd = err_reg,
6772 .rs1 = err_reg,
6773 } },
6774 });
67757813
6776 _ = try func.addInst(.{7814 const param_regs = abi.Registers.Integer.function_arg_regs;
6777 .tag = .add,7815 const dst_mcv = try func.allocRegOrMem(Type.u64, inst, false);
6778 .ops = .rrr,7816 try func.genSetReg(Type.u64, param_regs[0], dst_mcv.address());
6779 .data = .{ .r_type = .{
6780 .rd = addr_reg,
6781 .rs1 = addr_reg,
6782 .rs2 = err_reg,
6783 } },
6784 });
67857817
6786 _ = try func.addInst(.{7818 const operand = try func.resolveInst(un_op);
6787 .tag = .pseudo,7819 try func.genSetReg(enum_ty, param_regs[1], operand);
6788 .ops = .pseudo_load_rm,
6789 .data = .{
6790 .rm = .{
6791 .r = start_reg,
6792 .m = .{
6793 .base = .{ .reg = addr_reg },
6794 .mod = .{ .size = .dword, .unsigned = true },
6795 },
6796 },
6797 },
6798 });
67997820
6800 _ = try func.addInst(.{7821 const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(zcu), zcu);
6801 .tag = .pseudo,7822 const elf_file = func.bin_file.cast(link.File.Elf).?;
6802 .ops = .pseudo_load_rm,7823 const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
6803 .data = .{7824 return func.fail("{s} creating lazy symbol", .{@errorName(err)});
6804 .rm = .{7825 const sym = elf_file.symbol(sym_index);
6805 .r = end_reg,
6806 .m = .{
6807 .base = .{ .reg = addr_reg },
6808 .mod = .{ .size = .dword, .unsigned = true },
6809 },
6810 },
6811 },
6812 });
68137826
6814 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, false);7827 if (func.mod.pic) {
6815 const frame = dst_mcv.load_frame;7828 return func.fail("TODO: airTagName pic", .{});
6816 try func.genSetMem(7829 } else {
6817 .{ .frame = frame.index },7830 try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } });
6818 frame.off,7831 _ = try func.addInst(.{
6819 Type.usize,7832 .tag = .jalr,
6820 .{ .register = start_reg },7833 .data = .{ .i_type = .{
6821 );7834 .rd = .ra,
7835 .rs1 = .ra,
7836 .imm12 = Immediate.s(0),
7837 } },
7838 });
7839 }
68227840
6823 try func.genSetMem(7841 break :result dst_mcv;
6824 .{ .frame = frame.index },7842 };
6825 frame.off + 8,7843 return func.finishAir(inst, result, .{ un_op, .none, .none });
6826 Type.usize,7844}
6827 .{ .register = end_reg },
6828 );
68297845
6830 return func.finishAir(inst, dst_mcv, .{ un_op, .none, .none });7846fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {
7847 _ = inst;
7848 return func.fail("TODO: airErrorName", .{});
6831}7849}
68327850
6833fn airSplat(func: *Func, inst: Air.Inst.Index) !void {7851fn airSplat(func: *Func, inst: Air.Inst.Index) !void {
...@@ -7013,9 +8031,10 @@ fn getResolvedInstValue(func: *Func, inst: Air.Inst.Index) *InstTracking {...@@ -7013,9 +8031,10 @@ fn getResolvedInstValue(func: *Func, inst: Air.Inst.Index) *InstTracking {
70138031
7014fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {8032fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
7015 const pt = func.pt;8033 const pt = func.pt;
8034 const zcu = pt.zcu;
7016 const gpa = func.gpa;8035 const gpa = func.gpa;
70178036
7018 const owner_decl_index = pt.zcu.funcOwnerDeclIndex(func.func_index);8037 const owner_decl_index = func.owner.getDecl(zcu);
7019 const lf = func.bin_file;8038 const lf = func.bin_file;
7020 const src_loc = func.src_loc;8039 const src_loc = func.src_loc;
70218040
...@@ -7047,9 +8066,10 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {...@@ -7047,9 +8066,10 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
7047 .none => .none,8066 .none => .none,
7048 .undef => unreachable,8067 .undef => unreachable,
7049 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },8068 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },
8069 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
7050 .immediate => |imm| .{ .immediate = imm },8070 .immediate => |imm| .{ .immediate = imm },
7051 .memory => |addr| .{ .memory = addr },8071 .memory => |addr| .{ .memory = addr },
7052 .load_got, .load_direct, .load_tlv => {8072 .load_got, .load_direct => {
7053 return func.fail("TODO: genTypedValue {s}", .{@tagName(mcv)});8073 return func.fail("TODO: genTypedValue {s}", .{@tagName(mcv)});
7054 },8074 },
7055 },8075 },
src/arch/riscv64/Emit.zig+96-77
...@@ -40,7 +40,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -40,7 +40,7 @@ pub fn emitMir(emit: *Emit) Error!void {
40 .source = start_offset,40 .source = start_offset,
41 .target = target,41 .target = target,
42 .offset = 0,42 .offset = 0,
43 .enc = std.meta.activeTag(lowered_inst.encoding.data),43 .fmt = std.meta.activeTag(lowered_inst),
44 }),44 }),
45 .load_symbol_reloc => |symbol| {45 .load_symbol_reloc => |symbol| {
46 const is_obj_or_static_lib = switch (emit.lower.output_mode) {46 const is_obj_or_static_lib = switch (emit.lower.output_mode) {
...@@ -49,46 +49,70 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -49,46 +49,70 @@ pub fn emitMir(emit: *Emit) Error!void {
49 .Lib => emit.lower.link_mode == .static,49 .Lib => emit.lower.link_mode == .static,
50 };50 };
5151
52 if (emit.bin_file.cast(link.File.Elf)) |elf_file| {52 const elf_file = emit.bin_file.cast(link.File.Elf).?;
53 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;53
54 const sym_index = elf_file.zigObjectPtr().?.symbol(symbol.sym_index);54 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
55 const sym = elf_file.symbol(sym_index);55 const sym_index = elf_file.zigObjectPtr().?.symbol(symbol.sym_index);
5656 const sym = elf_file.symbol(sym_index);
57 var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);57
58 var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);58 var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
5959 var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);
60 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {60
61 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);61 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
6262 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
63 hi_r_type = Elf.R_ZIG_GOT_HI20;63
64 lo_r_type = Elf.R_ZIG_GOT_LO12;64 hi_r_type = Elf.R_ZIG_GOT_HI20;
65 }65 lo_r_type = Elf.R_ZIG_GOT_LO12;
6666 }
67 try atom_ptr.addReloc(elf_file, .{67
68 .r_offset = start_offset,68 try atom_ptr.addReloc(elf_file, .{
69 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | hi_r_type,69 .r_offset = start_offset,
70 .r_addend = 0,70 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | hi_r_type,
71 });71 .r_addend = 0,
7272 });
73 try atom_ptr.addReloc(elf_file, .{73
74 .r_offset = start_offset + 4,74 try atom_ptr.addReloc(elf_file, .{
75 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type,75 .r_offset = start_offset + 4,
76 .r_addend = 0,76 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type,
77 });77 .r_addend = 0,
78 } else unreachable;78 });
79 },
80 .load_tlv_reloc => |symbol| {
81 const elf_file = emit.bin_file.cast(link.File.Elf).?;
82
83 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
84
85 const R_RISCV = std.elf.R_RISCV;
86
87 try atom_ptr.addReloc(elf_file, .{
88 .r_offset = start_offset,
89 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_HI20),
90 .r_addend = 0,
91 });
92
93 try atom_ptr.addReloc(elf_file, .{
94 .r_offset = start_offset + 4,
95 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_ADD),
96 .r_addend = 0,
97 });
98
99 try atom_ptr.addReloc(elf_file, .{
100 .r_offset = start_offset + 8,
101 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_LO12_I),
102 .r_addend = 0,
103 });
79 },104 },
80 .call_extern_fn_reloc => |symbol| {105 .call_extern_fn_reloc => |symbol| {
81 if (emit.bin_file.cast(link.File.Elf)) |elf_file| {106 const elf_file = emit.bin_file.cast(link.File.Elf).?;
82 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;107 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
83108
84 const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT);109 const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT);
85110
86 try atom_ptr.addReloc(elf_file, .{111 try atom_ptr.addReloc(elf_file, .{
87 .r_offset = start_offset,112 .r_offset = start_offset,
88 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,113 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,
89 .r_addend = 0,114 .r_addend = 0,
90 });115 });
91 } else return emit.fail("TODO: call_extern_fn_reloc non-ELF", .{});
92 },116 },
93 };117 };
94 }118 }
...@@ -98,40 +122,37 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -98,40 +122,37 @@ pub fn emitMir(emit: *Emit) Error!void {
98 const mir_inst = emit.lower.mir.instructions.get(mir_index);122 const mir_inst = emit.lower.mir.instructions.get(mir_index);
99 switch (mir_inst.tag) {123 switch (mir_inst.tag) {
100 else => unreachable,124 else => unreachable,
101 .pseudo => switch (mir_inst.ops) {125 .pseudo_dbg_prologue_end => {
102 else => unreachable,126 switch (emit.debug_output) {
103 .pseudo_dbg_prologue_end => {127 .dwarf => |dw| {
104 switch (emit.debug_output) {128 try dw.setPrologueEnd();
105 .dwarf => |dw| {129 log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{
106 try dw.setPrologueEnd();130 emit.prev_di_line, emit.prev_di_column,
107 log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{131 });
108 emit.prev_di_line, emit.prev_di_column,132 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
109 });133 },
110 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);134 .plan9 => {},
111 },135 .none => {},
112 .plan9 => {},136 }
113 .none => {},
114 }
115 },
116 .pseudo_dbg_line_column => try emit.dbgAdvancePCAndLine(
117 mir_inst.data.pseudo_dbg_line_column.line,
118 mir_inst.data.pseudo_dbg_line_column.column,
119 ),
120 .pseudo_dbg_epilogue_begin => {
121 switch (emit.debug_output) {
122 .dwarf => |dw| {
123 try dw.setEpilogueBegin();
124 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
125 emit.prev_di_line, emit.prev_di_column,
126 });
127 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
128 },
129 .plan9 => {},
130 .none => {},
131 }
132 },
133 .pseudo_dead => {},
134 },137 },
138 .pseudo_dbg_line_column => try emit.dbgAdvancePCAndLine(
139 mir_inst.data.pseudo_dbg_line_column.line,
140 mir_inst.data.pseudo_dbg_line_column.column,
141 ),
142 .pseudo_dbg_epilogue_begin => {
143 switch (emit.debug_output) {
144 .dwarf => |dw| {
145 try dw.setEpilogueBegin();
146 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
147 emit.prev_di_line, emit.prev_di_column,
148 });
149 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
150 },
151 .plan9 => {},
152 .none => {},
153 }
154 },
155 .pseudo_dead => {},
135 }156 }
136 }157 }
137 }158 }
...@@ -151,8 +172,8 @@ const Reloc = struct {...@@ -151,8 +172,8 @@ const Reloc = struct {
151 target: Mir.Inst.Index,172 target: Mir.Inst.Index,
152 /// Offset of the relocation within the instruction.173 /// Offset of the relocation within the instruction.
153 offset: u32,174 offset: u32,
154 /// Encoding of the instruction, used to determine how to modify it.175 /// Format of the instruction, used to determine how to modify it.
155 enc: Encoding.InstEnc,176 fmt: encoding.Lir.Format,
156};177};
157178
158fn fixupRelocs(emit: *Emit) Error!void {179fn fixupRelocs(emit: *Emit) Error!void {
...@@ -164,12 +185,10 @@ fn fixupRelocs(emit: *Emit) Error!void {...@@ -164,12 +185,10 @@ fn fixupRelocs(emit: *Emit) Error!void {
164 const disp = @as(i32, @intCast(target)) - @as(i32, @intCast(reloc.source));185 const disp = @as(i32, @intCast(target)) - @as(i32, @intCast(reloc.source));
165 const code: *[4]u8 = emit.code.items[reloc.source + reloc.offset ..][0..4];186 const code: *[4]u8 = emit.code.items[reloc.source + reloc.offset ..][0..4];
166187
167 log.debug("disp: {x}", .{disp});188 switch (reloc.fmt) {
168
169 switch (reloc.enc) {
170 .J => riscv_util.writeInstJ(code, @bitCast(disp)),189 .J => riscv_util.writeInstJ(code, @bitCast(disp)),
171 .B => riscv_util.writeInstB(code, @bitCast(disp)),190 .B => riscv_util.writeInstB(code, @bitCast(disp)),
172 else => return emit.fail("tried to reloc encoding type {s}", .{@tagName(reloc.enc)}),191 else => return emit.fail("tried to reloc format type {s}", .{@tagName(reloc.fmt)}),
173 }192 }
174 }193 }
175}194}
...@@ -209,5 +228,5 @@ const Emit = @This();...@@ -209,5 +228,5 @@ const Emit = @This();
209const Lower = @import("Lower.zig");228const Lower = @import("Lower.zig");
210const Mir = @import("Mir.zig");229const Mir = @import("Mir.zig");
211const riscv_util = @import("../../link/riscv.zig");230const riscv_util = @import("../../link/riscv.zig");
212const Encoding = @import("Encoding.zig");
213const Elf = @import("../../link/Elf.zig");231const Elf = @import("../../link/Elf.zig");
232const encoding = @import("encoding.zig");
src/arch/riscv64/Encoding.zig deleted-1119
...@@ -1,1119 +0,0 @@
1mnemonic: Mnemonic,
2data: Data,
3
4const OpCode = enum(u7) {
5 LOAD = 0b0000011,
6 LOAD_FP = 0b0000111,
7 MISC_MEM = 0b0001111,
8 OP_IMM = 0b0010011,
9 AUIPC = 0b0010111,
10 OP_IMM_32 = 0b0011011,
11 STORE = 0b0100011,
12 STORE_FP = 0b0100111,
13 AMO = 0b0101111,
14 OP_V = 0b1010111,
15 OP = 0b0110011,
16 OP_32 = 0b0111011,
17 LUI = 0b0110111,
18 MADD = 0b1000011,
19 MSUB = 0b1000111,
20 NMSUB = 0b1001011,
21 NMADD = 0b1001111,
22 OP_FP = 0b1010011,
23 OP_IMM_64 = 0b1011011,
24 BRANCH = 0b1100011,
25 JALR = 0b1100111,
26 JAL = 0b1101111,
27 SYSTEM = 0b1110011,
28 OP_64 = 0b1111011,
29 NONE = 0b00000000,
30};
31
32const FpFmt = enum(u2) {
33 /// 32-bit single-precision
34 S = 0b00,
35 /// 64-bit double-precision
36 D = 0b01,
37
38 // H = 0b10, unused in the G extension
39
40 /// 128-bit quad-precision
41 Q = 0b11,
42};
43
44const AmoWidth = enum(u3) {
45 W = 0b010,
46 D = 0b011,
47};
48
49const FenceMode = enum(u4) {
50 none = 0b0000,
51 tso = 0b1000,
52};
53
54const Enc = struct {
55 opcode: OpCode,
56
57 data: union(enum) {
58 /// funct3 + funct7
59 ff: struct {
60 funct3: u3,
61 funct7: u7,
62 },
63 amo: struct {
64 funct5: u5,
65 width: AmoWidth,
66 },
67 fence: struct {
68 funct3: u3,
69 fm: FenceMode,
70 },
71 /// funct5 + rm + fmt
72 fmt: struct {
73 funct5: u5,
74 rm: u3,
75 fmt: FpFmt,
76 },
77 /// funct3
78 f: struct {
79 funct3: u3,
80 },
81 /// typ + funct3 + has_5
82 sh: struct {
83 typ: u6,
84 funct3: u3,
85 has_5: bool,
86 },
87 vecls: struct {
88 width: VecWidth,
89 umop: Umop,
90 vm: bool,
91 mop: Mop,
92 mew: bool,
93 nf: u3,
94 },
95 vecmath: struct {
96 vm: bool,
97 funct6: u6,
98 funct3: VecType,
99 },
100 /// U-type
101 none,
102 },
103
104 const Mop = enum(u2) {
105 unit = 0b00,
106 unord = 0b01,
107 stride = 0b10,
108 ord = 0b11,
109 };
110
111 const Umop = enum(u5) {
112 unit = 0b00000,
113 whole = 0b01000,
114 mask = 0b01011,
115 fault = 0b10000,
116 };
117
118 const VecWidth = enum(u3) {
119 // zig fmt: off
120 @"8" = 0b000,
121 @"16" = 0b101,
122 @"32" = 0b110,
123 @"64" = 0b111,
124 // zig fmt: on
125 };
126
127 const VecType = enum(u3) {
128 OPIVV = 0b000,
129 OPFVV = 0b001,
130 OPMVV = 0b010,
131 OPIVI = 0b011,
132 OPIVX = 0b100,
133 OPFVF = 0b101,
134 OPMVX = 0b110,
135 };
136};
137
138pub const Mnemonic = enum {
139 // base mnemonics
140
141 // I Type
142 ld,
143 lw,
144 lwu,
145 lh,
146 lhu,
147 lb,
148 lbu,
149
150 sltiu,
151 xori,
152 andi,
153
154 slli,
155 srli,
156 srai,
157
158 slliw,
159 srliw,
160 sraiw,
161
162 addi,
163 jalr,
164
165 vsetivli,
166 vsetvli,
167
168 // U Type
169 lui,
170 auipc,
171
172 // S Type
173 sd,
174 sw,
175 sh,
176 sb,
177
178 // J Type
179 jal,
180
181 // B Type
182 beq,
183
184 // R Type
185 add,
186 addw,
187 sub,
188 subw,
189 @"and",
190 @"or",
191 slt,
192 sltu,
193 xor,
194
195 sll,
196 srl,
197 sra,
198
199 sllw,
200 srlw,
201 sraw,
202
203 // System
204 ecall,
205 ebreak,
206 unimp,
207
208 csrrs,
209
210 // M extension
211 mul,
212 mulw,
213
214 mulh,
215 mulhu,
216 mulhsu,
217
218 div,
219 divu,
220
221 divw,
222 divuw,
223
224 rem,
225 remu,
226
227 remw,
228 remuw,
229
230 // F extension (32-bit float)
231 fadds,
232 fsubs,
233 fmuls,
234 fdivs,
235
236 fmins,
237 fmaxs,
238
239 fsqrts,
240
241 flw,
242 fsw,
243
244 feqs,
245 flts,
246 fles,
247
248 fsgnjns,
249 fsgnjxs,
250
251 // D extension (64-bit float)
252 faddd,
253 fsubd,
254 fmuld,
255 fdivd,
256
257 fmind,
258 fmaxd,
259
260 fsqrtd,
261
262 fld,
263 fsd,
264
265 feqd,
266 fltd,
267 fled,
268
269 fsgnjnd,
270 fsgnjxd,
271
272 // V Extension
273 vle8v,
274 vle16v,
275 vle32v,
276 vle64v,
277
278 vse8v,
279 vse16v,
280 vse32v,
281 vse64v,
282
283 vsoxei8v,
284
285 vaddvv,
286 vsubvv,
287
288 vfaddvv,
289 vfsubvv,
290
291 vadcvv,
292
293 vmvvx,
294
295 vslidedownvx,
296
297 // MISC
298 fence,
299 fencetso,
300
301 // AMO
302 amoswapw,
303 amoaddw,
304 amoandw,
305 amoorw,
306 amoxorw,
307 amomaxw,
308 amominw,
309 amomaxuw,
310 amominuw,
311
312 amoswapd,
313 amoaddd,
314 amoandd,
315 amoord,
316 amoxord,
317 amomaxd,
318 amomind,
319 amomaxud,
320 amominud,
321
322 // TODO: Q extension
323
324 pub fn encoding(mnem: Mnemonic) Enc {
325 return switch (mnem) {
326 // zig fmt: off
327
328 // OP
329
330 .add => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } },
331 .sub => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } },
332
333 .@"and" => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000000 } } },
334 .@"or" => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000000 } } },
335 .xor => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000000 } } },
336
337 .sltu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000000 } } },
338 .slt => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000000 } } },
339
340 .mul => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } },
341 .mulh => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000001 } } },
342 .mulhsu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000001 } } },
343 .mulhu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000001 } } },
344
345 .div => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000001 } } },
346 .divu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000001 } } },
347
348 .rem => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000001 } } },
349 .remu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000001 } } },
350
351 .sll => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } },
352 .srl => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000000 } } },
353 .sra => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0100000 } } },
354
355
356 // OP_IMM
357
358 .addi => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b000 } } },
359 .andi => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b111 } } },
360 .xori => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b100 } } },
361
362 .sltiu => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b011 } } },
363
364 .slli => .{ .opcode = .OP_IMM, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b001, .has_5 = true } } },
365 .srli => .{ .opcode = .OP_IMM, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b101, .has_5 = true } } },
366 .srai => .{ .opcode = .OP_IMM, .data = .{ .sh = .{ .typ = 0b010000, .funct3 = 0b101, .has_5 = true } } },
367
368
369 // OP_IMM_32
370
371 .slliw => .{ .opcode = .OP_IMM_32, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b001, .has_5 = false } } },
372 .srliw => .{ .opcode = .OP_IMM_32, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b101, .has_5 = false } } },
373 .sraiw => .{ .opcode = .OP_IMM_32, .data = .{ .sh = .{ .typ = 0b010000, .funct3 = 0b101, .has_5 = false } } },
374
375
376 // OP_32
377
378 .addw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } },
379 .subw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } },
380 .mulw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } },
381
382 .divw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000001 } } },
383 .divuw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000001 } } },
384
385 .remw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000001 } } },
386 .remuw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000001 } } },
387
388 .sllw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } },
389 .srlw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000000 } } },
390 .sraw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0100000 } } },
391
392
393 // OP_FP
394
395 .fadds => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .S, .rm = 0b111 } } },
396 .faddd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .D, .rm = 0b111 } } },
397
398 .fsubs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .S, .rm = 0b111 } } },
399 .fsubd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .D, .rm = 0b111 } } },
400
401 .fmuls => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .S, .rm = 0b111 } } },
402 .fmuld => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .D, .rm = 0b111 } } },
403
404 .fdivs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .S, .rm = 0b111 } } },
405 .fdivd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .D, .rm = 0b111 } } },
406
407 .fmins => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b000 } } },
408 .fmind => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b000 } } },
409
410 .fmaxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b001 } } },
411 .fmaxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b001 } } },
412
413 .fsqrts => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .S, .rm = 0b111 } } },
414 .fsqrtd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .D, .rm = 0b111 } } },
415
416 .fles => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b000 } } },
417 .fled => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b000 } } },
418
419 .flts => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b001 } } },
420 .fltd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b001 } } },
421
422 .feqs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b010 } } },
423 .feqd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b010 } } },
424
425 .fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } },
426 .fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } },
427
428 .fsgnjxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b0010} } },
429 .fsgnjxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b0010} } },
430
431
432 // LOAD
433
434 .lb => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b000 } } },
435 .lh => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b001 } } },
436 .lw => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b010 } } },
437 .ld => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b011 } } },
438 .lbu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b100 } } },
439 .lhu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b101 } } },
440 .lwu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b110 } } },
441
442
443 // STORE
444
445 .sb => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b000 } } },
446 .sh => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b001 } } },
447 .sw => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b010 } } },
448 .sd => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b011 } } },
449
450
451 // LOAD_FP
452
453 .flw => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },
454 .fld => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },
455
456 .vle8v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
457 .vle16v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"16", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
458 .vle32v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
459 .vle64v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
460
461
462 // STORE_FP
463
464 .fsw => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },
465 .fsd => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },
466
467 .vse8v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
468 .vse16v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"16", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
469 .vse32v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
470 .vse64v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
471
472 .vsoxei8v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .ord, .mew = false, .nf = 0b000 } } },
473
474 // JALR
475
476 .jalr => .{ .opcode = .JALR, .data = .{ .f = .{ .funct3 = 0b000 } } },
477
478
479 // LUI
480
481 .lui => .{ .opcode = .LUI, .data = .{ .none = {} } },
482
483
484 // AUIPC
485
486 .auipc => .{ .opcode = .AUIPC, .data = .{ .none = {} } },
487
488
489 // JAL
490
491 .jal => .{ .opcode = .JAL, .data = .{ .none = {} } },
492
493
494 // BRANCH
495
496 .beq => .{ .opcode = .BRANCH, .data = .{ .f = .{ .funct3 = 0b000 } } },
497
498
499 // SYSTEM
500
501 .ecall => .{ .opcode = .SYSTEM, .data = .{ .f = .{ .funct3 = 0b000 } } },
502 .ebreak => .{ .opcode = .SYSTEM, .data = .{ .f = .{ .funct3 = 0b000 } } },
503
504 .csrrs => .{ .opcode = .SYSTEM, .data = .{ .f = .{ .funct3 = 0b010 } } },
505
506
507 // NONE
508
509 .unimp => .{ .opcode = .NONE, .data = .{ .f = .{ .funct3 = 0b000 } } },
510
511
512 // MISC_MEM
513
514 .fence => .{ .opcode = .MISC_MEM, .data = .{ .fence = .{ .funct3 = 0b000, .fm = .none } } },
515 .fencetso => .{ .opcode = .MISC_MEM, .data = .{ .fence = .{ .funct3 = 0b000, .fm = .tso } } },
516
517
518 // AMO
519
520 .amoaddw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00000 } } },
521 .amoswapw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00001 } } },
522 // LR.W
523 // SC.W
524 .amoxorw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00100 } } },
525 .amoandw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b01100 } } },
526 .amoorw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b01000 } } },
527 .amominw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b10000 } } },
528 .amomaxw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b10100 } } },
529 .amominuw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b11000 } } },
530 .amomaxuw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b11100 } } },
531
532 .amoaddd => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00000 } } },
533 .amoswapd => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00001 } } },
534 // LR.D
535 // SC.D
536 .amoxord => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00100 } } },
537 .amoandd => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b01100 } } },
538 .amoord => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b01000 } } },
539 .amomind => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b10000 } } },
540 .amomaxd => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b10100 } } },
541 .amominud => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11000 } } },
542 .amomaxud => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11100 } } },
543
544 // OP_V
545 .vsetivli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } },
546 .vsetvli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } },
547 .vaddvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPIVV } } },
548 .vsubvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPIVV } } },
549
550 .vfaddvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPFVV } } },
551 .vfsubvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPFVV } } },
552
553 .vadcvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010000, .funct3 = .OPMVV } } },
554 .vmvvx => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010111, .funct3 = .OPIVX } } },
555
556 .vslidedownvx => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b001111, .funct3 = .OPIVX } } },
557
558 // zig fmt: on
559 };
560 }
561};
562
563pub const InstEnc = enum {
564 R,
565 R4,
566 I,
567 S,
568 B,
569 U,
570 J,
571 fence,
572 amo,
573 system,
574
575 pub fn fromMnemonic(mnem: Mnemonic) InstEnc {
576 return switch (mnem) {
577 .addi,
578 .jalr,
579 .sltiu,
580 .xori,
581 .andi,
582
583 .slli,
584 .srli,
585 .srai,
586
587 .slliw,
588 .srliw,
589 .sraiw,
590
591 .ld,
592 .lw,
593 .lwu,
594 .lh,
595 .lhu,
596 .lb,
597 .lbu,
598
599 .flw,
600 .fld,
601
602 .csrrs,
603 .vsetivli,
604 .vsetvli,
605 => .I,
606
607 .lui,
608 .auipc,
609 => .U,
610
611 .sd,
612 .sw,
613 .sh,
614 .sb,
615
616 .fsd,
617 .fsw,
618 => .S,
619
620 .jal,
621 => .J,
622
623 .beq,
624 => .B,
625
626 .slt,
627 .sltu,
628
629 .sll,
630 .srl,
631 .sra,
632
633 .sllw,
634 .srlw,
635 .sraw,
636
637 .div,
638 .divu,
639 .divw,
640 .divuw,
641
642 .rem,
643 .remu,
644 .remw,
645 .remuw,
646
647 .xor,
648 .@"and",
649 .@"or",
650
651 .add,
652 .addw,
653
654 .sub,
655 .subw,
656
657 .mul,
658 .mulw,
659 .mulh,
660 .mulhu,
661 .mulhsu,
662
663 .fadds,
664 .faddd,
665
666 .fsubs,
667 .fsubd,
668
669 .fmuls,
670 .fmuld,
671
672 .fdivs,
673 .fdivd,
674
675 .fmins,
676 .fmind,
677
678 .fmaxs,
679 .fmaxd,
680
681 .fsqrts,
682 .fsqrtd,
683
684 .fles,
685 .fled,
686
687 .flts,
688 .fltd,
689
690 .feqs,
691 .feqd,
692
693 .fsgnjns,
694 .fsgnjnd,
695
696 .fsgnjxs,
697 .fsgnjxd,
698
699 .vle8v,
700 .vle16v,
701 .vle32v,
702 .vle64v,
703
704 .vse8v,
705 .vse16v,
706 .vse32v,
707 .vse64v,
708
709 .vsoxei8v,
710
711 .vaddvv,
712 .vsubvv,
713 .vfaddvv,
714 .vfsubvv,
715 .vadcvv,
716 .vmvvx,
717 .vslidedownvx,
718 => .R,
719
720 .ecall,
721 .ebreak,
722 .unimp,
723 => .system,
724
725 .fence,
726 .fencetso,
727 => .fence,
728
729 .amoswapw,
730 .amoaddw,
731 .amoandw,
732 .amoorw,
733 .amoxorw,
734 .amomaxw,
735 .amominw,
736 .amomaxuw,
737 .amominuw,
738
739 .amoswapd,
740 .amoaddd,
741 .amoandd,
742 .amoord,
743 .amoxord,
744 .amomaxd,
745 .amomind,
746 .amomaxud,
747 .amominud,
748 => .amo,
749 };
750 }
751
752 pub fn opsList(enc: InstEnc) [5]std.meta.FieldEnum(Operand) {
753 return switch (enc) {
754 // zig fmt: off
755 .R => .{ .reg, .reg, .reg, .none, .none, },
756 .R4 => .{ .reg, .reg, .reg, .reg, .none, },
757 .I => .{ .reg, .reg, .imm, .none, .none, },
758 .S => .{ .reg, .reg, .imm, .none, .none, },
759 .B => .{ .reg, .reg, .imm, .none, .none, },
760 .U => .{ .reg, .imm, .none, .none, .none, },
761 .J => .{ .reg, .imm, .none, .none, .none, },
762 .system => .{ .none, .none, .none, .none, .none, },
763 .fence => .{ .barrier, .barrier, .none, .none, .none, },
764 .amo => .{ .reg, .reg, .reg, .barrier, .barrier },
765 // zig fmt: on
766 };
767 }
768};
769
770pub const Data = union(InstEnc) {
771 R: packed struct {
772 opcode: u7,
773 rd: u5,
774 funct3: u3,
775 rs1: u5,
776 rs2: u5,
777 funct7: u7,
778 },
779 R4: packed struct {
780 opcode: u7,
781 rd: u5,
782 funct3: u3,
783 rs1: u5,
784 rs2: u5,
785 funct2: u2,
786 rs3: u5,
787 },
788 I: packed struct {
789 opcode: u7,
790 rd: u5,
791 funct3: u3,
792 rs1: u5,
793 imm0_11: u12,
794 },
795 S: packed struct {
796 opcode: u7,
797 imm0_4: u5,
798 funct3: u3,
799 rs1: u5,
800 rs2: u5,
801 imm5_11: u7,
802 },
803 B: packed struct {
804 opcode: u7,
805 imm11: u1,
806 imm1_4: u4,
807 funct3: u3,
808 rs1: u5,
809 rs2: u5,
810 imm5_10: u6,
811 imm12: u1,
812 },
813 U: packed struct {
814 opcode: u7,
815 rd: u5,
816 imm12_31: u20,
817 },
818 J: packed struct {
819 opcode: u7,
820 rd: u5,
821 imm12_19: u8,
822 imm11: u1,
823 imm1_10: u10,
824 imm20: u1,
825 },
826 fence: packed struct {
827 opcode: u7,
828 rd: u5 = 0,
829 funct3: u3,
830 rs1: u5 = 0,
831 succ: u4,
832 pred: u4,
833 fm: u4,
834 },
835 amo: packed struct {
836 opcode: u7,
837 rd: u5,
838 funct3: u3,
839 rs1: u5,
840 rs2: u5,
841 rl: bool,
842 aq: bool,
843 funct5: u5,
844 },
845 system: u32,
846
847 comptime {
848 for (std.meta.fields(Data)) |field| {
849 assert(@bitSizeOf(field.type) == 32);
850 }
851 }
852
853 pub fn toU32(self: Data) u32 {
854 return switch (self) {
855 .fence => |v| @as(u32, @intCast(v.opcode)) + (@as(u32, @intCast(v.rd)) << 7) + (@as(u32, @intCast(v.funct3)) << 12) + (@as(u32, @intCast(v.rs1)) << 15) + (@as(u32, @intCast(v.succ)) << 20) + (@as(u32, @intCast(v.pred)) << 24) + (@as(u32, @intCast(v.fm)) << 28),
856 inline else => |v| @bitCast(v),
857 .system => unreachable,
858 };
859 }
860
861 pub fn construct(mnem: Mnemonic, ops: []const Operand) !Data {
862 const inst_enc = InstEnc.fromMnemonic(mnem);
863 const enc = mnem.encoding();
864
865 // special mnemonics
866 switch (mnem) {
867 .ecall,
868 .ebreak,
869 .unimp,
870 => {
871 assert(ops.len == 0);
872 return .{
873 .I = .{
874 .rd = Register.zero.encodeId(),
875 .rs1 = Register.zero.encodeId(),
876 .imm0_11 = switch (mnem) {
877 .ecall => 0x000,
878 .ebreak => 0x001,
879 .unimp => 0x000,
880 else => unreachable,
881 },
882
883 .opcode = @intFromEnum(enc.opcode),
884 .funct3 = enc.data.f.funct3,
885 },
886 };
887 },
888 .csrrs => {
889 assert(ops.len == 3);
890
891 const csr = ops[0].csr;
892 const rs1 = ops[1].reg;
893 const rd = ops[2].reg;
894
895 return .{
896 .I = .{
897 .rd = rd.encodeId(),
898 .rs1 = rs1.encodeId(),
899
900 .imm0_11 = @intFromEnum(csr),
901
902 .opcode = @intFromEnum(enc.opcode),
903 .funct3 = enc.data.f.funct3,
904 },
905 };
906 },
907 else => {},
908 }
909
910 switch (inst_enc) {
911 .R => {
912 assert(ops.len == 3);
913 return .{
914 .R = switch (enc.data) {
915 .ff => |ff| .{
916 .rd = ops[0].reg.encodeId(),
917 .rs1 = ops[1].reg.encodeId(),
918 .rs2 = ops[2].reg.encodeId(),
919
920 .opcode = @intFromEnum(enc.opcode),
921 .funct3 = ff.funct3,
922 .funct7 = ff.funct7,
923 },
924 .fmt => |fmt| .{
925 .rd = ops[0].reg.encodeId(),
926 .rs1 = ops[1].reg.encodeId(),
927 .rs2 = ops[2].reg.encodeId(),
928
929 .opcode = @intFromEnum(enc.opcode),
930 .funct3 = fmt.rm,
931 .funct7 = (@as(u7, fmt.funct5) << 2) | @intFromEnum(fmt.fmt),
932 },
933 .vecls => |vec| .{
934 .rd = ops[0].reg.encodeId(),
935 .rs1 = ops[1].reg.encodeId(),
936
937 .rs2 = @intFromEnum(vec.umop),
938
939 .opcode = @intFromEnum(enc.opcode),
940 .funct3 = @intFromEnum(vec.width),
941 .funct7 = (@as(u7, vec.nf) << 4) | (@as(u7, @intFromBool(vec.mew)) << 3) | (@as(u7, @intFromEnum(vec.mop)) << 1) | @intFromBool(vec.vm),
942 },
943 .vecmath => |vec| .{
944 .rd = ops[0].reg.encodeId(),
945 .rs1 = ops[1].reg.encodeId(),
946 .rs2 = ops[2].reg.encodeId(),
947
948 .opcode = @intFromEnum(enc.opcode),
949 .funct3 = @intFromEnum(vec.funct3),
950 .funct7 = (@as(u7, vec.funct6) << 1) | @intFromBool(vec.vm),
951 },
952 else => unreachable,
953 },
954 };
955 },
956 .S => {
957 assert(ops.len == 3);
958 const umm = ops[2].imm.asBits(u12);
959
960 return .{
961 .S = .{
962 .imm0_4 = @truncate(umm),
963 .rs1 = ops[0].reg.encodeId(),
964 .rs2 = ops[1].reg.encodeId(),
965 .imm5_11 = @truncate(umm >> 5),
966
967 .opcode = @intFromEnum(enc.opcode),
968 .funct3 = enc.data.f.funct3,
969 },
970 };
971 },
972 .I => {
973 assert(ops.len == 3);
974 return .{
975 .I = switch (enc.data) {
976 .f => |f| .{
977 .rd = ops[0].reg.encodeId(),
978 .rs1 = ops[1].reg.encodeId(),
979 .imm0_11 = ops[2].imm.asBits(u12),
980
981 .opcode = @intFromEnum(enc.opcode),
982 .funct3 = f.funct3,
983 },
984 .sh => |sh| .{
985 .rd = ops[0].reg.encodeId(),
986 .rs1 = ops[1].reg.encodeId(),
987 .imm0_11 = (@as(u12, sh.typ) << 6) |
988 if (sh.has_5) ops[2].imm.asBits(u6) else (@as(u6, 0) | ops[2].imm.asBits(u5)),
989
990 .opcode = @intFromEnum(enc.opcode),
991 .funct3 = sh.funct3,
992 },
993 else => unreachable,
994 },
995 };
996 },
997 .U => {
998 assert(ops.len == 2);
999 return .{
1000 .U = .{
1001 .rd = ops[0].reg.encodeId(),
1002 .imm12_31 = ops[1].imm.asBits(u20),
1003
1004 .opcode = @intFromEnum(enc.opcode),
1005 },
1006 };
1007 },
1008 .J => {
1009 assert(ops.len == 2);
1010
1011 const umm = ops[1].imm.asBits(u21);
1012 assert(umm % 4 == 0); // misaligned jump target
1013
1014 return .{
1015 .J = .{
1016 .rd = ops[0].reg.encodeId(),
1017 .imm1_10 = @truncate(umm >> 1),
1018 .imm11 = @truncate(umm >> 11),
1019 .imm12_19 = @truncate(umm >> 12),
1020 .imm20 = @truncate(umm >> 20),
1021
1022 .opcode = @intFromEnum(enc.opcode),
1023 },
1024 };
1025 },
1026 .B => {
1027 assert(ops.len == 3);
1028
1029 const umm = ops[2].imm.asBits(u13);
1030 assert(umm % 4 == 0); // misaligned branch target
1031
1032 return .{
1033 .B = .{
1034 .rs1 = ops[0].reg.encodeId(),
1035 .rs2 = ops[1].reg.encodeId(),
1036 .imm1_4 = @truncate(umm >> 1),
1037 .imm5_10 = @truncate(umm >> 5),
1038 .imm11 = @truncate(umm >> 11),
1039 .imm12 = @truncate(umm >> 12),
1040
1041 .opcode = @intFromEnum(enc.opcode),
1042 .funct3 = enc.data.f.funct3,
1043 },
1044 };
1045 },
1046 .fence => {
1047 assert(ops.len == 2);
1048
1049 const succ = ops[0].barrier;
1050 const pred = ops[1].barrier;
1051
1052 return .{
1053 .fence = .{
1054 .succ = @intFromEnum(succ),
1055 .pred = @intFromEnum(pred),
1056
1057 .opcode = @intFromEnum(enc.opcode),
1058 .funct3 = enc.data.fence.funct3,
1059 .fm = @intFromEnum(enc.data.fence.fm),
1060 },
1061 };
1062 },
1063 .amo => {
1064 assert(ops.len == 5);
1065
1066 const rd = ops[0].reg;
1067 const rs1 = ops[1].reg;
1068 const rs2 = ops[2].reg;
1069 const rl = ops[3].barrier;
1070 const aq = ops[4].barrier;
1071
1072 return .{
1073 .amo = .{
1074 .rd = rd.encodeId(),
1075 .rs1 = rs1.encodeId(),
1076 .rs2 = rs2.encodeId(),
1077
1078 // TODO: https://github.com/ziglang/zig/issues/20113
1079 .rl = if (rl == .rl) true else false,
1080 .aq = if (aq == .aq) true else false,
1081
1082 .opcode = @intFromEnum(enc.opcode),
1083 .funct3 = @intFromEnum(enc.data.amo.width),
1084 .funct5 = enc.data.amo.funct5,
1085 },
1086 };
1087 },
1088 else => std.debug.panic("TODO: construct {s}", .{@tagName(inst_enc)}),
1089 }
1090 }
1091};
1092
1093pub fn findByMnemonic(mnem: Mnemonic, ops: []const Operand) !?Encoding {
1094 if (!verifyOps(mnem, ops)) return null;
1095
1096 return .{
1097 .mnemonic = mnem,
1098 .data = try Data.construct(mnem, ops),
1099 };
1100}
1101
1102fn verifyOps(mnem: Mnemonic, ops: []const Operand) bool {
1103 const inst_enc = InstEnc.fromMnemonic(mnem);
1104 const list = std.mem.sliceTo(&inst_enc.opsList(), .none);
1105 for (list, ops) |l, o| if (l != std.meta.activeTag(o)) return false;
1106 return true;
1107}
1108
1109const std = @import("std");
1110const assert = std.debug.assert;
1111const log = std.log.scoped(.encoding);
1112
1113const Encoding = @This();
1114const bits = @import("bits.zig");
1115const Register = bits.Register;
1116const encoder = @import("encoder.zig");
1117const Instruction = encoder.Instruction;
1118const Operand = Instruction.Operand;
1119const OperandEnum = std.meta.FieldEnum(Operand);
src/arch/riscv64/Lower.zig+451-474
...@@ -34,6 +34,8 @@ pub const Reloc = struct {...@@ -34,6 +34,8 @@ pub const Reloc = struct {
3434
35 /// Relocs the lowered_inst_index and the next instruction.35 /// Relocs the lowered_inst_index and the next instruction.
36 load_symbol_reloc: bits.Symbol,36 load_symbol_reloc: bits.Symbol,
37 /// Relocs the lowered_inst_index and the next two instructions.
38 load_tlv_reloc: bits.Symbol,
37 /// Relocs the lowered_inst_index and the next instruction.39 /// Relocs the lowered_inst_index and the next instruction.
38 call_extern_fn_reloc: bits.Symbol,40 call_extern_fn_reloc: bits.Symbol,
39 };41 };
...@@ -61,453 +63,418 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {...@@ -61,453 +63,418 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
61 log.debug("lowerMir {}", .{inst});63 log.debug("lowerMir {}", .{inst});
62 switch (inst.tag) {64 switch (inst.tag) {
63 else => try lower.generic(inst),65 else => try lower.generic(inst),
64 .pseudo => switch (inst.ops) {66 .pseudo_dbg_line_column,
65 .pseudo_dbg_line_column,67 .pseudo_dbg_epilogue_begin,
66 .pseudo_dbg_epilogue_begin,68 .pseudo_dbg_prologue_end,
67 .pseudo_dbg_prologue_end,69 .pseudo_dead,
68 .pseudo_dead,70 => {},
69 => {},71
7072 .pseudo_load_rm, .pseudo_store_rm => {
71 .pseudo_load_rm, .pseudo_store_rm => {73 const rm = inst.data.rm;
72 const rm = inst.data.rm;74
7375 const frame_loc: Mir.FrameLoc = if (options.allow_frame_locs)
74 const frame_loc: Mir.FrameLoc = if (options.allow_frame_locs)76 rm.m.toFrameLoc(lower.mir)
75 rm.m.toFrameLoc(lower.mir)77 else
76 else78 .{ .base = .s0, .disp = 0 };
77 .{ .base = .s0, .disp = 0 };79
7880 switch (inst.tag) {
79 switch (inst.ops) {81 .pseudo_load_rm => {
80 .pseudo_load_rm => {82 const dest_reg = rm.r;
81 const dest_reg = rm.r;83 const dest_reg_class = dest_reg.class();
82 const dest_reg_class = dest_reg.class();84
8385 const src_size = rm.m.mod.size;
84 const src_size = rm.m.mod.size;86 const unsigned = rm.m.mod.unsigned;
85 const unsigned = rm.m.mod.unsigned;87
8688 const mnem: Mnemonic = switch (dest_reg_class) {
87 const tag: Encoding.Mnemonic = switch (dest_reg_class) {89 .int => switch (src_size) {
88 .int => switch (src_size) {90 .byte => if (unsigned) .lbu else .lb,
89 .byte => if (unsigned) .lbu else .lb,91 .hword => if (unsigned) .lhu else .lh,
90 .hword => if (unsigned) .lhu else .lh,92 .word => if (unsigned) .lwu else .lw,
91 .word => if (unsigned) .lwu else .lw,93 .dword => .ld,
92 .dword => .ld,
93 },
94 .float => switch (src_size) {
95 .byte => unreachable, // Zig does not support 8-bit floats
96 .hword => return lower.fail("TODO: lowerMir pseudo_load_rm support 16-bit floats", .{}),
97 .word => .flw,
98 .dword => .fld,
99 },
100 .vector => switch (src_size) {
101 .byte => .vle8v,
102 .hword => .vle32v,
103 .word => .vle32v,
104 .dword => .vle64v,
105 },
106 };
107
108 switch (dest_reg_class) {
109 .int, .float => {
110 try lower.emit(tag, &.{
111 .{ .reg = rm.r },
112 .{ .reg = frame_loc.base },
113 .{ .imm = Immediate.s(frame_loc.disp) },
114 });
115 },
116 .vector => {
117 assert(frame_loc.disp == 0);
118 try lower.emit(tag, &.{
119 .{ .reg = rm.r },
120 .{ .reg = frame_loc.base },
121 .{ .reg = .zero },
122 });
123 },
124 }
125 },
126 .pseudo_store_rm => {
127 const src_reg = rm.r;
128 const src_reg_class = src_reg.class();
129
130 const dest_size = rm.m.mod.size;
131
132 const tag: Encoding.Mnemonic = switch (src_reg_class) {
133 .int => switch (dest_size) {
134 .byte => .sb,
135 .hword => .sh,
136 .word => .sw,
137 .dword => .sd,
138 },
139 .float => switch (dest_size) {
140 .byte => unreachable, // Zig does not support 8-bit floats
141 .hword => return lower.fail("TODO: lowerMir pseudo_store_rm support 16-bit floats", .{}),
142 .word => .fsw,
143 .dword => .fsd,
144 },
145 .vector => switch (dest_size) {
146 .byte => .vse8v,
147 .hword => .vse16v,
148 .word => .vse32v,
149 .dword => .vse64v,
150 },
151 };
152
153 switch (src_reg_class) {
154 .int, .float => {
155 try lower.emit(tag, &.{
156 .{ .reg = frame_loc.base },
157 .{ .reg = rm.r },
158 .{ .imm = Immediate.s(frame_loc.disp) },
159 });
160 },
161 .vector => {
162 assert(frame_loc.disp == 0);
163 try lower.emit(tag, &.{
164 .{ .reg = rm.r },
165 .{ .reg = frame_loc.base },
166 .{ .reg = .zero },
167 });
168 },
169 }
170 },
171 else => unreachable,
172 }
173 },
174
175 .pseudo_mv => {
176 const rr = inst.data.rr;
177
178 const dst_class = rr.rd.class();
179 const src_class = rr.rs.class();
180
181 switch (src_class) {
182 .float => switch (dst_class) {
183 .float => {
184 try lower.emit(if (lower.hasFeature(.d)) .fsgnjnd else .fsgnjns, &.{
185 .{ .reg = rr.rd },
186 .{ .reg = rr.rs },
187 .{ .reg = rr.rs },
188 });
189 },94 },
190 .int, .vector => return lower.fail("TODO: lowerMir pseudo_mv float -> {s}", .{@tagName(dst_class)}),95 .float => switch (src_size) {
191 },96 .byte => unreachable, // Zig does not support 8-bit floats
192 .int => switch (dst_class) {97 .hword => return lower.fail("TODO: lowerMir pseudo_load_rm support 16-bit floats", .{}),
193 .int => {98 .word => .flw,
194 try lower.emit(.addi, &.{99 .dword => .fld,
195 .{ .reg = rr.rd },
196 .{ .reg = rr.rs },
197 .{ .imm = Immediate.s(0) },
198 });
199 },100 },
200 .vector => {101 .vector => switch (src_size) {
201 try lower.emit(.vmvvx, &.{102 .byte => .vle8v,
202 .{ .reg = rr.rd },103 .hword => .vle32v,
203 .{ .reg = rr.rs },104 .word => .vle32v,
204 .{ .reg = .x0 },105 .dword => .vle64v,
106 },
107 };
108
109 switch (dest_reg_class) {
110 .int, .float => {
111 try lower.emit(mnem, &.{
112 .{ .reg = rm.r },
113 .{ .reg = frame_loc.base },
114 .{ .imm = Immediate.s(frame_loc.disp) },
205 });115 });
206 },116 },
207 .float => return lower.fail("TODO: lowerMir pseudo_mv int -> {s}", .{@tagName(dst_class)}),117 .vector => {
208 },118 assert(frame_loc.disp == 0);
209 .vector => switch (dst_class) {119 try lower.emit(mnem, &.{
210 .int => {120 .{ .reg = rm.r },
211 try lower.emit(.vadcvv, &.{121 .{ .reg = frame_loc.base },
212 .{ .reg = rr.rd },
213 .{ .reg = .zero },122 .{ .reg = .zero },
214 .{ .reg = rr.rs },
215 });123 });
216 },124 },
217 .float, .vector => return lower.fail("TODO: lowerMir pseudo_mv vector -> {s}", .{@tagName(dst_class)}),125 }
218 },126 },
219 }127 .pseudo_store_rm => {
220 },128 const src_reg = rm.r;
221129 const src_reg_class = src_reg.class();
222 .pseudo_j => {130
223 try lower.emit(.jal, &.{131 const dest_size = rm.m.mod.size;
224 .{ .reg = .zero },132
225 .{ .imm = lower.reloc(.{ .inst = inst.data.inst }) },133 const mnem: Mnemonic = switch (src_reg_class) {
226 });134 .int => switch (dest_size) {
227 },135 .byte => .sb,
228136 .hword => .sh,
229 .pseudo_spill_regs => try lower.pushPopRegList(true, inst.data.reg_list),137 .word => .sw,
230 .pseudo_restore_regs => try lower.pushPopRegList(false, inst.data.reg_list),138 .dword => .sd,
231
232 .pseudo_load_symbol => {
233 const payload = inst.data.payload;
234 const data = lower.mir.extraData(Mir.LoadSymbolPayload, payload).data;
235 const dst_reg: bits.Register = @enumFromInt(data.register);
236 assert(dst_reg.class() == .int);
237
238 try lower.emit(.lui, &.{
239 .{ .reg = dst_reg },
240 .{ .imm = lower.reloc(.{
241 .load_symbol_reloc = .{
242 .atom_index = data.atom_index,
243 .sym_index = data.sym_index,
244 },139 },
245 }) },140 .float => switch (dest_size) {
246 });141 .byte => unreachable, // Zig does not support 8-bit floats
247142 .hword => return lower.fail("TODO: lowerMir pseudo_store_rm support 16-bit floats", .{}),
248 // the above reloc implies this one143 .word => .fsw,
249 try lower.emit(.addi, &.{144 .dword => .fsd,
250 .{ .reg = dst_reg },
251 .{ .reg = dst_reg },
252 .{ .imm = Immediate.s(0) },
253 });
254 },
255
256 .pseudo_lea_rm => {
257 const rm = inst.data.rm;
258 assert(rm.r.class() == .int);
259
260 const frame: Mir.FrameLoc = if (options.allow_frame_locs)
261 rm.m.toFrameLoc(lower.mir)
262 else
263 .{ .base = .s0, .disp = 0 };
264
265 try lower.emit(.addi, &.{
266 .{ .reg = rm.r },
267 .{ .reg = frame.base },
268 .{ .imm = Immediate.s(frame.disp) },
269 });
270 },
271
272 .pseudo_fabs => {
273 const fabs = inst.data.fabs;
274 assert(fabs.rs.class() == .float and fabs.rd.class() == .float);
275
276 const mnem: Encoding.Mnemonic = switch (fabs.bits) {
277 16 => return lower.fail("TODO: airAbs Float 16", .{}),
278 32 => .fsgnjxs,
279 64 => .fsgnjxd,
280 80 => return lower.fail("TODO: airAbs Float 80", .{}),
281 128 => return lower.fail("TODO: airAbs Float 128", .{}),
282 else => unreachable,
283 };
284
285 try lower.emit(mnem, &.{
286 .{ .reg = fabs.rs },
287 .{ .reg = fabs.rd },
288 .{ .reg = fabs.rd },
289 });
290 },
291
292 .pseudo_compare => {
293 const compare = inst.data.compare;
294 const op = compare.op;
295
296 const rd = compare.rd;
297 const rs1 = compare.rs1;
298 const rs2 = compare.rs2;
299
300 const class = rs1.class();
301 const ty = compare.ty;
302 const size = std.math.ceilPowerOfTwo(u64, ty.bitSize(pt)) catch {
303 return lower.fail("pseudo_compare size {}", .{ty.bitSize(pt)});
304 };
305
306 const is_unsigned = ty.isUnsignedInt(pt.zcu);
307
308 const less_than: Encoding.Mnemonic = if (is_unsigned) .sltu else .slt;
309
310 switch (class) {
311 .int => switch (op) {
312 .eq => {
313 try lower.emit(.xor, &.{
314 .{ .reg = rd },
315 .{ .reg = rs1 },
316 .{ .reg = rs2 },
317 });
318
319 try lower.emit(.sltiu, &.{
320 .{ .reg = rd },
321 .{ .reg = rd },
322 .{ .imm = Immediate.s(1) },
323 });
324 },145 },
325 .neq => {146 .vector => switch (dest_size) {
326 try lower.emit(.xor, &.{147 .byte => .vse8v,
327 .{ .reg = rd },148 .hword => .vse16v,
328 .{ .reg = rs1 },149 .word => .vse32v,
329 .{ .reg = rs2 },150 .dword => .vse64v,
330 });
331
332 try lower.emit(.sltu, &.{
333 .{ .reg = rd },
334 .{ .reg = .zero },
335 .{ .reg = rd },
336 });
337 },151 },
338 .gt => {152 };
339 try lower.emit(less_than, &.{153
340 .{ .reg = rd },154 switch (src_reg_class) {
341 .{ .reg = rs1 },155 .int, .float => {
342 .{ .reg = rs2 },156 try lower.emit(mnem, &.{
157 .{ .reg = frame_loc.base },
158 .{ .reg = rm.r },
159 .{ .imm = Immediate.s(frame_loc.disp) },
343 });160 });
344 },161 },
345 .gte => {162 .vector => {
346 try lower.emit(less_than, &.{163 assert(frame_loc.disp == 0);
347 .{ .reg = rd },164 try lower.emit(mnem, &.{
348 .{ .reg = rs1 },165 .{ .reg = rm.r },
349 .{ .reg = rs2 },166 .{ .reg = frame_loc.base },
350 });167 .{ .reg = .zero },
351
352 try lower.emit(.xori, &.{
353 .{ .reg = rd },
354 .{ .reg = rd },
355 .{ .imm = Immediate.s(1) },
356 });
357 },
358 .lt => {
359 try lower.emit(less_than, &.{
360 .{ .reg = rd },
361 .{ .reg = rs1 },
362 .{ .reg = rs2 },
363 });168 });
364 },169 },
365 .lte => {170 }
366 try lower.emit(less_than, &.{171 },
367 .{ .reg = rd },172 else => unreachable,
368 .{ .reg = rs2 },173 }
369 .{ .reg = rs1 },174 },
370 });
371175
372 try lower.emit(.xori, &.{176 .pseudo_mv => {
373 .{ .reg = rd },177 const rr = inst.data.rr;
374 .{ .reg = rd },178
375 .{ .imm = Immediate.s(1) },179 const dst_class = rr.rd.class();
376 });180 const src_class = rr.rs.class();
377 },181
182 switch (src_class) {
183 .float => switch (dst_class) {
184 .float => {
185 try lower.emit(if (lower.hasFeature(.d)) .fsgnjnd else .fsgnjns, &.{
186 .{ .reg = rr.rd },
187 .{ .reg = rr.rs },
188 .{ .reg = rr.rs },
189 });
378 },190 },
379 .float => switch (op) {191 .int, .vector => return lower.fail("TODO: lowerMir pseudo_mv float -> {s}", .{@tagName(dst_class)}),
380 // eq192 },
381 .eq => {193 .int => switch (dst_class) {
382 try lower.emit(if (size == 64) .feqd else .feqs, &.{194 .int => {
383 .{ .reg = rd },195 try lower.emit(.addi, &.{
384 .{ .reg = rs1 },196 .{ .reg = rr.rd },
385 .{ .reg = rs2 },197 .{ .reg = rr.rs },
386 });198 .{ .imm = Immediate.s(0) },
387 },199 });
388 // !(eq)200 },
389 .neq => {201 .vector => {
390 try lower.emit(if (size == 64) .feqd else .feqs, &.{202 try lower.emit(.vmvvx, &.{
391 .{ .reg = rd },203 .{ .reg = rr.rd },
392 .{ .reg = rs1 },204 .{ .reg = rr.rs },
393 .{ .reg = rs2 },205 .{ .reg = .x0 },
394 });206 });
395 try lower.emit(.xori, &.{207 },
396 .{ .reg = rd },208 .float => return lower.fail("TODO: lowerMir pseudo_mv int -> {s}", .{@tagName(dst_class)}),
397 .{ .reg = rd },209 },
398 .{ .imm = Immediate.s(1) },210 .vector => switch (dst_class) {
399 });211 .int => {
400 },212 try lower.emit(.vadcvv, &.{
401 .lt => {213 .{ .reg = rr.rd },
402 try lower.emit(if (size == 64) .fltd else .flts, &.{214 .{ .reg = .zero },
403 .{ .reg = rd },215 .{ .reg = rr.rs },
404 .{ .reg = rs1 },216 });
405 .{ .reg = rs2 },217 },
406 });218 .float, .vector => return lower.fail("TODO: lowerMir pseudo_mv vector -> {s}", .{@tagName(dst_class)}),
407 },219 },
408 .lte => {220 }
409 try lower.emit(if (size == 64) .fled else .fles, &.{221 },
410 .{ .reg = rd },222
411 .{ .reg = rs1 },223 .pseudo_j => {
412 .{ .reg = rs2 },224 const j_type = inst.data.j_type;
413 });225 try lower.emit(.jal, &.{
414 },226 .{ .reg = j_type.rd },
415 .gt => {227 .{ .imm = lower.reloc(.{ .inst = j_type.inst }) },
416 try lower.emit(if (size == 64) .fltd else .flts, &.{228 });
417 .{ .reg = rd },229 },
418 .{ .reg = rs2 },230
419 .{ .reg = rs1 },231 .pseudo_spill_regs => try lower.pushPopRegList(true, inst.data.reg_list),
420 });232 .pseudo_restore_regs => try lower.pushPopRegList(false, inst.data.reg_list),
421 },233
422 .gte => {234 .pseudo_load_symbol => {
423 try lower.emit(if (size == 64) .fled else .fles, &.{235 const payload = inst.data.reloc;
424 .{ .reg = rd },236 const dst_reg = payload.register;
425 .{ .reg = rs2 },237 assert(dst_reg.class() == .int);
426 .{ .reg = rs1 },238
427 });239 try lower.emit(.lui, &.{
428 },240 .{ .reg = dst_reg },
241 .{ .imm = lower.reloc(.{
242 .load_symbol_reloc = .{
243 .atom_index = payload.atom_index,
244 .sym_index = payload.sym_index,
245 },
246 }) },
247 });
248
249 // the reloc above implies this one
250 try lower.emit(.addi, &.{
251 .{ .reg = dst_reg },
252 .{ .reg = dst_reg },
253 .{ .imm = Immediate.s(0) },
254 });
255 },
256
257 .pseudo_load_tlv => {
258 const payload = inst.data.reloc;
259 const dst_reg = payload.register;
260 assert(dst_reg.class() == .int);
261
262 try lower.emit(.lui, &.{
263 .{ .reg = dst_reg },
264 .{ .imm = lower.reloc(.{
265 .load_tlv_reloc = .{
266 .atom_index = payload.atom_index,
267 .sym_index = payload.sym_index,
429 },268 },
430 .vector => return lower.fail("TODO: lowerMir pseudo_cmp vector", .{}),269 }) },
431 }270 });
432 },271
433272 try lower.emit(.add, &.{
434 .pseudo_not => {273 .{ .reg = dst_reg },
435 const rr = inst.data.rr;274 .{ .reg = dst_reg },
436 assert(rr.rs.class() == .int and rr.rd.class() == .int);275 .{ .reg = .tp },
437276 });
438 // mask out any other bits that aren't the boolean277
439 try lower.emit(.andi, &.{278 try lower.emit(.addi, &.{
440 .{ .reg = rr.rs },279 .{ .reg = dst_reg },
441 .{ .reg = rr.rs },280 .{ .reg = dst_reg },
442 .{ .imm = Immediate.s(1) },281 .{ .imm = Immediate.s(0) },
443 });282 });
444283 },
445 try lower.emit(.sltiu, &.{284
446 .{ .reg = rr.rd },285 .pseudo_lea_rm => {
447 .{ .reg = rr.rs },286 const rm = inst.data.rm;
448 .{ .imm = Immediate.s(1) },287 assert(rm.r.class() == .int);
449 });288
450 },289 const frame: Mir.FrameLoc = if (options.allow_frame_locs)
451290 rm.m.toFrameLoc(lower.mir)
452 .pseudo_extern_fn_reloc => {291 else
453 const inst_reloc = inst.data.reloc;292 .{ .base = .s0, .disp = 0 };
454293
455 try lower.emit(.auipc, &.{294 try lower.emit(.addi, &.{
456 .{ .reg = .ra },295 .{ .reg = rm.r },
457 .{ .imm = lower.reloc(296 .{ .reg = frame.base },
458 .{ .call_extern_fn_reloc = .{297 .{ .imm = Immediate.s(frame.disp) },
459 .atom_index = inst_reloc.atom_index,298 });
460 .sym_index = inst_reloc.sym_index,299 },
461 } },300
462 ) },301 .pseudo_compare => {
463 });302 const compare = inst.data.compare;
464303 const op = compare.op;
465 try lower.emit(.jalr, &.{304
466 .{ .reg = .ra },305 const rd = compare.rd;
467 .{ .reg = .ra },306 const rs1 = compare.rs1;
468 .{ .imm = Immediate.s(0) },307 const rs2 = compare.rs2;
469 });308
470 },309 const class = rs1.class();
471310 const ty = compare.ty;
472 .pseudo_amo => {311 const size = std.math.ceilPowerOfTwo(u64, ty.bitSize(pt)) catch {
473 const amo = inst.data.amo;312 return lower.fail("pseudo_compare size {}", .{ty.bitSize(pt)});
474 const is_d = amo.ty.abiSize(pt) == 8;313 };
475 const is_un = amo.ty.isUnsignedInt(pt.zcu);314
476315 const is_unsigned = ty.isUnsignedInt(pt.zcu);
477 const mnem: Encoding.Mnemonic = switch (amo.op) {316 const less_than: Mnemonic = if (is_unsigned) .sltu else .slt;
478 // zig fmt: off317
479 .SWAP => if (is_d) .amoswapd else .amoswapw,318 switch (class) {
480 .ADD => if (is_d) .amoaddd else .amoaddw,319 .int => switch (op) {
481 .AND => if (is_d) .amoandd else .amoandw,320 .eq => {
482 .OR => if (is_d) .amoord else .amoorw,321 try lower.emit(.xor, &.{
483 .XOR => if (is_d) .amoxord else .amoxorw,322 .{ .reg = rd },
484 .MAX => if (is_d) if (is_un) .amomaxud else .amomaxd else if (is_un) .amomaxuw else .amomaxw,323 .{ .reg = rs1 },
485 .MIN => if (is_d) if (is_un) .amominud else .amomind else if (is_un) .amominuw else .amominw,324 .{ .reg = rs2 },
486 // zig fmt: on325 });
487 };326
488327 try lower.emit(.sltiu, &.{
489 try lower.emit(mnem, &.{328 .{ .reg = rd },
490 .{ .reg = inst.data.amo.rd },329 .{ .reg = rd },
491 .{ .reg = inst.data.amo.rs1 },330 .{ .imm = Immediate.s(1) },
492 .{ .reg = inst.data.amo.rs2 },331 });
493 .{ .barrier = inst.data.amo.rl },332 },
494 .{ .barrier = inst.data.amo.aq },333 .neq => {
495 });334 try lower.emit(.xor, &.{
496 },335 .{ .reg = rd },
497336 .{ .reg = rs1 },
498 .pseudo_fence => {337 .{ .reg = rs2 },
499 const fence = inst.data.fence;338 });
500339
501 try lower.emit(switch (fence.fm) {340 try lower.emit(.sltu, &.{
502 .tso => .fencetso,341 .{ .reg = rd },
503 .none => .fence,342 .{ .reg = .zero },
504 }, &.{343 .{ .reg = rd },
505 .{ .barrier = fence.succ },344 });
506 .{ .barrier = fence.pred },345 },
507 });346 .gt => {
508 },347 try lower.emit(less_than, &.{
509348 .{ .reg = rd },
510 else => return lower.fail("TODO lower: psuedo {s}", .{@tagName(inst.ops)}),349 .{ .reg = rs2 },
350 .{ .reg = rs1 },
351 });
352 },
353 .gte => {
354 try lower.emit(less_than, &.{
355 .{ .reg = rd },
356 .{ .reg = rs1 },
357 .{ .reg = rs2 },
358 });
359 try lower.emit(.xori, &.{
360 .{ .reg = rd },
361 .{ .reg = rd },
362 .{ .imm = Immediate.s(1) },
363 });
364 },
365 .lt => {
366 try lower.emit(less_than, &.{
367 .{ .reg = rd },
368 .{ .reg = rs1 },
369 .{ .reg = rs2 },
370 });
371 },
372 .lte => {
373 try lower.emit(less_than, &.{
374 .{ .reg = rd },
375 .{ .reg = rs2 },
376 .{ .reg = rs1 },
377 });
378
379 try lower.emit(.xori, &.{
380 .{ .reg = rd },
381 .{ .reg = rd },
382 .{ .imm = Immediate.s(1) },
383 });
384 },
385 },
386 .float => switch (op) {
387 // eq
388 .eq => {
389 try lower.emit(if (size == 64) .feqd else .feqs, &.{
390 .{ .reg = rd },
391 .{ .reg = rs1 },
392 .{ .reg = rs2 },
393 });
394 },
395 // !(eq)
396 .neq => {
397 try lower.emit(if (size == 64) .feqd else .feqs, &.{
398 .{ .reg = rd },
399 .{ .reg = rs1 },
400 .{ .reg = rs2 },
401 });
402 try lower.emit(.xori, &.{
403 .{ .reg = rd },
404 .{ .reg = rd },
405 .{ .imm = Immediate.s(1) },
406 });
407 },
408 .lt => {
409 try lower.emit(if (size == 64) .fltd else .flts, &.{
410 .{ .reg = rd },
411 .{ .reg = rs1 },
412 .{ .reg = rs2 },
413 });
414 },
415 .lte => {
416 try lower.emit(if (size == 64) .fled else .fles, &.{
417 .{ .reg = rd },
418 .{ .reg = rs1 },
419 .{ .reg = rs2 },
420 });
421 },
422 .gt => {
423 try lower.emit(if (size == 64) .fltd else .flts, &.{
424 .{ .reg = rd },
425 .{ .reg = rs2 },
426 .{ .reg = rs1 },
427 });
428 },
429 .gte => {
430 try lower.emit(if (size == 64) .fled else .fles, &.{
431 .{ .reg = rd },
432 .{ .reg = rs2 },
433 .{ .reg = rs1 },
434 });
435 },
436 },
437 .vector => return lower.fail("TODO: lowerMir pseudo_cmp vector", .{}),
438 }
439 },
440
441 .pseudo_not => {
442 const rr = inst.data.rr;
443 assert(rr.rs.class() == .int and rr.rd.class() == .int);
444
445 // mask out any other bits that aren't the boolean
446 try lower.emit(.andi, &.{
447 .{ .reg = rr.rs },
448 .{ .reg = rr.rs },
449 .{ .imm = Immediate.s(1) },
450 });
451
452 try lower.emit(.sltiu, &.{
453 .{ .reg = rr.rd },
454 .{ .reg = rr.rs },
455 .{ .imm = Immediate.s(1) },
456 });
457 },
458
459 .pseudo_extern_fn_reloc => {
460 const inst_reloc = inst.data.reloc;
461 const link_reg = inst_reloc.register;
462
463 try lower.emit(.auipc, &.{
464 .{ .reg = link_reg },
465 .{ .imm = lower.reloc(
466 .{ .call_extern_fn_reloc = .{
467 .atom_index = inst_reloc.atom_index,
468 .sym_index = inst_reloc.sym_index,
469 } },
470 ) },
471 });
472
473 try lower.emit(.jalr, &.{
474 .{ .reg = link_reg },
475 .{ .reg = link_reg },
476 .{ .imm = Immediate.s(0) },
477 });
511 },478 },
512 }479 }
513480
...@@ -518,49 +485,57 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {...@@ -518,49 +485,57 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
518}485}
519486
520fn generic(lower: *Lower, inst: Mir.Inst) Error!void {487fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
521 const mnemonic = std.meta.stringToEnum(Encoding.Mnemonic, @tagName(inst.tag)) orelse {488 const mnemonic = inst.tag;
522 return lower.fail("generic inst name '{s}' with op {s} doesn't match with a mnemonic", .{489 try lower.emit(mnemonic, switch (inst.data) {
523 @tagName(inst.tag),
524 @tagName(inst.ops),
525 });
526 };
527 try lower.emit(mnemonic, switch (inst.ops) {
528 .none => &.{},490 .none => &.{},
529 .ri => &.{491 .u_type => |u| &.{
530 .{ .reg = inst.data.u_type.rd },492 .{ .reg = u.rd },
531 .{ .imm = inst.data.u_type.imm20 },493 .{ .imm = u.imm20 },
494 },
495 .i_type => |i| &.{
496 .{ .reg = i.rd },
497 .{ .reg = i.rs1 },
498 .{ .imm = i.imm12 },
499 },
500 .rr => |rr| &.{
501 .{ .reg = rr.rd },
502 .{ .reg = rr.rs },
532 },503 },
533 .rr => &.{504 .b_type => |b| &.{
534 .{ .reg = inst.data.rr.rd },505 .{ .reg = b.rs1 },
535 .{ .reg = inst.data.rr.rs },506 .{ .reg = b.rs2 },
507 .{ .imm = lower.reloc(.{ .inst = b.inst }) },
536 },508 },
537 .rri => &.{509 .r_type => |r| &.{
538 .{ .reg = inst.data.i_type.rd },510 .{ .reg = r.rd },
539 .{ .reg = inst.data.i_type.rs1 },511 .{ .reg = r.rs1 },
540 .{ .imm = inst.data.i_type.imm12 },512 .{ .reg = r.rs2 },
541 },513 },
542 .rr_inst => &.{514 .csr => |csr| &.{
543 .{ .reg = inst.data.b_type.rs1 },515 .{ .csr = csr.csr },
544 .{ .reg = inst.data.b_type.rs2 },516 .{ .reg = csr.rs1 },
545 .{ .imm = lower.reloc(.{ .inst = inst.data.b_type.inst }) },517 .{ .reg = csr.rd },
546 },518 },
547 .rrr => &.{519 .amo => |amo| &.{
548 .{ .reg = inst.data.r_type.rd },520 .{ .reg = amo.rd },
549 .{ .reg = inst.data.r_type.rs1 },521 .{ .reg = amo.rs1 },
550 .{ .reg = inst.data.r_type.rs2 },522 .{ .reg = amo.rs2 },
523 .{ .barrier = amo.rl },
524 .{ .barrier = amo.aq },
551 },525 },
552 .csr => &.{526 .fence => |fence| &.{
553 .{ .csr = inst.data.csr.csr },527 .{ .barrier = fence.succ },
554 .{ .reg = inst.data.csr.rs1 },528 .{ .barrier = fence.pred },
555 .{ .reg = inst.data.csr.rd },
556 },529 },
557 else => return lower.fail("TODO: generic lower ops {s}", .{@tagName(inst.ops)}),530 else => return lower.fail("TODO: generic lower {s}", .{@tagName(inst.data)}),
558 });531 });
559}532}
560533
561fn emit(lower: *Lower, mnemonic: Encoding.Mnemonic, ops: []const Instruction.Operand) !void {534fn emit(lower: *Lower, mnemonic: Mnemonic, ops: []const Instruction.Operand) !void {
562 lower.result_insts[lower.result_insts_len] =535 const lir = encoding.Lir.fromMnem(mnemonic);
563 try Instruction.new(mnemonic, ops);536 const inst = Instruction.fromLir(lir, ops);
537
538 lower.result_insts[lower.result_insts_len] = inst;
564 lower.result_insts_len += 1;539 lower.result_insts_len += 1;
565}540}
566541
...@@ -582,7 +557,7 @@ fn pushPopRegList(lower: *Lower, comptime spilling: bool, reg_list: Mir.Register...@@ -582,7 +557,7 @@ fn pushPopRegList(lower: *Lower, comptime spilling: bool, reg_list: Mir.Register
582 const reg = abi.Registers.all_preserved[i];557 const reg = abi.Registers.all_preserved[i];
583558
584 const reg_class = reg.class();559 const reg_class = reg.class();
585 const load_inst: Encoding.Mnemonic, const store_inst: Encoding.Mnemonic = switch (reg_class) {560 const load_inst: Mnemonic, const store_inst: Mnemonic = switch (reg_class) {
586 .int => .{ .ld, .sd },561 .int => .{ .ld, .sd },
587 .float => .{ .fld, .fsd },562 .float => .{ .fld, .fsd },
588 .vector => unreachable,563 .vector => unreachable,
...@@ -620,20 +595,22 @@ fn hasFeature(lower: *Lower, feature: std.Target.riscv.Feature) bool {...@@ -620,20 +595,22 @@ fn hasFeature(lower: *Lower, feature: std.Target.riscv.Feature) bool {
620}595}
621596
622const Lower = @This();597const Lower = @This();
623
624const abi = @import("abi.zig");
625const assert = std.debug.assert;
626const bits = @import("bits.zig");
627const encoder = @import("encoder.zig");
628const link = @import("../../link.zig");
629const Encoding = @import("Encoding.zig");
630const std = @import("std");598const std = @import("std");
599const assert = std.debug.assert;
631const log = std.log.scoped(.lower);600const log = std.log.scoped(.lower);
632601
633const Air = @import("../../Air.zig");
634const Allocator = std.mem.Allocator;602const Allocator = std.mem.Allocator;
635const ErrorMsg = Zcu.ErrorMsg;603const ErrorMsg = Zcu.ErrorMsg;
636const Mir = @import("Mir.zig");604
605const link = @import("../../link.zig");
606const Air = @import("../../Air.zig");
637const Zcu = @import("../../Zcu.zig");607const Zcu = @import("../../Zcu.zig");
638const Instruction = encoder.Instruction;608
609const Mir = @import("Mir.zig");
610const abi = @import("abi.zig");
611const bits = @import("bits.zig");
612const encoding = @import("encoding.zig");
613
614const Mnemonic = @import("mnem.zig").Mnemonic;
639const Immediate = bits.Immediate;615const Immediate = bits.Immediate;
616const Instruction = encoding.Instruction;
src/arch/riscv64/Mir.zig+19-281
...@@ -1,164 +1,17 @@...@@ -1,164 +1,17 @@
1//! Machine Intermediate Representation.1//! Machine Intermediate Representation.
2//! This data is produced by RISCV64 Codegen or RISCV64 assembly parsing2//! This data is produced by CodeGen.zig
3//! These instructions have a 1:1 correspondence with machine code instructions
4//! for the target. MIR can be lowered to source-annotated textual assembly code
5//! instructions, or it can be lowered to machine code.
6//! The main purpose of MIR is to postpone the assignment of offsets until Isel,
7//! so that, for example, the smaller encodings of jump instructions can be used.
83
9instructions: std.MultiArrayList(Inst).Slice,4instructions: std.MultiArrayList(Inst).Slice,
10/// The meaning of this data is determined by `Inst.Tag` value.
11extra: []const u32,
12frame_locs: std.MultiArrayList(FrameLoc).Slice,5frame_locs: std.MultiArrayList(FrameLoc).Slice,
136
14pub const Inst = struct {7pub const Inst = struct {
15 tag: Tag,8 tag: Mnemonic,
16 data: Data,9 data: Data,
17 ops: Ops,
1810
19 /// The position of an MIR instruction within the `Mir` instructions array.
20 pub const Index = u32;11 pub const Index = u32;
2112
22 pub const Tag = enum(u16) {13 pub const Data = union(enum) {
2314 none: void,
24 // base extension
25 addi,
26 addiw,
27
28 jalr,
29 lui,
30
31 @"and",
32 andi,
33
34 xori,
35 xor,
36 @"or",
37
38 ebreak,
39 ecall,
40 unimp,
41
42 add,
43 addw,
44 sub,
45 subw,
46
47 sltu,
48 slt,
49
50 slli,
51 srli,
52 srai,
53
54 slliw,
55 srliw,
56 sraiw,
57
58 sll,
59 srl,
60 sra,
61
62 sllw,
63 srlw,
64 sraw,
65
66 jal,
67
68 beq,
69 bne,
70
71 nop,
72
73 ld,
74 lw,
75 lh,
76 lb,
77
78 sd,
79 sw,
80 sh,
81 sb,
82
83 // M extension
84 mul,
85 mulw,
86
87 div,
88 divu,
89 divw,
90 divuw,
91
92 rem,
93 remu,
94 remw,
95 remuw,
96
97 // F extension (32-bit float)
98 fadds,
99 fsubs,
100 fmuls,
101 fdivs,
102
103 fabss,
104
105 fmins,
106 fmaxs,
107
108 fsqrts,
109
110 flw,
111 fsw,
112
113 feqs,
114 flts,
115 fles,
116
117 // D extension (64-bit float)
118 faddd,
119 fsubd,
120 fmuld,
121 fdivd,
122
123 fabsd,
124
125 fmind,
126 fmaxd,
127
128 fsqrtd,
129
130 fld,
131 fsd,
132
133 feqd,
134 fltd,
135 fled,
136
137 // Zicsr Extension Instructions
138 csrrs,
139
140 // V Extension Instructions
141 vsetvli,
142 vsetivli,
143 vsetvl,
144 vaddvv,
145 vfaddvv,
146 vsubvv,
147 vfsubvv,
148 vslidedownvx,
149
150 /// A pseudo-instruction. Used for anything that isn't 1:1 with an
151 /// assembly instruction.
152 pseudo,
153 };
154
155 /// All instructions have a 4-byte payload, which is contained within
156 /// this union. `Ops` determines which union field is active, as well as
157 /// how to interpret the data within.
158 pub const Data = union {
159 nop: void,
160 inst: Index,
161 payload: u32,
162 r_type: struct {15 r_type: struct {
163 rd: Register,16 rd: Register,
164 rs1: Register,17 rs1: Register,
...@@ -188,10 +41,6 @@ pub const Inst = struct {...@@ -188,10 +41,6 @@ pub const Inst = struct {
188 rd: Register,41 rd: Register,
189 inst: Inst.Index,42 inst: Inst.Index,
190 },43 },
191 pseudo_dbg_line_column: struct {
192 line: u32,
193 column: u32,
194 },
195 rm: struct {44 rm: struct {
196 r: Register,45 r: Register,
197 m: Memory,46 m: Memory,
...@@ -202,11 +51,6 @@ pub const Inst = struct {...@@ -202,11 +51,6 @@ pub const Inst = struct {
202 rd: Register,51 rd: Register,
203 rs: Register,52 rs: Register,
204 },53 },
205 fabs: struct {
206 rd: Register,
207 rs: Register,
208 bits: u16,
209 },
210 compare: struct {54 compare: struct {
211 rd: Register,55 rd: Register,
212 rs1: Register,56 rs1: Register,
...@@ -222,16 +66,13 @@ pub const Inst = struct {...@@ -222,16 +66,13 @@ pub const Inst = struct {
222 ty: Type,66 ty: Type,
223 },67 },
224 reloc: struct {68 reloc: struct {
69 register: Register,
225 atom_index: u32,70 atom_index: u32,
226 sym_index: u32,71 sym_index: u32,
227 },72 },
228 fence: struct {73 fence: struct {
229 pred: Barrier,74 pred: Barrier,
230 succ: Barrier,75 succ: Barrier,
231 fm: enum {
232 none,
233 tso,
234 },
235 },76 },
236 amo: struct {77 amo: struct {
237 rd: Register,78 rd: Register,
...@@ -239,123 +80,32 @@ pub const Inst = struct {...@@ -239,123 +80,32 @@ pub const Inst = struct {
239 rs2: Register,80 rs2: Register,
240 aq: Barrier,81 aq: Barrier,
241 rl: Barrier,82 rl: Barrier,
242 op: AmoOp,
243 ty: Type,
244 },83 },
245 csr: struct {84 csr: struct {
246 csr: CSR,85 csr: CSR,
247 rs1: Register,86 rs1: Register,
248 rd: Register,87 rd: Register,
249 },88 },
250 };89 pseudo_dbg_line_column: struct {
25190 line: u32,
252 pub const Ops = enum {91 column: u32,
253 /// No data associated with this instruction (only mnemonic is used).92 },
254 none,
255 /// Two registers
256 rr,
257 /// Three registers
258 rrr,
259
260 /// Two registers + immediate, uses the i_type payload.
261 rri,
262 //extern_fn_reloc/ Two registers + another instruction.
263 rr_inst,
264
265 /// Register + Memory
266 rm,
267
268 /// Register + Immediate
269 ri,
270
271 /// Another instruction.
272 inst,
273
274 /// Control and Status Register Instruction.
275 csr,
276
277 /// Pseudo-instruction that will generate a backpatched
278 /// function prologue.
279 pseudo_prologue,
280 /// Pseudo-instruction that will generate a backpatched
281 /// function epilogue
282 pseudo_epilogue,
283
284 /// Pseudo-instruction: End of prologue
285 pseudo_dbg_prologue_end,
286 /// Pseudo-instruction: Beginning of epilogue
287 pseudo_dbg_epilogue_begin,
288 /// Pseudo-instruction: Update debug line
289 pseudo_dbg_line_column,
290
291 /// Pseudo-instruction that loads from memory into a register.
292 ///
293 /// Uses `rm` payload.
294 pseudo_load_rm,
295 /// Pseudo-instruction that stores from a register into memory
296 ///
297 /// Uses `rm` payload.
298 pseudo_store_rm,
299
300 /// Pseudo-instruction that loads the address of memory into a register.
301 ///
302 /// Uses `rm` payload.
303 pseudo_lea_rm,
304
305 /// Jumps. Uses `inst` payload.
306 pseudo_j,
307
308 /// Floating point absolute value.
309 pseudo_fabs,
310
311 /// Dead inst, ignored by the emitter.
312 pseudo_dead,
313
314 /// Loads the address of a value that hasn't yet been allocated in memory.
315 ///
316 /// uses the Mir.LoadSymbolPayload payload.
317 pseudo_load_symbol,
318
319 /// Moves the value of rs1 to rd.
320 ///
321 /// uses the `rr` payload.
322 pseudo_mv,
323
324 pseudo_restore_regs,
325 pseudo_spill_regs,
326
327 pseudo_compare,
328
329 /// NOT operation on booleans. Does an `andi reg, reg, 1` to mask out any other bits from the boolean.
330 pseudo_not,
331
332 /// Generates an auipc + jalr pair, with a R_RISCV_CALL_PLT reloc
333 pseudo_extern_fn_reloc,
334
335 /// IORW, IORW
336 pseudo_fence,
337
338 /// Ordering, Src, Addr, Dest
339 pseudo_amo,
340 };93 };
34194
342 pub fn format(95 pub fn format(
343 inst: Inst,96 inst: Inst,
344 comptime fmt: []const u8,97 comptime fmt: []const u8,
345 options: std.fmt.FormatOptions,98 _: std.fmt.FormatOptions,
346 writer: anytype,99 writer: anytype,
347 ) !void {100 ) !void {
348 assert(fmt.len == 0);101 assert(fmt.len == 0);
349 _ = options;102 try writer.print("Tag: {s}, Data: {s}", .{ @tagName(inst.tag), @tagName(inst.data) });
350
351 try writer.print("Tag: {s}, Ops: {s}", .{ @tagName(inst.tag), @tagName(inst.ops) });
352 }103 }
353};104};
354105
355pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {106pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
356 mir.instructions.deinit(gpa);107 mir.instructions.deinit(gpa);
357 mir.frame_locs.deinit(gpa);108 mir.frame_locs.deinit(gpa);
358 gpa.free(mir.extra);
359 mir.* = undefined;109 mir.* = undefined;
360}110}
361111
...@@ -386,25 +136,12 @@ pub const AmoOp = enum(u5) {...@@ -386,25 +136,12 @@ pub const AmoOp = enum(u5) {
386 MIN,136 MIN,
387};137};
388138
389/// Returns the requested data, as well as the new index which is at the start of the139pub const FcvtOp = enum(u5) {
390/// trailers for the object.140 w = 0b00000,
391pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end: usize } {141 wu = 0b00001,
392 const fields = std.meta.fields(T);142 l = 0b00010,
393 var i: usize = index;143 lu = 0b00011,
394 var result: T = undefined;144};
395 inline for (fields) |field| {
396 @field(result, field.name) = switch (field.type) {
397 u32 => mir.extra[i],
398 i32 => @as(i32, @bitCast(mir.extra[i])),
399 else => @compileError("bad field type"),
400 };
401 i += 1;
402 }
403 return .{
404 .data = result,
405 .end = i,
406 };
407}
408145
409pub const LoadSymbolPayload = struct {146pub const LoadSymbolPayload = struct {
410 register: u32,147 register: u32,
...@@ -453,10 +190,10 @@ const Mir = @This();...@@ -453,10 +190,10 @@ const Mir = @This();
453const std = @import("std");190const std = @import("std");
454const builtin = @import("builtin");191const builtin = @import("builtin");
455const Type = @import("../../Type.zig");192const Type = @import("../../Type.zig");
193const bits = @import("bits.zig");
456194
457const assert = std.debug.assert;195const assert = std.debug.assert;
458196
459const bits = @import("bits.zig");
460const Register = bits.Register;197const Register = bits.Register;
461const CSR = bits.CSR;198const CSR = bits.CSR;
462const Immediate = bits.Immediate;199const Immediate = bits.Immediate;
...@@ -464,3 +201,4 @@ const Memory = bits.Memory;...@@ -464,3 +201,4 @@ const Memory = bits.Memory;
464const FrameIndex = bits.FrameIndex;201const FrameIndex = bits.FrameIndex;
465const FrameAddr = @import("CodeGen.zig").FrameAddr;202const FrameAddr = @import("CodeGen.zig").FrameAddr;
466const IntegerBitSet = std.bit_set.IntegerBitSet;203const IntegerBitSet = std.bit_set.IntegerBitSet;
204const Mnemonic = @import("mnem.zig").Mnemonic;
src/arch/riscv64/abi.zig+4-5
...@@ -125,10 +125,7 @@ pub fn classifySystem(ty: Type, pt: Zcu.PerThread) [8]SystemClass {...@@ -125,10 +125,7 @@ pub fn classifySystem(ty: Type, pt: Zcu.PerThread) [8]SystemClass {
125 result[0] = .integer;125 result[0] = .integer;
126 return result;126 return result;
127 }127 }
128 result[0] = .integer;128 return memory_class;
129 if (ty.optionalChild(zcu).abiSize(pt) == 0) return result;
130 result[1] = .integer;
131 return result;
132 },129 },
133 .Int, .Enum, .ErrorSet => {130 .Int, .Enum, .ErrorSet => {
134 const int_bits = ty.intInfo(pt.zcu).bits;131 const int_bits = ty.intInfo(pt.zcu).bits;
...@@ -167,7 +164,7 @@ pub fn classifySystem(ty: Type, pt: Zcu.PerThread) [8]SystemClass {...@@ -167,7 +164,7 @@ pub fn classifySystem(ty: Type, pt: Zcu.PerThread) [8]SystemClass {
167164
168 return memory_class;165 return memory_class;
169 },166 },
170 .Struct => {167 .Struct, .Union => {
171 const layout = ty.containerLayout(pt.zcu);168 const layout = ty.containerLayout(pt.zcu);
172 const ty_size = ty.abiSize(pt);169 const ty_size = ty.abiSize(pt);
173170
...@@ -200,6 +197,8 @@ pub fn classifySystem(ty: Type, pt: Zcu.PerThread) [8]SystemClass {...@@ -200,6 +197,8 @@ pub fn classifySystem(ty: Type, pt: Zcu.PerThread) [8]SystemClass {
200 result[0] = .integer;197 result[0] = .integer;
201 return result;198 return result;
202 }199 }
200 // we should pass vector registers of size <= 128 through 2 integer registers
201 // but we haven't implemented seperating vector registers into register_pairs
203 return memory_class;202 return memory_class;
204 },203 },
205 else => |bad_ty| std.debug.panic("classifySystem {s}", .{@tagName(bad_ty)}),204 else => |bad_ty| std.debug.panic("classifySystem {s}", .{@tagName(bad_ty)}),
src/arch/riscv64/bits.zig+2-6
...@@ -5,7 +5,6 @@ const testing = std.testing;...@@ -5,7 +5,6 @@ const testing = std.testing;
5const Target = std.Target;5const Target = std.Target;
66
7const Zcu = @import("../../Zcu.zig");7const Zcu = @import("../../Zcu.zig");
8const Encoding = @import("Encoding.zig");
9const Mir = @import("Mir.zig");8const Mir = @import("Mir.zig");
10const abi = @import("abi.zig");9const abi = @import("abi.zig");
1110
...@@ -16,7 +15,6 @@ pub const Memory = struct {...@@ -16,7 +15,6 @@ pub const Memory = struct {
16 pub const Base = union(enum) {15 pub const Base = union(enum) {
17 reg: Register,16 reg: Register,
18 frame: FrameIndex,17 frame: FrameIndex,
19 reloc: Symbol,
20 };18 };
2119
22 pub const Mod = struct {20 pub const Mod = struct {
...@@ -83,7 +81,6 @@ pub const Memory = struct {...@@ -83,7 +81,6 @@ pub const Memory = struct {
83 .disp = base_loc.disp + offset,81 .disp = base_loc.disp + offset,
84 };82 };
85 },83 },
86 .reloc => unreachable,
87 }84 }
88 }85 }
89};86};
...@@ -193,7 +190,7 @@ pub const Register = enum(u8) {...@@ -193,7 +190,7 @@ pub const Register = enum(u8) {
193 /// The goal of this function is to return the same ID for `zero` and `x0` but two190 /// The goal of this function is to return the same ID for `zero` and `x0` but two
194 /// seperate IDs for `x0` and `f0`. We will assume that each register set has 32 registers191 /// seperate IDs for `x0` and `f0`. We will assume that each register set has 32 registers
195 /// and is repeated twice, once for the named version, once for the number version.192 /// and is repeated twice, once for the named version, once for the number version.
196 pub fn id(reg: Register) u8 {193 pub fn id(reg: Register) std.math.IntFittingRange(0, @typeInfo(Register).Enum.fields.len) {
197 const base = switch (@intFromEnum(reg)) {194 const base = switch (@intFromEnum(reg)) {
198 // zig fmt: off195 // zig fmt: off
199 @intFromEnum(Register.zero) ... @intFromEnum(Register.x31) => @intFromEnum(Register.zero),196 @intFromEnum(Register.zero) ... @intFromEnum(Register.x31) => @intFromEnum(Register.zero),
...@@ -251,8 +248,7 @@ pub const FrameIndex = enum(u32) {...@@ -251,8 +248,7 @@ pub const FrameIndex = enum(u32) {
251 /// This index referes to a frame dedicated to setting up args for function called248 /// This index referes to a frame dedicated to setting up args for function called
252 /// in this function. Useful for aligning args separately.249 /// in this function. Useful for aligning args separately.
253 call_frame,250 call_frame,
254 /// This index referes to the frame where callee saved registers are spilled and restore251 /// This index referes to the frame where callee saved registers are spilled and restored from.
255 /// from.
256 spill_frame,252 spill_frame,
257 /// Other indices are used for local variable stack slots253 /// Other indices are used for local variable stack slots
258 _,254 _,
src/arch/riscv64/encoder.zig deleted-80
...@@ -1,80 +0,0 @@
1pub const Instruction = struct {
2 encoding: Encoding,
3 ops: [5]Operand = .{.none} ** 5,
4
5 pub const Operand = union(enum) {
6 none,
7 reg: Register,
8 csr: CSR,
9 mem: Memory,
10 imm: Immediate,
11 barrier: Mir.Barrier,
12 };
13
14 pub fn new(mnemonic: Encoding.Mnemonic, ops: []const Operand) !Instruction {
15 const encoding = (try Encoding.findByMnemonic(mnemonic, ops)) orelse {
16 std.log.err("no encoding found for: {s} [{s} {s} {s} {s} {s}]", .{
17 @tagName(mnemonic),
18 @tagName(if (ops.len > 0) ops[0] else .none),
19 @tagName(if (ops.len > 1) ops[1] else .none),
20 @tagName(if (ops.len > 2) ops[2] else .none),
21 @tagName(if (ops.len > 3) ops[3] else .none),
22 @tagName(if (ops.len > 4) ops[4] else .none),
23 });
24 return error.InvalidInstruction;
25 };
26
27 var result_ops: [5]Operand = .{.none} ** 5;
28 @memcpy(result_ops[0..ops.len], ops);
29
30 return .{
31 .encoding = encoding,
32 .ops = result_ops,
33 };
34 }
35
36 pub fn encode(inst: Instruction, writer: anytype) !void {
37 try writer.writeInt(u32, inst.encoding.data.toU32(), .little);
38 }
39
40 pub fn format(
41 inst: Instruction,
42 comptime fmt: []const u8,
43 _: std.fmt.FormatOptions,
44 writer: anytype,
45 ) !void {
46 std.debug.assert(fmt.len == 0);
47
48 const encoding = inst.encoding;
49
50 try writer.print("{s} ", .{@tagName(encoding.mnemonic)});
51
52 var i: u32 = 0;
53 while (i < inst.ops.len and inst.ops[i] != .none) : (i += 1) {
54 if (i != inst.ops.len and i != 0) try writer.writeAll(", ");
55
56 switch (@as(Instruction.Operand, inst.ops[i])) {
57 .none => unreachable, // it's sliced out above
58 .reg => |reg| try writer.writeAll(@tagName(reg)),
59 .imm => |imm| try writer.print("{d}", .{imm.asSigned(64)}),
60 .mem => try writer.writeAll("mem"),
61 .barrier => |barrier| try writer.writeAll(@tagName(barrier)),
62 .csr => |csr| try writer.writeAll(@tagName(csr)),
63 }
64 }
65 }
66};
67
68const std = @import("std");
69
70const Lower = @import("Lower.zig");
71const Mir = @import("Mir.zig");
72const bits = @import("bits.zig");
73const Encoding = @import("Encoding.zig");
74
75const Register = bits.Register;
76const CSR = bits.CSR;
77const Memory = bits.Memory;
78const Immediate = bits.Immediate;
79
80const log = std.log.scoped(.encode);
src/arch/riscv64/encoding.zig created+729
...@@ -0,0 +1,729 @@
1//! This file is responsible for going from MIR, which is emitted by CodeGen
2//! and converting it into Instructions, which can be used as needed.
3//!
4//! Here we encode how mnemonics relate to opcodes and where their operands go.
5
6/// Lower Instruction Representation
7///
8/// This format encodes a specific instruction, however it's still abstracted
9/// away from the true encoding it'll be in. It's meant to make the process of
10/// indicating unique encoding data easier.
11pub const Lir = struct {
12 opcode: OpCode,
13 format: Format,
14 data: Data,
15
16 pub const Format = enum {
17 R,
18 I,
19 S,
20 B,
21 U,
22 J,
23 extra,
24 };
25
26 const Data = union(enum) {
27 none,
28 f: struct { funct3: u3 },
29 ff: struct {
30 funct3: u3,
31 funct7: u7,
32 },
33 sh: struct {
34 typ: u6,
35 funct3: u3,
36 has_5: bool,
37 },
38
39 fmt: struct {
40 funct5: u5,
41 rm: u3,
42 fmt: FpFmt,
43 },
44 fcvt: struct {
45 funct5: u5,
46 rm: u3,
47 fmt: FpFmt,
48 width: Mir.FcvtOp,
49 },
50
51 vecls: struct {
52 width: VecWidth,
53 umop: Umop,
54 vm: bool,
55 mop: Mop,
56 mew: bool,
57 nf: u3,
58 },
59 vecmath: struct {
60 vm: bool,
61 funct6: u6,
62 funct3: VecType,
63 },
64
65 amo: struct {
66 funct5: u5,
67 width: AmoWidth,
68 },
69 fence: struct {
70 funct3: u3,
71 fm: FenceMode,
72 },
73
74 /// the mnemonic has some special properities that can't be handled in a generic fashion
75 extra: Mnemonic,
76 };
77
78 const OpCode = enum(u7) {
79 LOAD = 0b0000011,
80 LOAD_FP = 0b0000111,
81 MISC_MEM = 0b0001111,
82 OP_IMM = 0b0010011,
83 AUIPC = 0b0010111,
84 OP_IMM_32 = 0b0011011,
85 STORE = 0b0100011,
86 STORE_FP = 0b0100111,
87 AMO = 0b0101111,
88 OP_V = 0b1010111,
89 OP = 0b0110011,
90 OP_32 = 0b0111011,
91 LUI = 0b0110111,
92 MADD = 0b1000011,
93 MSUB = 0b1000111,
94 NMSUB = 0b1001011,
95 NMADD = 0b1001111,
96 OP_FP = 0b1010011,
97 OP_IMM_64 = 0b1011011,
98 BRANCH = 0b1100011,
99 JALR = 0b1100111,
100 JAL = 0b1101111,
101 SYSTEM = 0b1110011,
102 OP_64 = 0b1111011,
103 NONE = 0b00000000,
104 };
105
106 const FpFmt = enum(u2) {
107 /// 32-bit single-precision
108 S = 0b00,
109 /// 64-bit double-precision
110 D = 0b01,
111
112 // H = 0b10, unused in the G extension
113
114 /// 128-bit quad-precision
115 Q = 0b11,
116 };
117
118 const AmoWidth = enum(u3) {
119 W = 0b010,
120 D = 0b011,
121 };
122
123 const FenceMode = enum(u4) {
124 none = 0b0000,
125 tso = 0b1000,
126 };
127
128 const Mop = enum(u2) {
129 // zig fmt: off
130 unit = 0b00,
131 unord = 0b01,
132 stride = 0b10,
133 ord = 0b11,
134 // zig fmt: on
135 };
136
137 const Umop = enum(u5) {
138 // zig fmt: off
139 unit = 0b00000,
140 whole = 0b01000,
141 mask = 0b01011,
142 fault = 0b10000,
143 // zig fmt: on
144 };
145
146 const VecWidth = enum(u3) {
147 // zig fmt: off
148 @"8" = 0b000,
149 @"16" = 0b101,
150 @"32" = 0b110,
151 @"64" = 0b111,
152 // zig fmt: on
153 };
154
155 const VecType = enum(u3) {
156 OPIVV = 0b000,
157 OPFVV = 0b001,
158 OPMVV = 0b010,
159 OPIVI = 0b011,
160 OPIVX = 0b100,
161 OPFVF = 0b101,
162 OPMVX = 0b110,
163 };
164
165 pub fn fromMnem(mnem: Mnemonic) Lir {
166 return switch (mnem) {
167 // zig fmt: off
168
169 // OP
170 .add => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } },
171 .sub => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } },
172
173 .@"and" => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000000 } } },
174 .@"or" => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000000 } } },
175 .xor => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000000 } } },
176
177 .sltu => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000000 } } },
178 .slt => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000000 } } },
179
180 .mul => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } },
181 .mulh => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000001 } } },
182 .mulhsu => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000001 } } },
183 .mulhu => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000001 } } },
184
185 .div => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000001 } } },
186 .divu => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000001 } } },
187
188 .rem => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000001 } } },
189 .remu => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000001 } } },
190
191 .sll => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } },
192 .srl => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000000 } } },
193 .sra => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0100000 } } },
194
195
196 // OP_IMM
197
198 .addi => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } },
199 .andi => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .f = .{ .funct3 = 0b111 } } },
200 .xori => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .f = .{ .funct3 = 0b100 } } },
201
202 .sltiu => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .f = .{ .funct3 = 0b011 } } },
203
204 .slli => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b001, .has_5 = true } } },
205 .srli => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b101, .has_5 = true } } },
206 .srai => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .sh = .{ .typ = 0b010000, .funct3 = 0b101, .has_5 = true } } },
207
208 .clz => .{ .opcode = .OP_IMM, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0110000 } } },
209 .cpop => .{ .opcode = .OP_IMM, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0110000 } } },
210
211 // OP_IMM_32
212
213 .slliw => .{ .opcode = .OP_IMM_32, .format = .I, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b001, .has_5 = false } } },
214 .srliw => .{ .opcode = .OP_IMM_32, .format = .I, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b101, .has_5 = false } } },
215 .sraiw => .{ .opcode = .OP_IMM_32, .format = .I, .data = .{ .sh = .{ .typ = 0b010000, .funct3 = 0b101, .has_5 = false } } },
216
217 .clzw => .{ .opcode = .OP_IMM_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0110000 } } },
218 .cpopw => .{ .opcode = .OP_IMM_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0110000 } } },
219
220 // OP_32
221
222 .addw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } },
223 .subw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } },
224 .mulw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } },
225
226 .divw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000001 } } },
227 .divuw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000001 } } },
228
229 .remw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000001 } } },
230 .remuw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000001 } } },
231
232 .sllw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } },
233 .srlw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000000 } } },
234 .sraw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0100000 } } },
235
236
237 // OP_FP
238
239 .fadds => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .S, .rm = 0b111 } } },
240 .faddd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .D, .rm = 0b111 } } },
241
242 .fsubs => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .S, .rm = 0b111 } } },
243 .fsubd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .D, .rm = 0b111 } } },
244
245 .fmuls => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .S, .rm = 0b111 } } },
246 .fmuld => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .D, .rm = 0b111 } } },
247
248 .fdivs => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .S, .rm = 0b111 } } },
249 .fdivd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .D, .rm = 0b111 } } },
250
251 .fmins => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b000 } } },
252 .fmind => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b000 } } },
253
254 .fmaxs => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b001 } } },
255 .fmaxd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b001 } } },
256
257 .fsqrts => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .S, .rm = 0b111 } } },
258 .fsqrtd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .D, .rm = 0b111 } } },
259
260 .fles => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b000 } } },
261 .fled => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b000 } } },
262
263 .flts => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b001 } } },
264 .fltd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b001 } } },
265
266 .feqs => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b010 } } },
267 .feqd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b010 } } },
268
269 .fsgnjns => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } },
270 .fsgnjnd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } },
271
272 .fsgnjxs => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b010 } } },
273 .fsgnjxd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b010 } } },
274
275 .fcvtws => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .S, .rm = 0b111, .width = .w } } },
276 .fcvtwus => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .S, .rm = 0b111, .width = .wu } } },
277 .fcvtls => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .S, .rm = 0b111, .width = .l } } },
278 .fcvtlus => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .S, .rm = 0b111, .width = .lu } } },
279
280 .fcvtwd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .w } } },
281 .fcvtwud => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .wu } } },
282 .fcvtld => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .l } } },
283 .fcvtlud => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .lu } } },
284
285 .fcvtsw => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .w } } },
286 .fcvtswu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .wu } } },
287 .fcvtsl => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .l } } },
288 .fcvtslu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .lu } } },
289
290 .fcvtdw => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .w } } },
291 .fcvtdwu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .wu } } },
292 .fcvtdl => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .l } } },
293 .fcvtdlu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .lu } } },
294
295 // LOAD
296
297 .lb => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } },
298 .lh => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b001 } } },
299 .lw => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b010 } } },
300 .ld => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b011 } } },
301 .lbu => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b100 } } },
302 .lhu => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b101 } } },
303 .lwu => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b110 } } },
304
305
306 // STORE
307
308 .sb => .{ .opcode = .STORE, .format = .S, .data = .{ .f = .{ .funct3 = 0b000 } } },
309 .sh => .{ .opcode = .STORE, .format = .S, .data = .{ .f = .{ .funct3 = 0b001 } } },
310 .sw => .{ .opcode = .STORE, .format = .S, .data = .{ .f = .{ .funct3 = 0b010 } } },
311 .sd => .{ .opcode = .STORE, .format = .S, .data = .{ .f = .{ .funct3 = 0b011 } } },
312
313
314 // LOAD_FP
315
316 .flw => .{ .opcode = .LOAD_FP, .format = .I, .data = .{ .f = .{ .funct3 = 0b010 } } },
317 .fld => .{ .opcode = .LOAD_FP, .format = .I, .data = .{ .f = .{ .funct3 = 0b011 } } },
318
319 .vle8v => .{ .opcode = .LOAD_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
320 .vle16v => .{ .opcode = .LOAD_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"16", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
321 .vle32v => .{ .opcode = .LOAD_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
322 .vle64v => .{ .opcode = .LOAD_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
323
324
325 // STORE_FP
326
327 .fsw => .{ .opcode = .STORE_FP, .format = .S, .data = .{ .f = .{ .funct3 = 0b010 } } },
328 .fsd => .{ .opcode = .STORE_FP, .format = .S, .data = .{ .f = .{ .funct3 = 0b011 } } },
329
330 .vse8v => .{ .opcode = .STORE_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
331 .vse16v => .{ .opcode = .STORE_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"16", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
332 .vse32v => .{ .opcode = .STORE_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
333 .vse64v => .{ .opcode = .STORE_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
334
335 // JALR
336
337 .jalr => .{ .opcode = .JALR, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } },
338
339
340 // LUI
341
342 .lui => .{ .opcode = .LUI, .format = .U, .data = .{ .none = {} } },
343
344
345 // AUIPC
346
347 .auipc => .{ .opcode = .AUIPC, .format = .U, .data = .{ .none = {} } },
348
349
350 // JAL
351
352 .jal => .{ .opcode = .JAL, .format = .J, .data = .{ .none = {} } },
353
354
355 // BRANCH
356
357 .beq => .{ .opcode = .BRANCH, .format = .B, .data = .{ .f = .{ .funct3 = 0b000 } } },
358 .bne => .{ .opcode = .BRANCH, .format = .B, .data = .{ .f = .{ .funct3 = 0b001 } } },
359
360
361 // SYSTEM
362
363 .ecall => .{ .opcode = .SYSTEM, .format = .extra, .data = .{ .extra = .ecall } },
364 .ebreak => .{ .opcode = .SYSTEM, .format = .extra, .data = .{ .extra = .ebreak } },
365
366 .csrrs => .{ .opcode = .SYSTEM, .format = .I, .data = .{ .f = .{ .funct3 = 0b010 } } },
367
368
369 // NONE
370
371 .unimp => .{ .opcode = .NONE, .format = .extra, .data = .{ .extra = .unimp } },
372
373
374 // MISC_MEM
375
376 .fence => .{ .opcode = .MISC_MEM, .format = .I, .data = .{ .fence = .{ .funct3 = 0b000, .fm = .none } } },
377 .fencetso => .{ .opcode = .MISC_MEM, .format = .I, .data = .{ .fence = .{ .funct3 = 0b000, .fm = .tso } } },
378
379
380 // AMO
381
382 .amoaddw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00000 } } },
383 .amoswapw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00001 } } },
384 .lrw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00010 } } },
385 .scw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00011 } } },
386 .amoxorw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00100 } } },
387 .amoandw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b01100 } } },
388 .amoorw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b01000 } } },
389 .amominw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b10000 } } },
390 .amomaxw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b10100 } } },
391 .amominuw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b11000 } } },
392 .amomaxuw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b11100 } } },
393
394
395 .amoaddd => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00000 } } },
396 .amoswapd => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00001 } } },
397 .lrd => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00010 } } },
398 .scd => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00011 } } },
399 .amoxord => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00100 } } },
400 .amoandd => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b01100 } } },
401 .amoord => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b01000 } } },
402 .amomind => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b10000 } } },
403 .amomaxd => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b10100 } } },
404 .amominud => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11000 } } },
405 .amomaxud => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11100 } } },
406
407 // OP_V
408 .vsetivli => .{ .opcode = .OP_V, .format = .I, .data = .{ .f = .{ .funct3 = 0b111 } } },
409 .vsetvli => .{ .opcode = .OP_V, .format = .I, .data = .{ .f = .{ .funct3 = 0b111 } } },
410 .vaddvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPIVV } } },
411 .vsubvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPIVV } } },
412 .vmulvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b100101, .funct3 = .OPIVV } } },
413
414 .vfaddvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPFVV } } },
415 .vfsubvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPFVV } } },
416 .vfmulvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b100100, .funct3 = .OPFVV } } },
417
418 .vadcvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010000, .funct3 = .OPMVV } } },
419 .vmvvx => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010111, .funct3 = .OPIVX } } },
420
421 .vslidedownvx => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b001111, .funct3 = .OPIVX } } },
422
423
424 .pseudo_prologue,
425 .pseudo_epilogue,
426 .pseudo_dbg_prologue_end,
427 .pseudo_dbg_epilogue_begin,
428 .pseudo_dbg_line_column,
429 .pseudo_load_rm,
430 .pseudo_store_rm,
431 .pseudo_lea_rm,
432 .pseudo_j,
433 .pseudo_dead,
434 .pseudo_load_symbol,
435 .pseudo_load_tlv,
436 .pseudo_mv,
437 .pseudo_restore_regs,
438 .pseudo_spill_regs,
439 .pseudo_compare,
440 .pseudo_not,
441 .pseudo_extern_fn_reloc,
442 .nop,
443 => std.debug.panic("lir: didn't catch pseudo {s}", .{@tagName(mnem)}),
444 // zig fmt: on
445 };
446 }
447};
448
449/// This is the final form of the instruction. Lir is transformed into
450/// this, which is then bitcast into a u32.
451pub const Instruction = union(Lir.Format) {
452 R: packed struct(u32) {
453 opcode: u7,
454 rd: u5,
455 funct3: u3,
456 rs1: u5,
457 rs2: u5,
458 funct7: u7,
459 },
460 I: packed struct(u32) {
461 opcode: u7,
462 rd: u5,
463 funct3: u3,
464 rs1: u5,
465 imm0_11: u12,
466 },
467 S: packed struct(u32) {
468 opcode: u7,
469 imm0_4: u5,
470 funct3: u3,
471 rs1: u5,
472 rs2: u5,
473 imm5_11: u7,
474 },
475 B: packed struct(u32) {
476 opcode: u7,
477 imm11: u1,
478 imm1_4: u4,
479 funct3: u3,
480 rs1: u5,
481 rs2: u5,
482 imm5_10: u6,
483 imm12: u1,
484 },
485 U: packed struct(u32) {
486 opcode: u7,
487 rd: u5,
488 imm12_31: u20,
489 },
490 J: packed struct(u32) {
491 opcode: u7,
492 rd: u5,
493 imm12_19: u8,
494 imm11: u1,
495 imm1_10: u10,
496 imm20: u1,
497 },
498 extra: u32,
499
500 comptime {
501 for (std.meta.fields(Instruction)) |field| {
502 assert(@bitSizeOf(field.type) == 32);
503 }
504 }
505
506 pub const Operand = union(enum) {
507 none,
508 reg: Register,
509 csr: CSR,
510 mem: Memory,
511 imm: Immediate,
512 barrier: Mir.Barrier,
513 };
514
515 pub fn toU32(inst: Instruction) u32 {
516 return switch (inst) {
517 inline else => |v| @bitCast(v),
518 };
519 }
520
521 pub fn encode(inst: Instruction, writer: anytype) !void {
522 try writer.writeInt(u32, inst.toU32(), .little);
523 }
524
525 pub fn fromLir(lir: Lir, ops: []const Operand) Instruction {
526 const opcode: u7 = @intFromEnum(lir.opcode);
527
528 switch (lir.format) {
529 .R => {
530 return .{
531 .R = switch (lir.data) {
532 .ff => |ff| .{
533 .rd = ops[0].reg.encodeId(),
534 .rs1 = ops[1].reg.encodeId(),
535 .rs2 = ops[2].reg.encodeId(),
536
537 .opcode = opcode,
538 .funct3 = ff.funct3,
539 .funct7 = ff.funct7,
540 },
541 .fmt => |fmt| .{
542 .rd = ops[0].reg.encodeId(),
543 .rs1 = ops[1].reg.encodeId(),
544 .rs2 = ops[2].reg.encodeId(),
545
546 .opcode = opcode,
547 .funct3 = fmt.rm,
548 .funct7 = (@as(u7, fmt.funct5) << 2) | @intFromEnum(fmt.fmt),
549 },
550 .fcvt => |fcvt| .{
551 .rd = ops[0].reg.encodeId(),
552 .rs1 = ops[1].reg.encodeId(),
553 .rs2 = @intFromEnum(fcvt.width),
554
555 .opcode = opcode,
556 .funct3 = fcvt.rm,
557 .funct7 = (@as(u7, fcvt.funct5) << 2) | @intFromEnum(fcvt.fmt),
558 },
559 .vecls => |vec| .{
560 .rd = ops[0].reg.encodeId(),
561 .rs1 = ops[1].reg.encodeId(),
562
563 .rs2 = @intFromEnum(vec.umop),
564
565 .opcode = opcode,
566 .funct3 = @intFromEnum(vec.width),
567 .funct7 = (@as(u7, vec.nf) << 4) | (@as(u7, @intFromBool(vec.mew)) << 3) | (@as(u7, @intFromEnum(vec.mop)) << 1) | @intFromBool(vec.vm),
568 },
569 .vecmath => |vec| .{
570 .rd = ops[0].reg.encodeId(),
571 .rs1 = ops[1].reg.encodeId(),
572 .rs2 = ops[2].reg.encodeId(),
573
574 .opcode = opcode,
575 .funct3 = @intFromEnum(vec.funct3),
576 .funct7 = (@as(u7, vec.funct6) << 1) | @intFromBool(vec.vm),
577 },
578 .amo => |amo| .{
579 .rd = ops[0].reg.encodeId(),
580 .rs1 = ops[1].reg.encodeId(),
581 .rs2 = ops[2].reg.encodeId(),
582
583 .opcode = opcode,
584 .funct3 = @intFromEnum(amo.width),
585 .funct7 = @as(u7, amo.funct5) << 2 |
586 @as(u7, @intFromBool(ops[3].barrier == .rl)) << 1 |
587 @as(u7, @intFromBool(ops[4].barrier == .aq)),
588 },
589 else => unreachable,
590 },
591 };
592 },
593 .S => {
594 assert(ops.len == 3);
595 const umm = ops[2].imm.asBits(u12);
596 return .{
597 .S = .{
598 .imm0_4 = @truncate(umm),
599 .rs1 = ops[0].reg.encodeId(),
600 .rs2 = ops[1].reg.encodeId(),
601 .imm5_11 = @truncate(umm >> 5),
602
603 .opcode = opcode,
604 .funct3 = lir.data.f.funct3,
605 },
606 };
607 },
608 .I => {
609 return .{
610 .I = switch (lir.data) {
611 .f => |f| .{
612 .rd = ops[0].reg.encodeId(),
613 .rs1 = ops[1].reg.encodeId(),
614 .imm0_11 = ops[2].imm.asBits(u12),
615
616 .opcode = opcode,
617 .funct3 = f.funct3,
618 },
619 .sh => |sh| .{
620 .rd = ops[0].reg.encodeId(),
621 .rs1 = ops[1].reg.encodeId(),
622 .imm0_11 = (@as(u12, sh.typ) << 6) |
623 if (sh.has_5) ops[2].imm.asBits(u6) else (@as(u6, 0) | ops[2].imm.asBits(u5)),
624
625 .opcode = opcode,
626 .funct3 = sh.funct3,
627 },
628 .fence => |fence| .{
629 .rd = 0,
630 .rs1 = 0,
631 .funct3 = 0,
632 .imm0_11 = (@as(u12, @intFromEnum(fence.fm)) << 8) |
633 (@as(u12, @intFromEnum(ops[1].barrier)) << 4) |
634 @as(u12, @intFromEnum(ops[0].barrier)),
635 .opcode = opcode,
636 },
637 else => unreachable,
638 },
639 };
640 },
641 .U => {
642 assert(ops.len == 2);
643 return .{
644 .U = .{
645 .rd = ops[0].reg.encodeId(),
646 .imm12_31 = ops[1].imm.asBits(u20),
647
648 .opcode = opcode,
649 },
650 };
651 },
652 .J => {
653 assert(ops.len == 2);
654
655 const umm = ops[1].imm.asBits(u21);
656 // the RISC-V spec says the target index of a jump
657 // must be a multiple of 2
658 assert(umm % 2 == 0);
659
660 return .{
661 .J = .{
662 .rd = ops[0].reg.encodeId(),
663 .imm1_10 = @truncate(umm >> 1),
664 .imm11 = @truncate(umm >> 11),
665 .imm12_19 = @truncate(umm >> 12),
666 .imm20 = @truncate(umm >> 20),
667
668 .opcode = opcode,
669 },
670 };
671 },
672 .B => {
673 assert(ops.len == 3);
674
675 const umm = ops[2].imm.asBits(u13);
676 // the RISC-V spec says the target index of a branch
677 // must be a multiple of 2
678 assert(umm % 2 == 0);
679
680 return .{
681 .B = .{
682 .rs1 = ops[0].reg.encodeId(),
683 .rs2 = ops[1].reg.encodeId(),
684 .imm1_4 = @truncate(umm >> 1),
685 .imm5_10 = @truncate(umm >> 5),
686 .imm11 = @truncate(umm >> 11),
687 .imm12 = @truncate(umm >> 12),
688
689 .opcode = opcode,
690 .funct3 = lir.data.f.funct3,
691 },
692 };
693 },
694 .extra => {
695 assert(ops.len == 0);
696
697 return .{
698 .I = .{
699 .rd = Register.zero.encodeId(),
700 .rs1 = Register.zero.encodeId(),
701 .imm0_11 = switch (lir.data.extra) {
702 .ecall => 0x000,
703 .ebreak => 0x001,
704 .unimp => 0x000,
705 else => unreachable,
706 },
707
708 .opcode = opcode,
709 .funct3 = 0b000,
710 },
711 };
712 },
713 }
714 }
715};
716
717const std = @import("std");
718const assert = std.debug.assert;
719const log = std.log.scoped(.format);
720
721const bits = @import("bits.zig");
722const Mir = @import("Mir.zig");
723const Mnemonic = @import("mnem.zig").Mnemonic;
724const Lower = @import("Lower.zig");
725
726const Register = bits.Register;
727const CSR = bits.CSR;
728const Memory = bits.Memory;
729const Immediate = bits.Immediate;
src/arch/riscv64/mnem.zig created+257
...@@ -0,0 +1,257 @@
1pub const Mnemonic = enum(u16) {
2 // Arithmetics
3 addi,
4 add,
5 addw,
6
7 sub,
8 subw,
9
10 // Bits
11 xori,
12 xor,
13 @"or",
14
15 @"and",
16 andi,
17
18 slt,
19 sltu,
20 sltiu,
21
22 slli,
23 srli,
24 srai,
25
26 slliw,
27 srliw,
28 sraiw,
29
30 sll,
31 srl,
32 sra,
33
34 sllw,
35 srlw,
36 sraw,
37
38 // Control Flow
39 jalr,
40 jal,
41
42 beq,
43 bne,
44
45 // Memory
46 lui,
47 auipc,
48
49 ld,
50 lw,
51 lh,
52 lb,
53 lbu,
54 lhu,
55 lwu,
56
57 sd,
58 sw,
59 sh,
60 sb,
61
62 // System
63 ebreak,
64 ecall,
65 unimp,
66 nop,
67
68 // M extension
69 mul,
70 mulh,
71 mulhu,
72 mulhsu,
73 mulw,
74
75 div,
76 divu,
77 divw,
78 divuw,
79
80 rem,
81 remu,
82 remw,
83 remuw,
84
85 // F extension (32-bit float)
86 fadds,
87 fsubs,
88 fmuls,
89 fdivs,
90
91 fmins,
92 fmaxs,
93
94 fsqrts,
95
96 flw,
97 fsw,
98
99 feqs,
100 flts,
101 fles,
102
103 // D extension (64-bit float)
104 faddd,
105 fsubd,
106 fmuld,
107 fdivd,
108
109 fmind,
110 fmaxd,
111
112 fsqrtd,
113
114 fld,
115 fsd,
116
117 feqd,
118 fltd,
119 fled,
120
121 fcvtws,
122 fcvtwus,
123 fcvtls,
124 fcvtlus,
125
126 fcvtwd,
127 fcvtwud,
128 fcvtld,
129 fcvtlud,
130
131 fcvtsw,
132 fcvtswu,
133 fcvtsl,
134 fcvtslu,
135
136 fcvtdw,
137 fcvtdwu,
138 fcvtdl,
139 fcvtdlu,
140
141 fsgnjns,
142 fsgnjnd,
143
144 fsgnjxs,
145 fsgnjxd,
146
147 // Zicsr Extension Instructions
148 csrrs,
149
150 // V Extension Instructions
151 vsetvli,
152 vsetivli,
153 vaddvv,
154 vfaddvv,
155 vsubvv,
156 vfsubvv,
157 vmulvv,
158 vfmulvv,
159 vslidedownvx,
160
161 vle8v,
162 vle16v,
163 vle32v,
164 vle64v,
165
166 vse8v,
167 vse16v,
168 vse32v,
169 vse64v,
170
171 vadcvv,
172 vmvvx,
173
174 // Zbb Extension Instructions
175 clz,
176 clzw,
177 cpop,
178 cpopw,
179
180 // A Extension Instructions
181 fence,
182 fencetso,
183
184 lrw,
185 scw,
186 amoswapw,
187 amoaddw,
188 amoandw,
189 amoorw,
190 amoxorw,
191 amomaxw,
192 amominw,
193 amomaxuw,
194 amominuw,
195
196 lrd,
197 scd,
198 amoswapd,
199 amoaddd,
200 amoandd,
201 amoord,
202 amoxord,
203 amomaxd,
204 amomind,
205 amomaxud,
206 amominud,
207
208 // Pseudo-instructions. Used for anything that isn't 1:1 with an
209 // assembly instruction.
210
211 /// Pseudo-instruction that will generate a backpatched
212 /// function prologue.
213 pseudo_prologue,
214 /// Pseudo-instruction that will generate a backpatched
215 /// function epilogue
216 pseudo_epilogue,
217
218 /// Pseudo-instruction: End of prologue
219 pseudo_dbg_prologue_end,
220 /// Pseudo-instruction: Beginning of epilogue
221 pseudo_dbg_epilogue_begin,
222 /// Pseudo-instruction: Update debug line
223 pseudo_dbg_line_column,
224
225 /// Pseudo-instruction that loads from memory into a register.
226 pseudo_load_rm,
227 /// Pseudo-instruction that stores from a register into memory
228 pseudo_store_rm,
229 /// Pseudo-instruction that loads the address of memory into a register.
230 pseudo_lea_rm,
231 /// Jumps. Uses `inst` payload.
232 pseudo_j,
233 /// Dead inst, ignored by the emitter.
234 pseudo_dead,
235 /// Loads the address of a value that hasn't yet been allocated in memory.
236 pseudo_load_symbol,
237 /// Loads the address of a TLV.
238 pseudo_load_tlv,
239
240 /// Moves the value of rs1 to rd.
241 pseudo_mv,
242
243 pseudo_restore_regs,
244 pseudo_spill_regs,
245
246 pseudo_compare,
247 pseudo_not,
248 pseudo_extern_fn_reloc,
249};
250
251pub const Pseudo = enum(u8) {
252 li,
253 mv,
254 tail,
255 beqz,
256 ret,
257};
src/codegen.zig+3-1
...@@ -106,7 +106,9 @@ pub fn generateLazyFunction(...@@ -106,7 +106,9 @@ pub fn generateLazyFunction(
106 const target = namespace.fileScope(zcu).mod.resolved_target.result;106 const target = namespace.fileScope(zcu).mod.resolved_target.result;
107 switch (target_util.zigBackend(target, false)) {107 switch (target_util.zigBackend(target, false)) {
108 else => unreachable,108 else => unreachable,
109 inline .stage2_x86_64 => |backend| {109 inline .stage2_x86_64,
110 .stage2_riscv64,
111 => |backend| {
110 dev.check(devFeatureForBackend(backend));112 dev.check(devFeatureForBackend(backend));
111 return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output);113 return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output);
112 },114 },
src/link/riscv.zig+7-33
...@@ -25,47 +25,27 @@ pub fn writeAddend(...@@ -25,47 +25,27 @@ pub fn writeAddend(
25}25}
2626
27pub fn writeInstU(code: *[4]u8, value: u32) void {27pub fn writeInstU(code: *[4]u8, value: u32) void {
28 var data = Encoding.Data{28 var data: Instruction = .{ .U = mem.bytesToValue(std.meta.TagPayload(Instruction, .U), code) };
29 .U = mem.bytesToValue(std.meta.TagPayload(
30 Encoding.Data,
31 Encoding.Data.U,
32 ), code),
33 };
34 const compensated: u32 = @bitCast(@as(i32, @bitCast(value)) + 0x800);29 const compensated: u32 = @bitCast(@as(i32, @bitCast(value)) + 0x800);
35 data.U.imm12_31 = bitSlice(compensated, 31, 12);30 data.U.imm12_31 = bitSlice(compensated, 31, 12);
36 mem.writeInt(u32, code, data.toU32(), .little);31 mem.writeInt(u32, code, data.toU32(), .little);
37}32}
3833
39pub fn writeInstI(code: *[4]u8, value: u32) void {34pub fn writeInstI(code: *[4]u8, value: u32) void {
40 var data = Encoding.Data{35 var data: Instruction = .{ .I = mem.bytesToValue(std.meta.TagPayload(Instruction, .I), code) };
41 .I = mem.bytesToValue(std.meta.TagPayload(
42 Encoding.Data,
43 Encoding.Data.I,
44 ), code),
45 };
46 data.I.imm0_11 = bitSlice(value, 11, 0);36 data.I.imm0_11 = bitSlice(value, 11, 0);
47 mem.writeInt(u32, code, data.toU32(), .little);37 mem.writeInt(u32, code, data.toU32(), .little);
48}38}
4939
50pub fn writeInstS(code: *[4]u8, value: u32) void {40pub fn writeInstS(code: *[4]u8, value: u32) void {
51 var data = Encoding.Data{41 var data: Instruction = .{ .S = mem.bytesToValue(std.meta.TagPayload(Instruction, .S), code) };
52 .S = mem.bytesToValue(std.meta.TagPayload(
53 Encoding.Data,
54 Encoding.Data.S,
55 ), code),
56 };
57 data.S.imm0_4 = bitSlice(value, 4, 0);42 data.S.imm0_4 = bitSlice(value, 4, 0);
58 data.S.imm5_11 = bitSlice(value, 11, 5);43 data.S.imm5_11 = bitSlice(value, 11, 5);
59 mem.writeInt(u32, code, data.toU32(), .little);44 mem.writeInt(u32, code, data.toU32(), .little);
60}45}
6146
62pub fn writeInstJ(code: *[4]u8, value: u32) void {47pub fn writeInstJ(code: *[4]u8, value: u32) void {
63 var data = Encoding.Data{48 var data: Instruction = .{ .J = mem.bytesToValue(std.meta.TagPayload(Instruction, .J), code) };
64 .J = mem.bytesToValue(std.meta.TagPayload(
65 Encoding.Data,
66 Encoding.Data.J,
67 ), code),
68 };
69 data.J.imm1_10 = bitSlice(value, 10, 1);49 data.J.imm1_10 = bitSlice(value, 10, 1);
70 data.J.imm11 = bitSlice(value, 11, 11);50 data.J.imm11 = bitSlice(value, 11, 11);
71 data.J.imm12_19 = bitSlice(value, 19, 12);51 data.J.imm12_19 = bitSlice(value, 19, 12);
...@@ -74,12 +54,7 @@ pub fn writeInstJ(code: *[4]u8, value: u32) void {...@@ -74,12 +54,7 @@ pub fn writeInstJ(code: *[4]u8, value: u32) void {
74}54}
7555
76pub fn writeInstB(code: *[4]u8, value: u32) void {56pub fn writeInstB(code: *[4]u8, value: u32) void {
77 var data = Encoding.Data{57 var data: Instruction = .{ .B = mem.bytesToValue(std.meta.TagPayload(Instruction, .B), code) };
78 .B = mem.bytesToValue(std.meta.TagPayload(
79 Encoding.Data,
80 Encoding.Data.B,
81 ), code),
82 };
83 data.B.imm1_4 = bitSlice(value, 4, 1);58 data.B.imm1_4 = bitSlice(value, 4, 1);
84 data.B.imm5_10 = bitSlice(value, 10, 5);59 data.B.imm5_10 = bitSlice(value, 10, 5);
85 data.B.imm11 = bitSlice(value, 11, 11);60 data.B.imm11 = bitSlice(value, 11, 11);
...@@ -109,9 +84,8 @@ pub const RiscvEflags = packed struct(u32) {...@@ -109,9 +84,8 @@ pub const RiscvEflags = packed struct(u32) {
109 _unused: u8,84 _unused: u8,
110};85};
11186
112const encoder = @import("../arch/riscv64/encoder.zig");
113const Encoding = @import("../arch/riscv64/Encoding.zig");
114const mem = std.mem;87const mem = std.mem;
115const std = @import("std");88const std = @import("std");
11689
117pub const Instruction = encoder.Instruction;90const encoding = @import("../arch/riscv64/encoding.zig");
91const Instruction = encoding.Instruction;
test/behavior/abs.zig+1
...@@ -6,6 +6,7 @@ test "@abs integers" {...@@ -6,6 +6,7 @@ test "@abs integers" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
910
10 try comptime testAbsIntegers();11 try comptime testAbsIntegers();
11 try testAbsIntegers();12 try testAbsIntegers();
test/behavior/align.zig-3
...@@ -16,7 +16,6 @@ test "global variable alignment" {...@@ -16,7 +16,6 @@ test "global variable alignment" {
16}16}
1717
18test "large alignment of local constant" {18test "large alignment of local constant" {
19 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;20 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky21 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky
...@@ -26,7 +25,6 @@ test "large alignment of local constant" {...@@ -26,7 +25,6 @@ test "large alignment of local constant" {
26}25}
2726
28test "slicing array of length 1 can not assume runtime index is always zero" {27test "slicing array of length 1 can not assume runtime index is always zero" {
29 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky30 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky
...@@ -511,7 +509,6 @@ test "read 128-bit field from default aligned struct in global memory" {...@@ -511,7 +509,6 @@ test "read 128-bit field from default aligned struct in global memory" {
511}509}
512510
513test "struct field explicit alignment" {511test "struct field explicit alignment" {
514 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;512 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
516 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;513 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
517 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO514 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/array.zig-20
...@@ -22,7 +22,6 @@ test "arrays" {...@@ -22,7 +22,6 @@ test "arrays" {
22 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;22 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2625
27 var array: [5]u32 = undefined;26 var array: [5]u32 = undefined;
2827
...@@ -160,7 +159,6 @@ test "array len field" {...@@ -160,7 +159,6 @@ test "array len field" {
160test "array with sentinels" {159test "array with sentinels" {
161 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO161 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
164162
165 const S = struct {163 const S = struct {
166 fn doTheTest(is_ct: bool) !void {164 fn doTheTest(is_ct: bool) !void {
...@@ -532,7 +530,6 @@ test "sentinel element count towards the ABI size calculation" {...@@ -532,7 +530,6 @@ test "sentinel element count towards the ABI size calculation" {
532 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO530 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO531 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
534 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO532 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
535 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
536533
537 const S = struct {534 const S = struct {
538 fn doTheTest() !void {535 fn doTheTest() !void {
...@@ -614,7 +611,6 @@ test "type coercion of pointer to anon struct literal to pointer to array" {...@@ -614,7 +611,6 @@ test "type coercion of pointer to anon struct literal to pointer to array" {
614 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
615 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO612 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
616 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO613 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
617 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
618614
619 const S = struct {615 const S = struct {
620 const U = union {616 const U = union {
...@@ -667,7 +663,6 @@ test "array init of container level array variable" {...@@ -667,7 +663,6 @@ test "array init of container level array variable" {
667 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO663 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
668 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO664 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
669 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO665 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
670 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
671666
672 const S = struct {667 const S = struct {
673 var pair: [2]usize = .{ 1, 2 };668 var pair: [2]usize = .{ 1, 2 };
...@@ -688,8 +683,6 @@ test "array init of container level array variable" {...@@ -688,8 +683,6 @@ test "array init of container level array variable" {
688}683}
689684
690test "runtime initialized sentinel-terminated array literal" {685test "runtime initialized sentinel-terminated array literal" {
691 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
692
693 var c: u16 = 300;686 var c: u16 = 300;
694 _ = &c;687 _ = &c;
695 const f = &[_:0x9999]u16{c};688 const f = &[_:0x9999]u16{c};
...@@ -776,8 +769,6 @@ test "array init with no result pointer sets field result types" {...@@ -776,8 +769,6 @@ test "array init with no result pointer sets field result types" {
776}769}
777770
778test "runtime side-effects in comptime-known array init" {771test "runtime side-effects in comptime-known array init" {
779 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
780
781 var side_effects: u4 = 0;772 var side_effects: u4 = 0;
782 const init = [4]u4{773 const init = [4]u4{
783 blk: {774 blk: {
...@@ -802,8 +793,6 @@ test "runtime side-effects in comptime-known array init" {...@@ -802,8 +793,6 @@ test "runtime side-effects in comptime-known array init" {
802}793}
803794
804test "slice initialized through reference to anonymous array init provides result types" {795test "slice initialized through reference to anonymous array init provides result types" {
805 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
806
807 var my_u32: u32 = 123;796 var my_u32: u32 = 123;
808 var my_u64: u64 = 456;797 var my_u64: u64 = 456;
809 _ = .{ &my_u32, &my_u64 };798 _ = .{ &my_u32, &my_u64 };
...@@ -817,8 +806,6 @@ test "slice initialized through reference to anonymous array init provides resul...@@ -817,8 +806,6 @@ test "slice initialized through reference to anonymous array init provides resul
817}806}
818807
819test "sentinel-terminated slice initialized through reference to anonymous array init provides result types" {808test "sentinel-terminated slice initialized through reference to anonymous array init provides result types" {
820 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
821
822 var my_u32: u32 = 123;809 var my_u32: u32 = 123;
823 var my_u64: u64 = 456;810 var my_u64: u64 = 456;
824 _ = .{ &my_u32, &my_u64 };811 _ = .{ &my_u32, &my_u64 };
...@@ -869,8 +856,6 @@ test "many-item sentinel-terminated pointer initialized through reference to ano...@@ -869,8 +856,6 @@ test "many-item sentinel-terminated pointer initialized through reference to ano
869}856}
870857
871test "pointer to array initialized through reference to anonymous array init provides result types" {858test "pointer to array initialized through reference to anonymous array init provides result types" {
872 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
873
874 var my_u32: u32 = 123;859 var my_u32: u32 = 123;
875 var my_u64: u64 = 456;860 var my_u64: u64 = 456;
876 _ = .{ &my_u32, &my_u64 };861 _ = .{ &my_u32, &my_u64 };
...@@ -884,8 +869,6 @@ test "pointer to array initialized through reference to anonymous array init pro...@@ -884,8 +869,6 @@ test "pointer to array initialized through reference to anonymous array init pro
884}869}
885870
886test "pointer to sentinel-terminated array initialized through reference to anonymous array init provides result types" {871test "pointer to sentinel-terminated array initialized through reference to anonymous array init provides result types" {
887 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
888
889 var my_u32: u32 = 123;872 var my_u32: u32 = 123;
890 var my_u64: u64 = 456;873 var my_u64: u64 = 456;
891 _ = .{ &my_u32, &my_u64 };874 _ = .{ &my_u32, &my_u64 };
...@@ -912,7 +895,6 @@ test "copied array element doesn't alias source" {...@@ -912,7 +895,6 @@ test "copied array element doesn't alias source" {
912 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO895 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
913 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO896 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
914 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO897 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
915 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
916898
917 var x: [10][10]u32 = undefined;899 var x: [10][10]u32 = undefined;
918900
...@@ -925,7 +907,6 @@ test "copied array element doesn't alias source" {...@@ -925,7 +907,6 @@ test "copied array element doesn't alias source" {
925907
926test "array initialized with string literal" {908test "array initialized with string literal" {
927 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO909 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
928 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
929910
930 const S = struct {911 const S = struct {
931 a: u32,912 a: u32,
...@@ -993,7 +974,6 @@ test "accessing multidimensional global array at comptime" {...@@ -993,7 +974,6 @@ test "accessing multidimensional global array at comptime" {
993 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO974 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
994 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO975 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
995 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO976 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
996 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
997977
998 const S = struct {978 const S = struct {
999 const array = [_][]const []const u8{979 const array = [_][]const []const u8{
test/behavior/atomics.zig-5
...@@ -15,7 +15,6 @@ test "cmpxchg" {...@@ -15,7 +15,6 @@ test "cmpxchg" {
15 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO15 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;17 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
18 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1918
20 try testCmpxchg();19 try testCmpxchg();
21 try comptime testCmpxchg();20 try comptime testCmpxchg();
...@@ -108,7 +107,6 @@ test "cmpxchg with ignored result" {...@@ -108,7 +107,6 @@ test "cmpxchg with ignored result" {
108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO107 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO108 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
110 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;109 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
111 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
112110
113 var x: i32 = 1234;111 var x: i32 = 1234;
114112
...@@ -153,7 +151,6 @@ test "cmpxchg on a global variable" {...@@ -153,7 +151,6 @@ test "cmpxchg on a global variable" {
153 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO151 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO152 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;153 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
156 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
157154
158 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {155 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
159 // https://github.com/ziglang/zig/issues/10627156 // https://github.com/ziglang/zig/issues/10627
...@@ -169,7 +166,6 @@ test "atomic load and rmw with enum" {...@@ -169,7 +166,6 @@ test "atomic load and rmw with enum" {
169 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO166 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
170 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
171 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;168 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
172 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
173169
174 const Value = enum(u8) { a, b, c };170 const Value = enum(u8) { a, b, c };
175 var x = Value.a;171 var x = Value.a;
...@@ -205,7 +201,6 @@ test "atomicrmw with floats" {...@@ -205,7 +201,6 @@ test "atomicrmw with floats" {
205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO201 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
206 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO202 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
207 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;203 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
208 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
209204
210 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {205 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
211 // https://github.com/ziglang/zig/issues/10627206 // https://github.com/ziglang/zig/issues/10627
test/behavior/basic.zig-17
...@@ -16,8 +16,6 @@ test "empty function with comments" {...@@ -16,8 +16,6 @@ test "empty function with comments" {
16}16}
1717
18test "truncate" {18test "truncate" {
19 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
20
21 try expect(testTruncate(0x10fd) == 0xfd);19 try expect(testTruncate(0x10fd) == 0xfd);
22 comptime assert(testTruncate(0x10fd) == 0xfd);20 comptime assert(testTruncate(0x10fd) == 0xfd);
23}21}
...@@ -27,7 +25,6 @@ fn testTruncate(x: u32) u8 {...@@ -27,7 +25,6 @@ fn testTruncate(x: u32) u8 {
2725
28test "truncate to non-power-of-two integers" {26test "truncate to non-power-of-two integers" {
29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO27 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3128
32 try testTrunc(u32, u1, 0b10101, 0b1);29 try testTrunc(u32, u1, 0b10101, 0b1);
33 try testTrunc(u32, u1, 0b10110, 0b0);30 try testTrunc(u32, u1, 0b10110, 0b0);
...@@ -45,7 +42,6 @@ test "truncate to non-power-of-two integers from 128-bit" {...@@ -45,7 +42,6 @@ test "truncate to non-power-of-two integers from 128-bit" {
45 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
46 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO43 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
47 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;44 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
48 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
4945
50 try testTrunc(u128, u1, 0xffffffff_ffffffff_ffffffff_01010101, 0x01);46 try testTrunc(u128, u1, 0xffffffff_ffffffff_ffffffff_01010101, 0x01);
51 try testTrunc(u128, u1, 0xffffffff_ffffffff_ffffffff_01010110, 0x00);47 try testTrunc(u128, u1, 0xffffffff_ffffffff_ffffffff_01010110, 0x00);
...@@ -224,7 +220,6 @@ const OpaqueB = opaque {};...@@ -224,7 +220,6 @@ const OpaqueB = opaque {};
224test "opaque types" {220test "opaque types" {
225 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
226 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;222 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
227 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
228223
229 try expect(*OpaqueA != *OpaqueB);224 try expect(*OpaqueA != *OpaqueB);
230225
...@@ -376,7 +371,6 @@ test "take address of parameter" {...@@ -376,7 +371,6 @@ test "take address of parameter" {
376 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;371 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
377 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;372 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
378 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO373 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
379 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
380374
381 try testTakeAddressOfParameter(12.34);375 try testTakeAddressOfParameter(12.34);
382}376}
...@@ -401,7 +395,6 @@ test "array 2D const double ptr" {...@@ -401,7 +395,6 @@ test "array 2D const double ptr" {
401 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;395 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
402 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
403 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
404 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
405398
406 const rect_2d_vertexes = [_][1]f32{399 const rect_2d_vertexes = [_][1]f32{
407 [_]f32{1.0},400 [_]f32{1.0},
...@@ -414,7 +407,6 @@ test "array 2D const double ptr with offset" {...@@ -414,7 +407,6 @@ test "array 2D const double ptr with offset" {
414 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;407 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
415 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO408 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
416 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;409 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
417 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
418410
419 const rect_2d_vertexes = [_][2]f32{411 const rect_2d_vertexes = [_][2]f32{
420 [_]f32{ 3.0, 4.239 },412 [_]f32{ 3.0, 4.239 },
...@@ -427,7 +419,6 @@ test "array 3D const double ptr with offset" {...@@ -427,7 +419,6 @@ test "array 3D const double ptr with offset" {
427 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;419 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
428 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO420 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
429 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;421 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
430 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
431422
432 const rect_3d_vertexes = [_][2][2]f32{423 const rect_3d_vertexes = [_][2][2]f32{
433 [_][2]f32{424 [_][2]f32{
...@@ -622,7 +613,6 @@ var global_ptr = &gdt[0];...@@ -622,7 +613,6 @@ var global_ptr = &gdt[0];
622613
623test "global constant is loaded with a runtime-known index" {614test "global constant is loaded with a runtime-known index" {
624 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO615 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
625 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
626616
627 const S = struct {617 const S = struct {
628 fn doTheTest() !void {618 fn doTheTest() !void {
...@@ -641,7 +631,6 @@ test "global constant is loaded with a runtime-known index" {...@@ -641,7 +631,6 @@ test "global constant is loaded with a runtime-known index" {
641631
642test "multiline string literal is null terminated" {632test "multiline string literal is null terminated" {
643 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;633 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
644 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
645634
646 const s1 =635 const s1 =
647 \\one636 \\one
...@@ -656,7 +645,6 @@ test "string escapes" {...@@ -656,7 +645,6 @@ test "string escapes" {
656 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;645 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
657 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;646 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
658 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO647 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
659 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
660648
661 try expectEqualStrings("\"", "\x22");649 try expectEqualStrings("\"", "\x22");
662 try expectEqualStrings("\'", "\x27");650 try expectEqualStrings("\'", "\x27");
...@@ -789,7 +777,6 @@ test "discarding the result of various expressions" {...@@ -789,7 +777,6 @@ test "discarding the result of various expressions" {
789 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO777 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
790 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO778 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
791 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO779 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
792 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
793780
794 const S = struct {781 const S = struct {
795 fn foo() !u32 {782 fn foo() !u32 {
...@@ -1072,7 +1059,6 @@ test "returning an opaque type from a function" {...@@ -1072,7 +1059,6 @@ test "returning an opaque type from a function" {
1072test "orelse coercion as function argument" {1059test "orelse coercion as function argument" {
1073 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1060 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1074 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1061 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1075 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10761062
1077 const Loc = struct { start: i32 = -1 };1063 const Loc = struct { start: i32 = -1 };
1078 const Container = struct {1064 const Container = struct {
...@@ -1186,8 +1172,6 @@ fn testUnsignedCmp(comptime T: type) !void {...@@ -1186,8 +1172,6 @@ fn testUnsignedCmp(comptime T: type) !void {
1186}1172}
11871173
1188test "integer compare <= 64 bits" {1174test "integer compare <= 64 bits" {
1189 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1190
1191 inline for (.{ u8, u16, u32, u64, usize, u10, u20, u30, u60 }) |T| {1175 inline for (.{ u8, u16, u32, u64, usize, u10, u20, u30, u60 }) |T| {
1192 try testUnsignedCmp(T);1176 try testUnsignedCmp(T);
1193 try comptime testUnsignedCmp(T);1177 try comptime testUnsignedCmp(T);
...@@ -1324,7 +1308,6 @@ test "break out of block based on comptime known values" {...@@ -1324,7 +1308,6 @@ test "break out of block based on comptime known values" {
1324 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1308 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1325 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1309 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1326 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1310 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1327 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13281311
1329 const S = struct {1312 const S = struct {
1330 const source = "A-";1313 const source = "A-";
test/behavior/bit_shifting.zig-1
...@@ -65,7 +65,6 @@ test "sharded table" {...@@ -65,7 +65,6 @@ test "sharded table" {
65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO66 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
67 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;67 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
68 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
6968
70 // realistic 16-way sharding69 // realistic 16-way sharding
71 try testShardedTable(u32, 4, 8);70 try testShardedTable(u32, 4, 8);
test/behavior/bitcast.zig-3
...@@ -10,7 +10,6 @@ const native_endian = builtin.target.cpu.arch.endian();...@@ -10,7 +10,6 @@ const native_endian = builtin.target.cpu.arch.endian();
1010
11test "@bitCast iX -> uX (32, 64)" {11test "@bitCast iX -> uX (32, 64)" {
12 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;12 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1413
15 const bit_values = [_]usize{ 32, 64 };14 const bit_values = [_]usize{ 32, 64 };
1615
...@@ -165,7 +164,6 @@ test "@bitCast packed structs at runtime and comptime" {...@@ -165,7 +164,6 @@ test "@bitCast packed structs at runtime and comptime" {
165 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;164 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
166 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
167 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;166 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
168 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
169167
170 const Full = packed struct {168 const Full = packed struct {
171 number: u16,169 number: u16,
...@@ -491,7 +489,6 @@ test "@bitCast of packed struct of bools all true" {...@@ -491,7 +489,6 @@ test "@bitCast of packed struct of bools all true" {
491 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO489 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
492 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO490 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
493 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO491 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
494 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
495492
496 const P = packed struct {493 const P = packed struct {
497 b0: bool,494 b0: bool,
test/behavior/call.zig-2
...@@ -342,7 +342,6 @@ test "inline call preserves tail call" {...@@ -342,7 +342,6 @@ test "inline call preserves tail call" {
342test "inline call doesn't re-evaluate non generic struct" {342test "inline call doesn't re-evaluate non generic struct" {
343 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO343 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
344 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO344 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
345 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
346345
347 const S = struct {346 const S = struct {
348 fn foo(f: struct { a: u8, b: u8 }) !void {347 fn foo(f: struct { a: u8, b: u8 }) !void {
...@@ -441,7 +440,6 @@ test "non-anytype generic parameters provide result type" {...@@ -441,7 +440,6 @@ test "non-anytype generic parameters provide result type" {
441 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO440 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
442 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO441 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
443 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO442 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
444 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
445443
446 const S = struct {444 const S = struct {
447 fn f(comptime T: type, y: T) !void {445 fn f(comptime T: type, y: T) !void {
test/behavior/cast.zig-22
...@@ -24,7 +24,6 @@ test "peer type resolution: ?T and T" {...@@ -24,7 +24,6 @@ test "peer type resolution: ?T and T" {
24 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;24 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
27 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2827
29 try expect(peerTypeTAndOptionalT(true, false).? == 0);28 try expect(peerTypeTAndOptionalT(true, false).? == 0);
30 try expect(peerTypeTAndOptionalT(false, false).? == 3);29 try expect(peerTypeTAndOptionalT(false, false).? == 3);
...@@ -104,7 +103,6 @@ test "@floatFromInt" {...@@ -104,7 +103,6 @@ test "@floatFromInt" {
104 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO103 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO104 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
106 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO105 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
107 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
108106
109 const S = struct {107 const S = struct {
110 fn doTheTest() !void {108 fn doTheTest() !void {
...@@ -163,7 +161,6 @@ test "@intFromFloat" {...@@ -163,7 +161,6 @@ test "@intFromFloat" {
163 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
164 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO162 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO163 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
166 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
167164
168 try testIntFromFloats();165 try testIntFromFloats();
169 try comptime testIntFromFloats();166 try comptime testIntFromFloats();
...@@ -303,7 +300,6 @@ test "peer result null and comptime_int" {...@@ -303,7 +300,6 @@ test "peer result null and comptime_int" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;300 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;301 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
305 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO302 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
306 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
307303
308 const S = struct {304 const S = struct {
309 fn blah(n: i32) ?i32 {305 fn blah(n: i32) ?i32 {
...@@ -372,7 +368,6 @@ test "return u8 coercing into ?u32 return type" {...@@ -372,7 +368,6 @@ test "return u8 coercing into ?u32 return type" {
372 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;368 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
373 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;369 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
374 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO370 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
375 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
376371
377 const S = struct {372 const S = struct {
378 fn doTheTest() !void {373 fn doTheTest() !void {
...@@ -450,7 +445,6 @@ test "implicitly cast from T to anyerror!?T" {...@@ -450,7 +445,6 @@ test "implicitly cast from T to anyerror!?T" {
450 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;445 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
451 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;446 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
452 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO447 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
453 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
454448
455 try castToOptionalTypeError(1);449 try castToOptionalTypeError(1);
456 try comptime castToOptionalTypeError(1);450 try comptime castToOptionalTypeError(1);
...@@ -602,7 +596,6 @@ fn testCastPtrOfArrayToSliceAndPtr() !void {...@@ -602,7 +596,6 @@ fn testCastPtrOfArrayToSliceAndPtr() !void {
602test "cast *[1][*]const u8 to [*]const ?[*]const u8" {596test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
603 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;597 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
604 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO598 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
605 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
606599
607 const window_name = [1][*]const u8{"window name"};600 const window_name = [1][*]const u8{"window name"};
608 const x: [*]const ?[*]const u8 = &window_name;601 const x: [*]const ?[*]const u8 = &window_name;
...@@ -668,7 +661,6 @@ test "@floatCast cast down" {...@@ -668,7 +661,6 @@ test "@floatCast cast down" {
668test "peer type resolution: unreachable, error set, unreachable" {661test "peer type resolution: unreachable, error set, unreachable" {
669 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO662 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
670 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO663 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
671 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
672664
673 const Error = error{665 const Error = error{
674 FileDescriptorAlreadyPresentInSet,666 FileDescriptorAlreadyPresentInSet,
...@@ -763,7 +755,6 @@ test "peer type resolution: error union and error set" {...@@ -763,7 +755,6 @@ test "peer type resolution: error union and error set" {
763 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO755 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
764 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO756 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
765 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;757 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
766 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
767758
768 const a: error{Three} = undefined;759 const a: error{Three} = undefined;
769 const b: error{ One, Two }!u32 = undefined;760 const b: error{ One, Two }!u32 = undefined;
...@@ -957,7 +948,6 @@ test "peer cast [:x]T to [*:x]T" {...@@ -957,7 +948,6 @@ test "peer cast [:x]T to [*:x]T" {
957 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;948 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
958 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO949 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
959 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO950 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
960 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
961951
962 const S = struct {952 const S = struct {
963 fn doTheTest() !void {953 fn doTheTest() !void {
...@@ -1023,7 +1013,6 @@ test "variable initialization uses result locations properly with regards to the...@@ -1023,7 +1013,6 @@ test "variable initialization uses result locations properly with regards to the
1023test "cast between C pointer with different but compatible types" {1013test "cast between C pointer with different but compatible types" {
1024 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1014 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1025 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1015 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1026 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10271016
1028 const S = struct {1017 const S = struct {
1029 fn foo(arg: [*]c_ushort) u16 {1018 fn foo(arg: [*]c_ushort) u16 {
...@@ -1219,7 +1208,6 @@ test "implicitly cast from [N]T to ?[]const T" {...@@ -1219,7 +1208,6 @@ test "implicitly cast from [N]T to ?[]const T" {
1219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1208 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1210 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1222 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12231211
1224 try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));1212 try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
1225 comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi"));1213 comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
...@@ -1544,7 +1532,6 @@ test "cast typed undefined to int" {...@@ -1544,7 +1532,6 @@ test "cast typed undefined to int" {
15441532
1545test "implicit cast from [:0]T to [*c]T" {1533test "implicit cast from [:0]T to [*c]T" {
1546 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1534 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1547 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15481535
1549 var a: [:0]const u8 = "foo";1536 var a: [:0]const u8 = "foo";
1550 _ = &a;1537 _ = &a;
...@@ -1753,7 +1740,6 @@ test "peer type resolution: array and vector with same child type" {...@@ -1753,7 +1740,6 @@ test "peer type resolution: array and vector with same child type" {
1753 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1740 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1754 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1741 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1755 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1742 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1756 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
17571743
1758 var arr: [2]u32 = .{ 0, 1 };1744 var arr: [2]u32 = .{ 0, 1 };
1759 var vec: @Vector(2, u32) = .{ 2, 3 };1745 var vec: @Vector(2, u32) = .{ 2, 3 };
...@@ -1845,7 +1831,6 @@ test "peer type resolution: three-way resolution combines error set and optional...@@ -1845,7 +1831,6 @@ test "peer type resolution: three-way resolution combines error set and optional
1845 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1831 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1846 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1832 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1847 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1833 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1848 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
18491834
1850 const E = error{Foo};1835 const E = error{Foo};
1851 var a: E = error.Foo;1836 var a: E = error.Foo;
...@@ -1913,7 +1898,6 @@ test "peer type resolution: optional fixed-width int and comptime_int" {...@@ -1913,7 +1898,6 @@ test "peer type resolution: optional fixed-width int and comptime_int" {
1913 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1898 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1914 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1899 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1915 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1900 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1916 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19171901
1918 var a: ?i32 = 42;1902 var a: ?i32 = 42;
1919 _ = &a;1903 _ = &a;
...@@ -1960,7 +1944,6 @@ test "peer type resolution: vector and tuple" {...@@ -1960,7 +1944,6 @@ test "peer type resolution: vector and tuple" {
1960 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1944 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1961 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1945 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1962 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1946 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1963 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19641947
1965 var vec: @Vector(3, i32) = .{ 1, 2, 3 };1948 var vec: @Vector(3, i32) = .{ 1, 2, 3 };
1966 _ = &vec;1949 _ = &vec;
...@@ -1985,7 +1968,6 @@ test "peer type resolution: vector and array and tuple" {...@@ -1985,7 +1968,6 @@ test "peer type resolution: vector and array and tuple" {
1985 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1968 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1986 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1969 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1987 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1970 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1988 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19891971
1990 var vec: @Vector(2, i8) = .{ 10, 20 };1972 var vec: @Vector(2, i8) = .{ 10, 20 };
1991 var arr: [2]i8 = .{ 30, 40 };1973 var arr: [2]i8 = .{ 30, 40 };
...@@ -2094,7 +2076,6 @@ test "peer type resolution: many compatible pointers" {...@@ -2094,7 +2076,6 @@ test "peer type resolution: many compatible pointers" {
2094 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2076 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2095 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2077 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2096 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO2078 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
2097 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
20982079
2099 var buf = "foo-3".*;2080 var buf = "foo-3".*;
21002081
...@@ -2216,7 +2197,6 @@ test "peer type resolution: pointer attributes are combined correctly" {...@@ -2216,7 +2197,6 @@ test "peer type resolution: pointer attributes are combined correctly" {
2216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2197 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2217 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2198 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2218 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2199 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2219 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
22202200
2221 var buf_a align(4) = "foo".*;2201 var buf_a align(4) = "foo".*;
2222 var buf_b align(4) = "bar".*;2202 var buf_b align(4) = "bar".*;
...@@ -2277,7 +2257,6 @@ test "cast builtins can wrap result in optional" {...@@ -2277,7 +2257,6 @@ test "cast builtins can wrap result in optional" {
2277 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2278 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2279 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2280 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
22812260
2282 const S = struct {2261 const S = struct {
2283 const MyEnum = enum(u32) { _ };2262 const MyEnum = enum(u32) { _ };
...@@ -2586,7 +2565,6 @@ test "result information is preserved through many nested structures" {...@@ -2586,7 +2565,6 @@ test "result information is preserved through many nested structures" {
2586 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2565 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2587 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2566 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2588 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2567 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2589 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
25902568
2591 const S = struct {2569 const S = struct {
2592 fn doTheTest() !void {2570 fn doTheTest() !void {
test/behavior/cast_int.zig-2
...@@ -35,8 +35,6 @@ test "coerce i8 to i32 and @intCast back" {...@@ -35,8 +35,6 @@ test "coerce i8 to i32 and @intCast back" {
35}35}
3636
37test "coerce non byte-sized integers accross 32bits boundary" {37test "coerce non byte-sized integers accross 32bits boundary" {
38 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
39
40 {38 {
41 var v: u21 = 6417;39 var v: u21 = 6417;
42 _ = &v;40 _ = &v;
test/behavior/defer.zig+2-1
...@@ -53,7 +53,6 @@ test "return variable while defer expression in scope to modify it" {...@@ -53,7 +53,6 @@ test "return variable while defer expression in scope to modify it" {
53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5756
58 const S = struct {57 const S = struct {
59 fn doTheTest() !void {58 fn doTheTest() !void {
...@@ -116,6 +115,7 @@ test "errdefer with payload" {...@@ -116,6 +115,7 @@ test "errdefer with payload" {
116 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
117 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO116 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
118 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;117 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
118 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
119119
120 const S = struct {120 const S = struct {
121 fn foo() !i32 {121 fn foo() !i32 {
...@@ -138,6 +138,7 @@ test "reference to errdefer payload" {...@@ -138,6 +138,7 @@ test "reference to errdefer payload" {
138 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO138 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO140 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
141 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
141142
142 const S = struct {143 const S = struct {
143 fn foo() !i32 {144 fn foo() !i32 {
test/behavior/destructure.zig-2
...@@ -23,8 +23,6 @@ test "simple destructure" {...@@ -23,8 +23,6 @@ test "simple destructure" {
23}23}
2424
25test "destructure with comptime syntax" {25test "destructure with comptime syntax" {
26 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
27
28 const S = struct {26 const S = struct {
29 fn doTheTest() !void {27 fn doTheTest() !void {
30 {28 {
test/behavior/enum.zig-6
...@@ -618,7 +618,6 @@ test "enum with specified tag values" {...@@ -618,7 +618,6 @@ test "enum with specified tag values" {
618test "non-exhaustive enum" {618test "non-exhaustive enum" {
619 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;619 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
620 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO620 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
621 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
622621
623 const S = struct {622 const S = struct {
624 const E = enum(u8) { a, b, _ };623 const E = enum(u8) { a, b, _ };
...@@ -934,7 +933,6 @@ const Bar = enum { A, B, C, D };...@@ -934,7 +933,6 @@ const Bar = enum { A, B, C, D };
934test "enum literal casting to error union with payload enum" {933test "enum literal casting to error union with payload enum" {
935 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;934 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
936 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO935 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
937 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
938936
939 var bar: error{B}!Bar = undefined;937 var bar: error{B}!Bar = undefined;
940 bar = .B; // should never cast to the error set938 bar = .B; // should never cast to the error set
...@@ -1076,7 +1074,6 @@ test "enum literal casting to optional" {...@@ -1076,7 +1074,6 @@ test "enum literal casting to optional" {
1076 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1074 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1077 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1075 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1078 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1076 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1079 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10801077
1081 var bar: ?Bar = undefined;1078 var bar: ?Bar = undefined;
1082 bar = .B;1079 bar = .B;
...@@ -1105,7 +1102,6 @@ test "bit field access with enum fields" {...@@ -1105,7 +1102,6 @@ test "bit field access with enum fields" {
1105 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1106 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1107 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1104 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1108 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11091105
1110 var data = bit_field_1;1106 var data = bit_field_1;
1111 try expect(getA(&data) == A.Two);1107 try expect(getA(&data) == A.Two);
...@@ -1223,8 +1219,6 @@ test "enum tag from a local variable" {...@@ -1223,8 +1219,6 @@ test "enum tag from a local variable" {
1223}1219}
12241220
1225test "auto-numbered enum with signed tag type" {1221test "auto-numbered enum with signed tag type" {
1226 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1227
1228 const E = enum(i32) { a, b };1222 const E = enum(i32) { a, b };
12291223
1230 try std.testing.expectEqual(@as(i32, 0), @intFromEnum(E.a));1224 try std.testing.expectEqual(@as(i32, 0), @intFromEnum(E.a));
test/behavior/error.zig-10
...@@ -319,7 +319,6 @@ test "error inference with an empty set" {...@@ -319,7 +319,6 @@ test "error inference with an empty set" {
319319
320test "error union peer type resolution" {320test "error union peer type resolution" {
321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
322 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
323322
324 try testErrorUnionPeerTypeResolution(1);323 try testErrorUnionPeerTypeResolution(1);
325}324}
...@@ -403,7 +402,6 @@ test "nested error union function call in optional unwrap" {...@@ -403,7 +402,6 @@ test "nested error union function call in optional unwrap" {
403 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO402 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO403 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO404 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
406 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
407405
408 const S = struct {406 const S = struct {
409 const Foo = struct {407 const Foo = struct {
...@@ -450,7 +448,6 @@ test "nested error union function call in optional unwrap" {...@@ -450,7 +448,6 @@ test "nested error union function call in optional unwrap" {
450test "return function call to error set from error union function" {448test "return function call to error set from error union function" {
451 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO449 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
452 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO450 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
453 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
454451
455 const S = struct {452 const S = struct {
456 fn errorable() anyerror!i32 {453 fn errorable() anyerror!i32 {
...@@ -469,7 +466,6 @@ test "optional error set is the same size as error set" {...@@ -469,7 +466,6 @@ test "optional error set is the same size as error set" {
469 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO466 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
470 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO467 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
471 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO468 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
472 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
473469
474 comptime assert(@sizeOf(?anyerror) == @sizeOf(anyerror));470 comptime assert(@sizeOf(?anyerror) == @sizeOf(anyerror));
475 comptime assert(@alignOf(?anyerror) == @alignOf(anyerror));471 comptime assert(@alignOf(?anyerror) == @alignOf(anyerror));
...@@ -917,7 +913,6 @@ test "field access of anyerror results in smaller error set" {...@@ -917,7 +913,6 @@ test "field access of anyerror results in smaller error set" {
917test "optional error union return type" {913test "optional error union return type" {
918 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO914 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
919 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO915 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
920 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
921916
922 const S = struct {917 const S = struct {
923 fn foo() ?anyerror!u32 {918 fn foo() ?anyerror!u32 {
...@@ -932,7 +927,6 @@ test "optional error union return type" {...@@ -932,7 +927,6 @@ test "optional error union return type" {
932test "optional error set return type" {927test "optional error set return type" {
933 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO928 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
934 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO929 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
935 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
936930
937 const E = error{ A, B };931 const E = error{ A, B };
938 const S = struct {932 const S = struct {
...@@ -946,8 +940,6 @@ test "optional error set return type" {...@@ -946,8 +940,6 @@ test "optional error set return type" {
946}940}
947941
948test "optional error set function parameter" {942test "optional error set function parameter" {
949 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
950
951 const S = struct {943 const S = struct {
952 fn doTheTest(a: ?anyerror) !void {944 fn doTheTest(a: ?anyerror) !void {
953 try std.testing.expect(a.? == error.OutOfMemory);945 try std.testing.expect(a.? == error.OutOfMemory);
...@@ -977,7 +969,6 @@ test "returning an error union containing a type with no runtime bits" {...@@ -977,7 +969,6 @@ test "returning an error union containing a type with no runtime bits" {
977test "try used in recursive function with inferred error set" {969test "try used in recursive function with inferred error set" {
978 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO970 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
979 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO971 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
980 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
981 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;972 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
982973
983 const Value = union(enum) {974 const Value = union(enum) {
...@@ -1079,7 +1070,6 @@ test "result location initialization of error union with OPV payload" {...@@ -1079,7 +1070,6 @@ test "result location initialization of error union with OPV payload" {
1079 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1070 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1080 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1071 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1081 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1072 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1082 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10831073
1084 const S = struct {1074 const S = struct {
1085 x: u0,1075 x: u0,
test/behavior/eval.zig-1
...@@ -782,7 +782,6 @@ test "array concatenation peer resolves element types - pointer" {...@@ -782,7 +782,6 @@ test "array concatenation peer resolves element types - pointer" {
782 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;782 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
783 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;783 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
784 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO784 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
785 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
786785
787 var a = [2]u3{ 1, 7 };786 var a = [2]u3{ 1, 7 };
788 var b = [3]u8{ 200, 225, 255 };787 var b = [3]u8{ 200, 225, 255 };
test/behavior/floatop.zig-1
...@@ -134,7 +134,6 @@ test "cmp f16" {...@@ -134,7 +134,6 @@ test "cmp f16" {
134test "cmp f32/f64" {134test "cmp f32/f64" {
135 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO135 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
136 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;136 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
137 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
138137
139 try testCmp(f32);138 try testCmp(f32);
140 try comptime testCmp(f32);139 try comptime testCmp(f32);
test/behavior/fn.zig-2
...@@ -181,7 +181,6 @@ test "function with complex callconv and return type expressions" {...@@ -181,7 +181,6 @@ test "function with complex callconv and return type expressions" {
181 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;181 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
183 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO183 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
184 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
185184
186 try expect(fComplexCallconvRet(3).x == 9);185 try expect(fComplexCallconvRet(3).x == 9);
187}186}
...@@ -451,7 +450,6 @@ test "implicit cast function to function ptr" {...@@ -451,7 +450,6 @@ test "implicit cast function to function ptr" {
451test "method call with optional and error union first param" {450test "method call with optional and error union first param" {
452 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO451 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
453 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO452 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
454 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
455453
456 const S = struct {454 const S = struct {
457 x: i32 = 1234,455 x: i32 = 1234,
test/behavior/for.zig-4
...@@ -112,7 +112,6 @@ test "for with null and T peer types and inferred result location type" {...@@ -112,7 +112,6 @@ test "for with null and T peer types and inferred result location type" {
112 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;112 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
113 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;113 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
114 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO114 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
115 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
116115
117 const S = struct {116 const S = struct {
118 fn doTheTest(slice: []const u8) !void {117 fn doTheTest(slice: []const u8) !void {
...@@ -154,7 +153,6 @@ test "for loop with pointer elem var" {...@@ -154,7 +153,6 @@ test "for loop with pointer elem var" {
154 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO153 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
156 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO155 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
157 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
158156
159 const source = "abcdefg";157 const source = "abcdefg";
160 var target: [source.len]u8 = undefined;158 var target: [source.len]u8 = undefined;
...@@ -228,7 +226,6 @@ test "else continue outer for" {...@@ -228,7 +226,6 @@ test "else continue outer for" {
228226
229test "for loop with else branch" {227test "for loop with else branch" {
230 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO228 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
231 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
232229
233 {230 {
234 var x = [_]u32{ 1, 2 };231 var x = [_]u32{ 1, 2 };
...@@ -489,7 +486,6 @@ test "inferred alloc ptr of for loop" {...@@ -489,7 +486,6 @@ test "inferred alloc ptr of for loop" {
489 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO486 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
490 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO487 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
491 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO488 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
492 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
493489
494 {490 {
495 var cond = false;491 var cond = false;
test/behavior/generics.zig-6
...@@ -19,7 +19,6 @@ fn checkSize(comptime T: type) usize {...@@ -19,7 +19,6 @@ fn checkSize(comptime T: type) usize {
19test "simple generic fn" {19test "simple generic fn" {
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2322
24 try expect(max(i32, 3, -1) == 3);23 try expect(max(i32, 3, -1) == 3);
25 try expect(max(u8, 1, 100) == 100);24 try expect(max(u8, 1, 100) == 100);
...@@ -56,7 +55,6 @@ test "fn with comptime args" {...@@ -56,7 +55,6 @@ test "fn with comptime args" {
56 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;55 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
57 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;56 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
58 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO57 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
59 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
6058
61 try expect(gimmeTheBigOne(1234, 5678) == 5678);59 try expect(gimmeTheBigOne(1234, 5678) == 5678);
62 try expect(shouldCallSameInstance(34, 12) == 34);60 try expect(shouldCallSameInstance(34, 12) == 34);
...@@ -67,7 +65,6 @@ test "anytype params" {...@@ -67,7 +65,6 @@ test "anytype params" {
67 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
68 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO67 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
70 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7168
72 try expect(max_i32(12, 34) == 34);69 try expect(max_i32(12, 34) == 34);
73 try expect(max_f64(1.2, 3.4) == 3.4);70 try expect(max_f64(1.2, 3.4) == 3.4);
...@@ -404,8 +401,6 @@ test "generic struct as parameter type" {...@@ -404,8 +401,6 @@ test "generic struct as parameter type" {
404}401}
405402
406test "slice as parameter type" {403test "slice as parameter type" {
407 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
408
409 const S = struct {404 const S = struct {
410 fn internComptimeString(comptime str: []const u8) *const []const u8 {405 fn internComptimeString(comptime str: []const u8) *const []const u8 {
411 return &struct {406 return &struct {
...@@ -503,7 +498,6 @@ test "union in struct captures argument" {...@@ -503,7 +498,6 @@ test "union in struct captures argument" {
503test "function argument tuple used as struct field" {498test "function argument tuple used as struct field" {
504 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO499 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
505 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO500 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
506 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
507501
508 const S = struct {502 const S = struct {
509 fn DeleagateWithContext(comptime Function: type) type {503 fn DeleagateWithContext(comptime Function: type) type {
test/behavior/globals.zig-1
...@@ -18,7 +18,6 @@ test "store to global vector" {...@@ -18,7 +18,6 @@ test "store to global vector" {
18 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2221
23 try expect(vpos[1] == 0.0);22 try expect(vpos[1] == 0.0);
24 vpos = @Vector(2, f32){ 0.0, 1.0 };23 vpos = @Vector(2, f32){ 0.0, 1.0 };
test/behavior/if.zig-6
...@@ -82,7 +82,6 @@ test "const result loc, runtime if cond, else unreachable" {...@@ -82,7 +82,6 @@ test "const result loc, runtime if cond, else unreachable" {
82test "if copies its payload" {82test "if copies its payload" {
83 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;83 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
85 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8685
87 const S = struct {86 const S = struct {
88 fn doTheTest() !void {87 fn doTheTest() !void {
...@@ -119,7 +118,6 @@ test "if peer expressions inferred optional type" {...@@ -119,7 +118,6 @@ test "if peer expressions inferred optional type" {
119 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;118 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
120 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;119 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
121 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO120 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
122 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
123121
124 var self: []const u8 = "abcdef";122 var self: []const u8 = "abcdef";
125 var index: usize = 0;123 var index: usize = 0;
...@@ -147,8 +145,6 @@ test "if-else expression with runtime condition result location is inferred opti...@@ -147,8 +145,6 @@ test "if-else expression with runtime condition result location is inferred opti
147}145}
148146
149test "result location with inferred type ends up being pointer to comptime_int" {147test "result location with inferred type ends up being pointer to comptime_int" {
150 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
151
152 var a: ?u32 = 1234;148 var a: ?u32 = 1234;
153 var b: u32 = 2000;149 var b: u32 = 2000;
154 _ = .{ &a, &b };150 _ = .{ &a, &b };
...@@ -194,8 +190,6 @@ test "if value shouldn't be load-elided if used later (structs)" {...@@ -194,8 +190,6 @@ test "if value shouldn't be load-elided if used later (structs)" {
194}190}
195191
196test "if value shouldn't be load-elided if used later (optionals)" {192test "if value shouldn't be load-elided if used later (optionals)" {
197 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
198
199 var a: ?i32 = 1;193 var a: ?i32 = 1;
200 var b: ?i32 = 1;194 var b: ?i32 = 1;
201195
test/behavior/math.zig-9
...@@ -65,7 +65,6 @@ test "@clz" {...@@ -65,7 +65,6 @@ test "@clz" {
65 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO65 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
67 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO67 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
68 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
6968
70 try testClz();69 try testClz();
71 try comptime testClz();70 try comptime testClz();
...@@ -663,8 +662,6 @@ fn rem(comptime T: type, a: T, b: T) T {...@@ -663,8 +662,6 @@ fn rem(comptime T: type, a: T, b: T) T {
663}662}
664663
665test "unsigned wrapping" {664test "unsigned wrapping" {
666 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
667
668 try testUnsignedWrappingEval(maxInt(u32));665 try testUnsignedWrappingEval(maxInt(u32));
669 try comptime testUnsignedWrappingEval(maxInt(u32));666 try comptime testUnsignedWrappingEval(maxInt(u32));
670}667}
...@@ -676,8 +673,6 @@ fn testUnsignedWrappingEval(x: u32) !void {...@@ -676,8 +673,6 @@ fn testUnsignedWrappingEval(x: u32) !void {
676}673}
677674
678test "signed wrapping" {675test "signed wrapping" {
679 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
680
681 try testSignedWrappingEval(maxInt(i32));676 try testSignedWrappingEval(maxInt(i32));
682 try comptime testSignedWrappingEval(maxInt(i32));677 try comptime testSignedWrappingEval(maxInt(i32));
683}678}
...@@ -725,7 +720,6 @@ fn negateWrap(comptime T: type, x: T) T {...@@ -725,7 +720,6 @@ fn negateWrap(comptime T: type, x: T) T {
725test "unsigned 64-bit division" {720test "unsigned 64-bit division" {
726 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO721 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
727 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO722 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
728 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
729723
730 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) {724 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) {
731 // https://github.com/ziglang/zig/issues/16846725 // https://github.com/ziglang/zig/issues/16846
...@@ -838,7 +832,6 @@ test "@addWithOverflow" {...@@ -838,7 +832,6 @@ test "@addWithOverflow" {
838 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO832 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
839 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO833 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
840 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO834 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
841 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
842835
843 try testAddWithOverflow(u8, 250, 100, 94, 1);836 try testAddWithOverflow(u8, 250, 100, 94, 1);
844 try testAddWithOverflow(u8, 100, 150, 250, 0);837 try testAddWithOverflow(u8, 100, 150, 250, 0);
...@@ -899,7 +892,6 @@ test "@addWithOverflow > 64 bits" {...@@ -899,7 +892,6 @@ test "@addWithOverflow > 64 bits" {
899test "small int addition" {892test "small int addition" {
900 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO893 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
901 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO894 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
902 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
903895
904 var x: u2 = 0;896 var x: u2 = 0;
905 try expect(x == 0);897 try expect(x == 0);
...@@ -927,7 +919,6 @@ fn testMulWithOverflow(comptime T: type, a: T, b: T, mul: T, bit: u1) !void {...@@ -927,7 +919,6 @@ fn testMulWithOverflow(comptime T: type, a: T, b: T, mul: T, bit: u1) !void {
927test "basic @mulWithOverflow" {919test "basic @mulWithOverflow" {
928 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO920 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
929 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO921 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
930 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
931922
932 try testMulWithOverflow(u8, 86, 3, 2, 1);923 try testMulWithOverflow(u8, 86, 3, 2, 1);
933 try testMulWithOverflow(u8, 85, 3, 255, 0);924 try testMulWithOverflow(u8, 85, 3, 255, 0);
test/behavior/memcpy.zig-4
...@@ -7,7 +7,6 @@ test "memcpy and memset intrinsics" {...@@ -7,7 +7,6 @@ test "memcpy and memset intrinsics" {
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1110
12 try testMemcpyMemset();11 try testMemcpyMemset();
13 try comptime testMemcpyMemset();12 try comptime testMemcpyMemset();
...@@ -29,7 +28,6 @@ test "@memcpy with both operands single-ptr-to-array, one is null-terminated" {...@@ -29,7 +28,6 @@ test "@memcpy with both operands single-ptr-to-array, one is null-terminated" {
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;30 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3331
34 try testMemcpyBothSinglePtrArrayOneIsNullTerminated();32 try testMemcpyBothSinglePtrArrayOneIsNullTerminated();
35 try comptime testMemcpyBothSinglePtrArrayOneIsNullTerminated();33 try comptime testMemcpyBothSinglePtrArrayOneIsNullTerminated();
...@@ -50,7 +48,6 @@ test "@memcpy dest many pointer" {...@@ -50,7 +48,6 @@ test "@memcpy dest many pointer" {
50 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;48 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;49 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5451
55 try testMemcpyDestManyPtr();52 try testMemcpyDestManyPtr();
56 try comptime testMemcpyDestManyPtr();53 try comptime testMemcpyDestManyPtr();
...@@ -73,7 +70,6 @@ test "@memcpy slice" {...@@ -73,7 +70,6 @@ test "@memcpy slice" {
73 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;70 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
74 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;71 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
75 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;72 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
76 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7773
78 try testMemcpySlice();74 try testMemcpySlice();
79 try comptime testMemcpySlice();75 try comptime testMemcpySlice();
test/behavior/null.zig-3
...@@ -53,7 +53,6 @@ test "maybe return" {...@@ -53,7 +53,6 @@ test "maybe return" {
53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5756
58 try maybeReturnImpl();57 try maybeReturnImpl();
59 try comptime maybeReturnImpl();58 try comptime maybeReturnImpl();
...@@ -73,7 +72,6 @@ fn foo(x: ?i32) ?bool {...@@ -73,7 +72,6 @@ fn foo(x: ?i32) ?bool {
73test "test null runtime" {72test "test null runtime" {
74 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;73 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
75 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO74 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7775
78 try testTestNullRuntime(null);76 try testTestNullRuntime(null);
79}77}
...@@ -188,7 +186,6 @@ test "unwrap optional which is field of global var" {...@@ -188,7 +186,6 @@ test "unwrap optional which is field of global var" {
188 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;186 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;187 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
190 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO188 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
191 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
192189
193 struct_with_optional.field = null;190 struct_with_optional.field = null;
194 if (struct_with_optional.field) |payload| {191 if (struct_with_optional.field) |payload| {
test/behavior/optional.zig+1-9
...@@ -9,7 +9,6 @@ const expectEqualStrings = std.testing.expectEqualStrings;...@@ -9,7 +9,6 @@ const expectEqualStrings = std.testing.expectEqualStrings;
9test "passing an optional integer as a parameter" {9test "passing an optional integer as a parameter" {
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1312
14 const S = struct {13 const S = struct {
15 fn entry() bool {14 fn entry() bool {
...@@ -134,7 +133,6 @@ test "nested optional field in struct" {...@@ -134,7 +133,6 @@ test "nested optional field in struct" {
134 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
135 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO135 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
138136
139 const S2 = struct {137 const S2 = struct {
140 y: u8,138 y: u8,
...@@ -260,7 +258,6 @@ test "unwrap function call with optional pointer return value" {...@@ -260,7 +258,6 @@ test "unwrap function call with optional pointer return value" {
260test "nested orelse" {258test "nested orelse" {
261 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO259 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
262 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO260 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
263 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
264261
265 const S = struct {262 const S = struct {
266 fn entry() !void {263 fn entry() !void {
...@@ -287,7 +284,6 @@ test "nested orelse" {...@@ -287,7 +284,6 @@ test "nested orelse" {
287test "self-referential struct through a slice of optional" {284test "self-referential struct through a slice of optional" {
288 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO285 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
289 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO286 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
290 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
291287
292 const S = struct {288 const S = struct {
293 const Node = struct {289 const Node = struct {
...@@ -344,7 +340,6 @@ test "0-bit child type coerced to optional return ptr result location" {...@@ -344,7 +340,6 @@ test "0-bit child type coerced to optional return ptr result location" {
344 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO340 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
345 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
346 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO342 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
347 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
348343
349 const S = struct {344 const S = struct {
350 fn doTheTest() !void {345 fn doTheTest() !void {
...@@ -535,7 +530,6 @@ test "Optional slice size is optimized" {...@@ -535,7 +530,6 @@ test "Optional slice size is optimized" {
535 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;530 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
536 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;531 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
537 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO532 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
538 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
539533
540 try expect(@sizeOf(?[]u8) == @sizeOf([]u8));534 try expect(@sizeOf(?[]u8) == @sizeOf([]u8));
541 var a: ?[]const u8 = null;535 var a: ?[]const u8 = null;
...@@ -549,7 +543,6 @@ test "Optional slice passed to function" {...@@ -549,7 +543,6 @@ test "Optional slice passed to function" {
549 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO543 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
550 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO544 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
551 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;545 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
552 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
553546
554 const S = struct {547 const S = struct {
555 fn foo(a: ?[]const u8) !void {548 fn foo(a: ?[]const u8) !void {
...@@ -566,7 +559,6 @@ test "Optional slice passed to function" {...@@ -566,7 +559,6 @@ test "Optional slice passed to function" {
566test "peer type resolution in nested if expressions" {559test "peer type resolution in nested if expressions" {
567 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;560 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
568 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;561 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
569 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
570562
571 const Thing = struct { n: i32 };563 const Thing = struct { n: i32 };
572 var a = false;564 var a = false;
...@@ -594,6 +586,7 @@ test "cast slice to const slice nested in error union and optional" {...@@ -594,6 +586,7 @@ test "cast slice to const slice nested in error union and optional" {
594 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;586 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
595 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;587 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
596 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;588 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
589 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
597590
598 const S = struct {591 const S = struct {
599 fn inner() !?[]u8 {592 fn inner() !?[]u8 {
...@@ -632,7 +625,6 @@ test "result location initialization of optional with OPV payload" {...@@ -632,7 +625,6 @@ test "result location initialization of optional with OPV payload" {
632 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO625 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
633 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO626 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
634 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;627 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
635 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
636628
637 const S = struct {629 const S = struct {
638 x: u0,630 x: u0,
test/behavior/packed-struct.zig-11
...@@ -258,7 +258,6 @@ test "nested packed struct unaligned" {...@@ -258,7 +258,6 @@ test "nested packed struct unaligned" {
258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;260 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
261 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
262 if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet261 if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet
263262
264 const S1 = packed struct {263 const S1 = packed struct {
...@@ -331,7 +330,6 @@ test "byte-aligned field pointer offsets" {...@@ -331,7 +330,6 @@ test "byte-aligned field pointer offsets" {
331 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;330 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
332 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO331 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
333 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;332 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
334 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
335333
336 const S = struct {334 const S = struct {
337 const A = packed struct {335 const A = packed struct {
...@@ -434,7 +432,6 @@ test "nested packed struct field pointers" {...@@ -434,7 +432,6 @@ test "nested packed struct field pointers" {
434 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO432 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
435 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;433 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
436 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access434 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access
437 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
438 if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet435 if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet
439436
440 const S2 = packed struct {437 const S2 = packed struct {
...@@ -962,7 +959,6 @@ test "pointer to container level packed struct field" {...@@ -962,7 +959,6 @@ test "pointer to container level packed struct field" {
962 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;959 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
963 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO960 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
964 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;961 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
965 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
966962
967 const S = packed struct(u32) {963 const S = packed struct(u32) {
968 test_bit: bool,964 test_bit: bool,
...@@ -1008,8 +1004,6 @@ test "bitcast back and forth" {...@@ -1008,8 +1004,6 @@ test "bitcast back and forth" {
1008}1004}
10091005
1010test "field access of packed struct smaller than its abi size inside struct initialized with rls" {1006test "field access of packed struct smaller than its abi size inside struct initialized with rls" {
1011 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1012
1013 // Originally reported at https://github.com/ziglang/zig/issues/142001007 // Originally reported at https://github.com/ziglang/zig/issues/14200
1014 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1008 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10151009
...@@ -1028,8 +1022,6 @@ test "field access of packed struct smaller than its abi size inside struct init...@@ -1028,8 +1022,6 @@ test "field access of packed struct smaller than its abi size inside struct init
1028}1022}
10291023
1030test "modify nested packed struct aligned field" {1024test "modify nested packed struct aligned field" {
1031 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1032
1033 // Originally reported at https://github.com/ziglang/zig/issues/146321025 // Originally reported at https://github.com/ziglang/zig/issues/14632
1034 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1026 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1035 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1027 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
...@@ -1096,7 +1088,6 @@ test "packed struct used as part of anon decl name" {...@@ -1096,7 +1088,6 @@ test "packed struct used as part of anon decl name" {
1096 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1088 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1097 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1089 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1098 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1090 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1099 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11001091
1101 const S = packed struct { a: u0 = 0 };1092 const S = packed struct { a: u0 = 0 };
1102 var a: u8 = 0;1093 var a: u8 = 0;
...@@ -1164,7 +1155,6 @@ test "assignment to non-byte-aligned field in packed struct" {...@@ -1164,7 +1155,6 @@ test "assignment to non-byte-aligned field in packed struct" {
1164 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1165 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1156 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1166 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1157 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1167 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11681158
1169 const Frame = packed struct {1159 const Frame = packed struct {
1170 num: u20,1160 num: u20,
...@@ -1275,7 +1265,6 @@ test "2-byte packed struct argument in C calling convention" {...@@ -1275,7 +1265,6 @@ test "2-byte packed struct argument in C calling convention" {
1275 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;1265 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
1276 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1266 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1277 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1267 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1278 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12791268
1280 const S = packed struct(u16) {1269 const S = packed struct(u16) {
1281 x: u15 = 0,1270 x: u15 = 0,
test/behavior/packed-union.zig-2
...@@ -8,7 +8,6 @@ test "flags in packed union" {...@@ -8,7 +8,6 @@ test "flags in packed union" {
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1211
13 try testFlagsInPackedUnion();12 try testFlagsInPackedUnion();
14 try comptime testFlagsInPackedUnion();13 try comptime testFlagsInPackedUnion();
...@@ -51,7 +50,6 @@ test "flags in packed union at offset" {...@@ -51,7 +50,6 @@ test "flags in packed union at offset" {
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;50 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;51 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;52 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
54 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5553
56 try testFlagsInPackedUnionAtOffset();54 try testFlagsInPackedUnionAtOffset();
57 try comptime testFlagsInPackedUnionAtOffset();55 try comptime testFlagsInPackedUnionAtOffset();
test/behavior/pointers.zig+1-5
...@@ -125,7 +125,6 @@ test "initialize const optional C pointer to null" {...@@ -125,7 +125,6 @@ test "initialize const optional C pointer to null" {
125125
126test "assigning integer to C pointer" {126test "assigning integer to C pointer" {
127 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO127 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
128 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
129128
130 var x: i32 = 0;129 var x: i32 = 0;
131 var y: i32 = 1;130 var y: i32 = 1;
...@@ -143,7 +142,6 @@ test "assigning integer to C pointer" {...@@ -143,7 +142,6 @@ test "assigning integer to C pointer" {
143142
144test "C pointer comparison and arithmetic" {143test "C pointer comparison and arithmetic" {
145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO144 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
147145
148 const S = struct {146 const S = struct {
149 fn doTheTest() !void {147 fn doTheTest() !void {
...@@ -230,6 +228,7 @@ test "implicit cast error unions with non-optional to optional pointer" {...@@ -230,6 +228,7 @@ test "implicit cast error unions with non-optional to optional pointer" {
230 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO228 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
231 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO229 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
232 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;230 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
231 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
233232
234 const S = struct {233 const S = struct {
235 fn doTheTest() !void {234 fn doTheTest() !void {
...@@ -343,7 +342,6 @@ test "array initialization types" {...@@ -343,7 +342,6 @@ test "array initialization types" {
343test "null terminated pointer" {342test "null terminated pointer" {
344 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;343 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
345 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO344 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
346 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
347345
348 const S = struct {346 const S = struct {
349 fn doTheTest() !void {347 fn doTheTest() !void {
...@@ -517,7 +515,6 @@ test "element pointer to slice" {...@@ -517,7 +515,6 @@ test "element pointer to slice" {
517test "element pointer arithmetic to slice" {515test "element pointer arithmetic to slice" {
518 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO516 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
519 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO517 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
520 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
521518
522 const S = struct {519 const S = struct {
523 fn doTheTest() !void {520 fn doTheTest() !void {
...@@ -572,7 +569,6 @@ test "ptrCast comptime known slice to C pointer" {...@@ -572,7 +569,6 @@ test "ptrCast comptime known slice to C pointer" {
572 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO569 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
573 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO570 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
574 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO571 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
575 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
576572
577 const s: [:0]const u8 = "foo";573 const s: [:0]const u8 = "foo";
578 var p: [*c]const u8 = @ptrCast(s);574 var p: [*c]const u8 = @ptrCast(s);
test/behavior/popcount.zig-1
...@@ -8,7 +8,6 @@ test "@popCount integers" {...@@ -8,7 +8,6 @@ test "@popCount integers" {
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1211
13 try comptime testPopCountIntegers();12 try comptime testPopCountIntegers();
14 try testPopCountIntegers();13 try testPopCountIntegers();
test/behavior/slice.zig-6
...@@ -30,7 +30,6 @@ comptime {...@@ -30,7 +30,6 @@ comptime {
3030
31test "slicing" {31test "slicing" {
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3433
35 var array: [20]i32 = undefined;34 var array: [20]i32 = undefined;
3635
...@@ -256,7 +255,6 @@ test "C pointer slice access" {...@@ -256,7 +255,6 @@ test "C pointer slice access" {
256 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;255 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
257 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;256 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
258 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO257 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
259 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
260258
261 var buf: [10]u32 = [1]u32{42} ** 10;259 var buf: [10]u32 = [1]u32{42} ** 10;
262 const c_ptr = @as([*c]const u32, @ptrCast(&buf));260 const c_ptr = @as([*c]const u32, @ptrCast(&buf));
...@@ -836,7 +834,6 @@ test "global slice field access" {...@@ -836,7 +834,6 @@ test "global slice field access" {
836 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO834 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
837 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO835 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
838 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;836 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
839 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
840837
841 const S = struct {838 const S = struct {
842 var slice: []const u8 = undefined;839 var slice: []const u8 = undefined;
...@@ -892,7 +889,6 @@ test "empty slice ptr is non null" {...@@ -892,7 +889,6 @@ test "empty slice ptr is non null" {
892test "slice decays to many pointer" {889test "slice decays to many pointer" {
893 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;890 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
894 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;891 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
895 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
896892
897 var buf: [8]u8 = "abcdefg\x00".*;893 var buf: [8]u8 = "abcdefg\x00".*;
898 const p: [*:0]const u8 = buf[0..7 :0];894 const p: [*:0]const u8 = buf[0..7 :0];
...@@ -903,7 +899,6 @@ test "write through pointer to optional slice arg" {...@@ -903,7 +899,6 @@ test "write through pointer to optional slice arg" {
903 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;899 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
904 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;900 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
905 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;901 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
906 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
907902
908 const S = struct {903 const S = struct {
909 fn bar(foo: *?[]const u8) !void {904 fn bar(foo: *?[]const u8) !void {
...@@ -956,7 +951,6 @@ test "slicing slices gives correct result" {...@@ -956,7 +951,6 @@ test "slicing slices gives correct result" {
956 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO951 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
957 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO952 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
958 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO953 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
959 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
960954
961 const foo = "1234";955 const foo = "1234";
962 const bar = foo[0..4];956 const bar = foo[0..4];
test/behavior/src.zig-3
...@@ -17,7 +17,6 @@ test "@src" {...@@ -17,7 +17,6 @@ test "@src" {
17 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO17 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO18 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
20 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2120
22 try doTheTest();21 try doTheTest();
23}22}
...@@ -38,8 +37,6 @@ test "@src used as a comptime parameter" {...@@ -38,8 +37,6 @@ test "@src used as a comptime parameter" {
38}37}
3938
40test "@src in tuple passed to anytype function" {39test "@src in tuple passed to anytype function" {
41 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
42
43 const S = struct {40 const S = struct {
44 fn Foo(a: anytype) u32 {41 fn Foo(a: anytype) u32 {
45 return a[0].line;42 return a[0].line;
test/behavior/string_literals.zig-2
...@@ -34,7 +34,6 @@ const ptr_type_name: [*:0]const u8 = type_name;...@@ -34,7 +34,6 @@ const ptr_type_name: [*:0]const u8 = type_name;
34test "@typeName() returns a string literal" {34test "@typeName() returns a string literal" {
35 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO35 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
36 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO36 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
37 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;37 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
3938
40 try std.testing.expect(*const [type_name.len:0]u8 == @TypeOf(type_name));39 try std.testing.expect(*const [type_name.len:0]u8 == @TypeOf(type_name));
...@@ -65,7 +64,6 @@ fn testFnForSrc() std.builtin.SourceLocation {...@@ -65,7 +64,6 @@ fn testFnForSrc() std.builtin.SourceLocation {
65test "@src() returns a struct containing 0-terminated string slices" {64test "@src() returns a struct containing 0-terminated string slices" {
66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO65 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
67 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO66 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
68 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
6967
70 const src = testFnForSrc();68 const src = testFnForSrc();
71 try std.testing.expect([:0]const u8 == @TypeOf(src.file));69 try std.testing.expect([:0]const u8 == @TypeOf(src.file));
test/behavior/struct.zig-19
...@@ -68,7 +68,6 @@ const SmallStruct = struct {...@@ -68,7 +68,6 @@ const SmallStruct = struct {
6868
69test "lower unnamed constants" {69test "lower unnamed constants" {
70 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO70 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
71 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7271
73 var foo = SmallStruct{ .a = 1, .b = 255 };72 var foo = SmallStruct{ .a = 1, .b = 255 };
74 try expect(foo.first() == 1);73 try expect(foo.first() == 1);
...@@ -419,7 +418,6 @@ test "packed struct 24bits" {...@@ -419,7 +418,6 @@ test "packed struct 24bits" {
419 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;418 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
420 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO419 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
421 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
422 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
423 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO421 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO
424 if (comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; // TODO422 if (comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; // TODO
425 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO423 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -506,7 +504,6 @@ test "packed struct fields are ordered from LSB to MSB" {...@@ -506,7 +504,6 @@ test "packed struct fields are ordered from LSB to MSB" {
506 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO504 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
507 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO505 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
508 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;506 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
509 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
510507
511 var all: u64 = 0x7765443322221111;508 var all: u64 = 0x7765443322221111;
512 var bytes: [8]u8 align(@alignOf(Bitfields)) = undefined;509 var bytes: [8]u8 align(@alignOf(Bitfields)) = undefined;
...@@ -527,7 +524,6 @@ test "implicit cast packed struct field to const ptr" {...@@ -527,7 +524,6 @@ test "implicit cast packed struct field to const ptr" {
527 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO524 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
528 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO525 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
529 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;526 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
530 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
531527
532 const LevelUpMove = packed struct {528 const LevelUpMove = packed struct {
533 move_id: u9,529 move_id: u9,
...@@ -593,7 +589,6 @@ test "bit field access" {...@@ -593,7 +589,6 @@ test "bit field access" {
593 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO589 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
594 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO590 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
595 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;591 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
596 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
597592
598 var data = bit_field_1;593 var data = bit_field_1;
599 try expect(getA(&data) == 1);594 try expect(getA(&data) == 1);
...@@ -650,7 +645,6 @@ test "packed array 24bits" {...@@ -650,7 +645,6 @@ test "packed array 24bits" {
650 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;645 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
651 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO646 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
652 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;647 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
653 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
654648
655 comptime {649 comptime {
656 try expect(@sizeOf([9]Foo32Bits) == 9 * 4);650 try expect(@sizeOf([9]Foo32Bits) == 9 * 4);
...@@ -718,7 +712,6 @@ test "pointer to packed struct member in a stack variable" {...@@ -718,7 +712,6 @@ test "pointer to packed struct member in a stack variable" {
718 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO712 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
719 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO713 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
720 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;714 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
721 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
722715
723 const S = packed struct {716 const S = packed struct {
724 a: u2,717 a: u2,
...@@ -1103,7 +1096,6 @@ test "packed struct with undefined initializers" {...@@ -1103,7 +1096,6 @@ test "packed struct with undefined initializers" {
1103 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1096 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1104 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1097 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1105 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1098 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1106 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11071099
1108 const S = struct {1100 const S = struct {
1109 const P = packed struct {1101 const P = packed struct {
...@@ -1133,7 +1125,6 @@ test "packed struct with undefined initializers" {...@@ -1133,7 +1125,6 @@ test "packed struct with undefined initializers" {
1133test "for loop over pointers to struct, getting field from struct pointer" {1125test "for loop over pointers to struct, getting field from struct pointer" {
1134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1126 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1135 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1127 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1136 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11371128
1138 const S = struct {1129 const S = struct {
1139 const Foo = struct {1130 const Foo = struct {
...@@ -1243,7 +1234,6 @@ test "typed init through error unions and optionals" {...@@ -1243,7 +1234,6 @@ test "typed init through error unions and optionals" {
1243 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1234 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1244 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1235 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1245 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1236 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1246 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12471237
1248 const S = struct {1238 const S = struct {
1249 a: u32,1239 a: u32,
...@@ -1465,8 +1455,6 @@ test "struct field has a pointer to an aligned version of itself" {...@@ -1465,8 +1455,6 @@ test "struct field has a pointer to an aligned version of itself" {
1465}1455}
14661456
1467test "struct has only one reference" {1457test "struct has only one reference" {
1468 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1469
1470 const S = struct {1458 const S = struct {
1471 fn optionalStructParam(_: ?struct { x: u8 }) void {}1459 fn optionalStructParam(_: ?struct { x: u8 }) void {}
1472 fn errorUnionStructParam(_: error{}!struct { x: u8 }) void {}1460 fn errorUnionStructParam(_: error{}!struct { x: u8 }) void {}
...@@ -1573,7 +1561,6 @@ test "no dependency loop on optional field wrapped in generic function" {...@@ -1573,7 +1561,6 @@ test "no dependency loop on optional field wrapped in generic function" {
1573test "optional field init with tuple" {1561test "optional field init with tuple" {
1574 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1562 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1575 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1563 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1576 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15771564
1578 const S = struct {1565 const S = struct {
1579 a: ?struct { b: u32 },1566 a: ?struct { b: u32 },
...@@ -1588,7 +1575,6 @@ test "optional field init with tuple" {...@@ -1588,7 +1575,6 @@ test "optional field init with tuple" {
15881575
1589test "if inside struct init inside if" {1576test "if inside struct init inside if" {
1590 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1577 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1591 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15921578
1593 const MyStruct = struct { x: u32 };1579 const MyStruct = struct { x: u32 };
1594 const b: u32 = 5;1580 const b: u32 = 5;
...@@ -1770,8 +1756,6 @@ test "struct init with no result pointer sets field result types" {...@@ -1770,8 +1756,6 @@ test "struct init with no result pointer sets field result types" {
1770}1756}
17711757
1772test "runtime side-effects in comptime-known struct init" {1758test "runtime side-effects in comptime-known struct init" {
1773 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1774
1775 var side_effects: u4 = 0;1759 var side_effects: u4 = 0;
1776 const S = struct { a: u4, b: u4, c: u4, d: u4 };1760 const S = struct { a: u4, b: u4, c: u4, d: u4 };
1777 const init = S{1761 const init = S{
...@@ -1797,8 +1781,6 @@ test "runtime side-effects in comptime-known struct init" {...@@ -1797,8 +1781,6 @@ test "runtime side-effects in comptime-known struct init" {
1797}1781}
17981782
1799test "pointer to struct initialized through reference to anonymous initializer provides result types" {1783test "pointer to struct initialized through reference to anonymous initializer provides result types" {
1800 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1801
1802 const S = struct { a: u8, b: u16, c: *const anyopaque };1784 const S = struct { a: u8, b: u16, c: *const anyopaque };
1803 var my_u16: u16 = 0xABCD;1785 var my_u16: u16 = 0xABCD;
1804 _ = &my_u16;1786 _ = &my_u16;
...@@ -1995,7 +1977,6 @@ test "runtime call in nested initializer" {...@@ -1995,7 +1977,6 @@ test "runtime call in nested initializer" {
1995 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO1977 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
1996 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1978 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1997 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1979 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1998 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19991980
2000 const Holder = struct {1981 const Holder = struct {
2001 array: []const u8,1982 array: []const u8,
test/behavior/switch.zig+2-10
...@@ -316,7 +316,6 @@ test "switch on union with some prongs capturing" {...@@ -316,7 +316,6 @@ test "switch on union with some prongs capturing" {
316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
317 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO317 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
318 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO318 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
319 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
320319
321 const X = union(enum) {320 const X = union(enum) {
322 a,321 a,
...@@ -427,6 +426,7 @@ test "else prong of switch on error set excludes other cases" {...@@ -427,6 +426,7 @@ test "else prong of switch on error set excludes other cases" {
427 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO426 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
428 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO427 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
429 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;428 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
429 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
430430
431 const S = struct {431 const S = struct {
432 fn doTheTest() !void {432 fn doTheTest() !void {
...@@ -462,6 +462,7 @@ test "switch prongs with error set cases make a new error set type for capture v...@@ -462,6 +462,7 @@ test "switch prongs with error set cases make a new error set type for capture v
462 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO462 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
463 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO463 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
464 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;464 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
465 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
465466
466 const S = struct {467 const S = struct {
467 fn doTheTest() !void {468 fn doTheTest() !void {
...@@ -516,7 +517,6 @@ test "switch with null and T peer types and inferred result location type" {...@@ -516,7 +517,6 @@ test "switch with null and T peer types and inferred result location type" {
516 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO517 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
517 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO518 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
518 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO519 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
519 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
520520
521 const S = struct {521 const S = struct {
522 fn doTheTest(c: u8) !void {522 fn doTheTest(c: u8) !void {
...@@ -537,7 +537,6 @@ test "switch prongs with cases with identical payload types" {...@@ -537,7 +537,6 @@ test "switch prongs with cases with identical payload types" {
537 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO537 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
538 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO538 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
539 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO539 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
540 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
541540
542 const Union = union(enum) {541 const Union = union(enum) {
543 A: usize,542 A: usize,
...@@ -781,8 +780,6 @@ test "comptime inline switch" {...@@ -781,8 +780,6 @@ test "comptime inline switch" {
781}780}
782781
783test "switch capture peer type resolution" {782test "switch capture peer type resolution" {
784 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
785
786 const U = union(enum) {783 const U = union(enum) {
787 a: u32,784 a: u32,
788 b: u64,785 b: u64,
...@@ -798,8 +795,6 @@ test "switch capture peer type resolution" {...@@ -798,8 +795,6 @@ test "switch capture peer type resolution" {
798}795}
799796
800test "switch capture peer type resolution for in-memory coercible payloads" {797test "switch capture peer type resolution for in-memory coercible payloads" {
801 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
802
803 const T1 = c_int;798 const T1 = c_int;
804 const T2 = @Type(@typeInfo(T1));799 const T2 = @Type(@typeInfo(T1));
805800
...@@ -821,7 +816,6 @@ test "switch capture peer type resolution for in-memory coercible payloads" {...@@ -821,7 +816,6 @@ test "switch capture peer type resolution for in-memory coercible payloads" {
821816
822test "switch pointer capture peer type resolution" {817test "switch pointer capture peer type resolution" {
823 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;818 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
824 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
825819
826 const T1 = c_int;820 const T1 = c_int;
827 const T2 = @Type(@typeInfo(T1));821 const T2 = @Type(@typeInfo(T1));
...@@ -924,8 +918,6 @@ test "switch prong captures range" {...@@ -924,8 +918,6 @@ test "switch prong captures range" {
924}918}
925919
926test "prong with inline call to unreachable" {920test "prong with inline call to unreachable" {
927 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
928
929 const U = union(enum) {921 const U = union(enum) {
930 void: void,922 void: void,
931 bool: bool,923 bool: bool,
test/behavior/switch_prong_implicit_cast.zig-1
...@@ -18,7 +18,6 @@ test "switch prong implicit cast" {...@@ -18,7 +18,6 @@ test "switch prong implicit cast" {
18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO20 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
21 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2221
23 const result = switch (foo(2) catch unreachable) {22 const result = switch (foo(2) catch unreachable) {
24 FormValue.One => false,23 FormValue.One => false,
test/behavior/threadlocal.zig-3
...@@ -6,7 +6,6 @@ test "thread local variable" {...@@ -6,7 +6,6 @@ test "thread local variable" {
6 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_llvm) switch (builtin.cpu.arch) {9 if (builtin.zig_backend == .stage2_llvm) switch (builtin.cpu.arch) {
11 .x86_64, .x86 => {},10 .x86_64, .x86 => {},
12 else => return error.SkipZigTest,11 else => return error.SkipZigTest,
...@@ -29,7 +28,6 @@ test "pointer to thread local array" {...@@ -29,7 +28,6 @@ test "pointer to thread local array" {
29 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO28 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_llvm) switch (builtin.cpu.arch) {31 if (builtin.zig_backend == .stage2_llvm) switch (builtin.cpu.arch) {
34 .x86_64, .x86 => {},32 .x86_64, .x86 => {},
35 else => return error.SkipZigTest,33 else => return error.SkipZigTest,
...@@ -47,7 +45,6 @@ test "reference a global threadlocal variable" {...@@ -47,7 +45,6 @@ test "reference a global threadlocal variable" {
47 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO45 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
48 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO46 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
49 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
50 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
51 if (builtin.zig_backend == .stage2_llvm) switch (builtin.cpu.arch) {48 if (builtin.zig_backend == .stage2_llvm) switch (builtin.cpu.arch) {
52 .x86_64, .x86 => {},49 .x86_64, .x86 => {},
53 else => return error.SkipZigTest,50 else => return error.SkipZigTest,
test/behavior/try.zig+1
...@@ -51,6 +51,7 @@ test "`try`ing an if/else expression" {...@@ -51,6 +51,7 @@ test "`try`ing an if/else expression" {
51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
53 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;53 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
54 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5455
55 const S = struct {56 const S = struct {
56 fn getError() !void {57 fn getError() !void {
test/behavior/tuple.zig-5
...@@ -280,7 +280,6 @@ test "tuple in tuple passed to generic function" {...@@ -280,7 +280,6 @@ test "tuple in tuple passed to generic function" {
280 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO280 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
281 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO281 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
282 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO282 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
283 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
284283
285 const S = struct {284 const S = struct {
286 fn pair(x: f32, y: f32) std.meta.Tuple(&.{ f32, f32 }) {285 fn pair(x: f32, y: f32) std.meta.Tuple(&.{ f32, f32 }) {
...@@ -300,7 +299,6 @@ test "coerce tuple to tuple" {...@@ -300,7 +299,6 @@ test "coerce tuple to tuple" {
300 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO299 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
301 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO300 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
302 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO301 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
303 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
304302
305 const T = std.meta.Tuple(&.{u8});303 const T = std.meta.Tuple(&.{u8});
306 const S = struct {304 const S = struct {
...@@ -315,7 +313,6 @@ test "tuple type with void field" {...@@ -315,7 +313,6 @@ test "tuple type with void field" {
315 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO314 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
317 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO315 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
318 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
319316
320 const T = std.meta.Tuple(&[_]type{void});317 const T = std.meta.Tuple(&[_]type{void});
321 const x = T{{}};318 const x = T{{}};
...@@ -352,7 +349,6 @@ test "zero sized struct in tuple handled correctly" {...@@ -352,7 +349,6 @@ test "zero sized struct in tuple handled correctly" {
352test "tuple type with void field and a runtime field" {349test "tuple type with void field and a runtime field" {
353 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO350 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
354 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO351 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
355 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
356352
357 const T = std.meta.Tuple(&[_]type{ usize, void });353 const T = std.meta.Tuple(&[_]type{ usize, void });
358 var t: T = .{ 5, {} };354 var t: T = .{ 5, {} };
...@@ -409,7 +405,6 @@ test "nested runtime conditionals in tuple initializer" {...@@ -409,7 +405,6 @@ test "nested runtime conditionals in tuple initializer" {
409 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO405 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
410 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO406 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
411 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO407 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
412 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
413408
414 var data: u8 = 0;409 var data: u8 = 0;
415 _ = &data;410 _ = &data;
test/behavior/tuple_declarations.zig-2
...@@ -7,7 +7,6 @@ const expectEqualStrings = testing.expectEqualStrings;...@@ -7,7 +7,6 @@ const expectEqualStrings = testing.expectEqualStrings;
7test "tuple declaration type info" {7test "tuple declaration type info" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1110
12 {11 {
13 const T = struct { comptime u32 align(2) = 1, []const u8 };12 const T = struct { comptime u32 align(2) = 1, []const u8 };
...@@ -36,7 +35,6 @@ test "tuple declaration type info" {...@@ -36,7 +35,6 @@ test "tuple declaration type info" {
36test "Tuple declaration usage" {35test "Tuple declaration usage" {
37 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
4038
41 const T = struct { u32, []const u8 };39 const T = struct { u32, []const u8 };
42 var t: T = .{ 1, "foo" };40 var t: T = .{ 1, "foo" };
test/behavior/type_info.zig-5
...@@ -565,8 +565,6 @@ test "StructField.is_comptime" {...@@ -565,8 +565,6 @@ test "StructField.is_comptime" {
565}565}
566566
567test "typeInfo resolves usingnamespace declarations" {567test "typeInfo resolves usingnamespace declarations" {
568 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
569
570 const A = struct {568 const A = struct {
571 pub const f1 = 42;569 pub const f1 = 42;
572 };570 };
...@@ -592,7 +590,6 @@ test "value from struct @typeInfo default_value can be loaded at comptime" {...@@ -592,7 +590,6 @@ test "value from struct @typeInfo default_value can be loaded at comptime" {
592test "@typeInfo decls and usingnamespace" {590test "@typeInfo decls and usingnamespace" {
593 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO591 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
594 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO592 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
595 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
596593
597 const A = struct {594 const A = struct {
598 pub const x = 5;595 pub const x = 5;
...@@ -633,8 +630,6 @@ test "type info of tuple of string literal default value" {...@@ -633,8 +630,6 @@ test "type info of tuple of string literal default value" {
633}630}
634631
635test "@typeInfo only contains pub decls" {632test "@typeInfo only contains pub decls" {
636 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
637
638 const other = struct {633 const other = struct {
639 const std = @import("std");634 const std = @import("std");
640635
test/behavior/typename.zig-8
...@@ -16,7 +16,6 @@ test "anon fn param" {...@@ -16,7 +16,6 @@ test "anon fn param" {
16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO17 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2019
21 // https://github.com/ziglang/zig/issues/933920 // https://github.com/ziglang/zig/issues/9339
22 try expectEqualStringsIgnoreDigits(21 try expectEqualStringsIgnoreDigits(
...@@ -42,7 +41,6 @@ test "anon field init" {...@@ -42,7 +41,6 @@ test "anon field init" {
42 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO41 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
43 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
44 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO43 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
46 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;44 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
4745
48 const Foo = .{46 const Foo = .{
...@@ -69,7 +67,6 @@ test "basic" {...@@ -69,7 +67,6 @@ test "basic" {
69 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO67 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
70 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO68 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
71 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7370
74 try expectEqualStrings("i64", @typeName(i64));71 try expectEqualStrings("i64", @typeName(i64));
75 try expectEqualStrings("*usize", @typeName(*usize));72 try expectEqualStrings("*usize", @typeName(*usize));
...@@ -91,7 +88,6 @@ test "top level decl" {...@@ -91,7 +88,6 @@ test "top level decl" {
91 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO88 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
92 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO89 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
93 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO90 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
95 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;91 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
9692
97 try expectEqualStrings(93 try expectEqualStrings(
...@@ -142,7 +138,6 @@ test "fn param" {...@@ -142,7 +138,6 @@ test "fn param" {
142 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO138 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
143 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO139 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
144 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO140 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
146 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;141 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
147142
148 // https://github.com/ziglang/zig/issues/675143 // https://github.com/ziglang/zig/issues/675
...@@ -223,7 +218,6 @@ test "local variable" {...@@ -223,7 +218,6 @@ test "local variable" {
223 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO218 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
224 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO219 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
225 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO220 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
226 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
227 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;221 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
228222
229 const Foo = struct { a: u32 };223 const Foo = struct { a: u32 };
...@@ -243,7 +237,6 @@ test "comptime parameters not converted to anytype in function type" {...@@ -243,7 +237,6 @@ test "comptime parameters not converted to anytype in function type" {
243 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO237 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
244 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO238 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
245 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO239 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
246 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
247240
248 const T = fn (fn (type) void, void) void;241 const T = fn (fn (type) void, void) void;
249 try expectEqualStrings("fn (comptime fn (comptime type) void, void) void", @typeName(T));242 try expectEqualStrings("fn (comptime fn (comptime type) void, void) void", @typeName(T));
...@@ -253,7 +246,6 @@ test "anon name strategy used in sub expression" {...@@ -253,7 +246,6 @@ test "anon name strategy used in sub expression" {
253 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO246 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
254 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO247 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
255 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO248 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
256 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
257 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;249 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
258250
259 const S = struct {251 const S = struct {
test/behavior/union.zig-9
...@@ -100,7 +100,6 @@ const FooExtern = extern union {...@@ -100,7 +100,6 @@ const FooExtern = extern union {
100test "basic extern unions" {100test "basic extern unions" {
101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
104103
105 var foo = FooExtern{ .int = 1 };104 var foo = FooExtern{ .int = 1 };
106 try expect(foo.int == 1);105 try expect(foo.int == 1);
...@@ -172,7 +171,6 @@ test "constant tagged union with payload" {...@@ -172,7 +171,6 @@ test "constant tagged union with payload" {
172 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;171 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
173 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;172 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
174 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO173 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
175 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
176174
177 var empty = TaggedUnionWithPayload{ .Empty = {} };175 var empty = TaggedUnionWithPayload{ .Empty = {} };
178 var full = TaggedUnionWithPayload{ .Full = 13 };176 var full = TaggedUnionWithPayload{ .Full = 13 };
...@@ -656,7 +654,6 @@ test "union(enum(u32)) with specified and unspecified tag values" {...@@ -656,7 +654,6 @@ test "union(enum(u32)) with specified and unspecified tag values" {
656 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;654 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
657 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;655 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
658 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO656 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
659 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
660657
661 comptime assert(Tag(Tag(MultipleChoice2)) == u32);658 comptime assert(Tag(Tag(MultipleChoice2)) == u32);
662 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });659 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
...@@ -808,7 +805,6 @@ test "return union init with void payload" {...@@ -808,7 +805,6 @@ test "return union init with void payload" {
808 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;805 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
809 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;806 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
810 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO807 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
811 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
812808
813 const S = struct {809 const S = struct {
814 fn entry() !void {810 fn entry() !void {
...@@ -971,7 +967,6 @@ test "function call result coerces from tagged union to the tag" {...@@ -971,7 +967,6 @@ test "function call result coerces from tagged union to the tag" {
971 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO967 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
972 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO968 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
973 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO969 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
974 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
975970
976 const S = struct {971 const S = struct {
977 const Arch = union(enum) {972 const Arch = union(enum) {
...@@ -1136,7 +1131,6 @@ test "@unionInit on union with tag but no fields" {...@@ -1136,7 +1131,6 @@ test "@unionInit on union with tag but no fields" {
1136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1131 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1137 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1132 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1138 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1133 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1139 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11401134
1141 const S = struct {1135 const S = struct {
1142 const Type = enum(u8) { no_op = 105 };1136 const Type = enum(u8) { no_op = 105 };
...@@ -1700,7 +1694,6 @@ test "packed union field pointer has correct alignment" {...@@ -1700,7 +1694,6 @@ test "packed union field pointer has correct alignment" {
17001694
1701test "union with 128 bit integer" {1695test "union with 128 bit integer" {
1702 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1696 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1703 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
17041697
1705 const ValueTag = enum { int, other };1698 const ValueTag = enum { int, other };
17061699
...@@ -1917,7 +1910,6 @@ test "reinterpret packed union" {...@@ -1917,7 +1910,6 @@ test "reinterpret packed union" {
19171910
1918test "reinterpret packed union inside packed struct" {1911test "reinterpret packed union inside packed struct" {
1919 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1912 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1920 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19211913
1922 const U = packed union {1914 const U = packed union {
1923 a: u7,1915 a: u7,
...@@ -2196,7 +2188,6 @@ test "copied union field doesn't alias source" {...@@ -2196,7 +2188,6 @@ test "copied union field doesn't alias source" {
2196 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2188 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2197 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2198 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2190 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2199 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
22002191
2201 const U = union(enum) {2192 const U = union(enum) {
2202 array: [10]u32,2193 array: [10]u32,
test/behavior/union_with_members.zig-1
...@@ -21,7 +21,6 @@ test "enum with members" {...@@ -21,7 +21,6 @@ test "enum with members" {
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;23 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2524
26 const a = ET{ .SINT = -42 };25 const a = ET{ .SINT = -42 };
27 const b = ET{ .UINT = 42 };26 const b = ET{ .UINT = 42 };
test/behavior/vector.zig+3-10
...@@ -102,7 +102,6 @@ test "vector float operators" {...@@ -102,7 +102,6 @@ test "vector float operators" {
102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;103 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
104 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;104 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
105 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
106 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO105 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
107106
108 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {107 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
...@@ -119,7 +118,7 @@ test "vector float operators" {...@@ -119,7 +118,7 @@ test "vector float operators" {
119 try expectEqual(v + x, .{ 11, 22, 33, 44 });118 try expectEqual(v + x, .{ 11, 22, 33, 44 });
120 try expectEqual(v - x, .{ 9, 18, 27, 36 });119 try expectEqual(v - x, .{ 9, 18, 27, 36 });
121 try expectEqual(v * x, .{ 10, 40, 90, 160 });120 try expectEqual(v * x, .{ 10, 40, 90, 160 });
122 try expectEqual(-x, .{ -1, -2, -3, -4 });121 if (builtin.zig_backend != .stage2_riscv64) try expectEqual(-x, .{ -1, -2, -3, -4 });
123 }122 }
124 };123 };
125124
...@@ -129,6 +128,8 @@ test "vector float operators" {...@@ -129,6 +128,8 @@ test "vector float operators" {
129 try S.doTheTest(f64);128 try S.doTheTest(f64);
130 try comptime S.doTheTest(f64);129 try comptime S.doTheTest(f64);
131130
131 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
132
132 try S.doTheTest(f16);133 try S.doTheTest(f16);
133 try comptime S.doTheTest(f16);134 try comptime S.doTheTest(f16);
134135
...@@ -394,7 +395,6 @@ test "load vector elements via comptime index" {...@@ -394,7 +395,6 @@ test "load vector elements via comptime index" {
394 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO395 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
395 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO396 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO397 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
397 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
398398
399 const S = struct {399 const S = struct {
400 fn doTheTest() !void {400 fn doTheTest() !void {
...@@ -416,7 +416,6 @@ test "store vector elements via comptime index" {...@@ -416,7 +416,6 @@ test "store vector elements via comptime index" {
416 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO416 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
417 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO417 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
418 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO418 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
419 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
420419
421 const S = struct {420 const S = struct {
422 fn doTheTest() !void {421 fn doTheTest() !void {
...@@ -444,7 +443,6 @@ test "load vector elements via runtime index" {...@@ -444,7 +443,6 @@ test "load vector elements via runtime index" {
444 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO443 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
445 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO444 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
446 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO445 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
447 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
448446
449 const S = struct {447 const S = struct {
450 fn doTheTest() !void {448 fn doTheTest() !void {
...@@ -467,7 +465,6 @@ test "store vector elements via runtime index" {...@@ -467,7 +465,6 @@ test "store vector elements via runtime index" {
467 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO465 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
468 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO466 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
469 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO467 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
470 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
471468
472 const S = struct {469 const S = struct {
473 fn doTheTest() !void {470 fn doTheTest() !void {
...@@ -1239,7 +1236,6 @@ test "loading the second vector from a slice of vectors" {...@@ -1239,7 +1236,6 @@ test "loading the second vector from a slice of vectors" {
1239 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1236 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1240 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1241 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1242 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12431239
1244 @setRuntimeSafety(false);1240 @setRuntimeSafety(false);
1245 var small_bases = [2]@Vector(2, u8){1241 var small_bases = [2]@Vector(2, u8){
...@@ -1326,7 +1322,6 @@ test "zero multiplicand" {...@@ -1326,7 +1322,6 @@ test "zero multiplicand" {
1326 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1322 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1327 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1323 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1328 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1324 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1329 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13301325
1331 const zeros = @Vector(2, u32){ 0.0, 0.0 };1326 const zeros = @Vector(2, u32){ 0.0, 0.0 };
1332 var ones = @Vector(2, u32){ 1.0, 1.0 };1327 var ones = @Vector(2, u32){ 1.0, 1.0 };
...@@ -1487,7 +1482,6 @@ test "store vector with memset" {...@@ -1487,7 +1482,6 @@ test "store vector with memset" {
1487test "addition of vectors represented as strings" {1482test "addition of vectors represented as strings" {
1488 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1483 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1489 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1484 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1490 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14911485
1492 const V = @Vector(3, u8);1486 const V = @Vector(3, u8);
1493 const foo: V = "foo".*;1487 const foo: V = "foo".*;
...@@ -1514,7 +1508,6 @@ test "vector pointer is indexable" {...@@ -1514,7 +1508,6 @@ test "vector pointer is indexable" {
1514 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1508 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1515 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1509 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1516 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1510 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1517 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15181511
1519 const V = @Vector(2, u32);1512 const V = @Vector(2, u32);
15201513
test/behavior/while.zig-5
...@@ -106,7 +106,6 @@ fn testBreakOuter() void {...@@ -106,7 +106,6 @@ fn testBreakOuter() void {
106test "while copies its payload" {106test "while copies its payload" {
107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
110109
111 const S = struct {110 const S = struct {
112 fn doTheTest() !void {111 fn doTheTest() !void {
...@@ -208,7 +207,6 @@ test "while on optional with else result follow else prong" {...@@ -208,7 +207,6 @@ test "while on optional with else result follow else prong" {
208 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;207 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
209 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;208 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
210 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO209 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
211 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
212210
213 const result = while (returnNull()) |value| {211 const result = while (returnNull()) |value| {
214 break value;212 break value;
...@@ -220,7 +218,6 @@ test "while on optional with else result follow break prong" {...@@ -220,7 +218,6 @@ test "while on optional with else result follow break prong" {
220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;218 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
221 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
222 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO220 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
223 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
224221
225 const result = while (returnOptional(10)) |value| {222 const result = while (returnOptional(10)) |value| {
226 break value;223 break value;
...@@ -293,7 +290,6 @@ test "while optional 2 break statements and an else" {...@@ -293,7 +290,6 @@ test "while optional 2 break statements and an else" {
293 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO290 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
294 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO291 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
295 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO292 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
296 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
297293
298 const S = struct {294 const S = struct {
299 fn entry(opt_t: ?bool, f: bool) !void {295 fn entry(opt_t: ?bool, f: bool) !void {
...@@ -392,7 +388,6 @@ test "breaking from a loop in an if statement" {...@@ -392,7 +388,6 @@ test "breaking from a loop in an if statement" {
392 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;388 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
393 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;389 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
394 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO390 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
395 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
396391
397 const S = struct {392 const S = struct {
398 fn retOpt() ?u32 {393 fn retOpt() ?u32 {
test/tests.zig+1-1
...@@ -439,7 +439,7 @@ const test_targets = blk: {...@@ -439,7 +439,7 @@ const test_targets = blk: {
439 .target = std.Target.Query.parse(439 .target = std.Target.Query.parse(
440 .{440 .{
441 .arch_os_abi = "riscv64-linux-musl",441 .arch_os_abi = "riscv64-linux-musl",
442 .cpu_features = "baseline+v",442 .cpu_features = "baseline+v+zbb",
443 },443 },
444 ) catch @panic("OOM"),444 ) catch @panic("OOM"),
445 .use_llvm = false,445 .use_llvm = false,