authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-06-19 17:42:08+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-06-19 17:42:08+02:00
loga154d8da8e39e5d0ed180b4a1e5150349699e5df
tree5874c40fd206987d89d5118e3a49fa08c22552fc
parent1fdf13a14825d6e1bd247754e3677cf546ee4020
parente60c5811473df6c092aa772b63f2cf5d27b7ff46
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20070 from Rexicon226/riscv

more RISC-V backend progress

74 files changed, 4762 insertions(+), 3106 deletions(-)

lib/compiler/test_runner.zig+20-28
...@@ -12,10 +12,8 @@ var cmdline_buffer: [4096]u8 = undefined;...@@ -12,10 +12,8 @@ var cmdline_buffer: [4096]u8 = undefined;
12var fba = std.heap.FixedBufferAllocator.init(&cmdline_buffer);12var fba = std.heap.FixedBufferAllocator.init(&cmdline_buffer);
1313
14pub fn main() void {14pub fn main() void {
15 if (builtin.zig_backend == .stage2_riscv64) return mainExtraSimple() catch @panic("test failure");15 if (builtin.zig_backend == .stage2_riscv64) {
1616 return mainSimple() catch @panic("test failure\n");
17 if (builtin.zig_backend == .stage2_aarch64) {
18 return mainSimple() catch @panic("test failure");
19 }17 }
2018
21 const args = std.process.argsAlloc(fba.allocator()) catch19 const args = std.process.argsAlloc(fba.allocator()) catch
...@@ -221,20 +219,30 @@ pub fn log(...@@ -221,20 +219,30 @@ pub fn log(
221/// Simpler main(), exercising fewer language features, so that219/// Simpler main(), exercising fewer language features, so that
222/// work-in-progress backends can handle it.220/// work-in-progress backends can handle it.
223pub fn mainSimple() anyerror!void {221pub fn mainSimple() anyerror!void {
224 const enable_print = false;222 // is the backend capable of printing to stderr?
225 const print_all = false;223 const enable_print = switch (builtin.zig_backend) {
224 .stage2_riscv64 => true,
225 else => false,
226 };
227 // is the backend capable of using std.fmt.format to print a summary at the end?
228 const print_summary = switch (builtin.zig_backend) {
229 else => false,
230 };
226231
227 var passed: u64 = 0;232 var passed: u64 = 0;
228 var skipped: u64 = 0;233 var skipped: u64 = 0;
229 var failed: u64 = 0;234 var failed: u64 = 0;
230 const stderr = if (enable_print) std.io.getStdErr() else {};235
236 // we don't want to bring in File and Writer if the backend doesn't support it
237 const stderr = if (comptime enable_print) std.io.getStdErr() else {};
238
231 for (builtin.test_functions) |test_fn| {239 for (builtin.test_functions) |test_fn| {
232 if (enable_print and print_all) {240 if (enable_print) {
233 stderr.writeAll(test_fn.name) catch {};241 stderr.writeAll(test_fn.name) catch {};
234 stderr.writeAll("... ") catch {};242 stderr.writeAll("... ") catch {};
235 }243 }
236 test_fn.func() catch |err| {244 test_fn.func() catch |err| {
237 if (enable_print and !print_all) {245 if (enable_print) {
238 stderr.writeAll(test_fn.name) catch {};246 stderr.writeAll(test_fn.name) catch {};
239 stderr.writeAll("... ") catch {};247 stderr.writeAll("... ") catch {};
240 }248 }
...@@ -248,27 +256,11 @@ pub fn mainSimple() anyerror!void {...@@ -248,27 +256,11 @@ pub fn mainSimple() anyerror!void {
248 skipped += 1;256 skipped += 1;
249 continue;257 continue;
250 };258 };
251 if (enable_print and print_all) stderr.writeAll("PASS\n") catch {};259 if (enable_print) stderr.writeAll("PASS\n") catch {};
252 passed += 1;260 passed += 1;
253 }261 }
254 if (enable_print) {262 if (enable_print and print_summary) {
255 stderr.writer().print("{} passed, {} skipped, {} failed\n", .{ passed, skipped, failed }) catch {};263 stderr.writer().print("{} passed, {} skipped, {} failed\n", .{ passed, skipped, failed }) catch {};
256 if (failed != 0) std.process.exit(1);
257 }
258}
259
260pub fn mainExtraSimple() !void {
261 var fail_count: u8 = 0;
262
263 for (builtin.test_functions) |test_fn| {
264 test_fn.func() catch |err| {
265 if (err != error.SkipZigTest) {
266 fail_count += 1;
267 continue;
268 }
269 continue;
270 };
271 }264 }
272265 if (failed != 0) std.process.exit(1);
273 if (fail_count != 0) std.process.exit(1);
274}266}
src/arch/riscv64/CodeGen.zig+3599-2270
...@@ -22,6 +22,8 @@ const DW = std.dwarf;...@@ -22,6 +22,8 @@ const DW = std.dwarf;
22const leb128 = std.leb;22const leb128 = std.leb;
23const log = std.log.scoped(.riscv_codegen);23const log = std.log.scoped(.riscv_codegen);
24const tracking_log = std.log.scoped(.tracking);24const tracking_log = std.log.scoped(.tracking);
25const verbose_tracking_log = std.log.scoped(.verbose_tracking);
26const wip_mir_log = std.log.scoped(.wip_mir);
25const build_options = @import("build_options");27const build_options = @import("build_options");
26const codegen = @import("../../codegen.zig");28const codegen = @import("../../codegen.zig");
27const Alignment = InternPool.Alignment;29const Alignment = InternPool.Alignment;
...@@ -32,29 +34,17 @@ const DebugInfoOutput = codegen.DebugInfoOutput;...@@ -32,29 +34,17 @@ const DebugInfoOutput = codegen.DebugInfoOutput;
3234
33const bits = @import("bits.zig");35const bits = @import("bits.zig");
34const abi = @import("abi.zig");36const abi = @import("abi.zig");
37const Lower = @import("Lower.zig");
38
35const Register = bits.Register;39const Register = bits.Register;
36const Immediate = bits.Immediate;40const Immediate = bits.Immediate;
37const Memory = bits.Memory;41const Memory = bits.Memory;
38const FrameIndex = bits.FrameIndex;42const FrameIndex = bits.FrameIndex;
39const RegisterManager = abi.RegisterManager;43const RegisterManager = abi.RegisterManager;
40const RegisterLock = RegisterManager.RegisterLock;44const RegisterLock = RegisterManager.RegisterLock;
41const callee_preserved_regs = abi.callee_preserved_regs;
42/// General Purpose
43const gp = abi.RegisterClass.gp;
44/// Function Args
45const fa = abi.RegisterClass.fa;
46/// Function Returns
47const fr = abi.RegisterClass.fr;
48/// Temporary Use
49const tp = abi.RegisterClass.tp;
5045
51const InnerError = CodeGenError || error{OutOfRegisters};46const InnerError = CodeGenError || error{OutOfRegisters};
5247
53const RegisterView = enum(u1) {
54 caller,
55 callee,
56};
57
58gpa: Allocator,48gpa: Allocator,
59air: Air,49air: Air,
60mod: *Package.Module,50mod: *Package.Module,
...@@ -172,6 +162,14 @@ const MCValue = union(enum) {...@@ -172,6 +162,14 @@ const MCValue = union(enum) {
172 };162 };
173 }163 }
174164
165 fn isRegister(mcv: MCValue) bool {
166 return switch (mcv) {
167 .register => true,
168 .register_offset => |reg_off| return reg_off.off == 0,
169 else => false,
170 };
171 }
172
175 fn isMutable(mcv: MCValue) bool {173 fn isMutable(mcv: MCValue) bool {
176 return switch (mcv) {174 return switch (mcv) {
177 .none => unreachable,175 .none => unreachable,
...@@ -295,14 +293,15 @@ const MCValue = union(enum) {...@@ -295,14 +293,15 @@ const MCValue = union(enum) {
295const Branch = struct {293const Branch = struct {
296 inst_table: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, MCValue) = .{},294 inst_table: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, MCValue) = .{},
297295
298 fn deinit(self: *Branch, gpa: Allocator) void {296 fn deinit(func: *Branch, gpa: Allocator) void {
299 self.inst_table.deinit(gpa);297 func.inst_table.deinit(gpa);
300 self.* = undefined;298 func.* = undefined;
301 }299 }
302};300};
303301
304const InstTrackingMap = std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InstTracking);302const InstTrackingMap = std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InstTracking);
305const ConstTrackingMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, InstTracking);303const ConstTrackingMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, InstTracking);
304
306const InstTracking = struct {305const InstTracking = struct {
307 long: MCValue,306 long: MCValue,
308 short: MCValue,307 short: MCValue,
...@@ -331,33 +330,37 @@ const InstTracking = struct {...@@ -331,33 +330,37 @@ const InstTracking = struct {
331 }, .short = result };330 }, .short = result };
332 }331 }
333332
334 fn getReg(self: InstTracking) ?Register {333 fn getReg(inst_tracking: InstTracking) ?Register {
335 return self.short.getReg();334 return inst_tracking.short.getReg();
336 }335 }
337336
338 fn getRegs(self: *const InstTracking) []const Register {337 fn getRegs(inst_tracking: *const InstTracking) []const Register {
339 return self.short.getRegs();338 return inst_tracking.short.getRegs();
340 }339 }
341340
342 fn spill(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void {341 fn spill(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {
343 if (std.meta.eql(self.long, self.short)) return; // Already spilled342 if (std.meta.eql(inst_tracking.long, inst_tracking.short)) return; // Already spilled
344 // Allocate or reuse frame index343 // Allocate or reuse frame index
345 switch (self.long) {344 switch (inst_tracking.long) {
346 .none => self.long = try function.allocRegOrMem(inst, false),345 .none => inst_tracking.long = try function.allocRegOrMem(
346 function.typeOfIndex(inst),
347 inst,
348 false,
349 ),
347 .load_frame => {},350 .load_frame => {},
348 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },351 .reserved_frame => |index| inst_tracking.long = .{ .load_frame = .{ .index = index } },
349 else => unreachable,352 else => unreachable,
350 }353 }
351 tracking_log.debug("spill %{d} from {} to {}", .{ inst, self.short, self.long });354 tracking_log.debug("spill %{d} from {} to {}", .{ inst, inst_tracking.short, inst_tracking.long });
352 try function.genCopy(function.typeOfIndex(inst), self.long, self.short);355 try function.genCopy(function.typeOfIndex(inst), inst_tracking.long, inst_tracking.short);
353 }356 }
354357
355 fn reuseFrame(self: *InstTracking) void {358 fn reuseFrame(inst_tracking: *InstTracking) void {
356 switch (self.long) {359 switch (inst_tracking.long) {
357 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },360 .reserved_frame => |index| inst_tracking.long = .{ .load_frame = .{ .index = index } },
358 else => {},361 else => {},
359 }362 }
360 self.short = switch (self.long) {363 inst_tracking.short = switch (inst_tracking.long) {
361 .none,364 .none,
362 .unreach,365 .unreach,
363 .undef,366 .undef,
...@@ -367,7 +370,7 @@ const InstTracking = struct {...@@ -367,7 +370,7 @@ const InstTracking = struct {
367 .lea_frame,370 .lea_frame,
368 .load_symbol,371 .load_symbol,
369 .lea_symbol,372 .lea_symbol,
370 => self.long,373 => inst_tracking.long,
371 .dead,374 .dead,
372 .register,375 .register,
373 .register_pair,376 .register_pair,
...@@ -379,14 +382,14 @@ const InstTracking = struct {...@@ -379,14 +382,14 @@ const InstTracking = struct {
379 };382 };
380 }383 }
381384
382 fn trackSpill(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void {385 fn trackSpill(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {
383 try function.freeValue(self.short);386 try function.freeValue(inst_tracking.short);
384 self.reuseFrame();387 inst_tracking.reuseFrame();
385 tracking_log.debug("%{d} => {} (spilled)", .{ inst, self.* });388 tracking_log.debug("%{d} => {} (spilled)", .{ inst, inst_tracking.* });
386 }389 }
387390
388 fn verifyMaterialize(self: InstTracking, target: InstTracking) void {391 fn verifyMaterialize(inst_tracking: InstTracking, target: InstTracking) void {
389 switch (self.long) {392 switch (inst_tracking.long) {
390 .none,393 .none,
391 .unreach,394 .unreach,
392 .undef,395 .undef,
...@@ -395,7 +398,7 @@ const InstTracking = struct {...@@ -395,7 +398,7 @@ const InstTracking = struct {
395 .lea_frame,398 .lea_frame,
396 .load_symbol,399 .load_symbol,
397 .lea_symbol,400 .lea_symbol,
398 => assert(std.meta.eql(self.long, target.long)),401 => assert(std.meta.eql(inst_tracking.long, target.long)),
399 .load_frame,402 .load_frame,
400 .reserved_frame,403 .reserved_frame,
401 => switch (target.long) {404 => switch (target.long) {
...@@ -416,73 +419,73 @@ const InstTracking = struct {...@@ -416,73 +419,73 @@ const InstTracking = struct {
416 }419 }
417420
418 fn materialize(421 fn materialize(
419 self: *InstTracking,422 inst_tracking: *InstTracking,
420 function: *Self,423 function: *Func,
421 inst: Air.Inst.Index,424 inst: Air.Inst.Index,
422 target: InstTracking,425 target: InstTracking,
423 ) !void {426 ) !void {
424 self.verifyMaterialize(target);427 inst_tracking.verifyMaterialize(target);
425 try self.materializeUnsafe(function, inst, target);428 try inst_tracking.materializeUnsafe(function, inst, target);
426 }429 }
427430
428 fn materializeUnsafe(431 fn materializeUnsafe(
429 self: InstTracking,432 inst_tracking: InstTracking,
430 function: *Self,433 function: *Func,
431 inst: Air.Inst.Index,434 inst: Air.Inst.Index,
432 target: InstTracking,435 target: InstTracking,
433 ) !void {436 ) !void {
434 const ty = function.typeOfIndex(inst);437 const ty = function.typeOfIndex(inst);
435 if ((self.long == .none or self.long == .reserved_frame) and target.long == .load_frame)438 if ((inst_tracking.long == .none or inst_tracking.long == .reserved_frame) and target.long == .load_frame)
436 try function.genCopy(ty, target.long, self.short);439 try function.genCopy(ty, target.long, inst_tracking.short);
437 try function.genCopy(ty, target.short, self.short);440 try function.genCopy(ty, target.short, inst_tracking.short);
438 }441 }
439442
440 fn trackMaterialize(self: *InstTracking, inst: Air.Inst.Index, target: InstTracking) void {443 fn trackMaterialize(inst_tracking: *InstTracking, inst: Air.Inst.Index, target: InstTracking) void {
441 self.verifyMaterialize(target);444 inst_tracking.verifyMaterialize(target);
442 // Don't clobber reserved frame indices445 // Don't clobber reserved frame indices
443 self.long = if (target.long == .none) switch (self.long) {446 inst_tracking.long = if (target.long == .none) switch (inst_tracking.long) {
444 .load_frame => |addr| .{ .reserved_frame = addr.index },447 .load_frame => |addr| .{ .reserved_frame = addr.index },
445 .reserved_frame => self.long,448 .reserved_frame => inst_tracking.long,
446 else => target.long,449 else => target.long,
447 } else target.long;450 } else target.long;
448 self.short = target.short;451 inst_tracking.short = target.short;
449 tracking_log.debug("%{d} => {} (materialize)", .{ inst, self.* });452 tracking_log.debug("%{d} => {} (materialize)", .{ inst, inst_tracking.* });
450 }453 }
451454
452 fn resurrect(self: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {455 fn resurrect(inst_tracking: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {
453 switch (self.short) {456 switch (inst_tracking.short) {
454 .dead => |die_generation| if (die_generation >= scope_generation) {457 .dead => |die_generation| if (die_generation >= scope_generation) {
455 self.reuseFrame();458 inst_tracking.reuseFrame();
456 tracking_log.debug("%{d} => {} (resurrect)", .{ inst, self.* });459 tracking_log.debug("%{d} => {} (resurrect)", .{ inst, inst_tracking.* });
457 },460 },
458 else => {},461 else => {},
459 }462 }
460 }463 }
461464
462 fn die(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void {465 fn die(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {
463 if (self.short == .dead) return;466 if (inst_tracking.short == .dead) return;
464 try function.freeValue(self.short);467 try function.freeValue(inst_tracking.short);
465 self.short = .{ .dead = function.scope_generation };468 inst_tracking.short = .{ .dead = function.scope_generation };
466 tracking_log.debug("%{d} => {} (death)", .{ inst, self.* });469 tracking_log.debug("%{d} => {} (death)", .{ inst, inst_tracking.* });
467 }470 }
468471
469 fn reuse(472 fn reuse(
470 self: *InstTracking,473 inst_tracking: *InstTracking,
471 function: *Self,474 function: *Func,
472 new_inst: ?Air.Inst.Index,475 new_inst: ?Air.Inst.Index,
473 old_inst: Air.Inst.Index,476 old_inst: Air.Inst.Index,
474 ) void {477 ) void {
475 self.short = .{ .dead = function.scope_generation };478 inst_tracking.short = .{ .dead = function.scope_generation };
476 if (new_inst) |inst|479 if (new_inst) |inst|
477 tracking_log.debug("%{d} => {} (reuse %{d})", .{ inst, self.*, old_inst })480 tracking_log.debug("%{d} => {} (reuse %{d})", .{ inst, inst_tracking.*, old_inst })
478 else481 else
479 tracking_log.debug("tmp => {} (reuse %{d})", .{ self.*, old_inst });482 tracking_log.debug("tmp => {} (reuse %{d})", .{ inst_tracking.*, old_inst });
480 }483 }
481484
482 fn liveOut(self: *InstTracking, function: *Self, inst: Air.Inst.Index) void {485 fn liveOut(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) void {
483 for (self.getRegs()) |reg| {486 for (inst_tracking.getRegs()) |reg| {
484 if (function.register_manager.isRegFree(reg)) {487 if (function.register_manager.isRegFree(reg)) {
485 tracking_log.debug("%{d} => {} (live-out)", .{ inst, self.* });488 tracking_log.debug("%{d} => {} (live-out)", .{ inst, inst_tracking.* });
486 continue;489 continue;
487 }490 }
488491
...@@ -509,18 +512,18 @@ const InstTracking = struct {...@@ -509,18 +512,18 @@ const InstTracking = struct {
509 // Perform side-effects of freeValue manually.512 // Perform side-effects of freeValue manually.
510 function.register_manager.freeReg(reg);513 function.register_manager.freeReg(reg);
511514
512 tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, self.*, tracked_inst });515 tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, inst_tracking.*, tracked_inst });
513 }516 }
514 }517 }
515518
516 pub fn format(519 pub fn format(
517 self: InstTracking,520 inst_tracking: InstTracking,
518 comptime _: []const u8,521 comptime _: []const u8,
519 _: std.fmt.FormatOptions,522 _: std.fmt.FormatOptions,
520 writer: anytype,523 writer: anytype,
521 ) @TypeOf(writer).Error!void {524 ) @TypeOf(writer).Error!void {
522 if (!std.meta.eql(self.long, self.short)) try writer.print("|{}| ", .{self.long});525 if (!std.meta.eql(inst_tracking.long, inst_tracking.short)) try writer.print("|{}| ", .{inst_tracking.long});
523 try writer.print("{}", .{self.short});526 try writer.print("{}", .{inst_tracking.short});
524 }527 }
525};528};
526529
...@@ -560,19 +563,13 @@ const FrameAlloc = struct {...@@ -560,19 +563,13 @@ const FrameAlloc = struct {
560 }563 }
561};564};
562565
563const StackAllocation = struct {
564 inst: ?Air.Inst.Index,
565 /// TODO: make the size inferred from the bits of the inst
566 size: u32,
567};
568
569const BlockData = struct {566const BlockData = struct {
570 relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .{},567 relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .{},
571 state: State,568 state: State,
572569
573 fn deinit(self: *BlockData, gpa: Allocator) void {570 fn deinit(bd: *BlockData, gpa: Allocator) void {
574 self.relocs.deinit(gpa);571 bd.relocs.deinit(gpa);
575 self.* = undefined;572 bd.* = undefined;
576 }573 }
577};574};
578575
...@@ -584,31 +581,31 @@ const State = struct {...@@ -584,31 +581,31 @@ const State = struct {
584 scope_generation: u32,581 scope_generation: u32,
585};582};
586583
587fn initRetroactiveState(self: *Self) State {584fn initRetroactiveState(func: *Func) State {
588 var state: State = undefined;585 var state: State = undefined;
589 state.inst_tracking_len = @intCast(self.inst_tracking.count());586 state.inst_tracking_len = @intCast(func.inst_tracking.count());
590 state.scope_generation = self.scope_generation;587 state.scope_generation = func.scope_generation;
591 return state;588 return state;
592}589}
593590
594fn saveRetroactiveState(self: *Self, state: *State) !void {591fn saveRetroactiveState(func: *Func, state: *State) !void {
595 const free_registers = self.register_manager.free_registers;592 const free_registers = func.register_manager.free_registers;
596 var it = free_registers.iterator(.{ .kind = .unset });593 var it = free_registers.iterator(.{ .kind = .unset });
597 while (it.next()) |index| {594 while (it.next()) |index| {
598 const tracked_inst = self.register_manager.registers[index];595 const tracked_inst = func.register_manager.registers[index];
599 state.registers[index] = tracked_inst;596 state.registers[index] = tracked_inst;
600 state.reg_tracking[index] = self.inst_tracking.get(tracked_inst).?;597 state.reg_tracking[index] = func.inst_tracking.get(tracked_inst).?;
601 }598 }
602 state.free_registers = free_registers;599 state.free_registers = free_registers;
603}600}
604601
605fn saveState(self: *Self) !State {602fn saveState(func: *Func) !State {
606 var state = self.initRetroactiveState();603 var state = func.initRetroactiveState();
607 try self.saveRetroactiveState(&state);604 try func.saveRetroactiveState(&state);
608 return state;605 return state;
609}606}
610607
611fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, comptime opts: struct {608fn restoreState(func: *Func, state: State, deaths: []const Air.Inst.Index, comptime opts: struct {
612 emit_instructions: bool,609 emit_instructions: bool,
613 update_tracking: bool,610 update_tracking: bool,
614 resurrect: bool,611 resurrect: bool,
...@@ -616,80 +613,81 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt...@@ -616,80 +613,81 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt
616}) !void {613}) !void {
617 if (opts.close_scope) {614 if (opts.close_scope) {
618 for (615 for (
619 self.inst_tracking.keys()[state.inst_tracking_len..],616 func.inst_tracking.keys()[state.inst_tracking_len..],
620 self.inst_tracking.values()[state.inst_tracking_len..],617 func.inst_tracking.values()[state.inst_tracking_len..],
621 ) |inst, *tracking| try tracking.die(self, inst);618 ) |inst, *tracking| try tracking.die(func, inst);
622 self.inst_tracking.shrinkRetainingCapacity(state.inst_tracking_len);619 func.inst_tracking.shrinkRetainingCapacity(state.inst_tracking_len);
623 }620 }
624621
625 if (opts.resurrect) for (622 if (opts.resurrect) for (
626 self.inst_tracking.keys()[0..state.inst_tracking_len],623 func.inst_tracking.keys()[0..state.inst_tracking_len],
627 self.inst_tracking.values()[0..state.inst_tracking_len],624 func.inst_tracking.values()[0..state.inst_tracking_len],
628 ) |inst, *tracking| tracking.resurrect(inst, state.scope_generation);625 ) |inst, *tracking| tracking.resurrect(inst, state.scope_generation);
629 for (deaths) |death| try self.processDeath(death);626 for (deaths) |death| try func.processDeath(death);
630627
631 const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).Array.len]RegisterLock;628 const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).Array.len]RegisterLock;
632 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =629 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
633 if (opts.update_tracking)630 if (opts.update_tracking)
634 {} else std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);631 {} else std.heap.stackFallback(@sizeOf(ExpectedContents), func.gpa);
635632
636 var reg_locks = if (opts.update_tracking) {} else try std.ArrayList(RegisterLock).initCapacity(633 var reg_locks = if (opts.update_tracking) {} else try std.ArrayList(RegisterLock).initCapacity(
637 stack.get(),634 stack.get(),
638 @typeInfo(ExpectedContents).Array.len,635 @typeInfo(ExpectedContents).Array.len,
639 );636 );
640 defer if (!opts.update_tracking) {637 defer if (!opts.update_tracking) {
641 for (reg_locks.items) |lock| self.register_manager.unlockReg(lock);638 for (reg_locks.items) |lock| func.register_manager.unlockReg(lock);
642 reg_locks.deinit();639 reg_locks.deinit();
643 };640 };
644641
645 for (0..state.registers.len) |index| {642 for (0..state.registers.len) |index| {
646 const current_maybe_inst = if (self.register_manager.free_registers.isSet(index))643 const current_maybe_inst = if (func.register_manager.free_registers.isSet(index))
647 null644 null
648 else645 else
649 self.register_manager.registers[index];646 func.register_manager.registers[index];
650 const target_maybe_inst = if (state.free_registers.isSet(index))647 const target_maybe_inst = if (state.free_registers.isSet(index))
651 null648 null
652 else649 else
653 state.registers[index];650 state.registers[index];
654 if (std.debug.runtime_safety) if (target_maybe_inst) |target_inst|651 if (std.debug.runtime_safety) if (target_maybe_inst) |target_inst|
655 assert(self.inst_tracking.getIndex(target_inst).? < state.inst_tracking_len);652 assert(func.inst_tracking.getIndex(target_inst).? < state.inst_tracking_len);
656 if (opts.emit_instructions) {653 if (opts.emit_instructions) {
657 if (current_maybe_inst) |current_inst| {654 if (current_maybe_inst) |current_inst| {
658 try self.inst_tracking.getPtr(current_inst).?.spill(self, current_inst);655 try func.inst_tracking.getPtr(current_inst).?.spill(func, current_inst);
659 }656 }
660 if (target_maybe_inst) |target_inst| {657 if (target_maybe_inst) |target_inst| {
661 const target_tracking = self.inst_tracking.getPtr(target_inst).?;658 const target_tracking = func.inst_tracking.getPtr(target_inst).?;
662 try target_tracking.materialize(self, target_inst, state.reg_tracking[index]);659 try target_tracking.materialize(func, target_inst, state.reg_tracking[index]);
663 }660 }
664 }661 }
665 if (opts.update_tracking) {662 if (opts.update_tracking) {
666 if (current_maybe_inst) |current_inst| {663 if (current_maybe_inst) |current_inst| {
667 try self.inst_tracking.getPtr(current_inst).?.trackSpill(self, current_inst);664 try func.inst_tracking.getPtr(current_inst).?.trackSpill(func, current_inst);
668 }665 }
669 {666 blk: {
667 const inst = target_maybe_inst orelse break :blk;
670 const reg = RegisterManager.regAtTrackedIndex(@intCast(index));668 const reg = RegisterManager.regAtTrackedIndex(@intCast(index));
671 self.register_manager.freeReg(reg);669 func.register_manager.freeReg(reg);
672 self.register_manager.getRegAssumeFree(reg, target_maybe_inst);670 func.register_manager.getRegAssumeFree(reg, inst);
673 }671 }
674 if (target_maybe_inst) |target_inst| {672 if (target_maybe_inst) |target_inst| {
675 self.inst_tracking.getPtr(target_inst).?.trackMaterialize(673 func.inst_tracking.getPtr(target_inst).?.trackMaterialize(
676 target_inst,674 target_inst,
677 state.reg_tracking[index],675 state.reg_tracking[index],
678 );676 );
679 }677 }
680 } else if (target_maybe_inst) |_|678 } else if (target_maybe_inst) |_|
681 try reg_locks.append(self.register_manager.lockRegIndexAssumeUnused(@intCast(index)));679 try reg_locks.append(func.register_manager.lockRegIndexAssumeUnused(@intCast(index)));
682 }680 }
683681
684 if (opts.update_tracking and std.debug.runtime_safety) {682 if (opts.update_tracking and std.debug.runtime_safety) {
685 assert(self.register_manager.free_registers.eql(state.free_registers));683 assert(func.register_manager.free_registers.eql(state.free_registers));
686 var used_reg_it = state.free_registers.iterator(.{ .kind = .unset });684 var used_reg_it = state.free_registers.iterator(.{ .kind = .unset });
687 while (used_reg_it.next()) |index|685 while (used_reg_it.next()) |index|
688 assert(self.register_manager.registers[index] == state.registers[index]);686 assert(func.register_manager.registers[index] == state.registers[index]);
689 }687 }
690}688}
691689
692const Self = @This();690const Func = @This();
693691
694const CallView = enum(u1) {692const CallView = enum(u1) {
695 callee,693 callee,
...@@ -725,7 +723,7 @@ pub fn generate(...@@ -725,7 +723,7 @@ pub fn generate(
725 }723 }
726 try branch_stack.append(.{});724 try branch_stack.append(.{});
727725
728 var function = Self{726 var function = Func{
729 .gpa = gpa,727 .gpa = gpa,
730 .air = air,728 .air = air,
731 .mod = mod,729 .mod = mod,
...@@ -760,6 +758,8 @@ pub fn generate(...@@ -760,6 +758,8 @@ pub fn generate(
760 function.mir_extra.deinit(gpa);758 function.mir_extra.deinit(gpa);
761 }759 }
762760
761 wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)});
762
763 try function.frame_allocs.resize(gpa, FrameIndex.named_count);763 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
764 function.frame_allocs.set(764 function.frame_allocs.set(
765 @intFromEnum(FrameIndex.stack_frame),765 @intFromEnum(FrameIndex.stack_frame),
...@@ -774,7 +774,7 @@ pub fn generate(...@@ -774,7 +774,7 @@ pub fn generate(
774 );774 );
775775
776 const fn_info = zcu.typeToFunc(fn_type).?;776 const fn_info = zcu.typeToFunc(fn_type).?;
777 var call_info = function.resolveCallingConventionValues(fn_info) catch |err| switch (err) {777 var call_info = function.resolveCallingConventionValues(fn_info, &.{}) catch |err| switch (err) {
778 error.CodegenFail => return Result{ .fail = function.err_msg.? },778 error.CodegenFail => return Result{ .fail = function.err_msg.? },
779 error.OutOfRegisters => return Result{779 error.OutOfRegisters => return Result{
780 .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),780 .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
...@@ -865,51 +865,171 @@ pub fn generate(...@@ -865,51 +865,171 @@ pub fn generate(
865 }865 }
866}866}
867867
868fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {868const FormatWipMirData = struct {
869 const gpa = self.gpa;869 func: *Func,
870 inst: Mir.Inst.Index,
871};
872fn formatWipMir(
873 data: FormatWipMirData,
874 comptime _: []const u8,
875 _: std.fmt.FormatOptions,
876 writer: anytype,
877) @TypeOf(writer).Error!void {
878 const comp = data.func.bin_file.comp;
879 const mod = comp.root_mod;
880 var lower = Lower{
881 .bin_file = data.func.bin_file,
882 .allocator = data.func.gpa,
883 .mir = .{
884 .instructions = data.func.mir_instructions.slice(),
885 .extra = data.func.mir_extra.items,
886 .frame_locs = data.func.frame_locs.slice(),
887 },
888 .cc = .Unspecified,
889 .src_loc = data.func.src_loc,
890 .output_mode = comp.config.output_mode,
891 .link_mode = comp.config.link_mode,
892 .pic = mod.pic,
893 };
894 var first = true;
895 for ((lower.lowerMir(data.inst) catch |err| switch (err) {
896 error.LowerFail => {
897 defer {
898 lower.err_msg.?.deinit(data.func.gpa);
899 lower.err_msg = null;
900 }
901 try writer.writeAll(lower.err_msg.?.msg);
902 return;
903 },
904 error.OutOfMemory, error.InvalidInstruction => |e| {
905 try writer.writeAll(switch (e) {
906 error.OutOfMemory => "Out of memory",
907 error.InvalidInstruction => "CodeGen failed to find a viable instruction.",
908 });
909 return;
910 },
911 else => |e| return e,
912 }).insts) |lowered_inst| {
913 if (!first) try writer.writeAll("\ndebug(wip_mir): ");
914 try writer.print(" | {}", .{lowered_inst});
915 first = false;
916 }
917}
918fn fmtWipMir(func: *Func, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMir) {
919 return .{ .data = .{ .func = func, .inst = inst } };
920}
870921
871 try self.mir_instructions.ensureUnusedCapacity(gpa, 1);922const FormatDeclData = struct {
923 mod: *Module,
924 decl_index: InternPool.DeclIndex,
925};
926fn formatDecl(
927 data: FormatDeclData,
928 comptime _: []const u8,
929 _: std.fmt.FormatOptions,
930 writer: anytype,
931) @TypeOf(writer).Error!void {
932 try data.mod.declPtr(data.decl_index).renderFullyQualifiedName(data.mod, writer);
933}
934fn fmtDecl(func: *Func, decl_index: InternPool.DeclIndex) std.fmt.Formatter(formatDecl) {
935 return .{ .data = .{
936 .mod = func.bin_file.comp.module.?,
937 .decl_index = decl_index,
938 } };
939}
940
941const FormatAirData = struct {
942 func: *Func,
943 inst: Air.Inst.Index,
944};
945fn formatAir(
946 data: FormatAirData,
947 comptime _: []const u8,
948 _: std.fmt.FormatOptions,
949 writer: anytype,
950) @TypeOf(writer).Error!void {
951 @import("../../print_air.zig").dumpInst(
952 data.inst,
953 data.func.bin_file.comp.module.?,
954 data.func.air,
955 data.func.liveness,
956 );
957}
958fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {
959 return .{ .data = .{ .func = func, .inst = inst } };
960}
872961
873 const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len);962const FormatTrackingData = struct {
874 self.mir_instructions.appendAssumeCapacity(inst);963 func: *Func,
964};
965fn formatTracking(
966 data: FormatTrackingData,
967 comptime _: []const u8,
968 _: std.fmt.FormatOptions,
969 writer: anytype,
970) @TypeOf(writer).Error!void {
971 var it = data.func.inst_tracking.iterator();
972 while (it.next()) |entry| try writer.print("\n%{d} = {}", .{ entry.key_ptr.*, entry.value_ptr.* });
973}
974fn fmtTracking(func: *Func) std.fmt.Formatter(formatTracking) {
975 return .{ .data = .{ .func = func } };
976}
977
978fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
979 const gpa = func.gpa;
980 try func.mir_instructions.ensureUnusedCapacity(gpa, 1);
981 const result_index: Mir.Inst.Index = @intCast(func.mir_instructions.len);
982 func.mir_instructions.appendAssumeCapacity(inst);
983 if (inst.tag != .pseudo or switch (inst.ops) {
984 else => true,
985 .pseudo_dbg_prologue_end,
986 .pseudo_dbg_line_column,
987 .pseudo_dbg_epilogue_begin,
988 .pseudo_store_rm,
989 .pseudo_load_rm,
990 .pseudo_lea_rm,
991 .pseudo_mv,
992 .pseudo_dead,
993 => false,
994 }) wip_mir_log.debug("{}", .{func.fmtWipMir(result_index)}) else wip_mir_log.debug(" | uses-mem", .{});
875 return result_index;995 return result_index;
876}996}
877997
878fn addNop(self: *Self) error{OutOfMemory}!Mir.Inst.Index {998fn addNop(func: *Func) error{OutOfMemory}!Mir.Inst.Index {
879 return self.addInst(.{999 return func.addInst(.{
880 .tag = .nop,1000 .tag = .nop,
881 .ops = .none,1001 .ops = .none,
882 .data = undefined,1002 .data = undefined,
883 });1003 });
884}1004}
8851005
886fn addPseudoNone(self: *Self, ops: Mir.Inst.Ops) !void {1006fn addPseudoNone(func: *Func, ops: Mir.Inst.Ops) !void {
887 _ = try self.addInst(.{1007 _ = try func.addInst(.{
888 .tag = .pseudo,1008 .tag = .pseudo,
889 .ops = ops,1009 .ops = ops,
890 .data = undefined,1010 .data = undefined,
891 });1011 });
892}1012}
8931013
894fn addPseudo(self: *Self, ops: Mir.Inst.Ops) !Mir.Inst.Index {1014fn addPseudo(func: *Func, ops: Mir.Inst.Ops) !Mir.Inst.Index {
895 return self.addInst(.{1015 return func.addInst(.{
896 .tag = .pseudo,1016 .tag = .pseudo,
897 .ops = ops,1017 .ops = ops,
898 .data = undefined,1018 .data = undefined,
899 });1019 });
900}1020}
9011021
902pub fn addExtra(self: *Self, extra: anytype) Allocator.Error!u32 {1022pub fn addExtra(func: *Func, extra: anytype) Allocator.Error!u32 {
903 const fields = std.meta.fields(@TypeOf(extra));1023 const fields = std.meta.fields(@TypeOf(extra));
904 try self.mir_extra.ensureUnusedCapacity(self.gpa, fields.len);1024 try func.mir_extra.ensureUnusedCapacity(func.gpa, fields.len);
905 return self.addExtraAssumeCapacity(extra);1025 return func.addExtraAssumeCapacity(extra);
906}1026}
9071027
908pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {1028pub fn addExtraAssumeCapacity(func: *Func, extra: anytype) u32 {
909 const fields = std.meta.fields(@TypeOf(extra));1029 const fields = std.meta.fields(@TypeOf(extra));
910 const result: u32 = @intCast(self.mir_extra.items.len);1030 const result: u32 = @intCast(func.mir_extra.items.len);
911 inline for (fields) |field| {1031 inline for (fields) |field| {
912 self.mir_extra.appendAssumeCapacity(switch (field.type) {1032 func.mir_extra.appendAssumeCapacity(switch (field.type) {
913 u32 => @field(extra, field.name),1033 u32 => @field(extra, field.name),
914 i32 => @bitCast(@field(extra, field.name)),1034 i32 => @bitCast(@field(extra, field.name)),
915 else => @compileError("bad field type"),1035 else => @compileError("bad field type"),
...@@ -918,38 +1038,71 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {...@@ -918,38 +1038,71 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
918 return result;1038 return result;
919}1039}
9201040
921fn gen(self: *Self) !void {1041const required_features = [_]Target.riscv.Feature{
922 const mod = self.bin_file.comp.module.?;1042 .d,
923 const fn_info = mod.typeToFunc(self.fn_type).?;1043 .m,
1044};
1045
1046fn gen(func: *Func) !void {
1047 const mod = func.bin_file.comp.module.?;
1048 const fn_info = mod.typeToFunc(func.fn_type).?;
9241049
925 if (fn_info.cc != .Naked) {1050 inline for (required_features) |feature| {
926 try self.addPseudoNone(.pseudo_dbg_prologue_end);1051 if (!func.hasFeature(feature)) {
1052 return func.fail(
1053 "target missing required feature {s}",
1054 .{@tagName(feature)},
1055 );
1056 }
1057 }
9271058
928 const backpatch_stack_alloc = try self.addPseudo(.pseudo_dead);1059 if (fn_info.cc != .Naked) {
929 const backpatch_ra_spill = try self.addPseudo(.pseudo_dead);1060 try func.addPseudoNone(.pseudo_dbg_prologue_end);
930 const backpatch_fp_spill = try self.addPseudo(.pseudo_dead);1061
931 const backpatch_fp_add = try self.addPseudo(.pseudo_dead);1062 const backpatch_stack_alloc = try func.addPseudo(.pseudo_dead);
932 const backpatch_spill_callee_preserved_regs = try self.addPseudo(.pseudo_dead);1063 const backpatch_ra_spill = try func.addPseudo(.pseudo_dead);
1064 const backpatch_fp_spill = try func.addPseudo(.pseudo_dead);
1065 const backpatch_fp_add = try func.addPseudo(.pseudo_dead);
1066 const backpatch_spill_callee_preserved_regs = try func.addPseudo(.pseudo_dead);
1067
1068 switch (func.ret_mcv.long) {
1069 .none, .unreach => {},
1070 .indirect => {
1071 // The address where to store the return value for the caller is in a
1072 // register which the callee is free to clobber. Therefore, we purposely
1073 // spill it to stack immediately.
1074 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(Type.usize, mod));
1075 try func.genSetMem(
1076 .{ .frame = frame_index },
1077 0,
1078 Type.usize,
1079 func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off),
1080 );
1081 func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
1082 tracking_log.debug("spill {} to {}", .{ func.ret_mcv.long, frame_index });
1083 },
1084 else => unreachable,
1085 }
9331086
934 try self.genBody(self.air.getMainBody());1087 try func.genBody(func.air.getMainBody());
9351088
936 for (self.exitlude_jump_relocs.items) |jmp_reloc| {1089 for (func.exitlude_jump_relocs.items) |jmp_reloc| {
937 self.mir_instructions.items(.data)[jmp_reloc].inst =1090 func.mir_instructions.items(.data)[jmp_reloc].inst =
938 @intCast(self.mir_instructions.len);1091 @intCast(func.mir_instructions.len);
939 }1092 }
9401093
941 try self.addPseudoNone(.pseudo_dbg_epilogue_begin);1094 try func.addPseudoNone(.pseudo_dbg_epilogue_begin);
9421095
943 const backpatch_restore_callee_preserved_regs = try self.addPseudo(.pseudo_dead);1096 const backpatch_restore_callee_preserved_regs = try func.addPseudo(.pseudo_dead);
944 const backpatch_ra_restore = try self.addPseudo(.pseudo_dead);1097 const backpatch_ra_restore = try func.addPseudo(.pseudo_dead);
945 const backpatch_fp_restore = try self.addPseudo(.pseudo_dead);1098 const backpatch_fp_restore = try func.addPseudo(.pseudo_dead);
946 const backpatch_stack_alloc_restore = try self.addPseudo(.pseudo_dead);1099 const backpatch_stack_alloc_restore = try func.addPseudo(.pseudo_dead);
947 try self.addPseudoNone(.pseudo_ret);1100 try func.addPseudoNone(.pseudo_ret);
9481101
949 const frame_layout = try self.computeFrameLayout();1102 const frame_layout = try func.computeFrameLayout();
950 const need_save_reg = frame_layout.save_reg_list.count() > 0;1103 const need_save_reg = frame_layout.save_reg_list.count() > 0;
9511104
952 self.mir_instructions.set(backpatch_stack_alloc, .{1105 func.mir_instructions.set(backpatch_stack_alloc, .{
953 .tag = .addi,1106 .tag = .addi,
954 .ops = .rri,1107 .ops = .rri,
955 .data = .{ .i_type = .{1108 .data = .{ .i_type = .{
...@@ -958,51 +1111,51 @@ fn gen(self: *Self) !void {...@@ -958,51 +1111,51 @@ fn gen(self: *Self) !void {
958 .imm12 = Immediate.s(-@as(i32, @intCast(frame_layout.stack_adjust))),1111 .imm12 = Immediate.s(-@as(i32, @intCast(frame_layout.stack_adjust))),
959 } },1112 } },
960 });1113 });
961 self.mir_instructions.set(backpatch_ra_spill, .{1114 func.mir_instructions.set(backpatch_ra_spill, .{
962 .tag = .pseudo,1115 .tag = .pseudo,
963 .ops = .pseudo_store_rm,1116 .ops = .pseudo_store_rm,
964 .data = .{ .rm = .{1117 .data = .{ .rm = .{
965 .r = .ra,1118 .r = .ra,
966 .m = .{1119 .m = .{
967 .base = .{ .frame = .ret_addr },1120 .base = .{ .frame = .ret_addr },
968 .mod = .{ .rm = .{ .size = .dword } },1121 .mod = .{ .size = .dword, .unsigned = false },
969 },1122 },
970 } },1123 } },
971 });1124 });
972 self.mir_instructions.set(backpatch_ra_restore, .{1125 func.mir_instructions.set(backpatch_ra_restore, .{
973 .tag = .pseudo,1126 .tag = .pseudo,
974 .ops = .pseudo_load_rm,1127 .ops = .pseudo_load_rm,
975 .data = .{ .rm = .{1128 .data = .{ .rm = .{
976 .r = .ra,1129 .r = .ra,
977 .m = .{1130 .m = .{
978 .base = .{ .frame = .ret_addr },1131 .base = .{ .frame = .ret_addr },
979 .mod = .{ .rm = .{ .size = .dword } },1132 .mod = .{ .size = .dword, .unsigned = false },
980 },1133 },
981 } },1134 } },
982 });1135 });
983 self.mir_instructions.set(backpatch_fp_spill, .{1136 func.mir_instructions.set(backpatch_fp_spill, .{
984 .tag = .pseudo,1137 .tag = .pseudo,
985 .ops = .pseudo_store_rm,1138 .ops = .pseudo_store_rm,
986 .data = .{ .rm = .{1139 .data = .{ .rm = .{
987 .r = .s0,1140 .r = .s0,
988 .m = .{1141 .m = .{
989 .base = .{ .frame = .base_ptr },1142 .base = .{ .frame = .base_ptr },
990 .mod = .{ .rm = .{ .size = .dword } },1143 .mod = .{ .size = .dword, .unsigned = false },
991 },1144 },
992 } },1145 } },
993 });1146 });
994 self.mir_instructions.set(backpatch_fp_restore, .{1147 func.mir_instructions.set(backpatch_fp_restore, .{
995 .tag = .pseudo,1148 .tag = .pseudo,
996 .ops = .pseudo_load_rm,1149 .ops = .pseudo_load_rm,
997 .data = .{ .rm = .{1150 .data = .{ .rm = .{
998 .r = .s0,1151 .r = .s0,
999 .m = .{1152 .m = .{
1000 .base = .{ .frame = .base_ptr },1153 .base = .{ .frame = .base_ptr },
1001 .mod = .{ .rm = .{ .size = .dword } },1154 .mod = .{ .size = .dword, .unsigned = false },
1002 },1155 },
1003 } },1156 } },
1004 });1157 });
1005 self.mir_instructions.set(backpatch_fp_add, .{1158 func.mir_instructions.set(backpatch_fp_add, .{
1006 .tag = .addi,1159 .tag = .addi,
1007 .ops = .rri,1160 .ops = .rri,
1008 .data = .{ .i_type = .{1161 .data = .{ .i_type = .{
...@@ -1011,7 +1164,7 @@ fn gen(self: *Self) !void {...@@ -1011,7 +1164,7 @@ fn gen(self: *Self) !void {
1011 .imm12 = Immediate.s(@intCast(frame_layout.stack_adjust)),1164 .imm12 = Immediate.s(@intCast(frame_layout.stack_adjust)),
1012 } },1165 } },
1013 });1166 });
1014 self.mir_instructions.set(backpatch_stack_alloc_restore, .{1167 func.mir_instructions.set(backpatch_stack_alloc_restore, .{
1015 .tag = .addi,1168 .tag = .addi,
1016 .ops = .rri,1169 .ops = .rri,
1017 .data = .{ .i_type = .{1170 .data = .{ .i_type = .{
...@@ -1022,72 +1175,83 @@ fn gen(self: *Self) !void {...@@ -1022,72 +1175,83 @@ fn gen(self: *Self) !void {
1022 });1175 });
10231176
1024 if (need_save_reg) {1177 if (need_save_reg) {
1025 self.mir_instructions.set(backpatch_spill_callee_preserved_regs, .{1178 func.mir_instructions.set(backpatch_spill_callee_preserved_regs, .{
1026 .tag = .pseudo,1179 .tag = .pseudo,
1027 .ops = .pseudo_spill_regs,1180 .ops = .pseudo_spill_regs,
1028 .data = .{ .reg_list = frame_layout.save_reg_list },1181 .data = .{ .reg_list = frame_layout.save_reg_list },
1029 });1182 });
10301183
1031 self.mir_instructions.set(backpatch_restore_callee_preserved_regs, .{1184 func.mir_instructions.set(backpatch_restore_callee_preserved_regs, .{
1032 .tag = .pseudo,1185 .tag = .pseudo,
1033 .ops = .pseudo_restore_regs,1186 .ops = .pseudo_restore_regs,
1034 .data = .{ .reg_list = frame_layout.save_reg_list },1187 .data = .{ .reg_list = frame_layout.save_reg_list },
1035 });1188 });
1036 }1189 }
1037 } else {1190 } else {
1038 try self.addPseudoNone(.pseudo_dbg_prologue_end);1191 try func.addPseudoNone(.pseudo_dbg_prologue_end);
1039 try self.genBody(self.air.getMainBody());1192 try func.genBody(func.air.getMainBody());
1040 try self.addPseudoNone(.pseudo_dbg_epilogue_begin);1193 try func.addPseudoNone(.pseudo_dbg_epilogue_begin);
1041 }1194 }
10421195
1043 // Drop them off at the rbrace.1196 // Drop them off at the rbrace.
1044 _ = try self.addInst(.{1197 _ = try func.addInst(.{
1045 .tag = .pseudo,1198 .tag = .pseudo,
1046 .ops = .pseudo_dbg_line_column,1199 .ops = .pseudo_dbg_line_column,
1047 .data = .{ .pseudo_dbg_line_column = .{1200 .data = .{ .pseudo_dbg_line_column = .{
1048 .line = self.end_di_line,1201 .line = func.end_di_line,
1049 .column = self.end_di_column,1202 .column = func.end_di_column,
1050 } },1203 } },
1051 });1204 });
1052}1205}
10531206
1054fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {1207fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1055 const zcu = self.bin_file.comp.module.?;1208 const zcu = func.bin_file.comp.module.?;
1056 const ip = &zcu.intern_pool;1209 const ip = &zcu.intern_pool;
1057 const air_tags = self.air.instructions.items(.tag);1210 const air_tags = func.air.instructions.items(.tag);
10581211
1059 for (body) |inst| {1212 for (body) |inst| {
1060 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip)) continue;1213 if (func.liveness.isUnused(inst) and !func.air.mustLower(inst, ip)) continue;
10611214 wip_mir_log.debug("{}", .{func.fmtAir(inst)});
1062 const old_air_bookkeeping = self.air_bookkeeping;1215 verbose_tracking_log.debug("{}", .{func.fmtTracking()});
1063 try self.inst_tracking.ensureUnusedCapacity(self.gpa, 1);1216
1064 switch (air_tags[@intFromEnum(inst)]) {1217 const old_air_bookkeeping = func.air_bookkeeping;
1218 try func.inst_tracking.ensureUnusedCapacity(func.gpa, 1);
1219 const tag: Air.Inst.Tag = air_tags[@intFromEnum(inst)];
1220 switch (tag) {
1065 // zig fmt: off1221 // zig fmt: off
1066 .ptr_add => try self.airPtrArithmetic(inst, .ptr_add),1222 .add,
1067 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),1223 .add_wrap,
1224 .sub,
1225 .sub_wrap,
10681226
1069 .add => try self.airBinOp(inst, .add),1227 .mul,
1070 .sub => try self.airBinOp(inst, .sub),1228 .mul_wrap,
1229 .div_trunc,
10711230
1072 .add_safe,1231 .shl, .shl_exact,
1073 .sub_safe,1232 .shr, .shr_exact,
1074 .mul_safe,1233
1075 => return self.fail("TODO implement safety_checked_instructions", .{}),1234 .bool_and,
10761235 .bool_or,
1077 .add_wrap => try self.airAddWrap(inst),1236 .bit_and,
1078 .add_sat => try self.airAddSat(inst),1237 .bit_or,
1079 .sub_wrap => try self.airSubWrap(inst),1238
1080 .sub_sat => try self.airSubSat(inst),1239 .xor,
1081 .mul => try self.airMul(inst),1240
1082 .mul_wrap => try self.airMulWrap(inst),1241 .min,
1083 .mul_sat => try self.airMulSat(inst),1242 .max,
1084 .rem => try self.airRem(inst),1243 => try func.airBinOp(inst, tag),
1085 .mod => try self.airMod(inst),1244
1086 .shl, .shl_exact => try self.airShl(inst),1245
1087 .shl_sat => try self.airShlSat(inst),1246 .ptr_add,
1088 .min => try self.airMinMax(inst, .min),1247 .ptr_sub => try func.airPtrArithmetic(inst, tag),
1089 .max => try self.airMinMax(inst, .max),1248
1090 .slice => try self.airSlice(inst),1249 .rem,
1250 .mod,
1251 .div_float,
1252 .div_floor,
1253 .div_exact,
1254 => return func.fail("TODO: {s}", .{@tagName(tag)}),
10911255
1092 .sqrt,1256 .sqrt,
1093 .sin,1257 .sin,
...@@ -1103,157 +1267,164 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1103,157 +1267,164 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1103 .round,1267 .round,
1104 .trunc_float,1268 .trunc_float,
1105 .neg,1269 .neg,
1106 => try self.airUnaryMath(inst),1270 => try func.airUnaryMath(inst),
11071271
1108 .add_with_overflow => try self.airAddWithOverflow(inst),1272 .add_with_overflow => try func.airAddWithOverflow(inst),
1109 .sub_with_overflow => try self.airSubWithOverflow(inst),1273 .sub_with_overflow => try func.airSubWithOverflow(inst),
1110 .mul_with_overflow => try self.airMulWithOverflow(inst),1274 .mul_with_overflow => try func.airMulWithOverflow(inst),
1111 .shl_with_overflow => try self.airShlWithOverflow(inst),1275 .shl_with_overflow => try func.airShlWithOverflow(inst),
11121276
1113 .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst),1277
11141278 .add_sat => try func.airAddSat(inst),
1115 .cmp_lt => try self.airCmp(inst),1279 .sub_sat => try func.airSubSat(inst),
1116 .cmp_lte => try self.airCmp(inst),1280 .mul_sat => try func.airMulSat(inst),
1117 .cmp_eq => try self.airCmp(inst),1281 .shl_sat => try func.airShlSat(inst),
1118 .cmp_gte => try self.airCmp(inst),1282
1119 .cmp_gt => try self.airCmp(inst),1283 .add_safe,
1120 .cmp_neq => try self.airCmp(inst),1284 .sub_safe,
11211285 .mul_safe,
1122 .cmp_vector => try self.airCmpVector(inst),1286 => return func.fail("TODO implement safety_checked_instructions", .{}),
1123 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),1287
11241288 .cmp_lt,
1125 .bool_and => try self.airBoolOp(inst),1289 .cmp_lte,
1126 .bool_or => try self.airBoolOp(inst),1290 .cmp_eq,
1127 .bit_and => try self.airBitAnd(inst),1291 .cmp_gte,
1128 .bit_or => try self.airBitOr(inst),1292 .cmp_gt,
1129 .xor => try self.airXor(inst),1293 .cmp_neq,
1130 .shr, .shr_exact => try self.airShr(inst),1294 => try func.airCmp(inst, tag),
11311295
1132 .alloc => try self.airAlloc(inst),1296 .cmp_vector => try func.airCmpVector(inst),
1133 .ret_ptr => try self.airRetPtr(inst),1297 .cmp_lt_errors_len => try func.airCmpLtErrorsLen(inst),
1134 .arg => try self.airArg(inst),1298
1135 .assembly => try self.airAsm(inst),1299 .slice => try func.airSlice(inst),
1136 .bitcast => try self.airBitCast(inst),1300 .array_to_slice => try func.airArrayToSlice(inst),
1137 .block => try self.airBlock(inst),1301
1138 .br => try self.airBr(inst),1302 .slice_ptr => try func.airSlicePtr(inst),
1139 .trap => try self.airTrap(),1303 .slice_len => try func.airSliceLen(inst),
1140 .breakpoint => try self.airBreakpoint(),1304
1141 .ret_addr => try self.airRetAddr(inst),1305 .alloc => try func.airAlloc(inst),
1142 .frame_addr => try self.airFrameAddress(inst),1306 .ret_ptr => try func.airRetPtr(inst),
1143 .fence => try self.airFence(),1307 .arg => try func.airArg(inst),
1144 .cond_br => try self.airCondBr(inst),1308 .assembly => try func.airAsm(inst),
1145 .dbg_stmt => try self.airDbgStmt(inst),1309 .bitcast => try func.airBitCast(inst),
1146 .fptrunc => try self.airFptrunc(inst),1310 .block => try func.airBlock(inst),
1147 .fpext => try self.airFpext(inst),1311 .br => try func.airBr(inst),
1148 .intcast => try self.airIntCast(inst),1312 .trap => try func.airTrap(),
1149 .trunc => try self.airTrunc(inst),1313 .breakpoint => try func.airBreakpoint(),
1150 .int_from_bool => try self.airIntFromBool(inst),1314 .ret_addr => try func.airRetAddr(inst),
1151 .is_non_null => try self.airIsNonNull(inst),1315 .frame_addr => try func.airFrameAddress(inst),
1152 .is_non_null_ptr => try self.airIsNonNullPtr(inst),1316 .fence => try func.airFence(),
1153 .is_null => try self.airIsNull(inst),1317 .cond_br => try func.airCondBr(inst),
1154 .is_null_ptr => try self.airIsNullPtr(inst),1318 .dbg_stmt => try func.airDbgStmt(inst),
1155 .is_non_err => try self.airIsNonErr(inst),1319 .fptrunc => try func.airFptrunc(inst),
1156 .is_non_err_ptr => try self.airIsNonErrPtr(inst),1320 .fpext => try func.airFpext(inst),
1157 .is_err => try self.airIsErr(inst),1321 .intcast => try func.airIntCast(inst),
1158 .is_err_ptr => try self.airIsErrPtr(inst),1322 .trunc => try func.airTrunc(inst),
1159 .load => try self.airLoad(inst),1323 .int_from_bool => try func.airIntFromBool(inst),
1160 .loop => try self.airLoop(inst),1324 .is_non_null => try func.airIsNonNull(inst),
1161 .not => try self.airNot(inst),1325 .is_non_null_ptr => try func.airIsNonNullPtr(inst),
1162 .int_from_ptr => try self.airIntFromPtr(inst),1326 .is_null => try func.airIsNull(inst),
1163 .ret => try self.airRet(inst, false),1327 .is_null_ptr => try func.airIsNullPtr(inst),
1164 .ret_safe => try self.airRet(inst, true),1328 .is_non_err => try func.airIsNonErr(inst),
1165 .ret_load => try self.airRetLoad(inst),1329 .is_non_err_ptr => try func.airIsNonErrPtr(inst),
1166 .store => try self.airStore(inst, false),1330 .is_err => try func.airIsErr(inst),
1167 .store_safe => try self.airStore(inst, true),1331 .is_err_ptr => try func.airIsErrPtr(inst),
1168 .struct_field_ptr=> try self.airStructFieldPtr(inst),1332 .load => try func.airLoad(inst),
1169 .struct_field_val=> try self.airStructFieldVal(inst),1333 .loop => try func.airLoop(inst),
1170 .array_to_slice => try self.airArrayToSlice(inst),1334 .not => try func.airNot(inst),
1171 .float_from_int => try self.airFloatFromInt(inst),1335 .int_from_ptr => try func.airIntFromPtr(inst),
1172 .int_from_float => try self.airIntFromFloat(inst),1336 .ret => try func.airRet(inst, false),
1173 .cmpxchg_strong => try self.airCmpxchg(inst),1337 .ret_safe => try func.airRet(inst, true),
1174 .cmpxchg_weak => try self.airCmpxchg(inst),1338 .ret_load => try func.airRetLoad(inst),
1175 .atomic_rmw => try self.airAtomicRmw(inst),1339 .store => try func.airStore(inst, false),
1176 .atomic_load => try self.airAtomicLoad(inst),1340 .store_safe => try func.airStore(inst, true),
1177 .memcpy => try self.airMemcpy(inst),1341 .struct_field_ptr=> try func.airStructFieldPtr(inst),
1178 .memset => try self.airMemset(inst, false),1342 .struct_field_val=> try func.airStructFieldVal(inst),
1179 .memset_safe => try self.airMemset(inst, true),1343 .float_from_int => try func.airFloatFromInt(inst),
1180 .set_union_tag => try self.airSetUnionTag(inst),1344 .int_from_float => try func.airIntFromFloat(inst),
1181 .get_union_tag => try self.airGetUnionTag(inst),1345 .cmpxchg_strong => try func.airCmpxchg(inst),
1182 .clz => try self.airClz(inst),1346 .cmpxchg_weak => try func.airCmpxchg(inst),
1183 .ctz => try self.airCtz(inst),1347 .atomic_rmw => try func.airAtomicRmw(inst),
1184 .popcount => try self.airPopcount(inst),1348 .atomic_load => try func.airAtomicLoad(inst),
1185 .abs => try self.airAbs(inst),1349 .memcpy => try func.airMemcpy(inst),
1186 .byte_swap => try self.airByteSwap(inst),1350 .memset => try func.airMemset(inst, false),
1187 .bit_reverse => try self.airBitReverse(inst),1351 .memset_safe => try func.airMemset(inst, true),
1188 .tag_name => try self.airTagName(inst),1352 .set_union_tag => try func.airSetUnionTag(inst),
1189 .error_name => try self.airErrorName(inst),1353 .get_union_tag => try func.airGetUnionTag(inst),
1190 .splat => try self.airSplat(inst),1354 .clz => try func.airClz(inst),
1191 .select => try self.airSelect(inst),1355 .ctz => try func.airCtz(inst),
1192 .shuffle => try self.airShuffle(inst),1356 .popcount => try func.airPopcount(inst),
1193 .reduce => try self.airReduce(inst),1357 .abs => try func.airAbs(inst),
1194 .aggregate_init => try self.airAggregateInit(inst),1358 .byte_swap => try func.airByteSwap(inst),
1195 .union_init => try self.airUnionInit(inst),1359 .bit_reverse => try func.airBitReverse(inst),
1196 .prefetch => try self.airPrefetch(inst),1360 .tag_name => try func.airTagName(inst),
1197 .mul_add => try self.airMulAdd(inst),1361 .error_name => try func.airErrorName(inst),
1198 .addrspace_cast => return self.fail("TODO: addrspace_cast", .{}),1362 .splat => try func.airSplat(inst),
11991363 .select => try func.airSelect(inst),
1200 .@"try" => try self.airTry(inst),1364 .shuffle => try func.airShuffle(inst),
1201 .try_ptr => return self.fail("TODO: try_ptr", .{}),1365 .reduce => try func.airReduce(inst),
1366 .aggregate_init => try func.airAggregateInit(inst),
1367 .union_init => try func.airUnionInit(inst),
1368 .prefetch => try func.airPrefetch(inst),
1369 .mul_add => try func.airMulAdd(inst),
1370 .addrspace_cast => return func.fail("TODO: addrspace_cast", .{}),
1371
1372 .@"try" => try func.airTry(inst),
1373 .try_ptr => return func.fail("TODO: try_ptr", .{}),
12021374
1203 .dbg_var_ptr,1375 .dbg_var_ptr,
1204 .dbg_var_val,1376 .dbg_var_val,
1205 => try self.airDbgVar(inst),1377 => try func.airDbgVar(inst),
12061378
1207 .dbg_inline_block => try self.airDbgInlineBlock(inst),1379 .dbg_inline_block => try func.airDbgInlineBlock(inst),
12081380
1209 .call => try self.airCall(inst, .auto),1381 .call => try func.airCall(inst, .auto),
1210 .call_always_tail => try self.airCall(inst, .always_tail),1382 .call_always_tail => try func.airCall(inst, .always_tail),
1211 .call_never_tail => try self.airCall(inst, .never_tail),1383 .call_never_tail => try func.airCall(inst, .never_tail),
1212 .call_never_inline => try self.airCall(inst, .never_inline),1384 .call_never_inline => try func.airCall(inst, .never_inline),
12131385
1214 .atomic_store_unordered => try self.airAtomicStore(inst, .unordered),1386 .atomic_store_unordered => try func.airAtomicStore(inst, .unordered),
1215 .atomic_store_monotonic => try self.airAtomicStore(inst, .monotonic),1387 .atomic_store_monotonic => try func.airAtomicStore(inst, .monotonic),
1216 .atomic_store_release => try self.airAtomicStore(inst, .release),1388 .atomic_store_release => try func.airAtomicStore(inst, .release),
1217 .atomic_store_seq_cst => try self.airAtomicStore(inst, .seq_cst),1389 .atomic_store_seq_cst => try func.airAtomicStore(inst, .seq_cst),
1390 .struct_field_ptr_index_0 => try func.airStructFieldPtrIndex(inst, 0),
1391 .struct_field_ptr_index_1 => try func.airStructFieldPtrIndex(inst, 1),
1392 .struct_field_ptr_index_2 => try func.airStructFieldPtrIndex(inst, 2),
1393 .struct_field_ptr_index_3 => try func.airStructFieldPtrIndex(inst, 3),
12181394
1219 .struct_field_ptr_index_0 => try self.airStructFieldPtrIndex(inst, 0),1395 .field_parent_ptr => try func.airFieldParentPtr(inst),
1220 .struct_field_ptr_index_1 => try self.airStructFieldPtrIndex(inst, 1),
1221 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
1222 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
12231396
1224 .field_parent_ptr => try self.airFieldParentPtr(inst),1397 .switch_br => try func.airSwitchBr(inst),
12251398
1226 .switch_br => try self.airSwitch(inst),1399 .ptr_slice_len_ptr => try func.airPtrSliceLenPtr(inst),
1227 .slice_ptr => try self.airSlicePtr(inst),1400 .ptr_slice_ptr_ptr => try func.airPtrSlicePtrPtr(inst),
1228 .slice_len => try self.airSliceLen(inst),
12291401
1230 .ptr_slice_len_ptr => try self.airPtrSliceLenPtr(inst),1402 .array_elem_val => try func.airArrayElemVal(inst),
1231 .ptr_slice_ptr_ptr => try self.airPtrSlicePtrPtr(inst),1403
1404 .slice_elem_val => try func.airSliceElemVal(inst),
1405 .slice_elem_ptr => try func.airSliceElemPtr(inst),
12321406
1233 .array_elem_val => try self.airArrayElemVal(inst),1407 .ptr_elem_val => try func.airPtrElemVal(inst),
1234 .slice_elem_val => try self.airSliceElemVal(inst),1408 .ptr_elem_ptr => try func.airPtrElemPtr(inst),
1235 .slice_elem_ptr => try self.airSliceElemPtr(inst),
1236 .ptr_elem_val => try self.airPtrElemVal(inst),
1237 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
12381409
1239 .inferred_alloc, .inferred_alloc_comptime => unreachable,1410 .inferred_alloc, .inferred_alloc_comptime => unreachable,
1240 .unreach => self.finishAirBookkeeping(),1411 .unreach => func.finishAirBookkeeping(),
12411412
1242 .optional_payload => try self.airOptionalPayload(inst),1413 .optional_payload => try func.airOptionalPayload(inst),
1243 .optional_payload_ptr => try self.airOptionalPayloadPtr(inst),1414 .optional_payload_ptr => try func.airOptionalPayloadPtr(inst),
1244 .optional_payload_ptr_set => try self.airOptionalPayloadPtrSet(inst),1415 .optional_payload_ptr_set => try func.airOptionalPayloadPtrSet(inst),
1245 .unwrap_errunion_err => try self.airUnwrapErrErr(inst),1416 .unwrap_errunion_err => try func.airUnwrapErrErr(inst),
1246 .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst),1417 .unwrap_errunion_payload => try func.airUnwrapErrPayload(inst),
1247 .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst),1418 .unwrap_errunion_err_ptr => try func.airUnwrapErrErrPtr(inst),
1248 .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst),1419 .unwrap_errunion_payload_ptr=> try func.airUnwrapErrPayloadPtr(inst),
1249 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),1420 .errunion_payload_ptr_set => try func.airErrUnionPayloadPtrSet(inst),
1250 .err_return_trace => try self.airErrReturnTrace(inst),1421 .err_return_trace => try func.airErrReturnTrace(inst),
1251 .set_err_return_trace => try self.airSetErrReturnTrace(inst),1422 .set_err_return_trace => try func.airSetErrReturnTrace(inst),
1252 .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),1423 .save_err_return_trace_index=> try func.airSaveErrReturnTraceIndex(inst),
12531424
1254 .wrap_optional => try self.airWrapOptional(inst),1425 .wrap_optional => try func.airWrapOptional(inst),
1255 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),1426 .wrap_errunion_payload => try func.airWrapErrUnionPayload(inst),
1256 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),1427 .wrap_errunion_err => try func.airWrapErrUnionErr(inst),
12571428
1258 .add_optimized,1429 .add_optimized,
1259 .sub_optimized,1430 .sub_optimized,
...@@ -1274,16 +1445,16 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1274,16 +1445,16 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1274 .cmp_vector_optimized,1445 .cmp_vector_optimized,
1275 .reduce_optimized,1446 .reduce_optimized,
1276 .int_from_float_optimized,1447 .int_from_float_optimized,
1277 => return self.fail("TODO implement optimized float mode", .{}),1448 => return func.fail("TODO implement optimized float mode", .{}),
12781449
1279 .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),1450 .is_named_enum_value => return func.fail("TODO implement is_named_enum_value", .{}),
1280 .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}),1451 .error_set_has_value => return func.fail("TODO implement error_set_has_value", .{}),
1281 .vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}),1452 .vector_store_elem => return func.fail("TODO implement vector_store_elem", .{}),
12821453
1283 .c_va_arg => return self.fail("TODO implement c_va_arg", .{}),1454 .c_va_arg => return func.fail("TODO implement c_va_arg", .{}),
1284 .c_va_copy => return self.fail("TODO implement c_va_copy", .{}),1455 .c_va_copy => return func.fail("TODO implement c_va_copy", .{}),
1285 .c_va_end => return self.fail("TODO implement c_va_end", .{}),1456 .c_va_end => return func.fail("TODO implement c_va_end", .{}),
1286 .c_va_start => return self.fail("TODO implement c_va_start", .{}),1457 .c_va_start => return func.fail("TODO implement c_va_start", .{}),
12871458
1288 .wasm_memory_size => unreachable,1459 .wasm_memory_size => unreachable,
1289 .wasm_memory_grow => unreachable,1460 .wasm_memory_grow => unreachable,
...@@ -1294,95 +1465,97 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1294,95 +1465,97 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1294 // zig fmt: on1465 // zig fmt: on
1295 }1466 }
12961467
1297 assert(!self.register_manager.lockedRegsExist());1468 assert(!func.register_manager.lockedRegsExist());
12981469
1299 if (std.debug.runtime_safety) {1470 if (std.debug.runtime_safety) {
1300 if (self.air_bookkeeping < old_air_bookkeeping + 1) {1471 if (func.air_bookkeeping < old_air_bookkeeping + 1) {
1301 std.debug.panic("in codegen.zig, handling of AIR instruction %{d} ('{}') did not do proper bookkeeping. Look for a missing call to finishAir.", .{ inst, air_tags[@intFromEnum(inst)] });1472 std.debug.panic("in codegen.zig, handling of AIR instruction %{d} ('{}') did not do proper bookkeeping. Look for a missing call to finishAir.", .{ inst, air_tags[@intFromEnum(inst)] });
1302 }1473 }
13031474
1304 { // check consistency of tracked registers1475 { // check consistency of tracked registers
1305 var it = self.register_manager.free_registers.iterator(.{ .kind = .unset });1476 var it = func.register_manager.free_registers.iterator(.{ .kind = .unset });
1306 while (it.next()) |index| {1477 while (it.next()) |index| {
1307 const tracked_inst = self.register_manager.registers[index];1478 const tracked_inst = func.register_manager.registers[index];
1308 const tracking = self.getResolvedInstValue(tracked_inst);1479 tracking_log.debug("tracked inst: {}", .{tracked_inst});
1480 const tracking = func.getResolvedInstValue(tracked_inst);
1309 for (tracking.getRegs()) |reg| {1481 for (tracking.getRegs()) |reg| {
1310 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;1482 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
1311 } else return self.fail(1483 } else return std.debug.panic(
1312 \\%{} takes up these regs: {any}, however those regs don't use it1484 \\%{} takes up these regs: {any}, however these regs {any}, don't use it
1313 , .{ index, tracking.getRegs() });1485 , .{ tracked_inst, tracking.getRegs(), RegisterManager.regAtTrackedIndex(@intCast(index)) });
1314 }1486 }
1315 }1487 }
1316 }1488 }
1317 }1489 }
1490 verbose_tracking_log.debug("{}", .{func.fmtTracking()});
1318}1491}
13191492
1320fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) !void {1493fn getValue(func: *Func, value: MCValue, inst: ?Air.Inst.Index) !void {
1321 for (value.getRegs()) |reg| try self.register_manager.getReg(reg, inst);1494 for (value.getRegs()) |reg| try func.register_manager.getReg(reg, inst);
1322}1495}
13231496
1324fn getValueIfFree(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void {1497fn getValueIfFree(func: *Func, value: MCValue, inst: ?Air.Inst.Index) void {
1325 for (value.getRegs()) |reg| if (self.register_manager.isRegFree(reg))1498 for (value.getRegs()) |reg| if (func.register_manager.isRegFree(reg))
1326 self.register_manager.getRegAssumeFree(reg, inst);1499 func.register_manager.getRegAssumeFree(reg, inst);
1327}1500}
13281501
1329fn freeValue(self: *Self, value: MCValue) !void {1502fn freeValue(func: *Func, value: MCValue) !void {
1330 switch (value) {1503 switch (value) {
1331 .register => |reg| self.register_manager.freeReg(reg),1504 .register => |reg| func.register_manager.freeReg(reg),
1332 .register_pair => |regs| for (regs) |reg| self.register_manager.freeReg(reg),1505 .register_pair => |regs| for (regs) |reg| func.register_manager.freeReg(reg),
1333 .register_offset => |reg_off| self.register_manager.freeReg(reg_off.reg),1506 .register_offset => |reg_off| func.register_manager.freeReg(reg_off.reg),
1334 else => {}, // TODO process stack allocation death1507 else => {}, // TODO process stack allocation death
1335 }1508 }
1336}1509}
13371510
1338fn feed(self: *Self, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) !void {1511fn feed(func: *Func, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) !void {
1339 if (bt.feed()) if (operand.toIndex()) |inst| {1512 if (bt.feed()) if (operand.toIndex()) |inst| {
1340 log.debug("feed inst: %{}", .{inst});1513 log.debug("feed inst: %{}", .{inst});
1341 try self.processDeath(inst);1514 try func.processDeath(inst);
1342 };1515 };
1343}1516}
13441517
1345/// Asserts there is already capacity to insert into top branch inst_table.1518/// Asserts there is already capacity to insert into top branch inst_table.
1346fn processDeath(self: *Self, inst: Air.Inst.Index) !void {1519fn processDeath(func: *Func, inst: Air.Inst.Index) !void {
1347 try self.inst_tracking.getPtr(inst).?.die(self, inst);1520 try func.inst_tracking.getPtr(inst).?.die(func, inst);
1348}1521}
13491522
1350/// Called when there are no operands, and the instruction is always unreferenced.1523/// Called when there are no operands, and the instruction is always unreferenced.
1351fn finishAirBookkeeping(self: *Self) void {1524fn finishAirBookkeeping(func: *Func) void {
1352 if (std.debug.runtime_safety) {1525 if (std.debug.runtime_safety) {
1353 self.air_bookkeeping += 1;1526 func.air_bookkeeping += 1;
1354 }1527 }
1355}1528}
13561529
1357fn finishAirResult(self: *Self, inst: Air.Inst.Index, result: MCValue) void {1530fn finishAirResult(func: *Func, inst: Air.Inst.Index, result: MCValue) void {
1358 if (self.liveness.isUnused(inst)) switch (result) {1531 if (func.liveness.isUnused(inst)) switch (result) {
1359 .none, .dead, .unreach => {},1532 .none, .dead, .unreach => {},
1360 else => unreachable, // Why didn't the result die?1533 else => unreachable, // Why didn't the result die?
1361 } else {1534 } else {
1362 tracking_log.debug("%{d} => {} (birth)", .{ inst, result });1535 tracking_log.debug("%{d} => {} (birth)", .{ inst, result });
1363 self.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(result));1536 func.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(result));
1364 // In some cases, an operand may be reused as the result.1537 // In some cases, an operand may be reused as the result.
1365 // If that operand died and was a register, it was freed by1538 // If that operand died and was a register, it was freed by
1366 // processDeath, so we have to "re-allocate" the register.1539 // processDeath, so we have to "re-allocate" the register.
1367 self.getValueIfFree(result, inst);1540 func.getValueIfFree(result, inst);
1368 }1541 }
1369 self.finishAirBookkeeping();1542 func.finishAirBookkeeping();
1370}1543}
13711544
1372fn finishAir(1545fn finishAir(
1373 self: *Self,1546 func: *Func,
1374 inst: Air.Inst.Index,1547 inst: Air.Inst.Index,
1375 result: MCValue,1548 result: MCValue,
1376 operands: [Liveness.bpi - 1]Air.Inst.Ref,1549 operands: [Liveness.bpi - 1]Air.Inst.Ref,
1377) !void {1550) !void {
1378 var tomb_bits = self.liveness.getTombBits(inst);1551 var tomb_bits = func.liveness.getTombBits(inst);
1379 for (operands) |op| {1552 for (operands) |op| {
1380 const dies = @as(u1, @truncate(tomb_bits)) != 0;1553 const dies = @as(u1, @truncate(tomb_bits)) != 0;
1381 tomb_bits >>= 1;1554 tomb_bits >>= 1;
1382 if (!dies) continue;1555 if (!dies) continue;
1383 try self.processDeath(op.toIndexAllowNone() orelse continue);1556 try func.processDeath(op.toIndexAllowNone() orelse continue);
1384 }1557 }
1385 self.finishAirResult(inst, result);1558 func.finishAirResult(inst, result);
1386}1559}
13871560
1388const FrameLayout = struct {1561const FrameLayout = struct {
...@@ -1391,7 +1564,7 @@ const FrameLayout = struct {...@@ -1391,7 +1564,7 @@ const FrameLayout = struct {
1391};1564};
13921565
1393fn setFrameLoc(1566fn setFrameLoc(
1394 self: *Self,1567 func: *Func,
1395 frame_index: FrameIndex,1568 frame_index: FrameIndex,
1396 base: Register,1569 base: Register,
1397 offset: *i32,1570 offset: *i32,
...@@ -1399,24 +1572,24 @@ fn setFrameLoc(...@@ -1399,24 +1572,24 @@ fn setFrameLoc(
1399) void {1572) void {
1400 const frame_i = @intFromEnum(frame_index);1573 const frame_i = @intFromEnum(frame_index);
1401 if (aligned) {1574 if (aligned) {
1402 const alignment: InternPool.Alignment = self.frame_allocs.items(.abi_align)[frame_i];1575 const alignment: InternPool.Alignment = func.frame_allocs.items(.abi_align)[frame_i];
1403 offset.* = if (math.sign(offset.*) < 0)1576 offset.* = if (math.sign(offset.*) < 0)
1404 -1 * @as(i32, @intCast(alignment.backward(@intCast(@abs(offset.*)))))1577 -1 * @as(i32, @intCast(alignment.backward(@intCast(@abs(offset.*)))))
1405 else1578 else
1406 @intCast(alignment.forward(@intCast(@abs(offset.*))));1579 @intCast(alignment.forward(@intCast(@abs(offset.*))));
1407 }1580 }
1408 self.frame_locs.set(frame_i, .{ .base = base, .disp = offset.* });1581 func.frame_locs.set(frame_i, .{ .base = base, .disp = offset.* });
1409 offset.* += self.frame_allocs.items(.abi_size)[frame_i];1582 offset.* += func.frame_allocs.items(.abi_size)[frame_i];
1410}1583}
14111584
1412fn computeFrameLayout(self: *Self) !FrameLayout {1585fn computeFrameLayout(func: *Func) !FrameLayout {
1413 const frame_allocs_len = self.frame_allocs.len;1586 const frame_allocs_len = func.frame_allocs.len;
1414 try self.frame_locs.resize(self.gpa, frame_allocs_len);1587 try func.frame_locs.resize(func.gpa, frame_allocs_len);
1415 const stack_frame_order = try self.gpa.alloc(FrameIndex, frame_allocs_len - FrameIndex.named_count);1588 const stack_frame_order = try func.gpa.alloc(FrameIndex, frame_allocs_len - FrameIndex.named_count);
1416 defer self.gpa.free(stack_frame_order);1589 defer func.gpa.free(stack_frame_order);
14171590
1418 const frame_size = self.frame_allocs.items(.abi_size);1591 const frame_size = func.frame_allocs.items(.abi_size);
1419 const frame_align = self.frame_allocs.items(.abi_align);1592 const frame_align = func.frame_allocs.items(.abi_align);
14201593
1421 for (stack_frame_order, FrameIndex.named_count..) |*frame_order, frame_index|1594 for (stack_frame_order, FrameIndex.named_count..) |*frame_order, frame_index|
1422 frame_order.* = @enumFromInt(frame_index);1595 frame_order.* = @enumFromInt(frame_index);
...@@ -1433,9 +1606,9 @@ fn computeFrameLayout(self: *Self) !FrameLayout {...@@ -1433,9 +1606,9 @@ fn computeFrameLayout(self: *Self) !FrameLayout {
1433 }1606 }
14341607
1435 var save_reg_list = Mir.RegisterList{};1608 var save_reg_list = Mir.RegisterList{};
1436 for (callee_preserved_regs) |reg| {1609 for (abi.Registers.all_preserved) |reg| {
1437 if (self.register_manager.isRegAllocated(reg)) {1610 if (func.register_manager.isRegAllocated(reg)) {
1438 save_reg_list.push(&callee_preserved_regs, reg);1611 save_reg_list.push(&abi.Registers.all_preserved, reg);
1439 }1612 }
1440 }1613 }
14411614
...@@ -1468,11 +1641,11 @@ fn computeFrameLayout(self: *Self) !FrameLayout {...@@ -1468,11 +1641,11 @@ fn computeFrameLayout(self: *Self) !FrameLayout {
14681641
1469 // store the ra at total_size - 8, so it's the very first thing in the stack1642 // store the ra at total_size - 8, so it's the very first thing in the stack
1470 // relative to the fp1643 // relative to the fp
1471 self.frame_locs.set(1644 func.frame_locs.set(
1472 @intFromEnum(FrameIndex.ret_addr),1645 @intFromEnum(FrameIndex.ret_addr),
1473 .{ .base = .sp, .disp = acc_frame_size - 8 },1646 .{ .base = .sp, .disp = acc_frame_size - 8 },
1474 );1647 );
1475 self.frame_locs.set(1648 func.frame_locs.set(
1476 @intFromEnum(FrameIndex.base_ptr),1649 @intFromEnum(FrameIndex.base_ptr),
1477 .{ .base = .sp, .disp = acc_frame_size - 16 },1650 .{ .base = .sp, .disp = acc_frame_size - 16 },
1478 );1651 );
...@@ -1481,11 +1654,11 @@ fn computeFrameLayout(self: *Self) !FrameLayout {...@@ -1481,11 +1654,11 @@ fn computeFrameLayout(self: *Self) !FrameLayout {
1481 // not need to know the size of the first allocation. Stack offsets point at the "bottom"1654 // not need to know the size of the first allocation. Stack offsets point at the "bottom"
1482 // of variables.1655 // of variables.
1483 var s0_offset: i32 = -acc_frame_size;1656 var s0_offset: i32 = -acc_frame_size;
1484 self.setFrameLoc(.stack_frame, .s0, &s0_offset, true);1657 func.setFrameLoc(.stack_frame, .s0, &s0_offset, true);
1485 for (stack_frame_order) |frame_index| self.setFrameLoc(frame_index, .s0, &s0_offset, true);1658 for (stack_frame_order) |frame_index| func.setFrameLoc(frame_index, .s0, &s0_offset, true);
1486 self.setFrameLoc(.args_frame, .s0, &s0_offset, true);1659 func.setFrameLoc(.args_frame, .s0, &s0_offset, true);
1487 self.setFrameLoc(.call_frame, .s0, &s0_offset, true);1660 func.setFrameLoc(.call_frame, .s0, &s0_offset, true);
1488 self.setFrameLoc(.spill_frame, .s0, &s0_offset, true);1661 func.setFrameLoc(.spill_frame, .s0, &s0_offset, true);
14891662
1490 return .{1663 return .{
1491 .stack_adjust = @intCast(acc_frame_size),1664 .stack_adjust = @intCast(acc_frame_size),
...@@ -1493,21 +1666,21 @@ fn computeFrameLayout(self: *Self) !FrameLayout {...@@ -1493,21 +1666,21 @@ fn computeFrameLayout(self: *Self) !FrameLayout {
1493 };1666 };
1494}1667}
14951668
1496fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {1669fn ensureProcessDeathCapacity(func: *Func, additional_count: usize) !void {
1497 const table = &self.branch_stack.items[self.branch_stack.items.len - 1].inst_table;1670 const table = &func.branch_stack.items[func.branch_stack.items.len - 1].inst_table;
1498 try table.ensureUnusedCapacity(self.gpa, additional_count);1671 try table.ensureUnusedCapacity(func.gpa, additional_count);
1499}1672}
15001673
1501fn memSize(self: *Self, ty: Type) Memory.Size {1674fn memSize(func: *Func, ty: Type) Memory.Size {
1502 const mod = self.bin_file.comp.module.?;1675 const mod = func.bin_file.comp.module.?;
1503 return switch (ty.zigTypeTag(mod)) {1676 return switch (ty.zigTypeTag(mod)) {
1504 .Float => Memory.Size.fromBitSize(ty.floatBits(self.target.*)),1677 .Float => Memory.Size.fromBitSize(ty.floatBits(func.target.*)),
1505 else => Memory.Size.fromByteSize(ty.abiSize(mod)),1678 else => Memory.Size.fromByteSize(ty.abiSize(mod)),
1506 };1679 };
1507}1680}
15081681
1509fn splitType(self: *Self, ty: Type) ![2]Type {1682fn splitType(func: *Func, ty: Type) ![2]Type {
1510 const zcu = self.bin_file.comp.module.?;1683 const zcu = func.bin_file.comp.module.?;
1511 const classes = mem.sliceTo(&abi.classifySystem(ty, zcu), .none);1684 const classes = mem.sliceTo(&abi.classifySystem(ty, zcu), .none);
1512 var parts: [2]Type = undefined;1685 var parts: [2]Type = undefined;
1513 if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| {1686 if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| {
...@@ -1524,186 +1697,317 @@ fn splitType(self: *Self, ty: Type) ![2]Type {...@@ -1524,186 +1697,317 @@ fn splitType(self: *Self, ty: Type) ![2]Type {
1524 },1697 },
1525 else => unreachable,1698 else => unreachable,
1526 },1699 },
1527 else => return self.fail("TODO: splitType class {}", .{class}),1700 else => return func.fail("TODO: splitType class {}", .{class}),
1528 };1701 };
1529 } else if (parts[0].abiSize(zcu) + parts[1].abiSize(zcu) == ty.abiSize(zcu)) return parts;1702 } else if (parts[0].abiSize(zcu) + parts[1].abiSize(zcu) == ty.abiSize(zcu)) return parts;
1530 return self.fail("TODO implement splitType for {}", .{ty.fmt(zcu)});1703 return func.fail("TODO implement splitType for {}", .{ty.fmt(zcu)});
1704}
1705
1706/// Truncates the value in the register in place.
1707/// Clobbers any remaining bits.
1708fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {
1709 const mod = func.bin_file.comp.module.?;
1710 const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{
1711 .signedness = .unsigned,
1712 .bits = @intCast(ty.bitSize(mod)),
1713 };
1714 const shift = math.cast(u6, 64 - int_info.bits % 64) orelse return;
1715 switch (int_info.signedness) {
1716 .signed => {
1717 _ = try func.addInst(.{
1718 .tag = .slli,
1719 .ops = .rri,
1720 .data = .{
1721 .i_type = .{
1722 .rd = reg,
1723 .rs1 = reg,
1724 .imm12 = Immediate.u(shift),
1725 },
1726 },
1727 });
1728 _ = try func.addInst(.{
1729 .tag = .srai,
1730 .ops = .rri,
1731 .data = .{
1732 .i_type = .{
1733 .rd = reg,
1734 .rs1 = reg,
1735 .imm12 = Immediate.u(shift),
1736 },
1737 },
1738 });
1739 },
1740 .unsigned => {
1741 const mask = ~@as(u64, 0) >> shift;
1742 if (mask < 256) {
1743 _ = try func.addInst(.{
1744 .tag = .andi,
1745 .ops = .rri,
1746 .data = .{
1747 .i_type = .{
1748 .rd = reg,
1749 .rs1 = reg,
1750 .imm12 = Immediate.u(@intCast(mask)),
1751 },
1752 },
1753 });
1754 } else {
1755 _ = try func.addInst(.{
1756 .tag = .slli,
1757 .ops = .rri,
1758 .data = .{
1759 .i_type = .{
1760 .rd = reg,
1761 .rs1 = reg,
1762 .imm12 = Immediate.u(shift),
1763 },
1764 },
1765 });
1766 _ = try func.addInst(.{
1767 .tag = .srli,
1768 .ops = .rri,
1769 .data = .{
1770 .i_type = .{
1771 .rd = reg,
1772 .rs1 = reg,
1773 .imm12 = Immediate.u(shift),
1774 },
1775 },
1776 });
1777 }
1778 },
1779 }
1531}1780}
15321781
1533fn symbolIndex(self: *Self) !u32 {1782fn symbolIndex(func: *Func) !u32 {
1534 const zcu = self.bin_file.comp.module.?;1783 const zcu = func.bin_file.comp.module.?;
1535 const decl_index = zcu.funcOwnerDeclIndex(self.func_index);1784 const decl_index = zcu.funcOwnerDeclIndex(func.func_index);
1536 return switch (self.bin_file.tag) {1785 return switch (func.bin_file.tag) {
1537 .elf => blk: {1786 .elf => blk: {
1538 const elf_file = self.bin_file.cast(link.File.Elf).?;1787 const elf_file = func.bin_file.cast(link.File.Elf).?;
1539 const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);1788 const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
1540 break :blk atom_index;1789 break :blk atom_index;
1541 },1790 },
1542 else => return self.fail("TODO genSetReg load_symbol for {s}", .{@tagName(self.bin_file.tag)}),1791 else => return func.fail("TODO symbolIndex {s}", .{@tagName(func.bin_file.tag)}),
1543 };1792 };
1544}1793}
15451794
1546fn allocFrameIndex(self: *Self, alloc: FrameAlloc) !FrameIndex {1795fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex {
1547 const frame_allocs_slice = self.frame_allocs.slice();1796 const frame_allocs_slice = func.frame_allocs.slice();
1548 const frame_size = frame_allocs_slice.items(.abi_size);1797 const frame_size = frame_allocs_slice.items(.abi_size);
1549 const frame_align = frame_allocs_slice.items(.abi_align);1798 const frame_align = frame_allocs_slice.items(.abi_align);
15501799
1551 const stack_frame_align = &frame_align[@intFromEnum(FrameIndex.stack_frame)];1800 const stack_frame_align = &frame_align[@intFromEnum(FrameIndex.stack_frame)];
1552 stack_frame_align.* = stack_frame_align.max(alloc.abi_align);1801 stack_frame_align.* = stack_frame_align.max(alloc.abi_align);
15531802
1554 for (self.free_frame_indices.keys(), 0..) |frame_index, free_i| {1803 for (func.free_frame_indices.keys(), 0..) |frame_index, free_i| {
1555 const abi_size = frame_size[@intFromEnum(frame_index)];1804 const abi_size = frame_size[@intFromEnum(frame_index)];
1556 if (abi_size != alloc.abi_size) continue;1805 if (abi_size != alloc.abi_size) continue;
1557 const abi_align = &frame_align[@intFromEnum(frame_index)];1806 const abi_align = &frame_align[@intFromEnum(frame_index)];
1558 abi_align.* = abi_align.max(alloc.abi_align);1807 abi_align.* = abi_align.max(alloc.abi_align);
15591808
1560 _ = self.free_frame_indices.swapRemoveAt(free_i);1809 _ = func.free_frame_indices.swapRemoveAt(free_i);
1561 return frame_index;1810 return frame_index;
1562 }1811 }
1563 const frame_index: FrameIndex = @enumFromInt(self.frame_allocs.len);1812 const frame_index: FrameIndex = @enumFromInt(func.frame_allocs.len);
1564 try self.frame_allocs.append(self.gpa, alloc);1813 try func.frame_allocs.append(func.gpa, alloc);
1565 log.debug("allocated frame {}", .{frame_index});1814 log.debug("allocated frame {}", .{frame_index});
1566 return frame_index;1815 return frame_index;
1567}1816}
15681817
1569/// Use a pointer instruction as the basis for allocating stack memory.1818/// Use a pointer instruction as the basis for allocating stack memory.
1570fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex {1819fn allocMemPtr(func: *Func, inst: Air.Inst.Index) !FrameIndex {
1571 const zcu = self.bin_file.comp.module.?;1820 const zcu = func.bin_file.comp.module.?;
1572 const ptr_ty = self.typeOfIndex(inst);1821 const ptr_ty = func.typeOfIndex(inst);
1573 const val_ty = ptr_ty.childType(zcu);1822 const val_ty = ptr_ty.childType(zcu);
1574 return self.allocFrameIndex(FrameAlloc.init(.{1823 return func.allocFrameIndex(FrameAlloc.init(.{
1575 .size = math.cast(u32, val_ty.abiSize(zcu)) orelse {1824 .size = math.cast(u32, val_ty.abiSize(zcu)) orelse {
1576 return self.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(zcu)});1825 return func.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(zcu)});
1577 },1826 },
1578 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),1827 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),
1579 }));1828 }));
1580}1829}
15811830
1582fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {1831fn typeRegClass(func: *Func, ty: Type) abi.RegisterClass {
1583 const zcu = self.bin_file.comp.module.?;1832 const zcu = func.bin_file.comp.module.?;
1584 const elem_ty = self.typeOfIndex(inst);1833 return switch (ty.zigTypeTag(zcu)) {
1834 .Float => .float,
1835 .Vector => @panic("TODO: typeRegClass for Vectors"),
1836 inline else => .int,
1837 };
1838}
1839
1840fn regGeneralClassForType(func: *Func, ty: Type) RegisterManager.RegisterBitSet {
1841 const zcu = func.bin_file.comp.module.?;
1842 return switch (ty.zigTypeTag(zcu)) {
1843 .Float => abi.Registers.Float.general_purpose,
1844 .Vector => @panic("TODO: regGeneralClassForType for Vectors"),
1845 else => abi.Registers.Integer.general_purpose,
1846 };
1847}
1848
1849fn regTempClassForType(func: *Func, ty: Type) RegisterManager.RegisterBitSet {
1850 const zcu = func.bin_file.comp.module.?;
1851 return switch (ty.zigTypeTag(zcu)) {
1852 .Float => abi.Registers.Float.temporary,
1853 .Vector => @panic("TODO: regTempClassForType for Vectors"),
1854 else => abi.Registers.Integer.temporary,
1855 };
1856}
1857
1858fn allocRegOrMem(func: *Func, elem_ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue {
1859 const zcu = func.bin_file.comp.module.?;
15851860
1586 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {1861 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {
1587 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(zcu)});1862 return func.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(zcu)});
1588 };1863 };
15891864
1590 if (reg_ok) {1865 const min_size: u32 = switch (elem_ty.zigTypeTag(zcu)) {
1591 // Make sure the type can fit in a register before we try to allocate one.1866 .Float => 4,
1592 const ptr_bits = self.target.ptrBitWidth();1867 .Vector => @panic("allocRegOrMem Vector"),
1593 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1868 else => 8,
1594 if (abi_size <= ptr_bytes) {1869 };
1595 if (self.register_manager.tryAllocReg(inst, gp)) |reg| {1870
1596 return .{ .register = reg };1871 if (reg_ok and abi_size <= min_size) {
1597 }1872 if (func.register_manager.tryAllocReg(inst, func.regGeneralClassForType(elem_ty))) |reg| {
1873 return .{ .register = reg };
1598 }1874 }
1599 }1875 }
16001876
1601 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(elem_ty, zcu));1877 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(elem_ty, zcu));
1602 return .{ .load_frame = .{ .index = frame_index } };1878 return .{ .load_frame = .{ .index = frame_index } };
1603}1879}
16041880
1605/// Allocates a register from the general purpose set and returns the Register and the Lock.1881/// Allocates a register from the general purpose set and returns the Register and the Lock.
1606///1882///
1607/// Up to the user to unlock the register later.1883/// Up to the caller to unlock the register later.
1608fn allocReg(self: *Self) !struct { Register, RegisterLock } {1884fn allocReg(func: *Func, reg_class: abi.RegisterClass) !struct { Register, RegisterLock } {
1609 const reg = try self.register_manager.allocReg(null, gp);1885 if (reg_class == .float and !func.hasFeature(.f))
1610 const lock = self.register_manager.lockRegAssumeUnused(reg);1886 std.debug.panic("allocReg class == float where F isn't enabled", .{});
1887
1888 const class = switch (reg_class) {
1889 .int => abi.Registers.Integer.general_purpose,
1890 .float => abi.Registers.Float.general_purpose,
1891 };
1892
1893 const reg = try func.register_manager.allocReg(null, class);
1894 const lock = func.register_manager.lockRegAssumeUnused(reg);
1611 return .{ reg, lock };1895 return .{ reg, lock };
1612}1896}
16131897
1614fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Register {1898/// Similar to `allocReg` but will copy the MCValue into the Register unless `operand` is already
1899/// a register, in which case it will return a possible lock to that register.
1900fn promoteReg(func: *Func, ty: Type, operand: MCValue) !struct { Register, ?RegisterLock } {
1901 if (operand == .register) {
1902 const op_reg = operand.register;
1903 return .{ op_reg, func.register_manager.lockReg(operand.register) };
1904 }
1905
1906 const reg, const lock = try func.allocReg(func.typeRegClass(ty));
1907 try func.genSetReg(ty, reg, operand);
1908 return .{ reg, lock };
1909}
1910
1911fn elemOffset(func: *Func, index_ty: Type, index: MCValue, elem_size: u64) !Register {
1615 const reg: Register = blk: {1912 const reg: Register = blk: {
1616 switch (index) {1913 switch (index) {
1617 .immediate => |imm| {1914 .immediate => |imm| {
1618 // Optimisation: if index MCValue is an immediate, we can multiply in `comptime`1915 // Optimisation: if index MCValue is an immediate, we can multiply in `comptime`
1619 // and set the register directly to the scaled offset as an immediate.1916 // and set the register directly to the scaled offset as an immediate.
1620 const reg = try self.register_manager.allocReg(null, gp);1917 const reg = try func.register_manager.allocReg(null, func.regGeneralClassForType(index_ty));
1621 try self.genSetReg(index_ty, reg, .{ .immediate = imm * elem_size });1918 try func.genSetReg(index_ty, reg, .{ .immediate = imm * elem_size });
1622 break :blk reg;1919 break :blk reg;
1623 },1920 },
1624 else => {1921 else => {
1625 const reg = try self.copyToTmpRegister(index_ty, index);1922 const reg = try func.copyToTmpRegister(index_ty, index);
1626 const lock = self.register_manager.lockRegAssumeUnused(reg);1923 const lock = func.register_manager.lockRegAssumeUnused(reg);
1627 defer self.register_manager.unlockReg(lock);1924 defer func.register_manager.unlockReg(lock);
1925
1926 const result_reg, const result_lock = try func.allocReg(.int);
1927 defer func.register_manager.unlockReg(result_lock);
16281928
1629 const result = try self.binOp(1929 try func.genBinOp(
1630 .mul,1930 .mul,
1631 .{ .register = reg },1931 .{ .register = reg },
1632 index_ty,1932 index_ty,
1633 .{ .immediate = elem_size },1933 .{ .immediate = elem_size },
1634 index_ty,1934 index_ty,
1935 result_reg,
1635 );1936 );
1636 break :blk result.register;1937
1938 break :blk result_reg;
1637 },1939 },
1638 }1940 }
1639 };1941 };
1640 return reg;1942 return reg;
1641}1943}
16421944
1643pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {1945pub fn spillInstruction(func: *Func, reg: Register, inst: Air.Inst.Index) !void {
1644 const tracking = self.inst_tracking.getPtr(inst) orelse return;1946 const tracking = func.inst_tracking.getPtr(inst) orelse return;
1645 for (tracking.getRegs()) |tracked_reg| {1947 for (tracking.getRegs()) |tracked_reg| {
1646 if (tracked_reg.id() == reg.id()) break;1948 if (tracked_reg.id() == reg.id()) break;
1647 } else unreachable; // spilled reg not tracked with spilled instruciton1949 } else unreachable; // spilled reg not tracked with spilled instruciton
1648 try tracking.spill(self, inst);1950 try tracking.spill(func, inst);
1649 try tracking.trackSpill(self, inst);1951 try tracking.trackSpill(func, inst);
1650}1952}
16511953
1652/// Copies a value to a register without tracking the register. The register is not considered1954/// Copies a value to a register without tracking the register. The register is not considered
1653/// allocated. A second call to `copyToTmpRegister` may return the same register.1955/// allocated. A second call to `copyToTmpRegister` may return the same register.
1654/// This can have a side effect of spilling instructions to the stack to free up a register.1956/// This can have a side effect of spilling instructions to the stack to free up a register.
1655fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {1957fn copyToTmpRegister(func: *Func, ty: Type, mcv: MCValue) !Register {
1656 const reg = try self.register_manager.allocReg(null, tp);1958 log.debug("copyToTmpRegister ty: {}", .{ty.fmt(func.bin_file.comp.module.?)});
1657 try self.genSetReg(ty, reg, mcv);1959 const reg = try func.register_manager.allocReg(null, func.regTempClassForType(ty));
1960 try func.genSetReg(ty, reg, mcv);
1658 return reg;1961 return reg;
1659}1962}
16601963
1661/// Allocates a new register and copies `mcv` into it.1964/// Allocates a new register and copies `mcv` into it.
1662/// `reg_owner` is the instruction that gets associated with the register in the register table.1965/// `reg_owner` is the instruction that gets associated with the register in the register table.
1663/// This can have a side effect of spilling instructions to the stack to free up a register.1966/// This can have a side effect of spilling instructions to the stack to free up a register.
1664fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {1967fn copyToNewRegister(func: *Func, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
1665 const reg = try self.register_manager.allocReg(reg_owner, gp);1968 const ty = func.typeOfIndex(reg_owner);
1666 try self.genSetReg(self.typeOfIndex(reg_owner), reg, mcv);1969 const reg = try func.register_manager.allocReg(reg_owner, func.regGeneralClassForType(ty));
1970 try func.genSetReg(func.typeOfIndex(reg_owner), reg, mcv);
1667 return MCValue{ .register = reg };1971 return MCValue{ .register = reg };
1668}1972}
16691973
1670fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {1974fn airAlloc(func: *Func, inst: Air.Inst.Index) !void {
1671 const result = MCValue{ .lea_frame = .{ .index = try self.allocMemPtr(inst) } };1975 const result = MCValue{ .lea_frame = .{ .index = try func.allocMemPtr(inst) } };
1672 return self.finishAir(inst, result, .{ .none, .none, .none });1976 return func.finishAir(inst, result, .{ .none, .none, .none });
1673}1977}
16741978
1675fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {1979fn airRetPtr(func: *Func, inst: Air.Inst.Index) !void {
1676 const result: MCValue = switch (self.ret_mcv.long) {1980 const result: MCValue = switch (func.ret_mcv.long) {
1677 .none => .{ .lea_frame = .{ .index = try self.allocMemPtr(inst) } },1981 .none => .{ .lea_frame = .{ .index = try func.allocMemPtr(inst) } },
1678 .load_frame => .{ .register_offset = .{1982 .load_frame => .{ .register_offset = .{
1679 .reg = (try self.copyToNewRegister(1983 .reg = (try func.copyToNewRegister(
1680 inst,1984 inst,
1681 self.ret_mcv.long,1985 func.ret_mcv.long,
1682 )).register,1986 )).register,
1683 .off = self.ret_mcv.short.indirect.off,1987 .off = func.ret_mcv.short.indirect.off,
1684 } },1988 } },
1685 else => |t| return self.fail("TODO: airRetPtr {s}", .{@tagName(t)}),1989 else => |t| return func.fail("TODO: airRetPtr {s}", .{@tagName(t)}),
1686 };1990 };
1687 return self.finishAir(inst, result, .{ .none, .none, .none });1991 return func.finishAir(inst, result, .{ .none, .none, .none });
1688}1992}
16891993
1690fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {1994fn airFptrunc(func: *Func, inst: Air.Inst.Index) !void {
1691 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;1995 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1692 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airFptrunc for {}", .{self.target.cpu.arch});1996 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airFptrunc for {}", .{func.target.cpu.arch});
1693 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1997 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1694}1998}
16951999
1696fn airFpext(self: *Self, inst: Air.Inst.Index) !void {2000fn airFpext(func: *Func, inst: Air.Inst.Index) !void {
1697 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2001 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1698 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airFpext for {}", .{self.target.cpu.arch});2002 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airFpext for {}", .{func.target.cpu.arch});
1699 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2003 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1700}2004}
17012005
1702fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {2006fn airIntCast(func: *Func, inst: Air.Inst.Index) !void {
1703 const zcu = self.bin_file.comp.module.?;2007 const zcu = func.bin_file.comp.module.?;
1704 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2008 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1705 const src_ty = self.typeOf(ty_op.operand);2009 const src_ty = func.typeOf(ty_op.operand);
1706 const dst_ty = self.typeOfIndex(inst);2010 const dst_ty = func.typeOfIndex(inst);
17072011
1708 const result: MCValue = result: {2012 const result: MCValue = result: {
1709 const src_int_info = src_ty.intInfo(zcu);2013 const src_int_info = src_ty.intInfo(zcu);
...@@ -1711,20 +2015,20 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -1711,20 +2015,20 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
17112015
1712 const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty;2016 const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty;
17132017
1714 const src_mcv = try self.resolveInst(ty_op.operand);2018 const src_mcv = try func.resolveInst(ty_op.operand);
17152019
1716 const src_storage_bits: u16 = switch (src_mcv) {2020 const src_storage_bits: u16 = switch (src_mcv) {
1717 .register => 64,2021 .register => 64,
1718 .load_frame => src_int_info.bits,2022 .load_frame => src_int_info.bits,
1719 else => return self.fail("airIntCast from {s}", .{@tagName(src_mcv)}),2023 else => return func.fail("airIntCast from {s}", .{@tagName(src_mcv)}),
1720 };2024 };
17212025
1722 const dst_mcv = if (dst_int_info.bits <= src_storage_bits and2026 const dst_mcv = if (dst_int_info.bits <= src_storage_bits and
1723 math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==2027 math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
1724 math.divCeil(u32, src_storage_bits, 64) catch unreachable and2028 math.divCeil(u32, src_storage_bits, 64) catch unreachable and
1725 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {2029 func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
1726 const dst_mcv = try self.allocRegOrMem(inst, true);2030 const dst_mcv = try func.allocRegOrMem(dst_ty, inst, true);
1727 try self.genCopy(min_ty, dst_mcv, src_mcv);2031 try func.genCopy(min_ty, dst_mcv, src_mcv);
1728 break :dst dst_mcv;2032 break :dst dst_mcv;
1729 };2033 };
17302034
...@@ -1735,53 +2039,53 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -1735,53 +2039,53 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
1735 break :result null; // TODO2039 break :result null; // TODO
17362040
1737 break :result dst_mcv;2041 break :result dst_mcv;
1738 } orelse return self.fail("TODO implement airIntCast from {} to {}", .{2042 } orelse return func.fail("TODO: implement airIntCast from {} to {}", .{
1739 src_ty.fmt(zcu), dst_ty.fmt(zcu),2043 src_ty.fmt(zcu), dst_ty.fmt(zcu),
1740 });2044 });
17412045
1742 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2046 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1743}2047}
17442048
1745fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {2049fn airTrunc(func: *Func, inst: Air.Inst.Index) !void {
1746 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2050 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1747 if (self.liveness.isUnused(inst))2051 if (func.liveness.isUnused(inst))
1748 return self.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });2052 return func.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });
17492053
1750 const operand = try self.resolveInst(ty_op.operand);2054 const operand = try func.resolveInst(ty_op.operand);
1751 _ = operand;2055 _ = operand;
1752 return self.fail("TODO implement trunc for {}", .{self.target.cpu.arch});2056 return func.fail("TODO implement trunc for {}", .{func.target.cpu.arch});
1753 // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2057 // return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1754}2058}
17552059
1756fn airIntFromBool(self: *Self, inst: Air.Inst.Index) !void {2060fn airIntFromBool(func: *Func, inst: Air.Inst.Index) !void {
1757 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;2061 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
1758 const operand = try self.resolveInst(un_op);2062 const operand = try func.resolveInst(un_op);
1759 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else operand;2063 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else operand;
1760 return self.finishAir(inst, result, .{ un_op, .none, .none });2064 return func.finishAir(inst, result, .{ un_op, .none, .none });
1761}2065}
17622066
1763fn airNot(self: *Self, inst: Air.Inst.Index) !void {2067fn airNot(func: *Func, inst: Air.Inst.Index) !void {
1764 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2068 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1765 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2069 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
1766 const zcu = self.bin_file.comp.module.?;2070 const zcu = func.bin_file.comp.module.?;
17672071
1768 const operand = try self.resolveInst(ty_op.operand);2072 const operand = try func.resolveInst(ty_op.operand);
1769 const ty = self.typeOf(ty_op.operand);2073 const ty = func.typeOf(ty_op.operand);
17702074
1771 switch (ty.zigTypeTag(zcu)) {2075 switch (ty.zigTypeTag(zcu)) {
1772 .Bool => {2076 .Bool => {
1773 const operand_reg = blk: {2077 const operand_reg = blk: {
1774 if (operand == .register) break :blk operand.register;2078 if (operand == .register) break :blk operand.register;
1775 break :blk try self.copyToTmpRegister(ty, operand);2079 break :blk try func.copyToTmpRegister(ty, operand);
1776 };2080 };
17772081
1778 const dst_reg: Register =2082 const dst_reg: Register =
1779 if (self.reuseOperand(inst, ty_op.operand, 0, operand) and operand == .register)2083 if (func.reuseOperand(inst, ty_op.operand, 0, operand) and operand == .register)
1780 operand.register2084 operand.register
1781 else2085 else
1782 try self.register_manager.allocReg(inst, gp);2086 (try func.allocRegOrMem(func.typeOfIndex(inst), inst, true)).register;
17832087
1784 _ = try self.addInst(.{2088 _ = try func.addInst(.{
1785 .tag = .pseudo,2089 .tag = .pseudo,
1786 .ops = .pseudo_not,2090 .ops = .pseudo_not,
1787 .data = .{2091 .data = .{
...@@ -1794,718 +2098,906 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1794,718 +2098,906 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
17942098
1795 break :result .{ .register = dst_reg };2099 break :result .{ .register = dst_reg };
1796 },2100 },
1797 .Int => return self.fail("TODO: airNot ints", .{}),2101 .Int => return func.fail("TODO: airNot ints", .{}),
1798 else => unreachable,2102 else => unreachable,
1799 }2103 }
1800 };2104 };
1801 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2105 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1802}2106}
18032107
1804fn airMinMax(2108fn airSlice(func: *Func, inst: Air.Inst.Index) !void {
1805 self: *Self,2109 const zcu = func.bin_file.comp.module.?;
1806 inst: Air.Inst.Index,2110 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
1807 comptime tag: enum {2111 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;
1808 max,
1809 min,
1810 },
1811) !void {
1812 const zcu = self.bin_file.comp.module.?;
1813 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
1814
1815 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {
1816 const lhs = try self.resolveInst(bin_op.lhs);
1817 const rhs = try self.resolveInst(bin_op.rhs);
1818 const lhs_ty = self.typeOf(bin_op.lhs);
1819 const rhs_ty = self.typeOf(bin_op.rhs);
1820
1821 const int_info = lhs_ty.intInfo(zcu);
18222112
1823 if (int_info.bits > 64) return self.fail("TODO: > 64 bit @min", .{});2113 const slice_ty = func.typeOfIndex(inst);
2114 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(slice_ty, zcu));
18242115
1825 const lhs_reg, const lhs_lock = blk: {2116 const ptr_ty = func.typeOf(bin_op.lhs);
1826 if (lhs == .register) break :blk .{ lhs.register, null };2117 try func.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, .{ .air_ref = bin_op.lhs });
18272118
1828 const lhs_reg, const lhs_lock = try self.allocReg();2119 const len_ty = func.typeOf(bin_op.rhs);
1829 try self.genSetReg(lhs_ty, lhs_reg, lhs);2120 try func.genSetMem(
1830 break :blk .{ lhs_reg, lhs_lock };2121 .{ .frame = frame_index },
1831 };2122 @intCast(ptr_ty.abiSize(zcu)),
1832 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);2123 len_ty,
2124 .{ .air_ref = bin_op.rhs },
2125 );
18332126
1834 const rhs_reg, const rhs_lock = blk: {2127 const result = MCValue{ .load_frame = .{ .index = frame_index } };
1835 if (rhs == .register) break :blk .{ rhs.register, null };2128 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2129}
18362130
1837 const rhs_reg, const rhs_lock = try self.allocReg();2131fn airBinOp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1838 try self.genSetReg(rhs_ty, rhs_reg, rhs);2132 const zcu = func.bin_file.comp.module.?;
1839 break :blk .{ rhs_reg, rhs_lock };2133 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
1840 };2134 const dst_mcv = try func.binOp(inst, tag, bin_op.lhs, bin_op.rhs);
1841 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
18422135
1843 const mask_reg, const mask_lock = try self.allocReg();2136 const dst_ty = func.typeOfIndex(inst);
1844 defer self.register_manager.unlockReg(mask_lock);2137 if (dst_ty.isAbiInt(zcu)) {
2138 const abi_size: u32 = @intCast(dst_ty.abiSize(zcu));
2139 const bit_size: u32 = @intCast(dst_ty.bitSize(zcu));
2140 if (abi_size * 8 > bit_size) {
2141 const dst_lock = switch (dst_mcv) {
2142 .register => |dst_reg| func.register_manager.lockRegAssumeUnused(dst_reg),
2143 else => null,
2144 };
2145 defer if (dst_lock) |lock| func.register_manager.unlockReg(lock);
18452146
1846 const result_reg, const result_lock = try self.allocReg();2147 if (dst_mcv.isRegister()) {
1847 defer self.register_manager.unlockReg(result_lock);2148 try func.truncateRegister(dst_ty, dst_mcv.getReg().?);
2149 } else {
2150 const tmp_reg, const tmp_lock = try func.allocReg(.int);
2151 defer func.register_manager.unlockReg(tmp_lock);
2152
2153 const hi_ty = try zcu.intType(.unsigned, @intCast((dst_ty.bitSize(zcu) - 1) % 64 + 1));
2154 const hi_mcv = dst_mcv.address().offset(@intCast(bit_size / 64 * 8)).deref();
2155 try func.genSetReg(hi_ty, tmp_reg, hi_mcv);
2156 try func.truncateRegister(dst_ty, tmp_reg);
2157 try func.genCopy(hi_ty, hi_mcv, .{ .register = tmp_reg });
2158 }
2159 }
2160 }
18482161
1849 _ = try self.addInst(.{2162 return func.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
1850 .tag = if (int_info.signedness == .unsigned) .sltu else .slt,2163}
1851 .ops = .rrr,
1852 .data = .{ .r_type = .{
1853 .rd = mask_reg,
1854 .rs1 = lhs_reg,
1855 .rs2 = rhs_reg,
1856 } },
1857 });
18582164
1859 _ = try self.addInst(.{2165fn binOp(
1860 .tag = .sub,2166 func: *Func,
1861 .ops = .rrr,2167 maybe_inst: ?Air.Inst.Index,
1862 .data = .{ .r_type = .{2168 air_tag: Air.Inst.Tag,
1863 .rd = mask_reg,2169 lhs_air: Air.Inst.Ref,
1864 .rs1 = .zero,2170 rhs_air: Air.Inst.Ref,
1865 .rs2 = mask_reg,2171) !MCValue {
1866 } },2172 _ = maybe_inst;
1867 });2173 const zcu = func.bin_file.comp.module.?;
2174 const lhs_ty = func.typeOf(lhs_air);
2175 const rhs_ty = func.typeOf(rhs_air);
2176
2177 if (lhs_ty.isRuntimeFloat()) libcall: {
2178 const float_bits = lhs_ty.floatBits(func.target.*);
2179 const type_needs_libcall = switch (float_bits) {
2180 16 => true,
2181 32, 64 => false,
2182 80, 128 => true,
2183 else => unreachable,
2184 };
2185 switch (air_tag) {
2186 .rem, .mod => {},
2187 else => if (!type_needs_libcall) break :libcall,
2188 }
2189 return func.fail("binOp libcall runtime-float ops", .{});
2190 }
18682191
1869 _ = try self.addInst(.{2192 if (lhs_ty.bitSize(zcu) > 64) return func.fail("TODO: binOp >= 64 bits", .{});
1870 .tag = .xor,
1871 .ops = .rrr,
1872 .data = .{ .r_type = .{
1873 .rd = result_reg,
1874 .rs1 = lhs_reg,
1875 .rs2 = rhs_reg,
1876 } },
1877 });
18782193
1879 _ = try self.addInst(.{2194 const lhs_mcv = try func.resolveInst(lhs_air);
1880 .tag = .@"and",2195 const rhs_mcv = try func.resolveInst(rhs_air);
1881 .ops = .rrr,
1882 .data = .{ .r_type = .{
1883 .rd = mask_reg,
1884 .rs1 = result_reg,
1885 .rs2 = mask_reg,
1886 } },
1887 });
18882196
1889 _ = try self.addInst(.{2197 const class_for_dst_ty: abi.RegisterClass = switch (air_tag) {
1890 .tag = .xor,2198 // will always return int register no matter the input
1891 .ops = .rrr,2199 .cmp_eq,
1892 .data = .{ .r_type = .{2200 .cmp_neq,
1893 .rd = result_reg,2201 .cmp_lt,
1894 .rs1 = if (tag == .min) rhs_reg else lhs_reg,2202 .cmp_lte,
1895 .rs2 = mask_reg,2203 .cmp_gt,
1896 } },2204 .cmp_gte,
1897 });2205 => .int,
18982206
1899 break :result .{ .register = result_reg };2207 else => func.typeRegClass(lhs_ty),
1900 };2208 };
1901 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1902}
19032209
1904fn airSlice(self: *Self, inst: Air.Inst.Index) !void {2210 const dst_reg, const dst_lock = try func.allocReg(class_for_dst_ty);
1905 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2211 defer func.register_manager.unlockReg(dst_lock);
1906 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1907 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement slice for {}", .{self.target.cpu.arch});
1908 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1909}
19102212
1911fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {2213 try func.genBinOp(
1912 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2214 air_tag,
1913 const lhs = try self.resolveInst(bin_op.lhs);2215 lhs_mcv,
1914 const rhs = try self.resolveInst(bin_op.rhs);2216 lhs_ty,
1915 const lhs_ty = self.typeOf(bin_op.lhs);2217 rhs_mcv,
1916 const rhs_ty = self.typeOf(bin_op.rhs);2218 rhs_ty,
2219 dst_reg,
2220 );
19172221
1918 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2222 return .{ .register = dst_reg };
1919 break :result try self.binOp(tag, lhs, lhs_ty, rhs, rhs_ty);
1920 };
1921 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1922}2223}
19232224
1924/// For all your binary operation needs, this function will generate2225/// Does the same thing as binOp however is meant to be used internally to the backend.
1925/// the corresponding Mir instruction(s). Returns the location of the
1926/// result.
1927///
1928/// If the binary operation itself happens to be an Air instruction,
1929/// pass the corresponding index in the inst parameter. That helps
1930/// this function do stuff like reusing operands.
1931///2226///
1932/// This function does not do any lowering to Mir itself, but instead2227/// The `dst_reg` argument is meant to be caller-locked. Asserts that the binOp result can be
1933/// looks at the lhs and rhs and determines which kind of lowering2228/// fit into the register.
1934/// would be best suitable and then delegates the lowering to other
1935/// functions.
1936///2229///
1937/// `maybe_inst` **needs** to be a bin_op, make sure of that.2230/// Assumes that the `dst_reg` class is correct.
1938fn binOp(2231fn genBinOp(
1939 self: *Self,2232 func: *Func,
1940 tag: Air.Inst.Tag,2233 tag: Air.Inst.Tag,
1941 lhs: MCValue,2234 lhs_mcv: MCValue,
1942 lhs_ty: Type,2235 lhs_ty: Type,
1943 rhs: MCValue,2236 rhs_mcv: MCValue,
1944 rhs_ty: Type,2237 rhs_ty: Type,
1945) InnerError!MCValue {2238 dst_reg: Register,
1946 const zcu = self.bin_file.comp.module.?;2239) !void {
2240 const zcu = func.bin_file.comp.module.?;
2241 const bit_size = lhs_ty.bitSize(zcu);
2242 assert(bit_size <= 64);
2243
2244 const is_unsigned = lhs_ty.isUnsignedInt(zcu);
2245
2246 const lhs_reg, const maybe_lhs_lock = try func.promoteReg(lhs_ty, lhs_mcv);
2247 const rhs_reg, const maybe_rhs_lock = try func.promoteReg(rhs_ty, rhs_mcv);
2248
2249 defer if (maybe_lhs_lock) |lock| func.register_manager.unlockReg(lock);
2250 defer if (maybe_rhs_lock) |lock| func.register_manager.unlockReg(lock);
19472251
1948 switch (tag) {2252 switch (tag) {
1949 // Arithmetic operations on integers and floats
1950 .add,2253 .add,
2254 .add_wrap,
1951 .sub,2255 .sub,
2256 .sub_wrap,
1952 .mul,2257 .mul,
1953 .cmp_eq,2258 .mul_wrap,
1954 .cmp_neq,
1955 .cmp_gt,
1956 .cmp_gte,
1957 .cmp_lt,
1958 .cmp_lte,
1959 => {2259 => {
2260 if (!math.isPowerOfTwo(bit_size))
2261 return func.fail(
2262 "TODO: genBinOp {s} non-pow 2, found {}",
2263 .{ @tagName(tag), bit_size },
2264 );
2265
1960 switch (lhs_ty.zigTypeTag(zcu)) {2266 switch (lhs_ty.zigTypeTag(zcu)) {
1961 .Float => return self.fail("TODO binary operations on floats", .{}),
1962 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1963 .Int => {2267 .Int => {
1964 assert(lhs_ty.eql(rhs_ty, zcu));2268 const mir_tag: Mir.Inst.Tag = switch (tag) {
1965 const int_info = lhs_ty.intInfo(zcu);2269 .add, .add_wrap => switch (bit_size) {
1966 if (int_info.bits <= 64) {2270 8, 16, 64 => .add,
1967 return self.binOpRegister(tag, lhs, lhs_ty, rhs, rhs_ty);2271 32 => .addw,
1968 } else {2272 else => unreachable,
1969 return self.fail("TODO binary operations on int with bits > 64", .{});2273 },
2274 .sub, .sub_wrap => switch (bit_size) {
2275 8, 16, 32 => .subw,
2276 64 => .sub,
2277 else => unreachable,
2278 },
2279 .mul, .mul_wrap => switch (bit_size) {
2280 8, 16, 64 => .mul,
2281 32 => .mulw,
2282 else => unreachable,
2283 },
2284 else => unreachable,
2285 };
2286
2287 _ = try func.addInst(.{
2288 .tag = mir_tag,
2289 .ops = .rrr,
2290 .data = .{
2291 .r_type = .{
2292 .rd = dst_reg,
2293 .rs1 = lhs_reg,
2294 .rs2 = rhs_reg,
2295 },
2296 },
2297 });
2298
2299 // truncate when the instruction is larger than the bit size.
2300 switch (bit_size) {
2301 8, 16 => try func.truncateRegister(lhs_ty, dst_reg),
2302 32 => {}, // addw/subw affects the first 32-bits
2303 64 => {}, // add/sub affects the entire register
2304 else => unreachable,
1970 }2305 }
1971 },2306 },
1972 else => |x| return self.fail("TOOD: binOp {s}", .{@tagName(x)}),2307 .Float => {
2308 const mir_tag: Mir.Inst.Tag = switch (tag) {
2309 .add => switch (bit_size) {
2310 32 => .fadds,
2311 64 => .faddd,
2312 else => unreachable,
2313 },
2314 .sub => switch (bit_size) {
2315 32 => .fsubs,
2316 64 => .fsubd,
2317 else => unreachable,
2318 },
2319 .mul => switch (bit_size) {
2320 32 => .fmuls,
2321 64 => .fmuld,
2322 else => unreachable,
2323 },
2324 else => unreachable,
2325 };
2326
2327 _ = try func.addInst(.{
2328 .tag = mir_tag,
2329 .ops = .rrr,
2330 .data = .{
2331 .r_type = .{
2332 .rd = dst_reg,
2333 .rs1 = lhs_reg,
2334 .rs2 = rhs_reg,
2335 },
2336 },
2337 });
2338 },
2339 else => unreachable,
1973 }2340 }
1974 },2341 },
19752342
1976 .ptr_add,2343 .ptr_add,
1977 .ptr_sub,2344 .ptr_sub,
1978 => {2345 => {
1979 switch (lhs_ty.zigTypeTag(zcu)) {2346 const tmp_reg = try func.copyToTmpRegister(rhs_ty, .{ .register = rhs_reg });
1980 .Pointer => {2347 const tmp_mcv = MCValue{ .register = tmp_reg };
1981 const ptr_ty = lhs_ty;2348 const tmp_lock = func.register_manager.lockRegAssumeUnused(tmp_reg);
1982 const elem_ty = switch (ptr_ty.ptrSize(zcu)) {2349 defer func.register_manager.unlockReg(tmp_lock);
1983 .One => ptr_ty.childType(zcu).childType(zcu), // ptr to array, so get array element type2350
1984 else => ptr_ty.childType(zcu),2351 // RISC-V has no immediate mul, so we copy the size to a temporary register
1985 };2352 const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu);
1986 const elem_size = elem_ty.abiSize(zcu);2353 const elem_size_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = elem_size });
19872354
1988 if (elem_size == 1) {2355 try func.genBinOp(
1989 const base_tag: Air.Inst.Tag = switch (tag) {2356 .mul,
1990 .ptr_add => .add,2357 tmp_mcv,
1991 .ptr_sub => .sub,2358 rhs_ty,
1992 else => unreachable,2359 .{ .register = elem_size_reg },
1993 };2360 Type.usize,
2361 tmp_reg,
2362 );
19942363
1995 return try self.binOpRegister(base_tag, lhs, lhs_ty, rhs, rhs_ty);2364 try func.genBinOp(
1996 } else {2365 switch (tag) {
1997 const offset = try self.binOp(2366 .ptr_add => .add,
1998 .mul,2367 .ptr_sub => .sub,
1999 rhs,2368 else => unreachable,
2000 Type.usize,2369 },
2001 .{ .immediate = elem_size },2370 lhs_mcv,
2002 Type.usize,2371 Type.usize, // we know it's a pointer, so it'll be usize.
2003 );2372 tmp_mcv,
2373 Type.usize,
2374 dst_reg,
2375 );
2376 },
20042377
2005 const addr = try self.binOp(2378 .bit_and,
2006 tag,2379 .bit_or,
2007 lhs,2380 .bool_and,
2008 Type.manyptr_u8,2381 .bool_or,
2009 offset,2382 => {
2010 Type.usize,2383 _ = try func.addInst(.{
2011 );2384 .tag = switch (tag) {
2012 return addr;2385 .bit_and, .bool_and => .@"and",
2013 }2386 .bit_or, .bool_or => .@"or",
2387 else => unreachable,
2014 },2388 },
2015 else => unreachable,2389 .ops = .rrr,
2390 .data = .{
2391 .r_type = .{
2392 .rd = dst_reg,
2393 .rs1 = lhs_reg,
2394 .rs2 = rhs_reg,
2395 },
2396 },
2397 });
2398
2399 switch (tag) {
2400 .bool_and,
2401 .bool_or,
2402 => try func.truncateRegister(Type.bool, dst_reg),
2403 else => {},
2016 }2404 }
2017 },2405 },
20182406
2019 // These instructions have unsymteric bit sizes on RHS and LHS.2407 .div_trunc,
2020 .shr,
2021 .shl,
2022 => {2408 => {
2023 switch (lhs_ty.zigTypeTag(zcu)) {2409 if (!math.isPowerOfTwo(bit_size))
2024 .Float => return self.fail("TODO binary operations on floats", .{}),2410 return func.fail(
2025 .Vector => return self.fail("TODO binary operations on vectors", .{}),2411 "TODO: genBinOp {s} non-pow 2, found {}",
2026 .Int => {2412 .{ @tagName(tag), bit_size },
2027 const int_info = lhs_ty.intInfo(zcu);2413 );
2028 if (int_info.bits <= 64) {2414
2029 return self.binOpRegister(tag, lhs, lhs_ty, rhs, rhs_ty);2415 const mir_tag: Mir.Inst.Tag = switch (tag) {
2030 } else {2416 .div_trunc => switch (bit_size) {
2031 return self.fail("TODO binary operations on int with bits > 64", .{});2417 8, 16, 32 => if (is_unsigned) .divuw else .divw,
2032 }2418 64 => if (is_unsigned) .divu else .div,
2419 else => unreachable,
2033 },2420 },
2034 else => unreachable,2421 else => unreachable,
2035 }2422 };
2036 },
2037 else => return self.fail("TODO binOp {}", .{tag}),
2038 }
2039}
2040/// Don't call this function directly. Use binOp instead.
2041///
2042/// Calling this function signals an intention to generate a Mir
2043/// instruction of the form
2044///
2045/// op dest, lhs, rhs
2046///
2047/// Asserts that generating an instruction of that form is possible.
2048fn binOpRegister(
2049 self: *Self,
2050 tag: Air.Inst.Tag,
2051 lhs: MCValue,
2052 lhs_ty: Type,
2053 rhs: MCValue,
2054 rhs_ty: Type,
2055) !MCValue {
2056 const lhs_reg, const lhs_lock = blk: {
2057 if (lhs == .register) break :blk .{ lhs.register, null };
2058
2059 const lhs_reg, const lhs_lock = try self.allocReg();
2060 try self.genSetReg(lhs_ty, lhs_reg, lhs);
2061 break :blk .{ lhs_reg, lhs_lock };
2062 };
2063 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
2064
2065 const rhs_reg, const rhs_lock = blk: {
2066 if (rhs == .register) break :blk .{ rhs.register, null };
2067
2068 const rhs_reg, const rhs_lock = try self.allocReg();
2069 try self.genSetReg(rhs_ty, rhs_reg, rhs);
2070 break :blk .{ rhs_reg, rhs_lock };
2071 };
2072 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
2073
2074 const dest_reg, const dest_lock = try self.allocReg();
2075 defer self.register_manager.unlockReg(dest_lock);
2076
2077 const mir_tag: Mir.Inst.Tag = switch (tag) {
2078 .add => .add,
2079 .sub => .sub,
2080 .mul => .mul,
2081
2082 .shl => .sllw,
2083 .shr => .srlw,
2084
2085 .cmp_eq,
2086 .cmp_neq,
2087 .cmp_gt,
2088 .cmp_gte,
2089 .cmp_lt,
2090 .cmp_lte,
2091 => .pseudo,
2092
2093 else => return self.fail("TODO: binOpRegister {s}", .{@tagName(tag)}),
2094 };
20952423
2096 switch (mir_tag) {2424 _ = try func.addInst(.{
2097 .add,
2098 .sub,
2099 .mul,
2100 .sllw,
2101 .srlw,
2102 => {
2103 _ = try self.addInst(.{
2104 .tag = mir_tag,2425 .tag = mir_tag,
2105 .ops = .rrr,2426 .ops = .rrr,
2106 .data = .{2427 .data = .{
2107 .r_type = .{2428 .r_type = .{
2108 .rd = dest_reg,2429 .rd = dst_reg,
2109 .rs1 = lhs_reg,2430 .rs1 = lhs_reg,
2110 .rs2 = rhs_reg,2431 .rs2 = rhs_reg,
2111 },2432 },
2112 },2433 },
2113 });2434 });
2435
2436 if (!is_unsigned) {
2437 // truncate when the instruction is larger than the bit size.
2438 switch (bit_size) {
2439 8, 16 => try func.truncateRegister(lhs_ty, dst_reg),
2440 32 => {}, // divw affects the first 32-bits
2441 64 => {}, // div affects the entire register
2442 else => unreachable,
2443 }
2444 }
2114 },2445 },
21152446
2116 .pseudo => {2447 .shr,
2117 const pseudo_op = switch (tag) {2448 .shr_exact,
2118 .cmp_eq,2449 .shl,
2119 .cmp_neq,2450 .shl_exact,
2120 .cmp_gt,2451 => {
2121 .cmp_gte,2452 if (!math.isPowerOfTwo(bit_size))
2122 .cmp_lt,2453 return func.fail(
2123 .cmp_lte,2454 "TODO: genBinOp {s} non-pow 2, found {}",
2124 => .pseudo_compare,2455 .{ @tagName(tag), bit_size },
2456 );
2457
2458 // it's important that the shift amount is exact
2459 try func.truncateRegister(rhs_ty, rhs_reg);
2460
2461 const mir_tag: Mir.Inst.Tag = switch (tag) {
2462 .shl, .shl_exact => switch (bit_size) {
2463 8, 16, 64 => .sll,
2464 32 => .sllw,
2465 else => unreachable,
2466 },
2467 .shr, .shr_exact => switch (bit_size) {
2468 8, 16, 64 => .srl,
2469 32 => .srlw,
2470 else => unreachable,
2471 },
2125 else => unreachable,2472 else => unreachable,
2126 };2473 };
21272474
2128 _ = try self.addInst(.{2475 _ = try func.addInst(.{
2476 .tag = mir_tag,
2477 .ops = .rrr,
2478 .data = .{ .r_type = .{
2479 .rd = dst_reg,
2480 .rs1 = lhs_reg,
2481 .rs2 = rhs_reg,
2482 } },
2483 });
2484
2485 switch (bit_size) {
2486 8, 16 => try func.truncateRegister(lhs_ty, dst_reg),
2487 32 => {},
2488 64 => {},
2489 else => unreachable,
2490 }
2491 },
2492
2493 // TODO: move the isel logic out of lower and into here.
2494 .cmp_eq,
2495 .cmp_neq,
2496 .cmp_lt,
2497 .cmp_lte,
2498 .cmp_gt,
2499 .cmp_gte,
2500 => {
2501 _ = try func.addInst(.{
2129 .tag = .pseudo,2502 .tag = .pseudo,
2130 .ops = pseudo_op,2503 .ops = .pseudo_compare,
2131 .data = .{2504 .data = .{
2132 .compare = .{2505 .compare = .{
2133 .rd = dest_reg,
2134 .rs1 = lhs_reg,
2135 .rs2 = rhs_reg,
2136 .op = switch (tag) {2506 .op = switch (tag) {
2137 .cmp_eq => .eq,2507 .cmp_eq => .eq,
2138 .cmp_neq => .neq,2508 .cmp_neq => .neq,
2139 .cmp_gt => .gt,
2140 .cmp_gte => .gte,
2141 .cmp_lt => .lt,2509 .cmp_lt => .lt,
2142 .cmp_lte => .lte,2510 .cmp_lte => .lte,
2511 .cmp_gt => .gt,
2512 .cmp_gte => .gte,
2143 else => unreachable,2513 else => unreachable,
2144 },2514 },
2515 .rd = dst_reg,
2516 .rs1 = lhs_reg,
2517 .rs2 = rhs_reg,
2518 .ty = lhs_ty,
2145 },2519 },
2146 },2520 },
2147 });2521 });
2148 },2522 },
21492523
2150 else => unreachable,2524 // A branchless @min/@max sequence.
2151 }2525 //
21522526 // Assume that a0 and a1 are the lhs and rhs respectively.
2153 // generate the struct for OF checks2527 // Also assume that a2 is the destination register.
21542528 //
2155 return MCValue{ .register = dest_reg };2529 // Algorithm:
2156}2530 // slt s0, a0, a1
21572531 // sub s0, zero, s0
2158fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {2532 // xor a2, a0, a1
2159 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2533 // and s0, a2, s0
2160 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2534 // xor a2, a0, s0 # a0 is @min, a1 is @max
2161 const lhs = try self.resolveInst(bin_op.lhs);2535 //
2162 const rhs = try self.resolveInst(bin_op.rhs);2536 // "slt s0, a0, a1" will set s0 to 1 if a0 is less than a1, and 1 otherwise.
2163 const lhs_ty = self.typeOf(bin_op.lhs);2537 //
2164 const rhs_ty = self.typeOf(bin_op.rhs);2538 // "sub s0, zero, s0" will set all the bits of s0 to 1 if it was 1, otherwise it'll remain at 0.
21652539 //
2166 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2540 // "xor a2, a0, a1" stores the bitwise XOR of a0 and a1 in a2. Effectively getting the difference between them.
2167 break :result try self.binOp(tag, lhs, lhs_ty, rhs, rhs_ty);2541 //
2168 };2542 // "and a0, a2, s0" here we mask the result of the XOR with the negated s0. If a0 < a1, s0 is -1, which
2169 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2543 // doesn't change the bits of a2. If a0 >= a1, s0 is 0, nullifying a2.
2170}2544 //
21712545 // "xor a2, a0, s0" the final XOR operation adjusts a2 to be the minimum value of a0 and a1. If a0 was less than
2172fn airAddWrap(self: *Self, inst: Air.Inst.Index) !void {2546 // a1, s0 was -1, flipping all the bits in a2 and effectively restoring a0. If a0 was greater than or equal to a1,
2173 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2547 // s0 was 0, leaving a2 unchanged as a0.
2174 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement addwrap for {}", .{self.target.cpu.arch});2548 .min, .max => {
2175 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2549 const int_info = lhs_ty.intInfo(zcu);
2176}2550
21772551 const mask_reg, const mask_lock = try func.allocReg(.int);
2178fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {2552 defer func.register_manager.unlockReg(mask_lock);
2179 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2553
2180 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement add_sat for {}", .{self.target.cpu.arch});2554 _ = try func.addInst(.{
2181 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2555 .tag = if (int_info.signedness == .unsigned) .sltu else .slt,
2182}2556 .ops = .rrr,
21832557 .data = .{ .r_type = .{
2184fn airSubWrap(self: *Self, inst: Air.Inst.Index) !void {2558 .rd = mask_reg,
2185 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2559 .rs1 = lhs_reg,
2186 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2560 .rs2 = rhs_reg,
2187 // RISCV arthemtic instructions already wrap, so this is simply a sub binOp with2561 } },
2188 // no overflow checks.2562 });
2189 const lhs = try self.resolveInst(bin_op.lhs);
2190 const rhs = try self.resolveInst(bin_op.rhs);
2191 const lhs_ty = self.typeOf(bin_op.lhs);
2192 const rhs_ty = self.typeOf(bin_op.rhs);
21932563
2194 break :result try self.binOp(.sub, lhs, lhs_ty, rhs, rhs_ty);2564 _ = try func.addInst(.{
2195 };2565 .tag = .sub,
2196 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2566 .ops = .rrr,
2197}2567 .data = .{ .r_type = .{
2568 .rd = mask_reg,
2569 .rs1 = .zero,
2570 .rs2 = mask_reg,
2571 } },
2572 });
21982573
2199fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {2574 _ = try func.addInst(.{
2200 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2575 .tag = .xor,
2201 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement sub_sat for {}", .{self.target.cpu.arch});2576 .ops = .rrr,
2202 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2577 .data = .{ .r_type = .{
2203}2578 .rd = dst_reg,
2579 .rs1 = lhs_reg,
2580 .rs2 = rhs_reg,
2581 } },
2582 });
22042583
2205fn airMul(self: *Self, inst: Air.Inst.Index) !void {2584 _ = try func.addInst(.{
2206 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2585 .tag = .@"and",
2207 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement mul for {}", .{self.target.cpu.arch});2586 .ops = .rrr,
2208 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2587 .data = .{ .r_type = .{
2209}2588 .rd = mask_reg,
2589 .rs1 = dst_reg,
2590 .rs2 = mask_reg,
2591 } },
2592 });
22102593
2211fn airMulWrap(self: *Self, inst: Air.Inst.Index) !void {2594 _ = try func.addInst(.{
2212 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2595 .tag = .xor,
2213 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement mulwrap for {}", .{self.target.cpu.arch});2596 .ops = .rrr,
2214 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2597 .data = .{ .r_type = .{
2598 .rd = dst_reg,
2599 .rs1 = if (tag == .min) rhs_reg else lhs_reg,
2600 .rs2 = mask_reg,
2601 } },
2602 });
2603 },
2604 else => return func.fail("TODO: genBinOp {}", .{tag}),
2605 }
2215}2606}
22162607
2217fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {2608fn airPtrArithmetic(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
2218 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2609 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2219 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement mul_sat for {}", .{self.target.cpu.arch});2610 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;
2220 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2611 const dst_mcv = try func.binOp(inst, tag, bin_op.lhs, bin_op.rhs);
2612 return func.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
2221}2613}
22222614
2223fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2615fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2224 const zcu = self.bin_file.comp.module.?;2616 const zcu = func.bin_file.comp.module.?;
2225 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2617 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2226 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2618 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
22272619
2228 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2620 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2229 const lhs = try self.resolveInst(extra.lhs);2621 const lhs_ty = func.typeOf(extra.lhs);
2230 const rhs = try self.resolveInst(extra.rhs);
2231 const lhs_ty = self.typeOf(extra.lhs);
2232 const rhs_ty = self.typeOf(extra.rhs);
22332622
2234 const int_info = lhs_ty.intInfo(zcu);2623 const int_info = lhs_ty.intInfo(zcu);
22352624
2236 const tuple_ty = self.typeOfIndex(inst);2625 const tuple_ty = func.typeOfIndex(inst);
2237 const result_mcv = try self.allocRegOrMem(inst, false);2626 const result_mcv = try func.allocRegOrMem(tuple_ty, inst, false);
2238 const offset = result_mcv.load_frame;2627 const offset = result_mcv.load_frame;
22392628
2240 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {2629 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
2241 const add_result = try self.binOp(.add, lhs, lhs_ty, rhs, rhs_ty);2630 const add_result = try func.binOp(null, .add, extra.lhs, extra.rhs);
2242 const add_result_reg = try self.copyToTmpRegister(lhs_ty, add_result);2631 const add_result_reg = try func.copyToTmpRegister(lhs_ty, add_result);
2243 const add_result_reg_lock = self.register_manager.lockRegAssumeUnused(add_result_reg);2632 const add_result_reg_lock = func.register_manager.lockRegAssumeUnused(add_result_reg);
2244 defer self.register_manager.unlockReg(add_result_reg_lock);2633 defer func.register_manager.unlockReg(add_result_reg_lock);
22452634
2246 const shift_amount: u6 = @intCast(Type.usize.bitSize(zcu) - int_info.bits);2635 const shift_amount: u6 = @intCast(Type.usize.bitSize(zcu) - int_info.bits);
22472636
2248 const shift_reg, const shift_lock = try self.allocReg();2637 const shift_reg, const shift_lock = try func.allocReg(.int);
2249 defer self.register_manager.unlockReg(shift_lock);2638 defer func.register_manager.unlockReg(shift_lock);
22502639
2251 _ = try self.addInst(.{2640 _ = try func.addInst(.{
2252 .tag = .slli,2641 .tag = .slli,
2253 .ops = .rri,2642 .ops = .rri,
2254 .data = .{2643 .data = .{
2255 .i_type = .{2644 .i_type = .{
2256 .rd = shift_reg,2645 .rd = shift_reg,
2257 .rs1 = add_result_reg,2646 .rs1 = add_result_reg,
2258 .imm12 = Immediate.s(shift_amount),2647 .imm12 = Immediate.u(shift_amount),
2259 },2648 },
2260 },2649 },
2261 });2650 });
22622651
2263 _ = try self.addInst(.{2652 _ = try func.addInst(.{
2264 .tag = if (int_info.signedness == .unsigned) .srli else .srai,2653 .tag = if (int_info.signedness == .unsigned) .srli else .srai,
2265 .ops = .rri,2654 .ops = .rri,
2266 .data = .{2655 .data = .{
2267 .i_type = .{2656 .i_type = .{
2268 .rd = shift_reg,2657 .rd = shift_reg,
2269 .rs1 = shift_reg,2658 .rs1 = shift_reg,
2270 .imm12 = Immediate.s(shift_amount),2659 .imm12 = Immediate.u(shift_amount),
2271 },2660 },
2272 },2661 },
2273 });2662 });
22742663
2275 const add_result_frame: FrameAddr = .{2664 try func.genSetMem(
2276 .index = offset.index,2665 .{ .frame = offset.index },
2277 .off = offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))),2666 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))),
2278 };
2279 try self.genSetStack(
2280 lhs_ty,2667 lhs_ty,
2281 add_result_frame,
2282 add_result,2668 add_result,
2283 );2669 );
22842670
2285 const overflow_mcv = try self.binOp(2671 const overflow_reg, const overflow_lock = try func.allocReg(.int);
2672 defer func.register_manager.unlockReg(overflow_lock);
2673
2674 try func.genBinOp(
2286 .cmp_neq,2675 .cmp_neq,
2287 .{ .register = shift_reg },2676 .{ .register = shift_reg },
2288 lhs_ty,2677 lhs_ty,
2289 .{ .register = add_result_reg },2678 .{ .register = add_result_reg },
2290 lhs_ty,2679 lhs_ty,
2680 overflow_reg,
2291 );2681 );
22922682
2293 const overflow_frame: FrameAddr = .{2683 try func.genSetMem(
2294 .index = offset.index,2684 .{ .frame = offset.index },
2295 .off = offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),2685 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),
2296 };
2297 try self.genSetStack(
2298 Type.u1,2686 Type.u1,
2299 overflow_frame,2687 .{ .register = overflow_reg },
2300 overflow_mcv,
2301 );2688 );
23022689
2303 break :result result_mcv;2690 break :result result_mcv;
2304 } else {2691 } else {
2305 return self.fail("TODO: less than 8 bit or non-pow 2 addition", .{});2692 return func.fail("TODO: less than 8 bit or non-pow 2 addition", .{});
2306 }2693 }
2307 };2694 };
23082695
2309 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });2696 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2310}2697}
23112698
2312fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2699fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2313 _ = inst;2700 const zcu = func.bin_file.comp.module.?;
2314 return self.fail("TODO implement airSubWithOverflow for {}", .{self.target.cpu.arch});2701 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2702 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
2703
2704 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2705 const lhs = try func.resolveInst(extra.lhs);
2706 const rhs = try func.resolveInst(extra.rhs);
2707 const lhs_ty = func.typeOf(extra.lhs);
2708 const rhs_ty = func.typeOf(extra.rhs);
2709
2710 const int_info = lhs_ty.intInfo(zcu);
2711
2712 if (!math.isPowerOfTwo(int_info.bits) or int_info.bits < 8) {
2713 return func.fail("TODO: airSubWithOverflow non-power of 2 and less than 8 bits", .{});
2714 }
2715
2716 if (int_info.bits > 64) {
2717 return func.fail("TODO: airSubWithOverflow > 64 bits", .{});
2718 }
2719
2720 const tuple_ty = func.typeOfIndex(inst);
2721 const result_mcv = try func.allocRegOrMem(tuple_ty, inst, false);
2722 const offset = result_mcv.load_frame;
2723
2724 const dest_mcv = try func.binOp(null, .sub, extra.lhs, extra.rhs);
2725 assert(dest_mcv == .register);
2726 const dest_reg = dest_mcv.register;
2727
2728 try func.genSetMem(
2729 .{ .frame = offset.index },
2730 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))),
2731 lhs_ty,
2732 .{ .register = dest_reg },
2733 );
2734
2735 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs);
2736 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
2737
2738 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs);
2739 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
2740
2741 const overflow_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = 0 });
2742
2743 const overflow_lock = func.register_manager.lockRegAssumeUnused(overflow_reg);
2744 defer func.register_manager.unlockReg(overflow_lock);
2745
2746 switch (int_info.signedness) {
2747 .unsigned => {
2748 _ = try func.addInst(.{
2749 .tag = .sltu,
2750 .ops = .rrr,
2751 .data = .{ .r_type = .{
2752 .rd = overflow_reg,
2753 .rs1 = lhs_reg,
2754 .rs2 = rhs_reg,
2755 } },
2756 });
2757
2758 try func.genSetMem(
2759 .{ .frame = offset.index },
2760 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),
2761 Type.u1,
2762 .{ .register = overflow_reg },
2763 );
2764
2765 break :result result_mcv;
2766 },
2767 .signed => {
2768 switch (int_info.bits) {
2769 64 => {
2770 _ = try func.addInst(.{
2771 .tag = .slt,
2772 .ops = .rrr,
2773 .data = .{ .r_type = .{
2774 .rd = overflow_reg,
2775 .rs1 = overflow_reg,
2776 .rs2 = rhs_reg,
2777 } },
2778 });
2779
2780 _ = try func.addInst(.{
2781 .tag = .slt,
2782 .ops = .rrr,
2783 .data = .{ .r_type = .{
2784 .rd = rhs_reg,
2785 .rs1 = rhs_reg,
2786 .rs2 = lhs_reg,
2787 } },
2788 });
2789
2790 _ = try func.addInst(.{
2791 .tag = .xor,
2792 .ops = .rrr,
2793 .data = .{ .r_type = .{
2794 .rd = lhs_reg,
2795 .rs1 = overflow_reg,
2796 .rs2 = rhs_reg,
2797 } },
2798 });
2799
2800 try func.genBinOp(
2801 .cmp_neq,
2802 .{ .register = overflow_reg },
2803 Type.usize,
2804 .{ .register = rhs_reg },
2805 Type.usize,
2806 overflow_reg,
2807 );
2808
2809 try func.genSetMem(
2810 .{ .frame = offset.index },
2811 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),
2812 Type.u1,
2813 .{ .register = overflow_reg },
2814 );
2815
2816 break :result result_mcv;
2817 },
2818 else => |int_bits| return func.fail("TODO: airSubWithOverflow signed {}", .{int_bits}),
2819 }
2820 },
2821 }
2822 };
2823
2824 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2315}2825}
23162826
2317fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2827fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2318 //const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];2828 const zcu = func.bin_file.comp.module.?;
2319 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2829 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2320 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2830 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
2321 const zcu = self.bin_file.comp.module.?;2831
2322 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2832 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2323 const lhs = try self.resolveInst(extra.lhs);2833 const lhs = try func.resolveInst(extra.lhs);
2324 const rhs = try self.resolveInst(extra.rhs);2834 const rhs = try func.resolveInst(extra.rhs);
2325 const lhs_ty = self.typeOf(extra.lhs);2835 const lhs_ty = func.typeOf(extra.lhs);
2326 const rhs_ty = self.typeOf(extra.rhs);2836 const rhs_ty = func.typeOf(extra.rhs);
2837
2838 const tuple_ty = func.typeOfIndex(inst);
2839
2840 // genSetReg needs to support register_offset src_mcv for this to be true.
2841 const result_mcv = try func.allocRegOrMem(tuple_ty, inst, false);
2842
2843 const result_off: i32 = @intCast(tuple_ty.structFieldOffset(0, zcu));
2844 const overflow_off: i32 = @intCast(tuple_ty.structFieldOffset(1, zcu));
2845
2846 const dest_reg, const dest_lock = try func.allocReg(.int);
2847 defer func.register_manager.unlockReg(dest_lock);
2848
2849 try func.genBinOp(
2850 .mul,
2851 lhs,
2852 lhs_ty,
2853 rhs,
2854 rhs_ty,
2855 dest_reg,
2856 );
2857
2858 try func.genCopy(
2859 lhs_ty,
2860 result_mcv.offset(result_off),
2861 .{ .register = dest_reg },
2862 );
23272863
2328 switch (lhs_ty.zigTypeTag(zcu)) {2864 switch (lhs_ty.zigTypeTag(zcu)) {
2329 else => |x| return self.fail("TODO: airMulWithOverflow {s}", .{@tagName(x)}),2865 else => |x| return func.fail("TODO: airMulWithOverflow {s}", .{@tagName(x)}),
2330 .Int => {2866 .Int => {
2331 assert(lhs_ty.eql(rhs_ty, zcu));2867 assert(lhs_ty.eql(rhs_ty, zcu));
2332 const int_info = lhs_ty.intInfo(zcu);2868 const int_info = lhs_ty.intInfo(zcu);
2333 switch (int_info.bits) {2869 switch (int_info.bits) {
2334 1...32 => {2870 1...32 => {
2335 if (self.hasFeature(.m)) {2871 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
2336 const dest = try self.binOp(.mul, lhs, lhs_ty, rhs, rhs_ty);2872 if (int_info.signedness == .unsigned) {
23372873 switch (int_info.bits) {
2338 const add_result_lock = self.register_manager.lockRegAssumeUnused(dest.register);2874 1...8 => {
2339 defer self.register_manager.unlockReg(add_result_lock);2875 const max_val = std.math.pow(u16, 2, int_info.bits) - 1;
23402876
2341 const tuple_ty = self.typeOfIndex(inst);2877 const add_reg, const add_lock = try func.promoteReg(lhs_ty, lhs);
23422878 defer if (add_lock) |lock| func.register_manager.unlockReg(lock);
2343 // TODO: optimization, set this to true. needs the other struct access stuff to support2879
2344 // accessing registers.2880 const overflow_reg, const overflow_lock = try func.allocReg(.int);
2345 const result_mcv = try self.allocRegOrMem(inst, false);2881 defer func.register_manager.unlockReg(overflow_lock);
23462882
2347 const result_off: i32 = @intCast(tuple_ty.structFieldOffset(0, zcu));2883 _ = try func.addInst(.{
2348 const overflow_off: i32 = @intCast(tuple_ty.structFieldOffset(1, zcu));2884 .tag = .andi,
23492885 .ops = .rri,
2350 try self.genSetStack(lhs_ty, result_mcv.offset(result_off).load_frame, dest);2886 .data = .{ .i_type = .{
23512887 .rd = overflow_reg,
2352 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {2888 .rs1 = add_reg,
2353 if (int_info.signedness == .unsigned) {2889 .imm12 = Immediate.s(max_val),
2354 switch (int_info.bits) {2890 } },
2355 1...8 => {2891 });
2356 const max_val = std.math.pow(u16, 2, int_info.bits) - 1;2892
23572893 try func.genBinOp(
2358 const overflow_reg, const overflow_lock = try self.allocReg();2894 .cmp_neq,
2359 defer self.register_manager.unlockReg(overflow_lock);2895 .{ .register = overflow_reg },
23602896 lhs_ty,
2361 const add_reg, const add_lock = blk: {2897 .{ .register = add_reg },
2362 if (dest == .register) break :blk .{ dest.register, null };2898 lhs_ty,
23632899 overflow_reg,
2364 const add_reg, const add_lock = try self.allocReg();2900 );
2365 try self.genSetReg(lhs_ty, add_reg, dest);2901
2366 break :blk .{ add_reg, add_lock };2902 try func.genCopy(
2367 };2903 lhs_ty,
2368 defer if (add_lock) |lock| self.register_manager.unlockReg(lock);2904 result_mcv.offset(overflow_off),
23692905 .{ .register = overflow_reg },
2370 _ = try self.addInst(.{2906 );
2371 .tag = .andi,2907
2372 .ops = .rri,2908 break :result result_mcv;
2373 .data = .{ .i_type = .{2909 },
2374 .rd = overflow_reg,2910
2375 .rs1 = add_reg,2911 else => return func.fail("TODO: airMulWithOverflow check for size {d}", .{int_info.bits}),
2376 .imm12 = Immediate.s(max_val),
2377 } },
2378 });
2379
2380 const overflow_mcv = try self.binOp(
2381 .cmp_neq,
2382 .{ .register = overflow_reg },
2383 lhs_ty,
2384 .{ .register = add_reg },
2385 lhs_ty,
2386 );
2387
2388 try self.genSetStack(
2389 lhs_ty,
2390 result_mcv.offset(overflow_off).load_frame,
2391 overflow_mcv,
2392 );
2393
2394 break :result result_mcv;
2395 },
2396
2397 else => return self.fail("TODO: airMulWithOverflow check for size {d}", .{int_info.bits}),
2398 }
2399 } else {
2400 return self.fail("TODO: airMulWithOverflow calculate carry for signed addition", .{});
2401 }2912 }
2402 } else {2913 } else {
2403 return self.fail("TODO: airMulWithOverflow with < 8 bits or non-pow of 2", .{});2914 return func.fail("TODO: airMulWithOverflow calculate carry for signed addition", .{});
2404 }2915 }
2405 } else {2916 } else {
2406 return self.fail("TODO: emulate mul for targets without M feature", .{});2917 return func.fail("TODO: airMulWithOverflow with < 8 bits or non-pow of 2", .{});
2407 }2918 }
2408 },2919 },
2409 else => return self.fail("TODO: airMulWithOverflow larger than 32-bit mul", .{}),2920 else => return func.fail("TODO: airMulWithOverflow larger than 32-bit mul", .{}),
2410 }2921 }
2411 },2922 },
2412 }2923 }
2413 };2924 };
24142925
2415 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });2926 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2416}2927}
24172928
2418fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2929fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2419 _ = inst;2930 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2420 return self.fail("TODO implement airShlWithOverflow for {}", .{self.target.cpu.arch});2931 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShlWithOverflow", .{});
2421}2932 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2422
2423fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
2424 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2425 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement div for {}", .{self.target.cpu.arch});
2426 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2427}
2428
2429fn airRem(self: *Self, inst: Air.Inst.Index) !void {
2430 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2431 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement rem for {}", .{self.target.cpu.arch});
2432 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2433}2933}
24342934
2435fn airMod(self: *Self, inst: Air.Inst.Index) !void {2935fn airAddSat(func: *Func, inst: Air.Inst.Index) !void {
2436 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2936 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2437 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement zcu for {}", .{self.target.cpu.arch});2937 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airAddSat", .{});
2438 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2938 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2439}2939}
24402940
2441fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void {2941fn airSubSat(func: *Func, inst: Air.Inst.Index) !void {
2442 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2942 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2443 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement bitwise and for {}", .{self.target.cpu.arch});2943 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airSubSat", .{});
2444 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2944 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2445}2945}
24462946
2447fn airBitOr(self: *Self, inst: Air.Inst.Index) !void {2947fn airMulSat(func: *Func, inst: Air.Inst.Index) !void {
2448 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2948 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2449 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement bitwise or for {}", .{self.target.cpu.arch});2949 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airMulSat", .{});
2450 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2950 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2451}2951}
24522952
2453fn airXor(self: *Self, inst: Air.Inst.Index) !void {2953fn airShlSat(func: *Func, inst: Air.Inst.Index) !void {
2454 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2954 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2455 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement xor for {}", .{self.target.cpu.arch});2955 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShlSat", .{});
2456 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2956 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2457}2957}
24582958
2459fn airShl(self: *Self, inst: Air.Inst.Index) !void {2959fn airOptionalPayload(func: *Func, inst: Air.Inst.Index) !void {
2460 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2960 const zcu = func.bin_file.comp.module.?;
2461 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2961 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2462 const lhs = try self.resolveInst(bin_op.lhs);2962 const result: MCValue = result: {
2463 const rhs = try self.resolveInst(bin_op.rhs);2963 const pl_ty = func.typeOfIndex(inst);
2464 const lhs_ty = self.typeOf(bin_op.lhs);2964 if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none;
2465 const rhs_ty = self.typeOf(bin_op.rhs);2965
2966 const opt_mcv = try func.resolveInst(ty_op.operand);
2967 if (func.reuseOperand(inst, ty_op.operand, 0, opt_mcv)) {
2968 switch (opt_mcv) {
2969 .register => |pl_reg| try func.truncateRegister(pl_ty, pl_reg),
2970 else => {},
2971 }
2972 break :result opt_mcv;
2973 }
24662974
2467 break :result try self.binOp(.shl, lhs, lhs_ty, rhs, rhs_ty);2975 const pl_mcv = try func.allocRegOrMem(pl_ty, inst, true);
2976 try func.genCopy(pl_ty, pl_mcv, opt_mcv);
2977 break :result pl_mcv;
2468 };2978 };
2469 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2979 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2470}
2471
2472fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
2473 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2474 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
2475 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2476}
2477
2478fn airShr(self: *Self, inst: Air.Inst.Index) !void {
2479 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2480 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement shr for {}", .{self.target.cpu.arch});
2481 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2482}
2483
2484fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
2485 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2486 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement .optional_payload for {}", .{self.target.cpu.arch});
2487 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2488}2980}
24892981
2490fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {2982fn airOptionalPayloadPtr(func: *Func, inst: Air.Inst.Index) !void {
2491 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2983 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2492 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement .optional_payload_ptr for {}", .{self.target.cpu.arch});2984 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement .optional_payload_ptr for {}", .{func.target.cpu.arch});
2493 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2985 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2494}2986}
24952987
2496fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {2988fn airOptionalPayloadPtrSet(func: *Func, inst: Air.Inst.Index) !void {
2497 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2989 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2498 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement .optional_payload_ptr_set for {}", .{self.target.cpu.arch});2990 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement .optional_payload_ptr_set for {}", .{func.target.cpu.arch});
2499 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2991 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2500}2992}
25012993
2502fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {2994fn airUnwrapErrErr(func: *Func, inst: Air.Inst.Index) !void {
2503 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2995 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2504 const zcu = self.bin_file.comp.module.?;2996 const zcu = func.bin_file.comp.module.?;
2505 const err_union_ty = self.typeOf(ty_op.operand);2997 const err_union_ty = func.typeOf(ty_op.operand);
2506 const err_ty = err_union_ty.errorUnionSet(zcu);2998 const err_ty = err_union_ty.errorUnionSet(zcu);
2507 const payload_ty = err_union_ty.errorUnionPayload(zcu);2999 const payload_ty = err_union_ty.errorUnionPayload(zcu);
2508 const operand = try self.resolveInst(ty_op.operand);3000 const operand = try func.resolveInst(ty_op.operand);
25093001
2510 const result: MCValue = result: {3002 const result: MCValue = result: {
2511 if (err_ty.errorSetIsEmpty(zcu)) {3003 if (err_ty.errorSetIsEmpty(zcu)) {
...@@ -2520,43 +3012,47 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2520,43 +3012,47 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
25203012
2521 switch (operand) {3013 switch (operand) {
2522 .register => |reg| {3014 .register => |reg| {
2523 const eu_lock = self.register_manager.lockReg(reg);3015 const eu_lock = func.register_manager.lockReg(reg);
2524 defer if (eu_lock) |lock| self.register_manager.unlockReg(lock);3016 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);
2525
2526 var result = try self.copyToNewRegister(inst, operand);
25273017
3018 const result = try func.copyToNewRegister(inst, operand);
2528 if (err_off > 0) {3019 if (err_off > 0) {
2529 result = try self.binOp(3020 try func.genBinOp(
2530 .shr,3021 .shr,
2531 result,3022 result,
2532 err_union_ty,3023 err_union_ty,
2533 .{ .immediate = @as(u6, @intCast(err_off * 8)) },3024 .{ .immediate = @as(u6, @intCast(err_off * 8)) },
2534 Type.u8,3025 Type.u8,
3026 result.register,
2535 );3027 );
2536 }3028 }
2537 break :result result;3029 break :result result;
2538 },3030 },
2539 else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}),3031 .load_frame => |frame_addr| break :result .{ .load_frame = .{
3032 .index = frame_addr.index,
3033 .off = frame_addr.off + @as(i32, @intCast(err_off)),
3034 } },
3035 else => return func.fail("TODO implement unwrap_err_err for {}", .{operand}),
2540 }3036 }
2541 };3037 };
25423038
2543 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3039 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2544}3040}
25453041
2546fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {3042fn airUnwrapErrPayload(func: *Func, inst: Air.Inst.Index) !void {
2547 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3043 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2548 const operand_ty = self.typeOf(ty_op.operand);3044 const operand_ty = func.typeOf(ty_op.operand);
2549 const operand = try self.resolveInst(ty_op.operand);3045 const operand = try func.resolveInst(ty_op.operand);
2550 const result = try self.genUnwrapErrUnionPayloadMir(operand_ty, operand);3046 const result = try func.genUnwrapErrUnionPayloadMir(operand_ty, operand);
2551 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3047 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2552}3048}
25533049
2554fn genUnwrapErrUnionPayloadMir(3050fn genUnwrapErrUnionPayloadMir(
2555 self: *Self,3051 func: *Func,
2556 err_union_ty: Type,3052 err_union_ty: Type,
2557 err_union: MCValue,3053 err_union: MCValue,
2558) !MCValue {3054) !MCValue {
2559 const zcu = self.bin_file.comp.module.?;3055 const zcu = func.bin_file.comp.module.?;
2560 const payload_ty = err_union_ty.errorUnionPayload(zcu);3056 const payload_ty = err_union_ty.errorUnionPayload(zcu);
25613057
2562 const result: MCValue = result: {3058 const result: MCValue = result: {
...@@ -2569,24 +3065,23 @@ fn genUnwrapErrUnionPayloadMir(...@@ -2569,24 +3065,23 @@ fn genUnwrapErrUnionPayloadMir(
2569 .off = frame_addr.off + payload_off,3065 .off = frame_addr.off + payload_off,
2570 } },3066 } },
2571 .register => |reg| {3067 .register => |reg| {
2572 const eu_lock = self.register_manager.lockReg(reg);3068 const eu_lock = func.register_manager.lockReg(reg);
2573 defer if (eu_lock) |lock| self.register_manager.unlockReg(lock);3069 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);
2574
2575 var result: MCValue = .{ .register = try self.copyToTmpRegister(err_union_ty, err_union) };
25763070
3071 const result_reg = try func.copyToTmpRegister(err_union_ty, err_union);
2577 if (payload_off > 0) {3072 if (payload_off > 0) {
2578 result = try self.binOp(3073 try func.genBinOp(
2579 .shr,3074 .shr,
2580 result,3075 .{ .register = result_reg },
2581 err_union_ty,3076 err_union_ty,
2582 .{ .immediate = @as(u6, @intCast(payload_off * 8)) },3077 .{ .immediate = @as(u6, @intCast(payload_off * 8)) },
2583 Type.u8,3078 Type.u8,
3079 result_reg,
2584 );3080 );
2585 }3081 }
25863082 break :result .{ .register = result_reg };
2587 break :result result;
2588 },3083 },
2589 else => return self.fail("TODO implement genUnwrapErrUnionPayloadMir for {}", .{err_union}),3084 else => return func.fail("TODO implement genUnwrapErrUnionPayloadMir for {}", .{err_union}),
2590 }3085 }
2591 };3086 };
25923087
...@@ -2594,99 +3089,140 @@ fn genUnwrapErrUnionPayloadMir(...@@ -2594,99 +3089,140 @@ fn genUnwrapErrUnionPayloadMir(
2594}3089}
25953090
2596// *(E!T) -> E3091// *(E!T) -> E
2597fn airUnwrapErrErrPtr(self: *Self, inst: Air.Inst.Index) !void {3092fn airUnwrapErrErrPtr(func: *Func, inst: Air.Inst.Index) !void {
2598 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3093 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2599 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement unwrap error union error ptr for {}", .{self.target.cpu.arch});3094 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement unwrap error union error ptr for {}", .{func.target.cpu.arch});
2600 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3095 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2601}3096}
26023097
2603// *(E!T) -> *T3098// *(E!T) -> *T
2604fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {3099fn airUnwrapErrPayloadPtr(func: *Func, inst: Air.Inst.Index) !void {
2605 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3100 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2606 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement unwrap error union payload ptr for {}", .{self.target.cpu.arch});3101 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement unwrap error union payload ptr for {}", .{func.target.cpu.arch});
2607 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3102 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2608}3103}
26093104
2610fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {3105fn airErrUnionPayloadPtrSet(func: *Func, inst: Air.Inst.Index) !void {
2611 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3106 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2612 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch});3107 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement .errunion_payload_ptr_set for {}", .{func.target.cpu.arch});
2613 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3108 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2614}3109}
26153110
2616fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {3111fn airErrReturnTrace(func: *Func, inst: Air.Inst.Index) !void {
2617 const result: MCValue = if (self.liveness.isUnused(inst))3112 const result: MCValue = if (func.liveness.isUnused(inst))
2618 .unreach3113 .unreach
2619 else3114 else
2620 return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch});3115 return func.fail("TODO implement airErrReturnTrace for {}", .{func.target.cpu.arch});
2621 return self.finishAir(inst, result, .{ .none, .none, .none });3116 return func.finishAir(inst, result, .{ .none, .none, .none });
2622}3117}
26233118
2624fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {3119fn airSetErrReturnTrace(func: *Func, inst: Air.Inst.Index) !void {
2625 _ = inst;3120 _ = inst;
2626 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});3121 return func.fail("TODO implement airSetErrReturnTrace for {}", .{func.target.cpu.arch});
2627}3122}
26283123
2629fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {3124fn airSaveErrReturnTraceIndex(func: *Func, inst: Air.Inst.Index) !void {
2630 _ = inst;3125 _ = inst;
2631 return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch});3126 return func.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{func.target.cpu.arch});
2632}3127}
26333128
2634fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {3129fn airWrapOptional(func: *Func, inst: Air.Inst.Index) !void {
2635 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3130 const zcu = func.bin_file.comp.module.?;
2636 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3131 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2637 const zcu = self.bin_file.comp.module.?;3132 const result: MCValue = result: {
2638 const optional_ty = self.typeOfIndex(inst);3133 const pl_ty = func.typeOf(ty_op.operand);
3134 if (!pl_ty.hasRuntimeBits(zcu)) break :result .{ .immediate = 1 };
3135
3136 const opt_ty = func.typeOfIndex(inst);
3137 const pl_mcv = try func.resolveInst(ty_op.operand);
3138 const same_repr = opt_ty.optionalReprIsPayload(zcu);
3139 if (same_repr and func.reuseOperand(inst, ty_op.operand, 0, pl_mcv)) break :result pl_mcv;
3140
3141 const pl_lock: ?RegisterLock = switch (pl_mcv) {
3142 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
3143 else => null,
3144 };
3145 defer if (pl_lock) |lock| func.register_manager.unlockReg(lock);
26393146
2640 // Optional with a zero-bit payload type is just a boolean true3147 const opt_mcv = try func.allocRegOrMem(opt_ty, inst, true);
2641 if (optional_ty.abiSize(zcu) == 1)3148 try func.genCopy(pl_ty, opt_mcv, pl_mcv);
2642 break :result MCValue{ .immediate = 1 };
26433149
2644 return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch});3150 if (!same_repr) {
3151 const pl_abi_size: i32 = @intCast(pl_ty.abiSize(zcu));
3152 switch (opt_mcv) {
3153 .load_frame => |frame_addr| try func.genSetMem(
3154 .{ .frame = frame_addr.index },
3155 frame_addr.off + pl_abi_size,
3156 Type.u8,
3157 .{ .immediate = 1 },
3158 ),
3159 .register => return func.fail("TODO: airWrapOption opt_mcv register", .{}),
3160 else => unreachable,
3161 }
3162 }
3163 break :result opt_mcv;
2645 };3164 };
2646 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3165 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2647}3166}
26483167
2649/// T to E!T3168/// T to E!T
2650fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {3169fn airWrapErrUnionPayload(func: *Func, inst: Air.Inst.Index) !void {
2651 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3170 const zcu = func.bin_file.comp.module.?;
2652 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement wrap errunion payload for {}", .{self.target.cpu.arch});3171 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2653 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3172
3173 const eu_ty = ty_op.ty.toType();
3174 const pl_ty = eu_ty.errorUnionPayload(zcu);
3175 const err_ty = eu_ty.errorUnionSet(zcu);
3176 const operand = try func.resolveInst(ty_op.operand);
3177
3178 const result: MCValue = result: {
3179 if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .{ .immediate = 0 };
3180
3181 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));
3182 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));
3183 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
3184 try func.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand);
3185 try func.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 });
3186 break :result .{ .load_frame = .{ .index = frame_index } };
3187 };
3188
3189 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2654}3190}
26553191
2656/// E to E!T3192/// E to E!T
2657fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {3193fn airWrapErrUnionErr(func: *Func, inst: Air.Inst.Index) !void {
2658 const zcu = self.bin_file.comp.module.?;3194 const zcu = func.bin_file.comp.module.?;
2659 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3195 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
26603196
2661 const eu_ty = ty_op.ty.toType();3197 const eu_ty = ty_op.ty.toType();
2662 const pl_ty = eu_ty.errorUnionPayload(zcu);3198 const pl_ty = eu_ty.errorUnionPayload(zcu);
2663 const err_ty = eu_ty.errorUnionSet(zcu);3199 const err_ty = eu_ty.errorUnionSet(zcu);
26643200
2665 const result: MCValue = result: {3201 const result: MCValue = result: {
2666 if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result try self.resolveInst(ty_op.operand);3202 if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result try func.resolveInst(ty_op.operand);
26673203
2668 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));3204 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));
2669 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));3205 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));
2670 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));3206 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
2671 try self.genSetStack(pl_ty, .{ .index = frame_index, .off = pl_off }, .undef);3207 try func.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef);
2672 const operand = try self.resolveInst(ty_op.operand);3208 const operand = try func.resolveInst(ty_op.operand);
2673 try self.genSetStack(err_ty, .{ .index = frame_index, .off = err_off }, operand);3209 try func.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand);
2674 break :result .{ .load_frame = .{ .index = frame_index } };3210 break :result .{ .load_frame = .{ .index = frame_index } };
2675 };3211 };
2676 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3212 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2677}3213}
26783214
2679fn airTry(self: *Self, inst: Air.Inst.Index) !void {3215fn airTry(func: *Func, inst: Air.Inst.Index) !void {
2680 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;3216 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
2681 const extra = self.air.extraData(Air.Try, pl_op.payload);3217 const extra = func.air.extraData(Air.Try, pl_op.payload);
2682 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);3218 const body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]);
2683 const operand_ty = self.typeOf(pl_op.operand);3219 const operand_ty = func.typeOf(pl_op.operand);
2684 const result = try self.genTry(inst, pl_op.operand, body, operand_ty, false);3220 const result = try func.genTry(inst, pl_op.operand, body, operand_ty, false);
2685 return self.finishAir(inst, result, .{ .none, .none, .none });3221 return func.finishAir(inst, result, .{ .none, .none, .none });
2686}3222}
26873223
2688fn genTry(3224fn genTry(
2689 self: *Self,3225 func: *Func,
2690 inst: Air.Inst.Index,3226 inst: Air.Inst.Index,
2691 operand: Air.Inst.Ref,3227 operand: Air.Inst.Ref,
2692 body: []const Air.Inst.Index,3228 body: []const Air.Inst.Index,
...@@ -2695,180 +3231,204 @@ fn genTry(...@@ -2695,180 +3231,204 @@ fn genTry(
2695) !MCValue {3231) !MCValue {
2696 _ = operand_is_ptr;3232 _ = operand_is_ptr;
26973233
2698 const liveness_cond_br = self.liveness.getCondBr(inst);3234 const liveness_cond_br = func.liveness.getCondBr(inst);
26993235
2700 const operand_mcv = try self.resolveInst(operand);3236 const operand_mcv = try func.resolveInst(operand);
2701 const is_err_mcv = try self.isErr(null, operand_ty, operand_mcv);3237 const is_err_mcv = try func.isErr(null, operand_ty, operand_mcv);
27023238
2703 // A branch to the false section. Uses beq. 1 is the default "true" state.3239 // A branch to the false section. Uses beq. 1 is the default "true" state.
2704 const reloc = try self.condBr(Type.anyerror, is_err_mcv);3240 const reloc = try func.condBr(Type.anyerror, is_err_mcv);
27053241
2706 if (self.liveness.operandDies(inst, 0)) {3242 if (func.liveness.operandDies(inst, 0)) {
2707 if (operand.toIndex()) |operand_inst| try self.processDeath(operand_inst);3243 if (operand.toIndex()) |operand_inst| try func.processDeath(operand_inst);
2708 }3244 }
27093245
2710 self.scope_generation += 1;3246 func.scope_generation += 1;
2711 const state = try self.saveState();3247 const state = try func.saveState();
27123248
2713 for (liveness_cond_br.else_deaths) |death| try self.processDeath(death);3249 for (liveness_cond_br.else_deaths) |death| try func.processDeath(death);
2714 try self.genBody(body);3250 try func.genBody(body);
2715 try self.restoreState(state, &.{}, .{3251 try func.restoreState(state, &.{}, .{
2716 .emit_instructions = false,3252 .emit_instructions = false,
2717 .update_tracking = true,3253 .update_tracking = true,
2718 .resurrect = true,3254 .resurrect = true,
2719 .close_scope = true,3255 .close_scope = true,
2720 });3256 });
27213257
2722 self.performReloc(reloc);3258 func.performReloc(reloc);
27233259
2724 for (liveness_cond_br.then_deaths) |death| try self.processDeath(death);3260 for (liveness_cond_br.then_deaths) |death| try func.processDeath(death);
27253261
2726 const result = if (self.liveness.isUnused(inst))3262 const result = if (func.liveness.isUnused(inst))
2727 .unreach3263 .unreach
2728 else3264 else
2729 try self.genUnwrapErrUnionPayloadMir(operand_ty, operand_mcv);3265 try func.genUnwrapErrUnionPayloadMir(operand_ty, operand_mcv);
27303266
2731 return result;3267 return result;
2732}3268}
27333269
2734fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {3270fn airSlicePtr(func: *Func, inst: Air.Inst.Index) !void {
2735 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3271 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2736 const result = result: {3272 const result = result: {
2737 const src_mcv = try self.resolveInst(ty_op.operand);3273 const src_mcv = try func.resolveInst(ty_op.operand);
2738 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;3274 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
27393275
2740 const dst_mcv = try self.allocRegOrMem(inst, true);3276 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
2741 const dst_ty = self.typeOfIndex(inst);3277 const dst_ty = func.typeOfIndex(inst);
2742 try self.genCopy(dst_ty, dst_mcv, src_mcv);3278 try func.genCopy(dst_ty, dst_mcv, src_mcv);
2743 break :result dst_mcv;3279 break :result dst_mcv;
2744 };3280 };
2745 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3281 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2746}3282}
27473283
2748fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {3284fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
2749 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3285 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2750 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3286 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2751 const src_mcv = try self.resolveInst(ty_op.operand);3287 const src_mcv = try func.resolveInst(ty_op.operand);
3288 const ty = func.typeOfIndex(inst);
3289
2752 switch (src_mcv) {3290 switch (src_mcv) {
2753 .load_frame => |frame_addr| {3291 .load_frame => |frame_addr| {
2754 const len_mcv: MCValue = .{ .load_frame = .{3292 const len_mcv: MCValue = .{ .load_frame = .{
2755 .index = frame_addr.index,3293 .index = frame_addr.index,
2756 .off = frame_addr.off + 8,3294 .off = frame_addr.off + 8,
2757 } };3295 } };
2758 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;3296 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
27593297
2760 const dst_mcv = try self.allocRegOrMem(inst, true);3298 const dst_mcv = try func.allocRegOrMem(ty, inst, true);
2761 try self.genCopy(Type.usize, dst_mcv, len_mcv);3299 try func.genCopy(Type.usize, dst_mcv, len_mcv);
2762 break :result dst_mcv;3300 break :result dst_mcv;
2763 },3301 },
2764 .register_pair => |pair| {3302 .register_pair => |pair| {
2765 const len_mcv: MCValue = .{ .register = pair[1] };3303 const len_mcv: MCValue = .{ .register = pair[1] };
27663304
2767 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;3305 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
27683306
2769 const dst_mcv = try self.allocRegOrMem(inst, true);3307 const dst_mcv = try func.allocRegOrMem(ty, inst, true);
2770 try self.genCopy(Type.usize, dst_mcv, len_mcv);3308 try func.genCopy(Type.usize, dst_mcv, len_mcv);
2771 break :result dst_mcv;3309 break :result dst_mcv;
2772 },3310 },
2773 else => return self.fail("TODO airSliceLen for {}", .{src_mcv}),3311 else => return func.fail("TODO airSliceLen for {}", .{src_mcv}),
2774 }3312 }
2775 };3313 };
2776 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3314 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2777}3315}
27783316
2779fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {3317fn airPtrSliceLenPtr(func: *Func, inst: Air.Inst.Index) !void {
2780 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3318 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2781 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement ptr_slice_len_ptr for {}", .{self.target.cpu.arch});3319 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement ptr_slice_len_ptr for {}", .{func.target.cpu.arch});
2782 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3320 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2783}3321}
27843322
2785fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {3323fn airPtrSlicePtrPtr(func: *Func, inst: Air.Inst.Index) !void {
2786 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3324 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2787 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement ptr_slice_ptr_ptr for {}", .{self.target.cpu.arch});3325 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement ptr_slice_ptr_ptr for {}", .{func.target.cpu.arch});
2788 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3326 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2789}3327}
27903328
2791fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {3329fn airSliceElemVal(func: *Func, inst: Air.Inst.Index) !void {
2792 const zcu = self.bin_file.comp.module.?;3330 const mod = func.bin_file.comp.module.?;
2793 const is_volatile = false; // TODO3331 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2794 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
27953332
2796 if (!is_volatile and self.liveness.isUnused(inst)) return self.finishAir(
2797 inst,
2798 .unreach,
2799 .{ bin_op.lhs, bin_op.rhs, .none },
2800 );
2801 const result: MCValue = result: {3333 const result: MCValue = result: {
2802 const slice_mcv = try self.resolveInst(bin_op.lhs);3334 const elem_ty = func.typeOfIndex(inst);
2803 const index_mcv = try self.resolveInst(bin_op.rhs);3335 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
28043336
2805 const slice_ty = self.typeOf(bin_op.lhs);3337 const slice_ty = func.typeOf(bin_op.lhs);
28063338 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
2807 const slice_ptr_field_type = slice_ty.slicePtrFieldType(zcu);3339 const elem_ptr = try func.genSliceElemPtr(bin_op.lhs, bin_op.rhs);
3340 const dst_mcv = try func.allocRegOrMem(elem_ty, inst, false);
3341 try func.load(dst_mcv, elem_ptr, slice_ptr_field_type);
3342 break :result dst_mcv;
3343 };
3344 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3345}
28083346
2809 const index_lock: ?RegisterLock = if (index_mcv == .register)3347fn airSliceElemPtr(func: *Func, inst: Air.Inst.Index) !void {
2810 self.register_manager.lockRegAssumeUnused(index_mcv.register)3348 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2811 else3349 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
2812 null;3350 const dst_mcv = try func.genSliceElemPtr(extra.lhs, extra.rhs);
2813 defer if (index_lock) |reg| self.register_manager.unlockReg(reg);3351 return func.finishAir(inst, dst_mcv, .{ extra.lhs, extra.rhs, .none });
3352}
28143353
2815 const base_mcv: MCValue = switch (slice_mcv) {3354fn genSliceElemPtr(func: *Func, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
2816 .load_frame,3355 const zcu = func.bin_file.comp.module.?;
2817 .load_symbol,3356 const slice_ty = func.typeOf(lhs);
2818 => .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, slice_mcv) },3357 const slice_mcv = try func.resolveInst(lhs);
2819 else => return self.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}),3358 const slice_mcv_lock: ?RegisterLock = switch (slice_mcv) {
2820 };3359 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
3360 else => null,
3361 };
3362 defer if (slice_mcv_lock) |lock| func.register_manager.unlockReg(lock);
28213363
2822 const dest = try self.allocRegOrMem(inst, true);3364 const elem_ty = slice_ty.childType(zcu);
2823 const addr = try self.binOp(.ptr_add, base_mcv, slice_ptr_field_type, index_mcv, Type.usize);3365 const elem_size = elem_ty.abiSize(zcu);
2824 try self.load(dest, addr, slice_ptr_field_type);
28253366
2826 break :result dest;3367 const index_ty = func.typeOf(rhs);
3368 const index_mcv = try func.resolveInst(rhs);
3369 const index_mcv_lock: ?RegisterLock = switch (index_mcv) {
3370 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
3371 else => null,
2827 };3372 };
2828 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3373 defer if (index_mcv_lock) |lock| func.register_manager.unlockReg(lock);
2829}3374
3375 const offset_reg = try func.elemOffset(index_ty, index_mcv, elem_size);
3376 const offset_reg_lock = func.register_manager.lockRegAssumeUnused(offset_reg);
3377 defer func.register_manager.unlockReg(offset_reg_lock);
3378
3379 const addr_reg, const addr_lock = try func.allocReg(.int);
3380 defer func.register_manager.unlockReg(addr_lock);
3381 try func.genSetReg(Type.usize, addr_reg, slice_mcv);
3382
3383 _ = try func.addInst(.{
3384 .tag = .add,
3385 .ops = .rrr,
3386 .data = .{ .r_type = .{
3387 .rd = addr_reg,
3388 .rs1 = addr_reg,
3389 .rs2 = offset_reg,
3390 } },
3391 });
28303392
2831fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {3393 return .{ .register = addr_reg };
2832 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2833 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2834 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement slice_elem_ptr for {}", .{self.target.cpu.arch});
2835 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2836}3394}
28373395
2838fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {3396fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
2839 const zcu = self.bin_file.comp.module.?;3397 const zcu = func.bin_file.comp.module.?;
2840 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3398 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2841 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3399 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2842 const array_ty = self.typeOf(bin_op.lhs);3400 const result_ty = func.typeOfIndex(inst);
2843 const array_mcv = try self.resolveInst(bin_op.lhs);3401
3402 const array_ty = func.typeOf(bin_op.lhs);
3403 const array_mcv = try func.resolveInst(bin_op.lhs);
28443404
2845 const index_mcv = try self.resolveInst(bin_op.rhs);3405 const index_mcv = try func.resolveInst(bin_op.rhs);
2846 const index_ty = self.typeOf(bin_op.rhs);3406 const index_ty = func.typeOf(bin_op.rhs);
28473407
2848 const elem_ty = array_ty.childType(zcu);3408 const elem_ty = array_ty.childType(zcu);
2849 const elem_abi_size = elem_ty.abiSize(zcu);3409 const elem_abi_size = elem_ty.abiSize(zcu);
28503410
2851 const addr_reg, const addr_reg_lock = try self.allocReg();3411 const addr_reg, const addr_reg_lock = try func.allocReg(.int);
2852 defer self.register_manager.unlockReg(addr_reg_lock);3412 defer func.register_manager.unlockReg(addr_reg_lock);
28533413
2854 switch (array_mcv) {3414 switch (array_mcv) {
2855 .register => {3415 .register => {
2856 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, zcu));3416 const frame_index = try func.allocFrameIndex(FrameAlloc.initType(array_ty, zcu));
2857 try self.genSetStack(array_ty, .{ .index = frame_index }, array_mcv);3417 try func.genSetMem(.{ .frame = frame_index }, 0, array_ty, array_mcv);
2858 try self.genSetReg(Type.usize, addr_reg, .{ .lea_frame = .{ .index = frame_index } });3418 try func.genSetReg(Type.usize, addr_reg, .{ .lea_frame = .{ .index = frame_index } });
2859 },3419 },
2860 .load_frame => |frame_addr| {3420 .load_frame => |frame_addr| {
2861 try self.genSetReg(Type.usize, addr_reg, .{ .lea_frame = frame_addr });3421 try func.genSetReg(Type.usize, addr_reg, .{ .lea_frame = frame_addr });
2862 },3422 },
2863 else => try self.genSetReg(Type.usize, addr_reg, array_mcv.address()),3423 else => try func.genSetReg(Type.usize, addr_reg, array_mcv.address()),
2864 }3424 }
28653425
2866 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_abi_size);3426 const offset_reg = try func.elemOffset(index_ty, index_mcv, elem_abi_size);
2867 const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg);3427 const offset_lock = func.register_manager.lockRegAssumeUnused(offset_reg);
2868 defer self.register_manager.unlockReg(offset_lock);3428 defer func.register_manager.unlockReg(offset_lock);
28693429
2870 const dst_mcv = try self.allocRegOrMem(inst, false);3430 const dst_mcv = try func.allocRegOrMem(result_ty, inst, false);
2871 _ = try self.addInst(.{3431 _ = try func.addInst(.{
2872 .tag = .add,3432 .tag = .add,
2873 .ops = .rrr,3433 .ops = .rrr,
2874 .data = .{ .r_type = .{3434 .data = .{ .r_type = .{
...@@ -2877,163 +3437,225 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2877,163 +3437,225 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2877 .rs2 = addr_reg,3437 .rs2 = addr_reg,
2878 } },3438 } },
2879 });3439 });
2880 try self.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });3440 try func.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });
2881 break :result dst_mcv;3441 break :result dst_mcv;
2882 };3442 };
2883 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3443 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2884}3444}
28853445
2886fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {3446fn airPtrElemVal(func: *Func, inst: Air.Inst.Index) !void {
2887 const is_volatile = false; // TODO3447 const is_volatile = false; // TODO
2888 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3448 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2889 const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement ptr_elem_val for {}", .{self.target.cpu.arch});3449 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});
2890 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3450 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2891}3451}
28923452
2893fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {3453fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {
2894 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3454 const zcu = func.bin_file.comp.module.?;
2895 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;3455 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2896 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement ptr_elem_ptr for {}", .{self.target.cpu.arch});3456 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
2897 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2898}
2899
2900fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
2901 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2902 _ = bin_op;
2903 return self.fail("TODO implement airSetUnionTag for {}", .{self.target.cpu.arch});
2904 // return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2905}
2906
2907fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
2908 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2909 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airGetUnionTag for {}", .{self.target.cpu.arch});
2910 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2911}
2912
2913fn airClz(self: *Self, inst: Air.Inst.Index) !void {
2914 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2915 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airClz for {}", .{self.target.cpu.arch});
2916 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2917}
2918
2919fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
2920 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2921 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {
2922 const operand = try self.resolveInst(ty_op.operand);
2923 const operand_ty = self.typeOf(ty_op.operand);
29243457
2925 const dest_reg = try self.register_manager.allocReg(inst, gp);3458 const result = result: {
29263459 const elem_ptr_ty = func.typeOfIndex(inst);
2927 const source_reg, const source_lock = blk: {3460 const base_ptr_ty = func.typeOf(extra.lhs);
2928 if (operand == .register) break :blk .{ operand.register, null };
29293461
2930 const source_reg, const source_lock = try self.allocReg();3462 const base_ptr_mcv = try func.resolveInst(extra.lhs);
2931 try self.genSetReg(operand_ty, source_reg, operand);3463 const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) {
2932 break :blk .{ source_reg, source_lock };3464 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
3465 else => null,
2933 };3466 };
2934 defer if (source_lock) |lock| self.register_manager.unlockReg(lock);3467 defer if (base_ptr_lock) |lock| func.register_manager.unlockReg(lock);
29353468
2936 // TODO: the B extension for RISCV should have the ctz instruction, and we should use it.3469 if (elem_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) {
3470 break :result if (func.reuseOperand(inst, extra.lhs, 0, base_ptr_mcv))
3471 base_ptr_mcv
3472 else
3473 try func.copyToNewRegister(inst, base_ptr_mcv);
3474 }
29373475
2938 try self.ctz(source_reg, dest_reg, operand_ty);3476 const elem_ty = base_ptr_ty.elemType2(zcu);
3477 const elem_abi_size = elem_ty.abiSize(zcu);
3478 const index_ty = func.typeOf(extra.rhs);
3479 const index_mcv = try func.resolveInst(extra.rhs);
3480 const index_lock: ?RegisterLock = switch (index_mcv) {
3481 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
3482 else => null,
3483 };
3484 defer if (index_lock) |lock| func.register_manager.unlockReg(lock);
3485
3486 const offset_reg = try func.elemOffset(index_ty, index_mcv, elem_abi_size);
3487 const offset_reg_lock = func.register_manager.lockRegAssumeUnused(offset_reg);
3488 defer func.register_manager.unlockReg(offset_reg_lock);
3489
3490 const result_reg, const result_lock = try func.allocReg(.int);
3491 defer func.register_manager.unlockReg(result_lock);
3492
3493 try func.genBinOp(
3494 .ptr_add,
3495 base_ptr_mcv,
3496 base_ptr_ty,
3497 .{ .register = offset_reg },
3498 Type.usize,
3499 result_reg,
3500 );
29393501
2940 break :result .{ .register = dest_reg };3502 break :result MCValue{ .register = result_reg };
2941 };3503 };
2942 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3504 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2943}3505}
29443506
2945fn ctz(self: *Self, src: Register, dst: Register, ty: Type) !void {3507fn airSetUnionTag(func: *Func, inst: Air.Inst.Index) !void {
2946 const zcu = self.bin_file.comp.module.?;3508 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2947 const length = (ty.abiSize(zcu) * 8) - 1;3509 _ = bin_op;
29483510 return func.fail("TODO implement airSetUnionTag for {}", .{func.target.cpu.arch});
2949 const count_reg, const count_lock = try self.allocReg();3511 // return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2950 defer self.register_manager.unlockReg(count_lock);3512}
2951
2952 const len_reg, const len_lock = try self.allocReg();
2953 defer self.register_manager.unlockReg(len_lock);
29543513
2955 try self.genSetReg(Type.usize, count_reg, .{ .immediate = 0 });3514fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {
2956 try self.genSetReg(Type.usize, len_reg, .{ .immediate = length });3515 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3516 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airGetUnionTag for {}", .{func.target.cpu.arch});
3517 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3518}
29573519
2958 _ = src;3520fn airClz(func: *Func, inst: Air.Inst.Index) !void {
2959 _ = dst;3521 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3522 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airClz for {}", .{func.target.cpu.arch});
3523 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3524}
29603525
2961 return self.fail("TODO: finish ctz", .{});3526fn airCtz(func: *Func, inst: Air.Inst.Index) !void {
3527 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3528 _ = ty_op;
3529 return func.fail("TODO: finish ctz", .{});
2962}3530}
29633531
2964fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {3532fn airPopcount(func: *Func, inst: Air.Inst.Index) !void {
2965 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3533 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2966 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airPopcount for {}", .{self.target.cpu.arch});3534 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airPopcount for {}", .{func.target.cpu.arch});
2967 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3535 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2968}3536}
29693537
2970fn airAbs(self: *Self, inst: Air.Inst.Index) !void {3538fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
2971 const zcu = self.bin_file.comp.module.?;3539 const zcu = func.bin_file.comp.module.?;
2972 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3540 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2973 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3541 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2974 const ty = self.typeOf(ty_op.operand);3542 const ty = func.typeOf(ty_op.operand);
2975 const scalar_ty = ty.scalarType(zcu);3543 const scalar_ty = ty.scalarType(zcu);
2976 const operand = try self.resolveInst(ty_op.operand);3544 const operand = try func.resolveInst(ty_op.operand);
29773545
2978 switch (scalar_ty.zigTypeTag(zcu)) {3546 switch (scalar_ty.zigTypeTag(zcu)) {
2979 .Int => if (ty.zigTypeTag(zcu) == .Vector) {3547 .Int => if (ty.zigTypeTag(zcu) == .Vector) {
2980 return self.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)});3548 return func.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)});
2981 } else {3549 } else {
2982 const int_bits = ty.intInfo(zcu).bits;3550 const return_mcv = try func.copyToNewRegister(inst, operand);
3551 const operand_reg = return_mcv.register;
3552
3553 const temp_reg, const temp_lock = try func.allocReg(.int);
3554 defer func.register_manager.unlockReg(temp_lock);
3555
3556 _ = try func.addInst(.{
3557 .tag = .srai,
3558 .ops = .rri,
3559 .data = .{ .i_type = .{
3560 .rd = temp_reg,
3561 .rs1 = operand_reg,
3562 .imm12 = Immediate.u(63),
3563 } },
3564 });
29833565
2984 if (int_bits > 32) {3566 _ = try func.addInst(.{
2985 return self.fail("TODO: airAbs for larger than 32 bits", .{});3567 .tag = .xor,
3568 .ops = .rrr,
3569 .data = .{ .r_type = .{
3570 .rd = operand_reg,
3571 .rs1 = operand_reg,
3572 .rs2 = temp_reg,
3573 } },
3574 });
3575
3576 _ = try func.addInst(.{
3577 .tag = .sub,
3578 .ops = .rrr,
3579 .data = .{ .r_type = .{
3580 .rd = operand_reg,
3581 .rs1 = operand_reg,
3582 .rs2 = temp_reg,
3583 } },
3584 });
3585
3586 break :result return_mcv;
3587 },
3588 .Float => {
3589 const float_bits = scalar_ty.floatBits(zcu.getTarget());
3590 switch (float_bits) {
3591 16 => return func.fail("TODO: airAbs 16-bit float", .{}),
3592 32 => {},
3593 64 => {},
3594 80 => return func.fail("TODO: airAbs 80-bit float", .{}),
3595 128 => return func.fail("TODO: airAbs 128-bit float", .{}),
3596 else => unreachable,
2986 }3597 }
29873598
2988 // promote the src into a register3599 const return_mcv = try func.copyToNewRegister(inst, operand);
2989 const src_mcv = try self.copyToNewRegister(inst, operand);3600 const operand_reg = return_mcv.register;
2990 // temp register for shift
2991 const temp_reg = try self.register_manager.allocReg(inst, gp);
29923601
2993 _ = try self.addInst(.{3602 assert(operand_reg.class() == .float);
2994 .tag = .abs,3603
2995 .ops = .rri,3604 _ = try func.addInst(.{
3605 .tag = .pseudo,
3606 .ops = .pseudo_fabs,
2996 .data = .{3607 .data = .{
2997 .i_type = .{3608 .fabs = .{
2998 .rs1 = src_mcv.register,3609 .rd = operand_reg,
2999 .rd = temp_reg,3610 .rs = operand_reg,
3000 .imm12 = Immediate.s(int_bits - 1),3611 .bits = float_bits,
3001 },3612 },
3002 },3613 },
3003 });3614 });
30043615
3005 break :result src_mcv;3616 break :result return_mcv;
3006 },3617 },
3007 else => return self.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}),3618 else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}),
3008 }3619 }
3620
3621 break :result .unreach;
3009 };3622 };
3010 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3623 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3011}3624}
30123625
3013fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {3626fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void {
3014 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3627 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3015 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3628 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3016 const zcu = self.bin_file.comp.module.?;3629 const zcu = func.bin_file.comp.module.?;
3017 const ty = self.typeOf(ty_op.operand);3630 const ty = func.typeOf(ty_op.operand);
3018 const operand = try self.resolveInst(ty_op.operand);3631 const operand = try func.resolveInst(ty_op.operand);
30193632
3020 const int_bits = ty.intInfo(zcu).bits;3633 const int_bits = ty.intInfo(zcu).bits;
30213634
3022 // bytes are no-op3635 // bytes are no-op
3023 if (int_bits == 8 and self.reuseOperand(inst, ty_op.operand, 0, operand)) {3636 if (int_bits == 8 and func.reuseOperand(inst, ty_op.operand, 0, operand)) {
3024 return self.finishAir(inst, operand, .{ ty_op.operand, .none, .none });3637 return func.finishAir(inst, operand, .{ ty_op.operand, .none, .none });
3025 }3638 }
30263639
3027 const dest_reg = try self.register_manager.allocReg(null, gp);3640 const dest_mcv = try func.copyToNewRegister(inst, operand);
3028 try self.genSetReg(ty, dest_reg, operand);3641 const dest_reg = dest_mcv.register;
3642
3643 switch (int_bits) {
3644 16 => {
3645 const temp_reg, const temp_lock = try func.allocReg(.int);
3646 defer func.register_manager.unlockReg(temp_lock);
30293647
3030 const dest_mcv: MCValue = .{ .register = dest_reg };3648 _ = try func.addInst(.{
3649 .tag = .srli,
3650 .ops = .rri,
3651 .data = .{ .i_type = .{
3652 .imm12 = Immediate.s(8),
3653 .rd = temp_reg,
3654 .rs1 = dest_reg,
3655 } },
3656 });
30313657
3032 switch (int_bits) {3658 _ = try func.addInst(.{
3033 16 => {
3034 const temp = try self.binOp(.shr, dest_mcv, ty, .{ .immediate = 8 }, Type.u8);
3035 assert(temp == .register);
3036 _ = try self.addInst(.{
3037 .tag = .slli,3659 .tag = .slli,
3038 .ops = .rri,3660 .ops = .rri,
3039 .data = .{ .i_type = .{3661 .data = .{ .i_type = .{
...@@ -3042,58 +3664,59 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {...@@ -3042,58 +3664,59 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
3042 .rs1 = dest_reg,3664 .rs1 = dest_reg,
3043 } },3665 } },
3044 });3666 });
3045 _ = try self.addInst(.{3667 _ = try func.addInst(.{
3046 .tag = .@"or",3668 .tag = .@"or",
3047 .ops = .rri,3669 .ops = .rri,
3048 .data = .{ .r_type = .{3670 .data = .{ .r_type = .{
3049 .rd = dest_reg,3671 .rd = dest_reg,
3050 .rs1 = dest_reg,3672 .rs1 = dest_reg,
3051 .rs2 = temp.register,3673 .rs2 = temp_reg,
3052 } },3674 } },
3053 });3675 });
3054 },3676 },
3055 else => return self.fail("TODO: {d} bits for airByteSwap", .{int_bits}),3677 else => return func.fail("TODO: {d} bits for airByteSwap", .{int_bits}),
3056 }3678 }
30573679
3058 break :result dest_mcv;3680 break :result dest_mcv;
3059 };3681 };
3060 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3682 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3061}3683}
30623684
3063fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {3685fn airBitReverse(func: *Func, inst: Air.Inst.Index) !void {
3064 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3686 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3065 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airBitReverse for {}", .{self.target.cpu.arch});3687 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airBitReverse for {}", .{func.target.cpu.arch});
3066 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3688 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3067}3689}
30683690
3069fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {3691fn airUnaryMath(func: *Func, inst: Air.Inst.Index) !void {
3070 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;3692 const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];
3071 const result: MCValue = if (self.liveness.isUnused(inst))3693 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3694 const result: MCValue = if (func.liveness.isUnused(inst))
3072 .unreach3695 .unreach
3073 else3696 else
3074 return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});3697 return func.fail("TODO implementairUnaryMath {s} for {}", .{ @tagName(tag), func.target.cpu.arch });
3075 return self.finishAir(inst, result, .{ un_op, .none, .none });3698 return func.finishAir(inst, result, .{ un_op, .none, .none });
3076}3699}
30773700
3078fn reuseOperand(3701fn reuseOperand(
3079 self: *Self,3702 func: *Func,
3080 inst: Air.Inst.Index,3703 inst: Air.Inst.Index,
3081 operand: Air.Inst.Ref,3704 operand: Air.Inst.Ref,
3082 op_index: Liveness.OperandInt,3705 op_index: Liveness.OperandInt,
3083 mcv: MCValue,3706 mcv: MCValue,
3084) bool {3707) bool {
3085 return self.reuseOperandAdvanced(inst, operand, op_index, mcv, inst);3708 return func.reuseOperandAdvanced(inst, operand, op_index, mcv, inst);
3086}3709}
30873710
3088fn reuseOperandAdvanced(3711fn reuseOperandAdvanced(
3089 self: *Self,3712 func: *Func,
3090 inst: Air.Inst.Index,3713 inst: Air.Inst.Index,
3091 operand: Air.Inst.Ref,3714 operand: Air.Inst.Ref,
3092 op_index: Liveness.OperandInt,3715 op_index: Liveness.OperandInt,
3093 mcv: MCValue,3716 mcv: MCValue,
3094 maybe_tracked_inst: ?Air.Inst.Index,3717 maybe_tracked_inst: ?Air.Inst.Index,
3095) bool {3718) bool {
3096 if (!self.liveness.operandDies(inst, op_index))3719 if (!func.liveness.operandDies(inst, op_index))
3097 return false;3720 return false;
30983721
3099 switch (mcv) {3722 switch (mcv) {
...@@ -3103,55 +3726,59 @@ fn reuseOperandAdvanced(...@@ -3103,55 +3726,59 @@ fn reuseOperandAdvanced(
3103 // If it's in the registers table, need to associate the register(s) with the3726 // If it's in the registers table, need to associate the register(s) with the
3104 // new instruction.3727 // new instruction.
3105 if (maybe_tracked_inst) |tracked_inst| {3728 if (maybe_tracked_inst) |tracked_inst| {
3106 if (!self.register_manager.isRegFree(reg)) {3729 if (!func.register_manager.isRegFree(reg)) {
3107 if (RegisterManager.indexOfRegIntoTracked(reg)) |index| {3730 if (RegisterManager.indexOfRegIntoTracked(reg)) |index| {
3108 self.register_manager.registers[index] = tracked_inst;3731 func.register_manager.registers[index] = tracked_inst;
3109 }3732 }
3110 }3733 }
3111 } else self.register_manager.freeReg(reg);3734 } else func.register_manager.freeReg(reg);
3112 },3735 },
3113 .load_frame => |frame_addr| if (frame_addr.index.isNamed()) return false,3736 .load_frame => |frame_addr| if (frame_addr.index.isNamed()) return false,
3114 else => return false,3737 else => return false,
3115 }3738 }
31163739
3117 // Prevent the operand deaths processing code from deallocating it.3740 // Prevent the operand deaths processing code from deallocating it.
3118 self.liveness.clearOperandDeath(inst, op_index);3741 func.liveness.clearOperandDeath(inst, op_index);
3119 const op_inst = operand.toIndex().?;3742 const op_inst = operand.toIndex().?;
3120 self.getResolvedInstValue(op_inst).reuse(self, maybe_tracked_inst, op_inst);3743 func.getResolvedInstValue(op_inst).reuse(func, maybe_tracked_inst, op_inst);
31213744
3122 return true;3745 return true;
3123}3746}
31243747
3125fn airLoad(self: *Self, inst: Air.Inst.Index) !void {3748fn airLoad(func: *Func, inst: Air.Inst.Index) !void {
3126 const zcu = self.bin_file.comp.module.?;3749 const zcu = func.bin_file.comp.module.?;
3127 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3750 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3128 const elem_ty = self.typeOfIndex(inst);3751 const elem_ty = func.typeOfIndex(inst);
3752
3129 const result: MCValue = result: {3753 const result: MCValue = result: {
3130 if (!elem_ty.hasRuntimeBits(zcu))3754 if (!elem_ty.hasRuntimeBits(zcu))
3131 break :result .none;3755 break :result .none;
31323756
3133 const ptr = try self.resolveInst(ty_op.operand);3757 const ptr = try func.resolveInst(ty_op.operand);
3134 const is_volatile = self.typeOf(ty_op.operand).isVolatilePtr(zcu);3758 const is_volatile = func.typeOf(ty_op.operand).isVolatilePtr(zcu);
3135 if (self.liveness.isUnused(inst) and !is_volatile)3759 if (func.liveness.isUnused(inst) and !is_volatile)
3136 break :result .unreach;3760 break :result .unreach;
31373761
3762 const elem_size = elem_ty.abiSize(zcu);
3763
3138 const dst_mcv: MCValue = blk: {3764 const dst_mcv: MCValue = blk: {
3139 if (self.reuseOperand(inst, ty_op.operand, 0, ptr)) {3765 // Pointer is 8 bytes, and if the element is more than that, we cannot reuse it.
3766 if (elem_size <= 8 and func.reuseOperand(inst, ty_op.operand, 0, ptr)) {
3140 // The MCValue that holds the pointer can be re-used as the value.3767 // The MCValue that holds the pointer can be re-used as the value.
3141 break :blk ptr;3768 break :blk ptr;
3142 } else {3769 } else {
3143 break :blk try self.allocRegOrMem(inst, true);3770 break :blk try func.allocRegOrMem(elem_ty, inst, true);
3144 }3771 }
3145 };3772 };
31463773
3147 try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand));3774 try func.load(dst_mcv, ptr, func.typeOf(ty_op.operand));
3148 break :result dst_mcv;3775 break :result dst_mcv;
3149 };3776 };
3150 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3777 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3151}3778}
31523779
3153fn load(self: *Self, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerError!void {3780fn load(func: *Func, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerError!void {
3154 const zcu = self.bin_file.comp.module.?;3781 const zcu = func.bin_file.comp.module.?;
3155 const dst_ty = ptr_ty.childType(zcu);3782 const dst_ty = ptr_ty.childType(zcu);
31563783
3157 log.debug("loading {}:{} into {}", .{ ptr_mcv, ptr_ty.fmt(zcu), dst_mcv });3784 log.debug("loading {}:{} into {}", .{ ptr_mcv, ptr_ty.fmt(zcu), dst_mcv });
...@@ -3170,43 +3797,43 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro...@@ -3170,43 +3797,43 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro
3170 .register_offset,3797 .register_offset,
3171 .lea_frame,3798 .lea_frame,
3172 .lea_symbol,3799 .lea_symbol,
3173 => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()),3800 => try func.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()),
31743801
3175 .memory,3802 .memory,
3176 .indirect,3803 .indirect,
3177 .load_symbol,3804 .load_symbol,
3178 .load_frame,3805 .load_frame,
3179 => {3806 => {
3180 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv);3807 const addr_reg = try func.copyToTmpRegister(ptr_ty, ptr_mcv);
3181 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);3808 const addr_lock = func.register_manager.lockRegAssumeUnused(addr_reg);
3182 defer self.register_manager.unlockReg(addr_lock);3809 defer func.register_manager.unlockReg(addr_lock);
31833810
3184 try self.genCopy(dst_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });3811 try func.genCopy(dst_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });
3185 },3812 },
3186 .air_ref => |ptr_ref| try self.load(dst_mcv, try self.resolveInst(ptr_ref), ptr_ty),3813 .air_ref => |ptr_ref| try func.load(dst_mcv, try func.resolveInst(ptr_ref), ptr_ty),
3187 }3814 }
3188}3815}
31893816
3190fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {3817fn airStore(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
3191 if (safety) {3818 if (safety) {
3192 // TODO if the value is undef, write 0xaa bytes to dest3819 // TODO if the value is undef, write 0xaa bytes to dest
3193 } else {3820 } else {
3194 // TODO if the value is undef, don't lower this instruction3821 // TODO if the value is undef, don't lower this instruction
3195 }3822 }
3196 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3823 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3197 const ptr = try self.resolveInst(bin_op.lhs);3824 const ptr = try func.resolveInst(bin_op.lhs);
3198 const value = try self.resolveInst(bin_op.rhs);3825 const value = try func.resolveInst(bin_op.rhs);
3199 const ptr_ty = self.typeOf(bin_op.lhs);3826 const ptr_ty = func.typeOf(bin_op.lhs);
3200 const value_ty = self.typeOf(bin_op.rhs);3827 const value_ty = func.typeOf(bin_op.rhs);
32013828
3202 try self.store(ptr, value, ptr_ty, value_ty);3829 try func.store(ptr, value, ptr_ty, value_ty);
32033830
3204 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });3831 return func.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });
3205}3832}
32063833
3207/// Loads `value` into the "payload" of `pointer`.3834/// Loads `value` into the "payload" of `pointer`.
3208fn store(self: *Self, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty: Type) !void {3835fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty: Type) !void {
3209 const zcu = self.bin_file.comp.module.?;3836 const zcu = func.bin_file.comp.module.?;
32103837
3211 log.debug("storing {}:{} in {}:{}", .{ src_mcv, src_ty.fmt(zcu), ptr_mcv, ptr_ty.fmt(zcu) });3838 log.debug("storing {}:{} in {}:{}", .{ src_mcv, src_ty.fmt(zcu), ptr_mcv, ptr_ty.fmt(zcu) });
32123839
...@@ -3223,40 +3850,40 @@ fn store(self: *Self, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty:...@@ -3223,40 +3850,40 @@ fn store(self: *Self, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty:
3223 .register_offset,3850 .register_offset,
3224 .lea_symbol,3851 .lea_symbol,
3225 .lea_frame,3852 .lea_frame,
3226 => try self.genCopy(src_ty, ptr_mcv.deref(), src_mcv),3853 => try func.genCopy(src_ty, ptr_mcv.deref(), src_mcv),
32273854
3228 .memory,3855 .memory,
3229 .indirect,3856 .indirect,
3230 .load_symbol,3857 .load_symbol,
3231 .load_frame,3858 .load_frame,
3232 => {3859 => {
3233 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv);3860 const addr_reg = try func.copyToTmpRegister(ptr_ty, ptr_mcv);
3234 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);3861 const addr_lock = func.register_manager.lockRegAssumeUnused(addr_reg);
3235 defer self.register_manager.unlockReg(addr_lock);3862 defer func.register_manager.unlockReg(addr_lock);
32363863
3237 try self.genCopy(src_ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv);3864 try func.genCopy(src_ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv);
3238 },3865 },
3239 .air_ref => |ptr_ref| try self.store(try self.resolveInst(ptr_ref), src_mcv, ptr_ty, src_ty),3866 .air_ref => |ptr_ref| try func.store(try func.resolveInst(ptr_ref), src_mcv, ptr_ty, src_ty),
3240 }3867 }
3241}3868}
32423869
3243fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {3870fn airStructFieldPtr(func: *Func, inst: Air.Inst.Index) !void {
3244 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3871 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
3245 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;3872 const extra = func.air.extraData(Air.StructField, ty_pl.payload).data;
3246 const result = try self.structFieldPtr(inst, extra.struct_operand, extra.field_index);3873 const result = try func.structFieldPtr(inst, extra.struct_operand, extra.field_index);
3247 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });3874 return func.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
3248}3875}
32493876
3250fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {3877fn airStructFieldPtrIndex(func: *Func, inst: Air.Inst.Index, index: u8) !void {
3251 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3878 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3252 const result = try self.structFieldPtr(inst, ty_op.operand, index);3879 const result = try func.structFieldPtr(inst, ty_op.operand, index);
3253 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3880 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3254}3881}
32553882
3256fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {3883fn structFieldPtr(func: *Func, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
3257 const zcu = self.bin_file.comp.module.?;3884 const zcu = func.bin_file.comp.module.?;
3258 const ptr_field_ty = self.typeOfIndex(inst);3885 const ptr_field_ty = func.typeOfIndex(inst);
3259 const ptr_container_ty = self.typeOf(operand);3886 const ptr_container_ty = func.typeOf(operand);
3260 const ptr_container_ty_info = ptr_container_ty.ptrInfo(zcu);3887 const ptr_container_ty_info = ptr_container_ty.ptrInfo(zcu);
3261 const container_ty = ptr_container_ty.childType(zcu);3888 const container_ty = ptr_container_ty.childType(zcu);
32623889
...@@ -3269,27 +3896,27 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -3269,27 +3896,27 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
3269 else3896 else
3270 @intCast(container_ty.structFieldOffset(index, zcu));3897 @intCast(container_ty.structFieldOffset(index, zcu));
32713898
3272 const src_mcv = try self.resolveInst(operand);3899 const src_mcv = try func.resolveInst(operand);
3273 const dst_mcv = if (switch (src_mcv) {3900 const dst_mcv = if (switch (src_mcv) {
3274 .immediate, .lea_frame => true,3901 .immediate, .lea_frame => true,
3275 .register, .register_offset => self.reuseOperand(inst, operand, 0, src_mcv),3902 .register, .register_offset => func.reuseOperand(inst, operand, 0, src_mcv),
3276 else => false,3903 else => false,
3277 }) src_mcv else try self.copyToNewRegister(inst, src_mcv);3904 }) src_mcv else try func.copyToNewRegister(inst, src_mcv);
3278 return dst_mcv.offset(field_offset);3905 return dst_mcv.offset(field_offset);
3279}3906}
32803907
3281fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {3908fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
3282 const mod = self.bin_file.comp.module.?;3909 const mod = func.bin_file.comp.module.?;
32833910
3284 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3911 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
3285 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;3912 const extra = func.air.extraData(Air.StructField, ty_pl.payload).data;
3286 const operand = extra.struct_operand;3913 const operand = extra.struct_operand;
3287 const index = extra.field_index;3914 const index = extra.field_index;
32883915
3289 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3916 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3290 const zcu = self.bin_file.comp.module.?;3917 const zcu = func.bin_file.comp.module.?;
3291 const src_mcv = try self.resolveInst(operand);3918 const src_mcv = try func.resolveInst(operand);
3292 const struct_ty = self.typeOf(operand);3919 const struct_ty = func.typeOf(operand);
3293 const field_ty = struct_ty.structFieldType(index, zcu);3920 const field_ty = struct_ty.structFieldType(index, zcu);
3294 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none;3921 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none;
32953922
...@@ -3304,33 +3931,31 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3304,33 +3931,31 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3304 switch (src_mcv) {3931 switch (src_mcv) {
3305 .dead, .unreach => unreachable,3932 .dead, .unreach => unreachable,
3306 .register => |src_reg| {3933 .register => |src_reg| {
3307 const src_reg_lock = self.register_manager.lockRegAssumeUnused(src_reg);3934 const src_reg_lock = func.register_manager.lockRegAssumeUnused(src_reg);
3308 defer self.register_manager.unlockReg(src_reg_lock);3935 defer func.register_manager.unlockReg(src_reg_lock);
33093936
3310 const dst_reg = if (field_off == 0)3937 const dst_reg = if (field_off == 0)
3311 (try self.copyToNewRegister(inst, src_mcv)).register3938 (try func.copyToNewRegister(inst, src_mcv)).register
3312 else3939 else
3313 try self.copyToTmpRegister(Type.usize, .{ .register = src_reg });3940 try func.copyToTmpRegister(Type.usize, .{ .register = src_reg });
33143941
3315 const dst_mcv: MCValue = .{ .register = dst_reg };3942 const dst_mcv: MCValue = .{ .register = dst_reg };
3316 const dst_lock = self.register_manager.lockReg(dst_reg);3943 const dst_lock = func.register_manager.lockReg(dst_reg);
3317 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);3944 defer if (dst_lock) |lock| func.register_manager.unlockReg(lock);
33183945
3319 if (field_off > 0) {3946 if (field_off > 0) {
3320 _ = try self.addInst(.{3947 _ = try func.addInst(.{
3321 .tag = .srli,3948 .tag = .srli,
3322 .ops = .rri,3949 .ops = .rri,
3323 .data = .{ .i_type = .{3950 .data = .{ .i_type = .{
3324 .imm12 = Immediate.s(@intCast(field_off)),3951 .imm12 = Immediate.u(@intCast(field_off)),
3325 .rd = dst_reg,3952 .rd = dst_reg,
3326 .rs1 = dst_reg,3953 .rs1 = dst_reg,
3327 } },3954 } },
3328 });3955 });
3329
3330 return self.fail("TODO: airStructFieldVal register with field_off > 0", .{});
3331 }3956 }
33323957
3333 break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv);3958 break :result if (field_off == 0) dst_mcv else try func.copyToNewRegister(inst, dst_mcv);
3334 },3959 },
3335 .load_frame => {3960 .load_frame => {
3336 const field_abi_size: u32 = @intCast(field_ty.abiSize(mod));3961 const field_abi_size: u32 = @intCast(field_ty.abiSize(mod));
...@@ -3345,57 +3970,57 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3345,57 +3970,57 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3345 @intCast(field_bit_size),3970 @intCast(field_bit_size),
3346 );3971 );
33473972
3348 const dst_reg, const dst_lock = try self.allocReg();3973 const dst_reg, const dst_lock = try func.allocReg(.int);
3349 const dst_mcv = MCValue{ .register = dst_reg };3974 const dst_mcv = MCValue{ .register = dst_reg };
3350 defer self.register_manager.unlockReg(dst_lock);3975 defer func.register_manager.unlockReg(dst_lock);
33513976
3352 try self.genCopy(int_ty, dst_mcv, off_mcv);3977 try func.genCopy(int_ty, dst_mcv, off_mcv);
3353 break :result try self.copyToNewRegister(inst, dst_mcv);3978 break :result try func.copyToNewRegister(inst, dst_mcv);
3354 }3979 }
33553980
3356 const container_abi_size: u32 = @intCast(struct_ty.abiSize(mod));3981 const container_abi_size: u32 = @intCast(struct_ty.abiSize(mod));
3357 const dst_mcv = if (field_byte_off + field_abi_size <= container_abi_size and3982 const dst_mcv = if (field_byte_off + field_abi_size <= container_abi_size and
3358 self.reuseOperand(inst, operand, 0, src_mcv))3983 func.reuseOperand(inst, operand, 0, src_mcv))
3359 off_mcv3984 off_mcv
3360 else dst: {3985 else dst: {
3361 const dst_mcv = try self.allocRegOrMem(inst, true);3986 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
3362 try self.genCopy(field_ty, dst_mcv, off_mcv);3987 try func.genCopy(field_ty, dst_mcv, off_mcv);
3363 break :dst dst_mcv;3988 break :dst dst_mcv;
3364 };3989 };
3365 if (field_abi_size * 8 > field_bit_size and dst_mcv.isMemory()) {3990 if (field_abi_size * 8 > field_bit_size and dst_mcv.isMemory()) {
3366 const tmp_reg, const tmp_lock = try self.allocReg();3991 const tmp_reg, const tmp_lock = try func.allocReg(.int);
3367 defer self.register_manager.unlockReg(tmp_lock);3992 defer func.register_manager.unlockReg(tmp_lock);
33683993
3369 const hi_mcv =3994 const hi_mcv =
3370 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();3995 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();
3371 try self.genSetReg(Type.usize, tmp_reg, hi_mcv);3996 try func.genSetReg(Type.usize, tmp_reg, hi_mcv);
3372 try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });3997 try func.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });
3373 }3998 }
3374 break :result dst_mcv;3999 break :result dst_mcv;
3375 }4000 }
33764001
3377 return self.fail("TODO: airStructFieldVal load_frame field_off non multiple of 8", .{});4002 return func.fail("TODO: airStructFieldVal load_frame field_off non multiple of 8", .{});
3378 },4003 },
3379 else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}),4004 else => return func.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}),
3380 }4005 }
3381 };4006 };
33824007
3383 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });4008 return func.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
3384}4009}
33854010
3386fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {4011fn airFieldParentPtr(func: *Func, inst: Air.Inst.Index) !void {
3387 _ = inst;4012 _ = inst;
3388 return self.fail("TODO implement codegen airFieldParentPtr", .{});4013 return func.fail("TODO implement codegen airFieldParentPtr", .{});
3389}4014}
33904015
3391fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {4016fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void {
3392 const zcu = self.bin_file.comp.module.?;4017 const zcu = func.bin_file.comp.module.?;
3393 const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;4018 const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
3394 const ty = arg.ty.toType();4019 const ty = arg.ty.toType();
3395 const owner_decl = zcu.funcOwnerDeclIndex(self.func_index);4020 const owner_decl = zcu.funcOwnerDeclIndex(func.func_index);
3396 const name = zcu.getParamName(self.func_index, arg.src_index);4021 const name = zcu.getParamName(func.func_index, arg.src_index);
33974022
3398 switch (self.debug_output) {4023 switch (func.debug_output) {
3399 .dwarf => |dw| switch (mcv) {4024 .dwarf => |dw| switch (mcv) {
3400 .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{4025 .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{
3401 .register = reg.dwarfLocOp(),4026 .register = reg.dwarfLocOp(),
...@@ -3408,119 +4033,100 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {...@@ -3408,119 +4033,100 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
3408 }4033 }
3409}4034}
34104035
3411fn airArg(self: *Self, inst: Air.Inst.Index) !void {4036fn airArg(func: *Func, inst: Air.Inst.Index) !void {
3412 const zcu = self.bin_file.comp.module.?;4037 var arg_index = func.arg_index;
3413 var arg_index = self.arg_index;
34144038
3415 // we skip over args that have no bits4039 // we skip over args that have no bits
3416 while (self.args[arg_index] == .none) arg_index += 1;4040 while (func.args[arg_index] == .none) arg_index += 1;
3417 self.arg_index = arg_index + 1;4041 func.arg_index = arg_index + 1;
34184042
3419 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4043 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3420 const src_mcv = self.args[arg_index];4044 const src_mcv = func.args[arg_index];
4045 const arg_ty = func.typeOfIndex(inst);
34214046
3422 const arg_ty = self.typeOfIndex(inst);4047 const dst_mcv = try func.allocRegOrMem(arg_ty, inst, false);
34234048
3424 const dst_mcv = switch (src_mcv) {4049 log.debug("airArg {} -> {}", .{ src_mcv, dst_mcv });
3425 .register => dst: {
3426 const frame = try self.allocFrameIndex(FrameAlloc.init(.{
3427 .size = Type.usize.abiSize(zcu),
3428 .alignment = Type.usize.abiAlignment(zcu),
3429 }));
3430 const dst_mcv: MCValue = .{ .load_frame = .{ .index = frame } };
3431 try self.genCopy(Type.usize, dst_mcv, src_mcv);
3432 break :dst dst_mcv;
3433 },
3434 .register_pair => dst: {
3435 const frame = try self.allocFrameIndex(FrameAlloc.init(.{
3436 .size = Type.usize.abiSize(zcu) * 2,
3437 .alignment = Type.usize.abiAlignment(zcu),
3438 }));
3439 const dst_mcv: MCValue = .{ .load_frame = .{ .index = frame } };
3440 try self.genCopy(arg_ty, dst_mcv, src_mcv);
3441 break :dst dst_mcv;
3442 },
3443 .load_frame => src_mcv,
3444 else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}),
3445 };
34464050
3447 try self.genArgDbgInfo(inst, src_mcv);4051 try func.genCopy(arg_ty, dst_mcv, src_mcv);
4052
4053 try func.genArgDbgInfo(inst, src_mcv);
3448 break :result dst_mcv;4054 break :result dst_mcv;
3449 };4055 };
34504056
3451 return self.finishAir(inst, result, .{ .none, .none, .none });4057 return func.finishAir(inst, result, .{ .none, .none, .none });
3452}4058}
34534059
3454fn airTrap(self: *Self) !void {4060fn airTrap(func: *Func) !void {
3455 _ = try self.addInst(.{4061 _ = try func.addInst(.{
3456 .tag = .unimp,4062 .tag = .unimp,
3457 .ops = .none,4063 .ops = .none,
3458 .data = undefined,4064 .data = undefined,
3459 });4065 });
3460 return self.finishAirBookkeeping();4066 return func.finishAirBookkeeping();
3461}4067}
34624068
3463fn airBreakpoint(self: *Self) !void {4069fn airBreakpoint(func: *Func) !void {
3464 _ = try self.addInst(.{4070 _ = try func.addInst(.{
3465 .tag = .ebreak,4071 .tag = .ebreak,
3466 .ops = .none,4072 .ops = .none,
3467 .data = undefined,4073 .data = undefined,
3468 });4074 });
3469 return self.finishAirBookkeeping();4075 return func.finishAirBookkeeping();
3470}4076}
34714077
3472fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void {4078fn airRetAddr(func: *Func, inst: Air.Inst.Index) !void {
3473 const dst_mcv = try self.allocRegOrMem(inst, true);4079 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
3474 try self.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } });4080 try func.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } });
3475 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });4081 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
3476}4082}
34774083
3478fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {4084fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void {
3479 const dst_mcv = try self.allocRegOrMem(inst, true);4085 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
3480 try self.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } });4086 try func.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } });
3481 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });4087 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
3482}4088}
34834089
3484fn airFence(self: *Self) !void {4090fn airFence(func: *Func) !void {
3485 return self.fail("TODO implement fence() for {}", .{self.target.cpu.arch});4091 return func.fail("TODO implement fence() for {}", .{func.target.cpu.arch});
3486 //return self.finishAirBookkeeping();4092 //return func.finishAirBookkeeping();
3487}4093}
34884094
3489fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {4095fn airCall(func: *Func, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {
3490 if (modifier == .always_tail) return self.fail("TODO implement tail calls for riscv64", .{});4096 if (modifier == .always_tail) return func.fail("TODO implement tail calls for riscv64", .{});
3491 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4097 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
3492 const callee = pl_op.operand;4098 const callee = pl_op.operand;
3493 const extra = self.air.extraData(Air.Call, pl_op.payload);4099 const extra = func.air.extraData(Air.Call, pl_op.payload);
3494 const arg_refs: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]);4100 const arg_refs: []const Air.Inst.Ref = @ptrCast(func.air.extra[extra.end..][0..extra.data.args_len]);
34954101
3496 const expected_num_args = 8;4102 const expected_num_args = 8;
3497 const ExpectedContents = extern struct {4103 const ExpectedContents = extern struct {
3498 vals: [expected_num_args][@sizeOf(MCValue)]u8 align(@alignOf(MCValue)),4104 vals: [expected_num_args][@sizeOf(MCValue)]u8 align(@alignOf(MCValue)),
3499 };4105 };
3500 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =4106 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
3501 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);4107 std.heap.stackFallback(@sizeOf(ExpectedContents), func.gpa);
3502 const allocator = stack.get();4108 const allocator = stack.get();
35034109
3504 const arg_tys = try allocator.alloc(Type, arg_refs.len);4110 const arg_tys = try allocator.alloc(Type, arg_refs.len);
3505 defer allocator.free(arg_tys);4111 defer allocator.free(arg_tys);
3506 for (arg_tys, arg_refs) |*arg_ty, arg_ref| arg_ty.* = self.typeOf(arg_ref);4112 for (arg_tys, arg_refs) |*arg_ty, arg_ref| arg_ty.* = func.typeOf(arg_ref);
35074113
3508 const arg_vals = try allocator.alloc(MCValue, arg_refs.len);4114 const arg_vals = try allocator.alloc(MCValue, arg_refs.len);
3509 defer allocator.free(arg_vals);4115 defer allocator.free(arg_vals);
3510 for (arg_vals, arg_refs) |*arg_val, arg_ref| arg_val.* = .{ .air_ref = arg_ref };4116 for (arg_vals, arg_refs) |*arg_val, arg_ref| arg_val.* = .{ .air_ref = arg_ref };
35114117
3512 const call_ret = try self.genCall(.{ .air = callee }, arg_tys, arg_vals);4118 const call_ret = try func.genCall(.{ .air = callee }, arg_tys, arg_vals);
35134119
3514 var bt = self.liveness.iterateBigTomb(inst);4120 var bt = func.liveness.iterateBigTomb(inst);
3515 try self.feed(&bt, pl_op.operand);4121 try func.feed(&bt, pl_op.operand);
3516 for (arg_refs) |arg_ref| try self.feed(&bt, arg_ref);4122 for (arg_refs) |arg_ref| try func.feed(&bt, arg_ref);
35174123
3518 const result = if (self.liveness.isUnused(inst)) .unreach else call_ret;4124 const result = if (func.liveness.isUnused(inst)) .unreach else call_ret;
3519 return self.finishAirResult(inst, result);4125 return func.finishAirResult(inst, result);
3520}4126}
35214127
3522fn genCall(4128fn genCall(
3523 self: *Self,4129 func: *Func,
3524 info: union(enum) {4130 info: union(enum) {
3525 air: Air.Inst.Ref,4131 air: Air.Inst.Ref,
3526 lib: struct {4132 lib: struct {
...@@ -3533,11 +4139,11 @@ fn genCall(...@@ -3533,11 +4139,11 @@ fn genCall(
3533 arg_tys: []const Type,4139 arg_tys: []const Type,
3534 args: []const MCValue,4140 args: []const MCValue,
3535) !MCValue {4141) !MCValue {
3536 const zcu = self.bin_file.comp.module.?;4142 const zcu = func.bin_file.comp.module.?;
35374143
3538 const fn_ty = switch (info) {4144 const fn_ty = switch (info) {
3539 .air => |callee| fn_info: {4145 .air => |callee| fn_info: {
3540 const callee_ty = self.typeOf(callee);4146 const callee_ty = func.typeOf(callee);
3541 break :fn_info switch (callee_ty.zigTypeTag(zcu)) {4147 break :fn_info switch (callee_ty.zigTypeTag(zcu)) {
3542 .Fn => callee_ty,4148 .Fn => callee_ty,
3543 .Pointer => callee_ty.childType(zcu),4149 .Pointer => callee_ty.childType(zcu),
...@@ -3552,8 +4158,15 @@ fn genCall(...@@ -3552,8 +4158,15 @@ fn genCall(
3552 };4158 };
35534159
3554 const fn_info = zcu.typeToFunc(fn_ty).?;4160 const fn_info = zcu.typeToFunc(fn_ty).?;
3555 var call_info = try self.resolveCallingConventionValues(fn_info);4161
3556 defer call_info.deinit(self);4162 const allocator = func.gpa;
4163
4164 const var_args = try allocator.alloc(Type, args.len - fn_info.param_types.len);
4165 defer allocator.free(var_args);
4166 for (var_args, arg_tys[fn_info.param_types.len..]) |*var_arg, arg_ty| var_arg.* = arg_ty;
4167
4168 var call_info = try func.resolveCallingConventionValues(fn_info, var_args);
4169 defer call_info.deinit(func);
35574170
3558 // We need a properly aligned and sized call frame to be able to call this function.4171 // We need a properly aligned and sized call frame to be able to call this function.
3559 {4172 {
...@@ -3561,7 +4174,7 @@ fn genCall(...@@ -3561,7 +4174,7 @@ fn genCall(
3561 .size = call_info.stack_byte_count,4174 .size = call_info.stack_byte_count,
3562 .alignment = call_info.stack_align,4175 .alignment = call_info.stack_align,
3563 });4176 });
3564 const frame_allocs_slice = self.frame_allocs.slice();4177 const frame_allocs_slice = func.frame_allocs.slice();
3565 const stack_frame_size =4178 const stack_frame_size =
3566 &frame_allocs_slice.items(.abi_size)[@intFromEnum(FrameIndex.call_frame)];4179 &frame_allocs_slice.items(.abi_size)[@intFromEnum(FrameIndex.call_frame)];
3567 stack_frame_size.* = @max(stack_frame_size.*, needed_call_frame.abi_size);4180 stack_frame_size.* = @max(stack_frame_size.*, needed_call_frame.abi_size);
...@@ -3570,13 +4183,75 @@ fn genCall(...@@ -3570,13 +4183,75 @@ fn genCall(
3570 stack_frame_align.* = stack_frame_align.max(needed_call_frame.abi_align);4183 stack_frame_align.* = stack_frame_align.max(needed_call_frame.abi_align);
3571 }4184 }
35724185
3573 for (call_info.args, 0..) |mc_arg, arg_i| try self.genCopy(arg_tys[arg_i], mc_arg, args[arg_i]);4186 var reg_locks = std.ArrayList(?RegisterLock).init(allocator);
4187 defer reg_locks.deinit();
4188 try reg_locks.ensureTotalCapacity(8);
4189 defer for (reg_locks.items) |reg_lock| if (reg_lock) |lock| func.register_manager.unlockReg(lock);
4190
4191 const frame_indices = try allocator.alloc(FrameIndex, args.len);
4192 defer allocator.free(frame_indices);
4193
4194 switch (call_info.return_value.long) {
4195 .none, .unreach => {},
4196 .indirect => |reg_off| try func.register_manager.getReg(reg_off.reg, null),
4197 else => unreachable,
4198 }
4199 for (call_info.args, args, arg_tys, frame_indices) |dst_arg, src_arg, arg_ty, *frame_index| {
4200 switch (dst_arg) {
4201 .none => {},
4202 .register => |reg| {
4203 try func.register_manager.getReg(reg, null);
4204 try reg_locks.append(func.register_manager.lockReg(reg));
4205 },
4206 .register_pair => |regs| {
4207 for (regs) |reg| try func.register_manager.getReg(reg, null);
4208 try reg_locks.appendSlice(&func.register_manager.lockRegs(2, regs));
4209 },
4210 .indirect => |reg_off| {
4211 frame_index.* = try func.allocFrameIndex(FrameAlloc.initType(arg_ty, zcu));
4212 try func.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg);
4213 try func.register_manager.getReg(reg_off.reg, null);
4214 try reg_locks.append(func.register_manager.lockReg(reg_off.reg));
4215 },
4216 else => return func.fail("TODO: genCall set arg {s}", .{@tagName(dst_arg)}),
4217 }
4218 }
4219
4220 switch (call_info.return_value.long) {
4221 .none, .unreach => {},
4222 .indirect => |reg_off| {
4223 const ret_ty = Type.fromInterned(fn_info.return_type);
4224 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(ret_ty, zcu));
4225 try func.genSetReg(Type.usize, reg_off.reg, .{
4226 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
4227 });
4228 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
4229 try reg_locks.append(func.register_manager.lockReg(reg_off.reg));
4230 },
4231 else => unreachable,
4232 }
4233
4234 for (call_info.args, arg_tys, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| {
4235 switch (dst_arg) {
4236 .none, .load_frame => {},
4237 .register_pair => try func.genCopy(arg_ty, dst_arg, src_arg),
4238 .register => |dst_reg| try func.genSetReg(
4239 arg_ty,
4240 dst_reg,
4241 src_arg,
4242 ),
4243 .indirect => |reg_off| try func.genSetReg(Type.usize, reg_off.reg, .{
4244 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
4245 }),
4246 else => return func.fail("TODO: genCall actual set {s}", .{@tagName(dst_arg)}),
4247 }
4248 }
35744249
3575 // Due to incremental compilation, how function calls are generated depends4250 // Due to incremental compilation, how function calls are generated depends
3576 // on linking.4251 // on linking.
3577 switch (info) {4252 switch (info) {
3578 .air => |callee| {4253 .air => |callee| {
3579 if (try self.air.value(callee, zcu)) |func_value| {4254 if (try func.air.value(callee, zcu)) |func_value| {
3580 const func_key = zcu.intern_pool.indexToKey(func_value.ip_index);4255 const func_key = zcu.intern_pool.indexToKey(func_value.ip_index);
3581 switch (switch (func_key) {4256 switch (switch (func_key) {
3582 else => func_key,4257 else => func_key,
...@@ -3585,35 +4260,53 @@ fn genCall(...@@ -3585,35 +4260,53 @@ fn genCall(
3585 else => func_key,4260 else => func_key,
3586 } else func_key,4261 } else func_key,
3587 }) {4262 }) {
3588 .func => |func| {4263 .func => |func_val| {
3589 if (self.bin_file.cast(link.File.Elf)) |elf_file| {4264 if (func.bin_file.cast(link.File.Elf)) |elf_file| {
3590 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);4265 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func_val.owner_decl);
3591 const sym = elf_file.symbol(sym_index);4266 const sym = elf_file.symbol(sym_index);
35924267
3593 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);4268 if (func.mod.pic) {
3594 const got_addr = sym.zigGotAddress(elf_file);4269 return func.fail("TODO: genCall pic", .{});
3595 try self.genSetReg(Type.usize, .ra, .{ .memory = @intCast(got_addr) });4270 } else {
35964271 try func.genSetReg(Type.usize, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } });
3597 _ = try self.addInst(.{4272 _ = try func.addInst(.{
3598 .tag = .jalr,4273 .tag = .jalr,
3599 .ops = .rri,4274 .ops = .rri,
3600 .data = .{ .i_type = .{4275 .data = .{ .i_type = .{
3601 .rd = .ra,4276 .rd = .ra,
3602 .rs1 = .ra,4277 .rs1 = .ra,
3603 .imm12 = Immediate.s(0),4278 .imm12 = Immediate.s(0),
4279 } },
4280 });
4281 }
4282 } else unreachable; // not a valid riscv64 format
4283 },
4284 .extern_func => |extern_func| {
4285 const owner_decl = zcu.declPtr(extern_func.decl);
4286 const lib_name = extern_func.lib_name.toSlice(&zcu.intern_pool);
4287 const decl_name = owner_decl.name.toSlice(&zcu.intern_pool);
4288 const atom_index = try func.symbolIndex();
4289
4290 if (func.bin_file.cast(link.File.Elf)) |elf_file| {
4291 _ = try func.addInst(.{
4292 .tag = .pseudo,
4293 .ops = .pseudo_extern_fn_reloc,
4294 .data = .{ .reloc = .{
4295 .atom_index = atom_index,
4296 .sym_index = try elf_file.getGlobalSymbol(decl_name, lib_name),
3604 } },4297 } },
3605 });4298 });
3606 } else unreachable;4299 } else unreachable; // not a valid riscv64 format
3607 },4300 },
3608 .extern_func => return self.fail("TODO: extern func calls", .{}),4301 else => return func.fail("TODO implement calling bitcasted functions", .{}),
3609 else => return self.fail("TODO implement calling bitcasted functions", .{}),
3610 }4302 }
3611 } else {4303 } else {
3612 assert(self.typeOf(callee).zigTypeTag(zcu) == .Pointer);4304 assert(func.typeOf(callee).zigTypeTag(zcu) == .Pointer);
3613 const addr_reg, const addr_lock = try self.allocReg();4305 const addr_reg, const addr_lock = try func.allocReg(.int);
3614 defer self.register_manager.unlockReg(addr_lock);4306 defer func.register_manager.unlockReg(addr_lock);
3615 try self.genSetReg(Type.usize, addr_reg, .{ .air_ref = callee });4307 try func.genSetReg(Type.usize, addr_reg, .{ .air_ref = callee });
3616 _ = try self.addInst(.{4308
4309 _ = try func.addInst(.{
3617 .tag = .jalr,4310 .tag = .jalr,
3618 .ops = .rri,4311 .ops = .rri,
3619 .data = .{ .i_type = .{4312 .data = .{ .i_type = .{
...@@ -3624,15 +4317,15 @@ fn genCall(...@@ -3624,15 +4317,15 @@ fn genCall(
3624 });4317 });
3625 }4318 }
3626 },4319 },
3627 .lib => return self.fail("TODO: lib func calls", .{}),4320 .lib => return func.fail("TODO: lib func calls", .{}),
3628 }4321 }
36294322
3630 return call_info.return_value.short;4323 return call_info.return_value.short;
3631}4324}
36324325
3633fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void {4326fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
3634 const zcu = self.bin_file.comp.module.?;4327 const zcu = func.bin_file.comp.module.?;
3635 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4328 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
36364329
3637 if (safety) {4330 if (safety) {
3638 // safe4331 // safe
...@@ -3640,123 +4333,138 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -3640,123 +4333,138 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
3640 // not safe4333 // not safe
3641 }4334 }
36424335
3643 const ret_ty = self.fn_type.fnReturnType(zcu);4336 const ret_ty = func.fn_type.fnReturnType(zcu);
3644 switch (self.ret_mcv.short) {4337 switch (func.ret_mcv.short) {
3645 .none => {},4338 .none => {},
3646 .register,4339 .register,
3647 .register_pair,4340 .register_pair,
3648 => try self.genCopy(ret_ty, self.ret_mcv.short, .{ .air_ref = un_op }),4341 => try func.genCopy(ret_ty, func.ret_mcv.short, .{ .air_ref = un_op }),
3649 .indirect => |reg_off| {4342 .indirect => |reg_off| {
3650 try self.register_manager.getReg(reg_off.reg, null);4343 try func.register_manager.getReg(reg_off.reg, null);
3651 const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg);4344 const lock = func.register_manager.lockRegAssumeUnused(reg_off.reg);
3652 defer self.register_manager.unlockReg(lock);4345 defer func.register_manager.unlockReg(lock);
36534346
3654 try self.genSetReg(Type.usize, reg_off.reg, self.ret_mcv.long);4347 try func.genSetReg(Type.usize, reg_off.reg, func.ret_mcv.long);
3655 try self.genCopy(4348 try func.genSetMem(
4349 .{ .reg = reg_off.reg },
4350 reg_off.off,
3656 ret_ty,4351 ret_ty,
3657 .{ .register_offset = reg_off },
3658 .{ .air_ref = un_op },4352 .{ .air_ref = un_op },
3659 );4353 );
3660 },4354 },
3661 else => unreachable,4355 else => unreachable,
3662 }4356 }
36634357
3664 self.ret_mcv.liveOut(self, inst);4358 func.ret_mcv.liveOut(func, inst);
3665 try self.finishAir(inst, .unreach, .{ un_op, .none, .none });4359 try func.finishAir(inst, .unreach, .{ un_op, .none, .none });
36664360
3667 // Just add space for an instruction, reloced this later4361 // Just add space for an instruction, reloced this later
3668 const index = try self.addInst(.{4362 const index = try func.addInst(.{
3669 .tag = .pseudo,4363 .tag = .pseudo,
3670 .ops = .pseudo_j,4364 .ops = .pseudo_j,
3671 .data = .{ .inst = undefined },4365 .data = .{ .inst = undefined },
3672 });4366 });
36734367
3674 try self.exitlude_jump_relocs.append(self.gpa, index);4368 try func.exitlude_jump_relocs.append(func.gpa, index);
3675}4369}
36764370
3677fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {4371fn airRetLoad(func: *Func, inst: Air.Inst.Index) !void {
3678 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4372 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3679 const ptr = try self.resolveInst(un_op);4373 const ptr = try func.resolveInst(un_op);
36804374
3681 const ptr_ty = self.typeOf(un_op);4375 const ptr_ty = func.typeOf(un_op);
3682 switch (self.ret_mcv.short) {4376 switch (func.ret_mcv.short) {
3683 .none => {},4377 .none => {},
3684 .register, .register_pair => try self.load(self.ret_mcv.short, ptr, ptr_ty),4378 .register, .register_pair => try func.load(func.ret_mcv.short, ptr, ptr_ty),
3685 .indirect => |reg_off| try self.genSetReg(ptr_ty, reg_off.reg, ptr),4379 .indirect => |reg_off| try func.genSetReg(ptr_ty, reg_off.reg, ptr),
3686 else => unreachable,4380 else => unreachable,
3687 }4381 }
3688 self.ret_mcv.liveOut(self, inst);4382 func.ret_mcv.liveOut(func, inst);
3689 try self.finishAir(inst, .unreach, .{ un_op, .none, .none });4383 try func.finishAir(inst, .unreach, .{ un_op, .none, .none });
36904384
3691 // Just add space for an instruction, reloced this later4385 // Just add space for an instruction, reloced this later
3692 const index = try self.addInst(.{4386 const index = try func.addInst(.{
3693 .tag = .pseudo,4387 .tag = .pseudo,
3694 .ops = .pseudo_j,4388 .ops = .pseudo_j,
3695 .data = .{ .inst = undefined },4389 .data = .{ .inst = undefined },
3696 });4390 });
36974391
3698 try self.exitlude_jump_relocs.append(self.gpa, index);4392 try func.exitlude_jump_relocs.append(func.gpa, index);
3699}4393}
37004394
3701fn airCmp(self: *Self, inst: Air.Inst.Index) !void {4395fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
3702 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];4396 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3703 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;4397 const zcu = func.bin_file.comp.module.?;
3704 const zcu = self.bin_file.comp.module.?;4398
37054399 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3706 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4400 const lhs_ty = func.typeOf(bin_op.lhs);
3707 const lhs = try self.resolveInst(bin_op.lhs);4401
3708 const rhs = try self.resolveInst(bin_op.rhs);4402 switch (lhs_ty.zigTypeTag(zcu)) {
3709 const lhs_ty = self.typeOf(bin_op.lhs);4403 .Int,
37104404 .Enum,
3711 const int_ty = switch (lhs_ty.zigTypeTag(zcu)) {4405 .Bool,
3712 .Vector => unreachable, // Handled by cmp_vector.4406 .Pointer,
3713 .Enum => lhs_ty.intTagType(zcu),4407 .ErrorSet,
3714 .Int => lhs_ty,4408 .Optional,
3715 .Bool => Type.u1,4409 => {
3716 .Pointer => Type.usize,4410 const int_ty = switch (lhs_ty.zigTypeTag(zcu)) {
3717 .ErrorSet => Type.u16,4411 .Enum => lhs_ty.intTagType(zcu),
3718 .Optional => blk: {4412 .Int => lhs_ty,
3719 const payload_ty = lhs_ty.optionalChild(zcu);4413 .Bool => Type.u1,
3720 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {4414 .Pointer => Type.usize,
3721 break :blk Type.u1;4415 .ErrorSet => Type.anyerror,
3722 } else if (lhs_ty.isPtrLikeOptional(zcu)) {4416 .Optional => blk: {
3723 break :blk Type.usize;4417 const payload_ty = lhs_ty.optionalChild(zcu);
4418 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
4419 break :blk Type.u1;
4420 } else if (lhs_ty.isPtrLikeOptional(zcu)) {
4421 break :blk Type.usize;
4422 } else {
4423 return func.fail("TODO riscv cmp non-pointer optionals", .{});
4424 }
4425 },
4426 else => unreachable,
4427 };
4428
4429 const int_info = int_ty.intInfo(zcu);
4430 if (int_info.bits <= 64) {
4431 break :result try func.binOp(inst, tag, bin_op.lhs, bin_op.rhs);
3724 } else {4432 } else {
3725 return self.fail("TODO riscv cmp non-pointer optionals", .{});4433 return func.fail("TODO riscv cmp for ints > 64 bits", .{});
4434 }
4435 },
4436 .Float => {
4437 const float_bits = lhs_ty.floatBits(func.target.*);
4438 const float_reg_size: u32 = if (func.hasFeature(.d)) 64 else 32;
4439 if (float_bits > float_reg_size) {
4440 return func.fail("TODO: airCmp float > 64/32 bits", .{});
3726 }4441 }
4442 break :result try func.binOp(inst, tag, bin_op.lhs, bin_op.rhs);
3727 },4443 },
3728 .Float => return self.fail("TODO riscv cmp floats", .{}),
3729 else => unreachable,4444 else => unreachable,
3730 };
3731
3732 const int_info = int_ty.intInfo(zcu);
3733 if (int_info.bits <= 64) {
3734 break :result try self.binOp(tag, lhs, int_ty, rhs, int_ty);
3735 } else {
3736 return self.fail("TODO riscv cmp for ints > 64 bits", .{});
3737 }4445 }
3738 };4446 };
37394447
3740 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });4448 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3741}4449}
37424450
3743fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {4451fn airCmpVector(func: *Func, inst: Air.Inst.Index) !void {
3744 _ = inst;4452 _ = inst;
3745 return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});4453 return func.fail("TODO implement airCmpVector for {}", .{func.target.cpu.arch});
3746}4454}
37474455
3748fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {4456fn airCmpLtErrorsLen(func: *Func, inst: Air.Inst.Index) !void {
3749 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4457 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3750 const operand = try self.resolveInst(un_op);4458 const operand = try func.resolveInst(un_op);
3751 _ = operand;4459 _ = operand;
3752 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airCmpLtErrorsLen for {}", .{self.target.cpu.arch});4460 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airCmpLtErrorsLen for {}", .{func.target.cpu.arch});
3753 return self.finishAir(inst, result, .{ un_op, .none, .none });4461 return func.finishAir(inst, result, .{ un_op, .none, .none });
3754}4462}
37554463
3756fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {4464fn airDbgStmt(func: *Func, inst: Air.Inst.Index) !void {
3757 const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;4465 const dbg_stmt = func.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
37584466
3759 _ = try self.addInst(.{4467 _ = try func.addInst(.{
3760 .tag = .pseudo,4468 .tag = .pseudo,
3761 .ops = .pseudo_dbg_line_column,4469 .ops = .pseudo_dbg_line_column,
3762 .data = .{ .pseudo_dbg_line_column = .{4470 .data = .{ .pseudo_dbg_line_column = .{
...@@ -3765,44 +4473,44 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -3765,44 +4473,44 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
3765 } },4473 } },
3766 });4474 });
37674475
3768 return self.finishAirBookkeeping();4476 return func.finishAirBookkeeping();
3769}4477}
37704478
3771fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {4479fn airDbgInlineBlock(func: *Func, inst: Air.Inst.Index) !void {
3772 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;4480 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
3773 const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);4481 const extra = func.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
3774 try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));4482 try func.lowerBlock(inst, @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]));
3775}4483}
37764484
3777fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {4485fn airDbgVar(func: *Func, inst: Air.Inst.Index) !void {
3778 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4486 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
3779 const operand = pl_op.operand;4487 const operand = pl_op.operand;
3780 const ty = self.typeOf(operand);4488 const ty = func.typeOf(operand);
3781 const mcv = try self.resolveInst(operand);4489 const mcv = try func.resolveInst(operand);
37824490
3783 const name = self.air.nullTerminatedString(pl_op.payload);4491 const name = func.air.nullTerminatedString(pl_op.payload);
37844492
3785 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];4493 const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];
3786 try self.genVarDbgInfo(tag, ty, mcv, name);4494 try func.genVarDbgInfo(tag, ty, mcv, name);
37874495
3788 return self.finishAir(inst, .unreach, .{ operand, .none, .none });4496 return func.finishAir(inst, .unreach, .{ operand, .none, .none });
3789}4497}
37904498
3791fn genVarDbgInfo(4499fn genVarDbgInfo(
3792 self: Self,4500 func: Func,
3793 tag: Air.Inst.Tag,4501 tag: Air.Inst.Tag,
3794 ty: Type,4502 ty: Type,
3795 mcv: MCValue,4503 mcv: MCValue,
3796 name: [:0]const u8,4504 name: [:0]const u8,
3797) !void {4505) !void {
3798 const zcu = self.bin_file.comp.module.?;4506 const zcu = func.bin_file.comp.module.?;
3799 const is_ptr = switch (tag) {4507 const is_ptr = switch (tag) {
3800 .dbg_var_ptr => true,4508 .dbg_var_ptr => true,
3801 .dbg_var_val => false,4509 .dbg_var_val => false,
3802 else => unreachable,4510 else => unreachable,
3803 };4511 };
38044512
3805 switch (self.debug_output) {4513 switch (func.debug_output) {
3806 .dwarf => |dw| {4514 .dwarf => |dw| {
3807 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {4515 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {
3808 .register => |reg| .{ .register = reg.dwarfLocOp() },4516 .register => |reg| .{ .register = reg.dwarfLocOp() },
...@@ -3819,47 +4527,47 @@ fn genVarDbgInfo(...@@ -3819,47 +4527,47 @@ fn genVarDbgInfo(
3819 break :blk .nop;4527 break :blk .nop;
3820 },4528 },
3821 };4529 };
3822 try dw.genVarDbgInfo(name, ty, zcu.funcOwnerDeclIndex(self.func_index), is_ptr, loc);4530 try dw.genVarDbgInfo(name, ty, zcu.funcOwnerDeclIndex(func.func_index), is_ptr, loc);
3823 },4531 },
3824 .plan9 => {},4532 .plan9 => {},
3825 .none => {},4533 .none => {},
3826 }4534 }
3827}4535}
38284536
3829fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {4537fn airCondBr(func: *Func, inst: Air.Inst.Index) !void {
3830 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4538 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
3831 const cond = try self.resolveInst(pl_op.operand);4539 const cond = try func.resolveInst(pl_op.operand);
3832 const cond_ty = self.typeOf(pl_op.operand);4540 const cond_ty = func.typeOf(pl_op.operand);
3833 const extra = self.air.extraData(Air.CondBr, pl_op.payload);4541 const extra = func.air.extraData(Air.CondBr, pl_op.payload);
3834 const then_body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.then_body_len]);4542 const then_body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end..][0..extra.data.then_body_len]);
3835 const else_body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]);4543 const else_body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]);
3836 const liveness_cond_br = self.liveness.getCondBr(inst);4544 const liveness_cond_br = func.liveness.getCondBr(inst);
38374545
3838 // If the condition dies here in this condbr instruction, process4546 // If the condition dies here in this condbr instruction, process
3839 // that death now instead of later as this has an effect on4547 // that death now instead of later as this has an effect on
3840 // whether it needs to be spilled in the branches4548 // whether it needs to be spilled in the branches
3841 if (self.liveness.operandDies(inst, 0)) {4549 if (func.liveness.operandDies(inst, 0)) {
3842 if (pl_op.operand.toIndex()) |op_inst| try self.processDeath(op_inst);4550 if (pl_op.operand.toIndex()) |op_inst| try func.processDeath(op_inst);
3843 }4551 }
38444552
3845 self.scope_generation += 1;4553 func.scope_generation += 1;
3846 const state = try self.saveState();4554 const state = try func.saveState();
3847 const reloc = try self.condBr(cond_ty, cond);4555 const reloc = try func.condBr(cond_ty, cond);
38484556
3849 for (liveness_cond_br.then_deaths) |death| try self.processDeath(death);4557 for (liveness_cond_br.then_deaths) |death| try func.processDeath(death);
3850 try self.genBody(then_body);4558 try func.genBody(then_body);
3851 try self.restoreState(state, &.{}, .{4559 try func.restoreState(state, &.{}, .{
3852 .emit_instructions = false,4560 .emit_instructions = false,
3853 .update_tracking = true,4561 .update_tracking = true,
3854 .resurrect = true,4562 .resurrect = true,
3855 .close_scope = true,4563 .close_scope = true,
3856 });4564 });
38574565
3858 self.performReloc(reloc);4566 func.performReloc(reloc);
38594567
3860 for (liveness_cond_br.else_deaths) |death| try self.processDeath(death);4568 for (liveness_cond_br.else_deaths) |death| try func.processDeath(death);
3861 try self.genBody(else_body);4569 try func.genBody(else_body);
3862 try self.restoreState(state, &.{}, .{4570 try func.restoreState(state, &.{}, .{
3863 .emit_instructions = false,4571 .emit_instructions = false,
3864 .update_tracking = true,4572 .update_tracking = true,
3865 .resurrect = true,4573 .resurrect = true,
...@@ -3867,13 +4575,13 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3867,13 +4575,13 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
3867 });4575 });
38684576
3869 // We already took care of pl_op.operand earlier, so there's nothing left to do.4577 // We already took care of pl_op.operand earlier, so there's nothing left to do.
3870 self.finishAirBookkeeping();4578 func.finishAirBookkeeping();
3871}4579}
38724580
3873fn condBr(self: *Self, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {4581fn condBr(func: *Func, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {
3874 const cond_reg = try self.copyToTmpRegister(cond_ty, condition);4582 const cond_reg = try func.copyToTmpRegister(cond_ty, condition);
38754583
3876 return try self.addInst(.{4584 return try func.addInst(.{
3877 .tag = .beq,4585 .tag = .beq,
3878 .ops = .rr_inst,4586 .ops = .rr_inst,
3879 .data = .{4587 .data = .{
...@@ -3886,168 +4594,249 @@ fn condBr(self: *Self, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {...@@ -3886,168 +4594,249 @@ fn condBr(self: *Self, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {
3886 });4594 });
3887}4595}
38884596
3889fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {4597fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue {
3890 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4598 const zcu = func.bin_file.comp.module.?;
3891 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4599 const pl_ty = opt_ty.optionalChild(zcu);
3892 const operand = try self.resolveInst(un_op);
3893 break :result try self.isNull(operand);
3894 };
3895 return self.finishAir(inst, result, .{ un_op, .none, .none });
3896}
38974600
3898fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {4601 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(zcu))
3899 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4602 .{ .off = 0, .ty = if (pl_ty.isSlice(zcu)) pl_ty.slicePtrFieldType(zcu) else pl_ty }
3900 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4603 else
3901 const operand_ptr = try self.resolveInst(un_op);4604 .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = Type.bool };
3902 const operand: MCValue = blk: {4605
3903 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {4606 const return_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
3904 // The MCValue that holds the pointer can be re-used as the value.4607 assert(return_mcv == .register); // should not be larger 8 bytes
3905 break :blk operand_ptr;4608 const return_reg = return_mcv.register;
3906 } else {4609
3907 break :blk try self.allocRegOrMem(inst, true);4610 switch (opt_mcv) {
4611 .none,
4612 .unreach,
4613 .dead,
4614 .undef,
4615 .immediate,
4616 .register_pair,
4617 .register_offset,
4618 .lea_frame,
4619 .lea_symbol,
4620 .reserved_frame,
4621 .air_ref,
4622 => return func.fail("TODO: hmm {}", .{opt_mcv}),
4623
4624 .register => |opt_reg| {
4625 if (some_info.off == 0) {
4626 _ = try func.addInst(.{
4627 .tag = .pseudo,
4628 .ops = .pseudo_compare,
4629 .data = .{
4630 .compare = .{
4631 .op = .eq,
4632 .rd = return_reg,
4633 .rs1 = opt_reg,
4634 .rs2 = try func.copyToTmpRegister(
4635 some_info.ty,
4636 .{ .immediate = 0 },
4637 ),
4638 .ty = Type.bool,
4639 },
4640 },
4641 });
4642 return return_mcv;
3908 }4643 }
3909 };4644 assert(some_info.ty.ip_index == .bool_type);
3910 try self.load(operand, operand_ptr, self.typeOf(un_op));4645 const opt_abi_size: u32 = @intCast(opt_ty.abiSize(zcu));
3911 break :result try self.isNull(operand);4646 _ = opt_abi_size;
3912 };4647 return func.fail("TODO: isNull some_info.off != 0 register", .{});
3913 return self.finishAir(inst, result, .{ un_op, .none, .none });4648 },
4649
4650 .load_frame => {
4651 const opt_reg = try func.copyToTmpRegister(
4652 some_info.ty,
4653 opt_mcv.address().offset(some_info.off).deref(),
4654 );
4655 const opt_reg_lock = func.register_manager.lockRegAssumeUnused(opt_reg);
4656 defer func.register_manager.unlockReg(opt_reg_lock);
4657
4658 _ = try func.addInst(.{
4659 .tag = .pseudo,
4660 .ops = .pseudo_compare,
4661 .data = .{
4662 .compare = .{
4663 .op = .eq,
4664 .rd = return_reg,
4665 .rs1 = opt_reg,
4666 .rs2 = try func.copyToTmpRegister(
4667 some_info.ty,
4668 .{ .immediate = 0 },
4669 ),
4670 .ty = Type.bool,
4671 },
4672 },
4673 });
4674 return return_mcv;
4675 },
4676
4677 else => return func.fail("TODO: isNull {}", .{opt_mcv}),
4678 }
4679}
4680
4681fn airIsNull(func: *Func, inst: Air.Inst.Index) !void {
4682 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4683 const operand = try func.resolveInst(un_op);
4684 const ty = func.typeOf(un_op);
4685 const result = try func.isNull(inst, ty, operand);
4686 return func.finishAir(inst, result, .{ un_op, .none, .none });
3914}4687}
39154688
3916fn isNull(self: *Self, operand: MCValue) !MCValue {4689fn airIsNullPtr(func: *Func, inst: Air.Inst.Index) !void {
4690 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4691 const operand = try func.resolveInst(un_op);
3917 _ = operand;4692 _ = operand;
3918 // Here you can specialize this instruction if it makes sense to, otherwise the default4693 const ty = func.typeOf(un_op);
3919 // will call isNonNull and invert the result.4694 _ = ty;
3920 return self.fail("TODO call isNonNull and invert the result", .{});4695
4696 if (true) return func.fail("TODO: airIsNullPtr", .{});
4697
4698 return func.finishAir(inst, .unreach, .{ un_op, .none, .none });
3921}4699}
39224700
3923fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {4701fn airIsNonNull(func: *Func, inst: Air.Inst.Index) !void {
3924 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4702 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3925 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4703 const operand = try func.resolveInst(un_op);
3926 const operand = try self.resolveInst(un_op);4704 const ty = func.typeOf(un_op);
3927 break :result try self.isNonNull(operand);4705 const result = try func.isNull(inst, ty, operand);
3928 };4706 assert(result == .register);
3929 return self.finishAir(inst, result, .{ un_op, .none, .none });4707
4708 _ = try func.addInst(.{
4709 .tag = .pseudo,
4710 .ops = .pseudo_not,
4711 .data = .{
4712 .rr = .{
4713 .rd = result.register,
4714 .rs = result.register,
4715 },
4716 },
4717 });
4718
4719 return func.finishAir(inst, result, .{ un_op, .none, .none });
3930}4720}
39314721
3932fn isNonNull(self: *Self, operand: MCValue) !MCValue {4722fn airIsNonNullPtr(func: *Func, inst: Air.Inst.Index) !void {
4723 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4724 const operand = try func.resolveInst(un_op);
3933 _ = operand;4725 _ = operand;
3934 // Here you can specialize this instruction if it makes sense to, otherwise the default4726 const ty = func.typeOf(un_op);
3935 // will call isNull and invert the result.4727 _ = ty;
3936 return self.fail("TODO call isNull and invert the result", .{});
3937}
39384728
3939fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {4729 if (true) return func.fail("TODO: airIsNonNullPtr", .{});
3940 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4730
3941 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4731 return func.finishAir(inst, .unreach, .{ un_op, .none, .none });
3942 const operand_ptr = try self.resolveInst(un_op);
3943 const operand: MCValue = blk: {
3944 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
3945 // The MCValue that holds the pointer can be re-used as the value.
3946 break :blk operand_ptr;
3947 } else {
3948 break :blk try self.allocRegOrMem(inst, true);
3949 }
3950 };
3951 try self.load(operand, operand_ptr, self.typeOf(un_op));
3952 break :result try self.isNonNull(operand);
3953 };
3954 return self.finishAir(inst, result, .{ un_op, .none, .none });
3955}4732}
39564733
3957fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {4734fn airIsErr(func: *Func, inst: Air.Inst.Index) !void {
3958 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4735 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3959 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4736 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3960 const operand = try self.resolveInst(un_op);4737 const operand = try func.resolveInst(un_op);
3961 const operand_ty = self.typeOf(un_op);4738 const operand_ty = func.typeOf(un_op);
3962 break :result try self.isErr(inst, operand_ty, operand);4739 break :result try func.isErr(inst, operand_ty, operand);
3963 };4740 };
3964 return self.finishAir(inst, result, .{ un_op, .none, .none });4741 return func.finishAir(inst, result, .{ un_op, .none, .none });
3965}4742}
39664743
3967fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {4744fn airIsErrPtr(func: *Func, inst: Air.Inst.Index) !void {
3968 const zcu = self.bin_file.comp.module.?;4745 const zcu = func.bin_file.comp.module.?;
3969 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4746 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3970 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4747 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3971 const operand_ptr = try self.resolveInst(un_op);4748 const operand_ptr = try func.resolveInst(un_op);
3972 const operand: MCValue = blk: {4749 const operand: MCValue = blk: {
3973 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {4750 if (func.reuseOperand(inst, un_op, 0, operand_ptr)) {
3974 // The MCValue that holds the pointer can be re-used as the value.4751 // The MCValue that holds the pointer can be re-used as the value.
3975 break :blk operand_ptr;4752 break :blk operand_ptr;
3976 } else {4753 } else {
3977 break :blk try self.allocRegOrMem(inst, true);4754 break :blk try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
3978 }4755 }
3979 };4756 };
3980 try self.load(operand, operand_ptr, self.typeOf(un_op));4757 try func.load(operand, operand_ptr, func.typeOf(un_op));
3981 const operand_ptr_ty = self.typeOf(un_op);4758 const operand_ptr_ty = func.typeOf(un_op);
3982 const operand_ty = operand_ptr_ty.childType(zcu);4759 const operand_ty = operand_ptr_ty.childType(zcu);
39834760
3984 break :result try self.isErr(inst, operand_ty, operand);4761 break :result try func.isErr(inst, operand_ty, operand);
3985 };4762 };
3986 return self.finishAir(inst, result, .{ un_op, .none, .none });4763 return func.finishAir(inst, result, .{ un_op, .none, .none });
3987}4764}
39884765
3989/// Generates a compare instruction which will indicate if `eu_mcv` is an error.4766/// Generates a compare instruction which will indicate if `eu_mcv` is an error.
3990///4767///
3991/// Result is in the return register.4768/// Result is in the return register.
3992fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue {4769fn isErr(func: *Func, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue {
3993 const zcu = self.bin_file.comp.module.?;4770 _ = maybe_inst;
4771 const zcu = func.bin_file.comp.module.?;
3994 const err_ty = eu_ty.errorUnionSet(zcu);4772 const err_ty = eu_ty.errorUnionSet(zcu);
3995 if (err_ty.errorSetIsEmpty(zcu)) return MCValue{ .immediate = 0 }; // always false4773 if (err_ty.errorSetIsEmpty(zcu)) return MCValue{ .immediate = 0 }; // always false
4774 const err_off: u31 = @intCast(errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
39964775
3997 _ = maybe_inst;4776 const return_reg, const return_lock = try func.allocReg(.int);
39984777 defer func.register_manager.unlockReg(return_lock);
3999 const err_off = errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu);
40004778
4001 switch (eu_mcv) {4779 switch (eu_mcv) {
4002 .register => |reg| {4780 .register => |reg| {
4003 const eu_lock = self.register_manager.lockReg(reg);4781 const eu_lock = func.register_manager.lockReg(reg);
4004 defer if (eu_lock) |lock| self.register_manager.unlockReg(lock);4782 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);
4005
4006 const return_reg = try self.copyToTmpRegister(eu_ty, eu_mcv);
4007 const return_lock = self.register_manager.lockRegAssumeUnused(return_reg);
4008 defer self.register_manager.unlockReg(return_lock);
40094783
4010 var return_mcv: MCValue = .{ .register = return_reg };4784 try func.genCopy(eu_ty, .{ .register = return_reg }, eu_mcv);
40114785
4012 if (err_off > 0) {4786 if (err_off > 0) {
4013 return_mcv = try self.binOp(4787 try func.genBinOp(
4014 .shr,4788 .shr,
4015 return_mcv,4789 .{ .register = return_reg },
4016 eu_ty,4790 eu_ty,
4017 .{ .immediate = @as(u6, @intCast(err_off * 8)) },4791 .{ .immediate = @as(u6, @intCast(err_off * 8)) },
4018 Type.u8,4792 Type.u8,
4793 return_reg,
4019 );4794 );
4020 }4795 }
40214796
4022 return_mcv = try self.binOp(4797 try func.genBinOp(
4023 .cmp_neq,4798 .cmp_neq,
4024 return_mcv,4799 .{ .register = return_reg },
4025 Type.u16,4800 Type.anyerror,
4026 .{ .immediate = 0 },4801 .{ .immediate = 0 },
4027 Type.u16,4802 Type.u8,
4803 return_reg,
4028 );4804 );
4029
4030 return return_mcv;
4031 },4805 },
4032 else => return self.fail("TODO implement isErr for {}", .{eu_mcv}),4806 .load_frame => |frame_addr| {
4807 try func.genBinOp(
4808 .cmp_neq,
4809 .{ .load_frame = .{
4810 .index = frame_addr.index,
4811 .off = frame_addr.off + err_off,
4812 } },
4813 Type.anyerror,
4814 .{ .immediate = 0 },
4815 Type.anyerror,
4816 return_reg,
4817 );
4818 },
4819 else => return func.fail("TODO implement isErr for {}", .{eu_mcv}),
4033 }4820 }
4821
4822 return .{ .register = return_reg };
4034}4823}
40354824
4036fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {4825fn airIsNonErr(func: *Func, inst: Air.Inst.Index) !void {
4037 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4826 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4038 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4827 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4039 const operand = try self.resolveInst(un_op);4828 const operand = try func.resolveInst(un_op);
4040 const ty = self.typeOf(un_op);4829 const ty = func.typeOf(un_op);
4041 break :result try self.isNonErr(inst, ty, operand);4830 break :result try func.isNonErr(inst, ty, operand);
4042 };4831 };
4043 return self.finishAir(inst, result, .{ un_op, .none, .none });4832 return func.finishAir(inst, result, .{ un_op, .none, .none });
4044}4833}
40454834
4046fn isNonErr(self: *Self, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue {4835fn isNonErr(func: *Func, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue {
4047 const is_err_res = try self.isErr(inst, eu_ty, eu_mcv);4836 const is_err_res = try func.isErr(inst, eu_ty, eu_mcv);
4048 switch (is_err_res) {4837 switch (is_err_res) {
4049 .register => |reg| {4838 .register => |reg| {
4050 _ = try self.addInst(.{4839 _ = try func.addInst(.{
4051 .tag = .pseudo,4840 .tag = .pseudo,
4052 .ops = .pseudo_not,4841 .ops = .pseudo_not,
4053 .data = .{4842 .data = .{
...@@ -4068,53 +4857,53 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MC...@@ -4068,53 +4857,53 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MC
4068 }4857 }
4069}4858}
40704859
4071fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {4860fn airIsNonErrPtr(func: *Func, inst: Air.Inst.Index) !void {
4072 const zcu = self.bin_file.comp.module.?;4861 const zcu = func.bin_file.comp.module.?;
4073 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4862 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4074 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4863 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4075 const operand_ptr = try self.resolveInst(un_op);4864 const operand_ptr = try func.resolveInst(un_op);
4076 const operand: MCValue = blk: {4865 const operand: MCValue = blk: {
4077 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {4866 if (func.reuseOperand(inst, un_op, 0, operand_ptr)) {
4078 // The MCValue that holds the pointer can be re-used as the value.4867 // The MCValue that holds the pointer can be re-used as the value.
4079 break :blk operand_ptr;4868 break :blk operand_ptr;
4080 } else {4869 } else {
4081 break :blk try self.allocRegOrMem(inst, true);4870 break :blk try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
4082 }4871 }
4083 };4872 };
4084 const operand_ptr_ty = self.typeOf(un_op);4873 const operand_ptr_ty = func.typeOf(un_op);
4085 const operand_ty = operand_ptr_ty.childType(zcu);4874 const operand_ty = operand_ptr_ty.childType(zcu);
40864875
4087 try self.load(operand, operand_ptr, self.typeOf(un_op));4876 try func.load(operand, operand_ptr, func.typeOf(un_op));
4088 break :result try self.isNonErr(inst, operand_ty, operand);4877 break :result try func.isNonErr(inst, operand_ty, operand);
4089 };4878 };
4090 return self.finishAir(inst, result, .{ un_op, .none, .none });4879 return func.finishAir(inst, result, .{ un_op, .none, .none });
4091}4880}
40924881
4093fn airLoop(self: *Self, inst: Air.Inst.Index) !void {4882fn airLoop(func: *Func, inst: Air.Inst.Index) !void {
4094 // A loop is a setup to be able to jump back to the beginning.4883 // A loop is a setup to be able to jump back to the beginning.
4095 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;4884 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
4096 const loop = self.air.extraData(Air.Block, ty_pl.payload);4885 const loop = func.air.extraData(Air.Block, ty_pl.payload);
4097 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[loop.end..][0..loop.data.body_len]);4886 const body: []const Air.Inst.Index = @ptrCast(func.air.extra[loop.end..][0..loop.data.body_len]);
40984887
4099 self.scope_generation += 1;4888 func.scope_generation += 1;
4100 const state = try self.saveState();4889 const state = try func.saveState();
41014890
4102 const jmp_target: Mir.Inst.Index = @intCast(self.mir_instructions.len);4891 const jmp_target: Mir.Inst.Index = @intCast(func.mir_instructions.len);
4103 try self.genBody(body);4892 try func.genBody(body);
4104 try self.restoreState(state, &.{}, .{4893 try func.restoreState(state, &.{}, .{
4105 .emit_instructions = true,4894 .emit_instructions = true,
4106 .update_tracking = false,4895 .update_tracking = false,
4107 .resurrect = false,4896 .resurrect = false,
4108 .close_scope = true,4897 .close_scope = true,
4109 });4898 });
4110 _ = try self.jump(jmp_target);4899 _ = try func.jump(jmp_target);
41114900
4112 self.finishAirBookkeeping();4901 func.finishAirBookkeeping();
4113}4902}
41144903
4115/// Send control flow to the `index` of `self.code`.4904/// Send control flow to the `index` of `func.code`.
4116fn jump(self: *Self, index: Mir.Inst.Index) !Mir.Inst.Index {4905fn jump(func: *Func, index: Mir.Inst.Index) !Mir.Inst.Index {
4117 return self.addInst(.{4906 return func.addInst(.{
4118 .tag = .pseudo,4907 .tag = .pseudo,
4119 .ops = .pseudo_j,4908 .ops = .pseudo_j,
4120 .data = .{4909 .data = .{
...@@ -4123,113 +4912,200 @@ fn jump(self: *Self, index: Mir.Inst.Index) !Mir.Inst.Index {...@@ -4123,113 +4912,200 @@ fn jump(self: *Self, index: Mir.Inst.Index) !Mir.Inst.Index {
4123 });4912 });
4124}4913}
41254914
4126fn airBlock(self: *Self, inst: Air.Inst.Index) !void {4915fn airBlock(func: *Func, inst: Air.Inst.Index) !void {
4127 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;4916 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
4128 const extra = self.air.extraData(Air.Block, ty_pl.payload);4917 const extra = func.air.extraData(Air.Block, ty_pl.payload);
4129 try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));4918 try func.lowerBlock(inst, @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]));
4130}4919}
41314920
4132fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void {4921fn lowerBlock(func: *Func, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void {
4133 // A block is a setup to be able to jump to the end.4922 // A block is a setup to be able to jump to the end.
4134 const inst_tracking_i = self.inst_tracking.count();4923 const inst_tracking_i = func.inst_tracking.count();
4135 self.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(.unreach));4924 func.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(.unreach));
41364925
4137 self.scope_generation += 1;4926 func.scope_generation += 1;
4138 try self.blocks.putNoClobber(self.gpa, inst, .{ .state = self.initRetroactiveState() });4927 try func.blocks.putNoClobber(func.gpa, inst, .{ .state = func.initRetroactiveState() });
4139 const liveness = self.liveness.getBlock(inst);4928 const liveness = func.liveness.getBlock(inst);
41404929
4141 // TODO emit debug info lexical block4930 // TODO emit debug info lexical block
4142 try self.genBody(body);4931 try func.genBody(body);
41434932
4144 var block_data = self.blocks.fetchRemove(inst).?;4933 var block_data = func.blocks.fetchRemove(inst).?;
4145 defer block_data.value.deinit(self.gpa);4934 defer block_data.value.deinit(func.gpa);
4146 if (block_data.value.relocs.items.len > 0) {4935 if (block_data.value.relocs.items.len > 0) {
4147 try self.restoreState(block_data.value.state, liveness.deaths, .{4936 try func.restoreState(block_data.value.state, liveness.deaths, .{
4148 .emit_instructions = false,4937 .emit_instructions = false,
4149 .update_tracking = true,4938 .update_tracking = true,
4150 .resurrect = true,4939 .resurrect = true,
4151 .close_scope = true,4940 .close_scope = true,
4152 });4941 });
4153 for (block_data.value.relocs.items) |reloc| self.performReloc(reloc);4942 for (block_data.value.relocs.items) |reloc| func.performReloc(reloc);
4154 }4943 }
41554944
4156 if (std.debug.runtime_safety) assert(self.inst_tracking.getIndex(inst).? == inst_tracking_i);4945 if (std.debug.runtime_safety) assert(func.inst_tracking.getIndex(inst).? == inst_tracking_i);
4157 const tracking = &self.inst_tracking.values()[inst_tracking_i];4946 const tracking = &func.inst_tracking.values()[inst_tracking_i];
4158 if (self.liveness.isUnused(inst)) try tracking.die(self, inst);4947 if (func.liveness.isUnused(inst)) try tracking.die(func, inst);
4159 self.getValueIfFree(tracking.short, inst);4948 func.getValueIfFree(tracking.short, inst);
4160 self.finishAirBookkeeping();4949 func.finishAirBookkeeping();
4161}4950}
41624951
4163fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {4952fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {
4164 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4953 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
4165 const condition = pl_op.operand;4954 const condition = try func.resolveInst(pl_op.operand);
4166 _ = condition;4955 const condition_ty = func.typeOf(pl_op.operand);
4167 return self.fail("TODO airSwitch for {}", .{self.target.cpu.arch});4956 const switch_br = func.air.extraData(Air.SwitchBr, pl_op.payload);
4168 // return self.finishAir(inst, .dead, .{ condition, .none, .none });4957 var extra_index: usize = switch_br.end;
4958 var case_i: u32 = 0;
4959 const liveness = try func.liveness.getSwitchBr(func.gpa, inst, switch_br.data.cases_len + 1);
4960 defer func.gpa.free(liveness.deaths);
4961
4962 // If the condition dies here in this switch instruction, process
4963 // that death now instead of later as this has an effect on
4964 // whether it needs to be spilled in the branches
4965 if (func.liveness.operandDies(inst, 0)) {
4966 if (pl_op.operand.toIndex()) |op_inst| try func.processDeath(op_inst);
4967 }
4968
4969 func.scope_generation += 1;
4970 const state = try func.saveState();
4971
4972 while (case_i < switch_br.data.cases_len) : (case_i += 1) {
4973 const case = func.air.extraData(Air.SwitchBr.Case, extra_index);
4974 const items: []const Air.Inst.Ref =
4975 @ptrCast(func.air.extra[case.end..][0..case.data.items_len]);
4976 const case_body: []const Air.Inst.Index =
4977 @ptrCast(func.air.extra[case.end + items.len ..][0..case.data.body_len]);
4978 extra_index = case.end + items.len + case_body.len;
4979
4980 var relocs = try func.gpa.alloc(Mir.Inst.Index, items.len);
4981 defer func.gpa.free(relocs);
4982
4983 for (items, relocs, 0..) |item, *reloc, i| {
4984 // switch branches must be comptime-known, so this is stored in an immediate
4985 const item_mcv = try func.resolveInst(item);
4986
4987 const cmp_reg, const cmp_lock = try func.allocReg(.int);
4988 defer func.register_manager.unlockReg(cmp_lock);
4989
4990 try func.genBinOp(
4991 .cmp_neq,
4992 condition,
4993 condition_ty,
4994 item_mcv,
4995 condition_ty,
4996 cmp_reg,
4997 );
4998
4999 if (!(i < relocs.len - 1)) {
5000 _ = try func.addInst(.{
5001 .tag = .pseudo,
5002 .ops = .pseudo_not,
5003 .data = .{ .rr = .{
5004 .rd = cmp_reg,
5005 .rs = cmp_reg,
5006 } },
5007 });
5008 }
5009
5010 reloc.* = try func.condBr(condition_ty, .{ .register = cmp_reg });
5011 }
5012
5013 for (liveness.deaths[case_i]) |operand| try func.processDeath(operand);
5014
5015 for (relocs[0 .. relocs.len - 1]) |reloc| func.performReloc(reloc);
5016 try func.genBody(case_body);
5017 try func.restoreState(state, &.{}, .{
5018 .emit_instructions = false,
5019 .update_tracking = true,
5020 .resurrect = true,
5021 .close_scope = true,
5022 });
5023
5024 func.performReloc(relocs[relocs.len - 1]);
5025 }
5026
5027 if (switch_br.data.else_body_len > 0) {
5028 const else_body: []const Air.Inst.Index =
5029 @ptrCast(func.air.extra[extra_index..][0..switch_br.data.else_body_len]);
5030
5031 const else_deaths = liveness.deaths.len - 1;
5032 for (liveness.deaths[else_deaths]) |operand| try func.processDeath(operand);
5033
5034 try func.genBody(else_body);
5035 try func.restoreState(state, &.{}, .{
5036 .emit_instructions = false,
5037 .update_tracking = true,
5038 .resurrect = true,
5039 .close_scope = true,
5040 });
5041 }
5042
5043 // We already took care of pl_op.operand earlier, so there's nothing left to do
5044 func.finishAirBookkeeping();
4169}5045}
41705046
4171fn performReloc(self: *Self, inst: Mir.Inst.Index) void {5047fn performReloc(func: *Func, inst: Mir.Inst.Index) void {
4172 const tag = self.mir_instructions.items(.tag)[inst];5048 const tag = func.mir_instructions.items(.tag)[inst];
4173 const ops = self.mir_instructions.items(.ops)[inst];5049 const ops = func.mir_instructions.items(.ops)[inst];
4174 const target: Mir.Inst.Index = @intCast(self.mir_instructions.len);5050 const target: Mir.Inst.Index = @intCast(func.mir_instructions.len);
41755051
4176 switch (tag) {5052 switch (tag) {
4177 .bne,5053 .bne,
4178 .beq,5054 .beq,
4179 => self.mir_instructions.items(.data)[inst].b_type.inst = target,5055 => func.mir_instructions.items(.data)[inst].b_type.inst = target,
4180 .jal => self.mir_instructions.items(.data)[inst].j_type.inst = target,5056 .jal => func.mir_instructions.items(.data)[inst].j_type.inst = target,
4181 .pseudo => switch (ops) {5057 .pseudo => switch (ops) {
4182 .pseudo_j => self.mir_instructions.items(.data)[inst].inst = target,5058 .pseudo_j => func.mir_instructions.items(.data)[inst].inst = target,
4183 else => std.debug.panic("TODO: performReloc {s}", .{@tagName(ops)}),5059 else => std.debug.panic("TODO: performReloc {s}", .{@tagName(ops)}),
4184 },5060 },
4185 else => std.debug.panic("TODO: performReloc {s}", .{@tagName(tag)}),5061 else => std.debug.panic("TODO: performReloc {s}", .{@tagName(tag)}),
4186 }5062 }
4187}5063}
41885064
4189fn airBr(self: *Self, inst: Air.Inst.Index) !void {5065fn airBr(func: *Func, inst: Air.Inst.Index) !void {
4190 const mod = self.bin_file.comp.module.?;5066 const mod = func.bin_file.comp.module.?;
4191 const br = self.air.instructions.items(.data)[@intFromEnum(inst)].br;5067 const br = func.air.instructions.items(.data)[@intFromEnum(inst)].br;
41925068
4193 const block_ty = self.typeOfIndex(br.block_inst);5069 const block_ty = func.typeOfIndex(br.block_inst);
4194 const block_unused =5070 const block_unused =
4195 !block_ty.hasRuntimeBitsIgnoreComptime(mod) or self.liveness.isUnused(br.block_inst);5071 !block_ty.hasRuntimeBitsIgnoreComptime(mod) or func.liveness.isUnused(br.block_inst);
4196 const block_tracking = self.inst_tracking.getPtr(br.block_inst).?;5072 const block_tracking = func.inst_tracking.getPtr(br.block_inst).?;
4197 const block_data = self.blocks.getPtr(br.block_inst).?;5073 const block_data = func.blocks.getPtr(br.block_inst).?;
4198 const first_br = block_data.relocs.items.len == 0;5074 const first_br = block_data.relocs.items.len == 0;
4199 const block_result = result: {5075 const block_result = result: {
4200 if (block_unused) break :result .none;5076 if (block_unused) break :result .none;
42015077
4202 if (!first_br) try self.getValue(block_tracking.short, null);5078 if (!first_br) try func.getValue(block_tracking.short, null);
4203 const src_mcv = try self.resolveInst(br.operand);5079 const src_mcv = try func.resolveInst(br.operand);
42045080
4205 if (self.reuseOperandAdvanced(inst, br.operand, 0, src_mcv, br.block_inst)) {5081 if (func.reuseOperandAdvanced(inst, br.operand, 0, src_mcv, br.block_inst)) {
4206 if (first_br) break :result src_mcv;5082 if (first_br) break :result src_mcv;
42075083
4208 try self.getValue(block_tracking.short, br.block_inst);5084 try func.getValue(block_tracking.short, br.block_inst);
4209 // .long = .none to avoid merging operand and block result stack frames.5085 // .long = .none to avoid merging operand and block result stack frames.
4210 const current_tracking: InstTracking = .{ .long = .none, .short = src_mcv };5086 const current_tracking: InstTracking = .{ .long = .none, .short = src_mcv };
4211 try current_tracking.materializeUnsafe(self, br.block_inst, block_tracking.*);5087 try current_tracking.materializeUnsafe(func, br.block_inst, block_tracking.*);
4212 for (current_tracking.getRegs()) |src_reg| self.register_manager.freeReg(src_reg);5088 for (current_tracking.getRegs()) |src_reg| func.register_manager.freeReg(src_reg);
4213 break :result block_tracking.short;5089 break :result block_tracking.short;
4214 }5090 }
42155091
4216 const dst_mcv = if (first_br) try self.allocRegOrMem(br.block_inst, true) else dst: {5092 const dst_mcv = if (first_br) try func.allocRegOrMem(block_ty, br.block_inst, true) else dst: {
4217 try self.getValue(block_tracking.short, br.block_inst);5093 try func.getValue(block_tracking.short, br.block_inst);
4218 break :dst block_tracking.short;5094 break :dst block_tracking.short;
4219 };5095 };
4220 try self.genCopy(block_ty, dst_mcv, try self.resolveInst(br.operand));5096 try func.genCopy(block_ty, dst_mcv, try func.resolveInst(br.operand));
4221 break :result dst_mcv;5097 break :result dst_mcv;
4222 };5098 };
42235099
4224 // Process operand death so that it is properly accounted for in the State below.5100 // Process operand death so that it is properly accounted for in the State below.
4225 if (self.liveness.operandDies(inst, 0)) {5101 if (func.liveness.operandDies(inst, 0)) {
4226 if (br.operand.toIndex()) |op_inst| try self.processDeath(op_inst);5102 if (br.operand.toIndex()) |op_inst| try func.processDeath(op_inst);
4227 }5103 }
42285104
4229 if (first_br) {5105 if (first_br) {
4230 block_tracking.* = InstTracking.init(block_result);5106 block_tracking.* = InstTracking.init(block_result);
4231 try self.saveRetroactiveState(&block_data.state);5107 try func.saveRetroactiveState(&block_data.state);
4232 } else try self.restoreState(block_data.state, &.{}, .{5108 } else try func.restoreState(block_data.state, &.{}, .{
4233 .emit_instructions = true,5109 .emit_instructions = true,
4234 .update_tracking = false,5110 .update_tracking = false,
4235 .resurrect = false,5111 .resurrect = false,
...@@ -4238,49 +5114,88 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4238,49 +5114,88 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
42385114
4239 // Emit a jump with a relocation. It will be patched up after the block ends.5115 // Emit a jump with a relocation. It will be patched up after the block ends.
4240 // Leave the jump offset undefined5116 // Leave the jump offset undefined
4241 const jmp_reloc = try self.jump(undefined);5117 const jmp_reloc = try func.jump(undefined);
4242 try block_data.relocs.append(self.gpa, jmp_reloc);5118 try block_data.relocs.append(func.gpa, jmp_reloc);
42435119
4244 // Stop tracking block result without forgetting tracking info5120 // Stop tracking block result without forgetting tracking info
4245 try self.freeValue(block_tracking.short);5121 try func.freeValue(block_tracking.short);
42465122
4247 self.finishAirBookkeeping();5123 func.finishAirBookkeeping();
4248}5124}
42495125
4250fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {5126fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void {
4251 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;5127 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
4252 const air_tags = self.air.instructions.items(.tag);5128 const tag: Air.Inst.Tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];
4253 _ = air_tags;5129
4254 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement boolean operations for {}", .{self.target.cpu.arch});5130 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4255 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });5131 const lhs = try func.resolveInst(bin_op.lhs);
5132 const rhs = try func.resolveInst(bin_op.rhs);
5133 const lhs_ty = Type.bool;
5134 const rhs_ty = Type.bool;
5135
5136 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs);
5137 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
5138
5139 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs);
5140 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
5141
5142 const result_reg, const result_lock = try func.allocReg(.int);
5143 defer func.register_manager.unlockReg(result_lock);
5144
5145 _ = try func.addInst(.{
5146 .tag = if (tag == .bool_or) .@"or" else .@"and",
5147 .ops = .rrr,
5148 .data = .{ .r_type = .{
5149 .rd = result_reg,
5150 .rs1 = lhs_reg,
5151 .rs2 = rhs_reg,
5152 } },
5153 });
5154
5155 // safety truncate
5156 if (func.wantSafety()) {
5157 _ = try func.addInst(.{
5158 .tag = .andi,
5159 .ops = .rri,
5160 .data = .{ .i_type = .{
5161 .rd = result_reg,
5162 .rs1 = result_reg,
5163 .imm12 = Immediate.s(1),
5164 } },
5165 });
5166 }
5167
5168 break :result .{ .register = result_reg };
5169 };
5170 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
4256}5171}
42575172
4258fn airAsm(self: *Self, inst: Air.Inst.Index) !void {5173fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
4259 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;5174 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
4260 const extra = self.air.extraData(Air.Asm, ty_pl.payload);5175 const extra = func.air.extraData(Air.Asm, ty_pl.payload);
4261 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;5176 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
4262 const clobbers_len: u31 = @truncate(extra.data.flags);5177 const clobbers_len: u31 = @truncate(extra.data.flags);
4263 var extra_i: usize = extra.end;5178 var extra_i: usize = extra.end;
4264 const outputs: []const Air.Inst.Ref =5179 const outputs: []const Air.Inst.Ref =
4265 @ptrCast(self.air.extra[extra_i..][0..extra.data.outputs_len]);5180 @ptrCast(func.air.extra[extra_i..][0..extra.data.outputs_len]);
4266 extra_i += outputs.len;5181 extra_i += outputs.len;
4267 const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra_i..][0..extra.data.inputs_len]);5182 const inputs: []const Air.Inst.Ref = @ptrCast(func.air.extra[extra_i..][0..extra.data.inputs_len]);
4268 extra_i += inputs.len;5183 extra_i += inputs.len;
42695184
4270 log.debug("airAsm input: {any}", .{inputs});5185 log.debug("airAsm input: {any}", .{inputs});
42715186
4272 const dead = !is_volatile and self.liveness.isUnused(inst);5187 const dead = !is_volatile and func.liveness.isUnused(inst);
4273 const result: MCValue = if (dead) .unreach else result: {5188 const result: MCValue = if (dead) .unreach else result: {
4274 if (outputs.len > 1) {5189 if (outputs.len > 1) {
4275 return self.fail("TODO implement codegen for asm with more than 1 output", .{});5190 return func.fail("TODO implement codegen for asm with more than 1 output", .{});
4276 }5191 }
42775192
4278 const output_constraint: ?[]const u8 = for (outputs) |output| {5193 const output_constraint: ?[]const u8 = for (outputs) |output| {
4279 if (output != .none) {5194 if (output != .none) {
4280 return self.fail("TODO implement codegen for non-expr asm", .{});5195 return func.fail("TODO implement codegen for non-expr asm", .{});
4281 }5196 }
4282 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);5197 const extra_bytes = std.mem.sliceAsBytes(func.air.extra[extra_i..]);
4283 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);5198 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(func.air.extra[extra_i..]), 0);
4284 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);5199 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
4285 // This equation accounts for the fact that even if we have exactly 4 bytes5200 // This equation accounts for the fact that even if we have exactly 4 bytes
4286 // for the string, we still use the next u32 for the null terminator.5201 // for the string, we still use the next u32 for the null terminator.
...@@ -4290,7 +5205,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -4290,7 +5205,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
4290 } else null;5205 } else null;
42915206
4292 for (inputs) |input| {5207 for (inputs) |input| {
4293 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);5208 const input_bytes = std.mem.sliceAsBytes(func.air.extra[extra_i..]);
4294 const constraint = std.mem.sliceTo(input_bytes, 0);5209 const constraint = std.mem.sliceTo(input_bytes, 0);
4295 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);5210 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
4296 // This equation accounts for the fact that even if we have exactly 4 bytes5211 // This equation accounts for the fact that even if we have exactly 4 bytes
...@@ -4298,21 +5213,21 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -4298,21 +5213,21 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
4298 extra_i += (constraint.len + name.len + (2 + 3)) / 4;5213 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
42995214
4300 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {5215 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
4301 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});5216 return func.fail("unrecognized asm input constraint: '{s}'", .{constraint});
4302 }5217 }
4303 const reg_name = constraint[1 .. constraint.len - 1];5218 const reg_name = constraint[1 .. constraint.len - 1];
4304 const reg = parseRegName(reg_name) orelse5219 const reg = parseRegName(reg_name) orelse
4305 return self.fail("unrecognized register: '{s}'", .{reg_name});5220 return func.fail("unrecognized register: '{s}'", .{reg_name});
43065221
4307 const arg_mcv = try self.resolveInst(input);5222 const arg_mcv = try func.resolveInst(input);
4308 try self.register_manager.getReg(reg, null);5223 try func.register_manager.getReg(reg, null);
4309 try self.genSetReg(self.typeOf(input), reg, arg_mcv);5224 try func.genSetReg(func.typeOf(input), reg, arg_mcv);
4310 }5225 }
43115226
4312 {5227 {
4313 var clobber_i: u32 = 0;5228 var clobber_i: u32 = 0;
4314 while (clobber_i < clobbers_len) : (clobber_i += 1) {5229 while (clobber_i < clobbers_len) : (clobber_i += 1) {
4315 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);5230 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(func.air.extra[extra_i..]), 0);
4316 // This equation accounts for the fact that even if we have exactly 4 bytes5231 // This equation accounts for the fact that even if we have exactly 4 bytes
4317 // for the string, we still use the next u32 for the null terminator.5232 // for the string, we still use the next u32 for the null terminator.
4318 extra_i += clobber.len / 4 + 1;5233 extra_i += clobber.len / 4 + 1;
...@@ -4320,31 +5235,31 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -4320,31 +5235,31 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
4320 if (std.mem.eql(u8, clobber, "") or std.mem.eql(u8, clobber, "memory")) {5235 if (std.mem.eql(u8, clobber, "") or std.mem.eql(u8, clobber, "memory")) {
4321 // nothing really to do5236 // nothing really to do
4322 } else {5237 } else {
4323 try self.register_manager.getReg(parseRegName(clobber) orelse5238 try func.register_manager.getReg(parseRegName(clobber) orelse
4324 return self.fail("invalid clobber: '{s}'", .{clobber}), null);5239 return func.fail("invalid clobber: '{s}'", .{clobber}), null);
4325 }5240 }
4326 }5241 }
4327 }5242 }
43285243
4329 const asm_source = std.mem.sliceAsBytes(self.air.extra[extra_i..])[0..extra.data.source_len];5244 const asm_source = std.mem.sliceAsBytes(func.air.extra[extra_i..])[0..extra.data.source_len];
43305245
4331 if (std.meta.stringToEnum(Mir.Inst.Tag, asm_source)) |tag| {5246 if (std.meta.stringToEnum(Mir.Inst.Tag, asm_source)) |tag| {
4332 _ = try self.addInst(.{5247 _ = try func.addInst(.{
4333 .tag = tag,5248 .tag = tag,
4334 .ops = .none,5249 .ops = .none,
4335 .data = undefined,5250 .data = undefined,
4336 });5251 });
4337 } else {5252 } else {
4338 return self.fail("TODO: asm_source {s}", .{asm_source});5253 return func.fail("TODO: asm_source {s}", .{asm_source});
4339 }5254 }
43405255
4341 if (output_constraint) |output| {5256 if (output_constraint) |output| {
4342 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {5257 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {
4343 return self.fail("unrecognized asm output constraint: '{s}'", .{output});5258 return func.fail("unrecognized asm output constraint: '{s}'", .{output});
4344 }5259 }
4345 const reg_name = output[2 .. output.len - 1];5260 const reg_name = output[2 .. output.len - 1];
4346 const reg = parseRegName(reg_name) orelse5261 const reg = parseRegName(reg_name) orelse
4347 return self.fail("unrecognized register: '{s}'", .{reg_name});5262 return func.fail("unrecognized register: '{s}'", .{reg_name});
4348 break :result .{ .register = reg };5263 break :result .{ .register = reg };
4349 } else {5264 } else {
4350 break :result .{ .none = {} };5265 break :result .{ .none = {} };
...@@ -4363,29 +5278,29 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -4363,29 +5278,29 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
4363 }5278 }
4364 if (buf_index + inputs.len > buf.len) break :simple;5279 if (buf_index + inputs.len > buf.len) break :simple;
4365 @memcpy(buf[buf_index..][0..inputs.len], inputs);5280 @memcpy(buf[buf_index..][0..inputs.len], inputs);
4366 return self.finishAir(inst, result, buf);5281 return func.finishAir(inst, result, buf);
4367 }5282 }
4368 var bt = self.liveness.iterateBigTomb(inst);5283 var bt = func.liveness.iterateBigTomb(inst);
4369 for (outputs) |output| if (output != .none) try self.feed(&bt, output);5284 for (outputs) |output| if (output != .none) try func.feed(&bt, output);
4370 for (inputs) |input| try self.feed(&bt, input);5285 for (inputs) |input| try func.feed(&bt, input);
4371 return self.finishAirResult(inst, result);5286 return func.finishAirResult(inst, result);
4372}5287}
43735288
4374/// Sets the value without any modifications to register allocation metadata or stack allocation metadata.5289/// Sets the value of `dst_mcv` to the value of `src_mcv`.
4375fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {5290fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
4376 const zcu = self.bin_file.comp.module.?;5291 const zcu = func.bin_file.comp.module.?;
43775292
4378 // There isn't anything to store5293 // There isn't anything to store
4379 if (dst_mcv == .none) return;5294 if (dst_mcv == .none) return;
43805295
4381 if (!dst_mcv.isMutable()) {5296 if (!dst_mcv.isMutable()) {
4382 // panic so we can see the trace5297 // panic so we can see the trace
4383 return self.fail("tried to genCopy immutable: {s}", .{@tagName(dst_mcv)});5298 return std.debug.panic("tried to genCopy immutable: {s}", .{@tagName(dst_mcv)});
4384 }5299 }
43855300
4386 switch (dst_mcv) {5301 switch (dst_mcv) {
4387 .register => |reg| return self.genSetReg(ty, reg, src_mcv),5302 .register => |reg| return func.genSetReg(ty, reg, src_mcv),
4388 .register_offset => |dst_reg_off| try self.genSetReg(ty, dst_reg_off.reg, switch (src_mcv) {5303 .register_offset => |dst_reg_off| try func.genSetReg(ty, dst_reg_off.reg, switch (src_mcv) {
4389 .none,5304 .none,
4390 .unreach,5305 .unreach,
4391 .dead,5306 .dead,
...@@ -4396,167 +5311,85 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {...@@ -4396,167 +5311,85 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
4396 .register_offset,5311 .register_offset,
4397 => src_mcv.offset(-dst_reg_off.off),5312 => src_mcv.offset(-dst_reg_off.off),
4398 else => .{ .register_offset = .{5313 else => .{ .register_offset = .{
4399 .reg = try self.copyToTmpRegister(ty, src_mcv),5314 .reg = try func.copyToTmpRegister(ty, src_mcv),
4400 .off = -dst_reg_off.off,5315 .off = -dst_reg_off.off,
4401 } },5316 } },
4402 }),5317 }),
4403 .indirect => |ro| {5318 .indirect => |reg_off| try func.genSetMem(
4404 const src_reg = try self.copyToTmpRegister(ty, src_mcv);5319 .{ .reg = reg_off.reg },
44055320 reg_off.off,
4406 _ = try self.addInst(.{5321 ty,
4407 .tag = .pseudo,5322 src_mcv,
4408 .ops = .pseudo_store_rm,5323 ),
4409 .data = .{ .rm = .{5324 .load_frame => |frame_addr| try func.genSetMem(
4410 .r = src_reg,5325 .{ .frame = frame_addr.index },
4411 .m = .{5326 frame_addr.off,
4412 .base = .{ .reg = ro.reg },5327 ty,
4413 .mod = .{ .rm = .{ .disp = ro.off, .size = self.memSize(ty) } },5328 src_mcv,
4414 },5329 ),
4415 } },5330 .memory => return func.fail("TODO: genCopy memory", .{}),
4416 });
4417 },
4418 .load_frame => |frame| return self.genSetStack(ty, frame, src_mcv),
4419 .memory => return self.fail("TODO: genCopy memory", .{}),
4420 .register_pair => |dst_regs| {5331 .register_pair => |dst_regs| {
4421 const src_info: ?struct { addr_reg: Register, addr_lock: RegisterLock } = switch (src_mcv) {5332 const src_info: ?struct { addr_reg: Register, addr_lock: ?RegisterLock } = switch (src_mcv) {
4422 .register_pair, .memory, .indirect, .load_frame => null,5333 .register_pair, .memory, .indirect, .load_frame => null,
4423 .load_symbol => src: {5334 .load_symbol => src: {
4424 const src_addr_reg, const src_addr_lock = try self.allocReg();5335 const src_addr_reg, const src_addr_lock = try func.promoteReg(Type.usize, src_mcv.address());
4425 errdefer self.register_manager.unlockReg(src_addr_lock);5336 errdefer func.register_manager.unlockReg(src_addr_lock);
44265337
4427 try self.genSetReg(Type.usize, src_addr_reg, src_mcv.address());
4428 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };5338 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
4429 },5339 },
4430 .air_ref => |src_ref| return self.genCopy(5340 .air_ref => |src_ref| return func.genCopy(
4431 ty,5341 ty,
4432 dst_mcv,5342 dst_mcv,
4433 try self.resolveInst(src_ref),5343 try func.resolveInst(src_ref),
4434 ),5344 ),
4435 else => unreachable,5345 else => return func.fail("genCopy register_pair src: {}", .{src_mcv}),
4436 };5346 };
4437 defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
4438
4439 var part_disp: i32 = 0;
4440 for (dst_regs, try self.splitType(ty), 0..) |dst_reg, dst_ty, part_i| {
4441 try self.genSetReg(dst_ty, dst_reg, switch (src_mcv) {
4442 .register_pair => |src_regs| .{ .register = src_regs[part_i] },
4443 .memory, .indirect, .load_frame => src_mcv.address().offset(part_disp).deref(),
4444 .load_symbol => .{ .indirect = .{
4445 .reg = src_info.?.addr_reg,
4446 .off = part_disp,
4447 } },
4448 else => unreachable,
4449 });
4450 part_disp += @intCast(dst_ty.abiSize(zcu));
4451 }
4452 },
4453 else => return self.fail("TODO: genCopy to {s} from {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),
4454 }
4455}
4456
4457fn genSetStack(
4458 self: *Self,
4459 ty: Type,
4460 frame: FrameAddr,
4461 src_mcv: MCValue,
4462) InnerError!void {
4463 const zcu = self.bin_file.comp.module.?;
4464 const abi_size: u32 = @intCast(ty.abiSize(zcu));
4465
4466 switch (src_mcv) {
4467 .none => return,
4468 .dead => unreachable,
4469 .undef => {
4470 if (!self.wantSafety()) return;
4471 try self.genSetStack(ty, frame, .{ .immediate = 0xaaaaaaaaaaaaaaaa });
4472 },
4473 .immediate,
4474 .lea_frame,
4475 => {
4476 // TODO: remove this lock in favor of a copyToTmpRegister when we load 64 bit immediates with
4477 // a register allocation.
4478 const reg, const reg_lock = try self.allocReg();
4479 defer self.register_manager.unlockReg(reg_lock);
44805347
4481 try self.genSetReg(ty, reg, src_mcv);5348 defer if (src_info) |info| {
5349 if (info.addr_lock) |lock| {
5350 func.register_manager.unlockReg(lock);
5351 }
5352 };
44825353
4483 return self.genSetStack(ty, frame, .{ .register = reg });5354 var part_disp: i32 = 0;
4484 },5355 for (dst_regs, try func.splitType(ty), 0..) |dst_reg, dst_ty, part_i| {
4485 .register => |reg| {5356 try func.genSetReg(dst_ty, dst_reg, switch (src_mcv) {
4486 switch (abi_size) {5357 .register_pair => |src_regs| .{ .register = src_regs[part_i] },
4487 1, 2, 4, 8 => {5358 .memory, .indirect, .load_frame => src_mcv.address().offset(part_disp).deref(),
4488 _ = try self.addInst(.{5359 .load_symbol => .{ .indirect = .{
4489 .tag = .pseudo,5360 .reg = src_info.?.addr_reg,
4490 .ops = .pseudo_store_rm,5361 .off = part_disp,
4491 .data = .{ .rm = .{5362 } },
4492 .r = reg,5363 else => unreachable,
4493 .m = .{5364 });
4494 .base = .{ .frame = frame.index },5365 part_disp += @intCast(dst_ty.abiSize(zcu));
4495 .mod = .{
4496 .rm = .{
4497 .size = self.memSize(ty),
4498 .disp = frame.off,
4499 },
4500 },
4501 },
4502 } },
4503 });
4504 },
4505 else => unreachable, // register can hold a max of 8 bytes
4506 }
4507 },
4508 .register_pair => |pair| {
4509 var part_disp: i32 = frame.off;
4510 for (try self.splitType(ty), pair) |src_ty, src_reg| {
4511 try self.genSetStack(
4512 src_ty,
4513 .{ .index = frame.index, .off = part_disp },
4514 .{ .register = src_reg },
4515 );
4516 part_disp += @intCast(src_ty.abiSize(zcu));
4517 }
4518 },
4519 .load_frame,
4520 .indirect,
4521 .load_symbol,
4522 => {
4523 if (abi_size <= 8) {
4524 const reg = try self.copyToTmpRegister(ty, src_mcv);
4525 return self.genSetStack(ty, frame, .{ .register = reg });
4526 }5366 }
4527
4528 try self.genInlineMemcpy(
4529 .{ .lea_frame = frame },
4530 src_mcv.address(),
4531 .{ .immediate = abi_size },
4532 );
4533 },5367 },
4534 .air_ref => |ref| try self.genSetStack(ty, frame, try self.resolveInst(ref)),5368 else => return func.fail("TODO: genCopy to {s} from {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),
4535 else => return self.fail("TODO: genSetStack {s}", .{@tagName(src_mcv)}),
4536 }5369 }
4537}5370}
45385371
4539fn genInlineMemcpy(5372fn genInlineMemcpy(
4540 self: *Self,5373 func: *Func,
4541 dst_ptr: MCValue,5374 dst_ptr: MCValue,
4542 src_ptr: MCValue,5375 src_ptr: MCValue,
4543 len: MCValue,5376 len: MCValue,
4544) !void {5377) !void {
4545 const regs = try self.register_manager.allocRegs(4, .{null} ** 4, tp);5378 const regs = try func.register_manager.allocRegs(4, .{null} ** 4, abi.Registers.Integer.temporary);
4546 const locks = self.register_manager.lockRegsAssumeUnused(4, regs);5379 const locks = func.register_manager.lockRegsAssumeUnused(4, regs);
4547 defer for (locks) |lock| self.register_manager.unlockReg(lock);5380 defer for (locks) |lock| func.register_manager.unlockReg(lock);
45485381
4549 const count = regs[0];5382 const count = regs[0];
4550 const tmp = regs[1];5383 const tmp = regs[1];
4551 const src = regs[2];5384 const src = regs[2];
4552 const dst = regs[3];5385 const dst = regs[3];
45535386
4554 try self.genSetReg(Type.usize, count, len);5387 try func.genSetReg(Type.usize, count, len);
4555 try self.genSetReg(Type.usize, src, src_ptr);5388 try func.genSetReg(Type.usize, src, src_ptr);
4556 try self.genSetReg(Type.usize, dst, dst_ptr);5389 try func.genSetReg(Type.usize, dst, dst_ptr);
45575390
4558 // lb tmp, 0(src)5391 // lb tmp, 0(src)
4559 const first_inst = try self.addInst(.{5392 const first_inst = try func.addInst(.{
4560 .tag = .lb,5393 .tag = .lb,
4561 .ops = .rri,5394 .ops = .rri,
4562 .data = .{5395 .data = .{
...@@ -4569,7 +5402,7 @@ fn genInlineMemcpy(...@@ -4569,7 +5402,7 @@ fn genInlineMemcpy(
4569 });5402 });
45705403
4571 // sb tmp, 0(dst)5404 // sb tmp, 0(dst)
4572 _ = try self.addInst(.{5405 _ = try func.addInst(.{
4573 .tag = .sb,5406 .tag = .sb,
4574 .ops = .rri,5407 .ops = .rri,
4575 .data = .{5408 .data = .{
...@@ -4582,7 +5415,7 @@ fn genInlineMemcpy(...@@ -4582,7 +5415,7 @@ fn genInlineMemcpy(
4582 });5415 });
45835416
4584 // dec count by 15417 // dec count by 1
4585 _ = try self.addInst(.{5418 _ = try func.addInst(.{
4586 .tag = .addi,5419 .tag = .addi,
4587 .ops = .rri,5420 .ops = .rri,
4588 .data = .{5421 .data = .{
...@@ -4595,12 +5428,12 @@ fn genInlineMemcpy(...@@ -4595,12 +5428,12 @@ fn genInlineMemcpy(
4595 });5428 });
45965429
4597 // branch if count is 05430 // branch if count is 0
4598 _ = try self.addInst(.{5431 _ = try func.addInst(.{
4599 .tag = .beq,5432 .tag = .beq,
4600 .ops = .rr_inst,5433 .ops = .rr_inst,
4601 .data = .{5434 .data = .{
4602 .b_type = .{5435 .b_type = .{
4603 .inst = @intCast(self.mir_instructions.len + 4), // points after the last inst5436 .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst
4604 .rs1 = count,5437 .rs1 = count,
4605 .rs2 = .zero,5438 .rs2 = .zero,
4606 },5439 },
...@@ -4608,7 +5441,7 @@ fn genInlineMemcpy(...@@ -4608,7 +5441,7 @@ fn genInlineMemcpy(
4608 });5441 });
46095442
4610 // increment the pointers5443 // increment the pointers
4611 _ = try self.addInst(.{5444 _ = try func.addInst(.{
4612 .tag = .addi,5445 .tag = .addi,
4613 .ops = .rri,5446 .ops = .rri,
4614 .data = .{5447 .data = .{
...@@ -4620,7 +5453,85 @@ fn genInlineMemcpy(...@@ -4620,7 +5453,85 @@ fn genInlineMemcpy(
4620 },5453 },
4621 });5454 });
46225455
4623 _ = try self.addInst(.{5456 _ = try func.addInst(.{
5457 .tag = .addi,
5458 .ops = .rri,
5459 .data = .{
5460 .i_type = .{
5461 .rd = dst,
5462 .rs1 = dst,
5463 .imm12 = Immediate.s(1),
5464 },
5465 },
5466 });
5467
5468 // jump back to start of loop
5469 _ = try func.addInst(.{
5470 .tag = .pseudo,
5471 .ops = .pseudo_j,
5472 .data = .{ .inst = first_inst },
5473 });
5474}
5475
5476fn genInlineMemset(
5477 func: *Func,
5478 dst_ptr: MCValue,
5479 src_value: MCValue,
5480 len: MCValue,
5481) !void {
5482 const regs = try func.register_manager.allocRegs(3, .{null} ** 3, abi.Registers.Integer.temporary);
5483 const locks = func.register_manager.lockRegsAssumeUnused(3, regs);
5484 defer for (locks) |lock| func.register_manager.unlockReg(lock);
5485
5486 const count = regs[0];
5487 const src = regs[1];
5488 const dst = regs[2];
5489
5490 try func.genSetReg(Type.usize, count, len);
5491 try func.genSetReg(Type.usize, src, src_value);
5492 try func.genSetReg(Type.usize, dst, dst_ptr);
5493
5494 // sb src, 0(dst)
5495 const first_inst = try func.addInst(.{
5496 .tag = .sb,
5497 .ops = .rri,
5498 .data = .{
5499 .i_type = .{
5500 .rd = dst,
5501 .rs1 = src,
5502 .imm12 = Immediate.s(0),
5503 },
5504 },
5505 });
5506
5507 // dec count by 1
5508 _ = try func.addInst(.{
5509 .tag = .addi,
5510 .ops = .rri,
5511 .data = .{
5512 .i_type = .{
5513 .rd = count,
5514 .rs1 = count,
5515 .imm12 = Immediate.s(-1),
5516 },
5517 },
5518 });
5519
5520 // branch if count is 0
5521 _ = try func.addInst(.{
5522 .tag = .beq,
5523 .ops = .rr_inst,
5524 .data = .{
5525 .b_type = .{
5526 .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst
5527 .rs1 = count,
5528 .rs2 = .zero,
5529 },
5530 },
5531 });
5532
5533 // increment the pointers
5534 _ = try func.addInst(.{
4624 .tag = .addi,5535 .tag = .addi,
4625 .ops = .rri,5536 .ops = .rri,
4626 .data = .{5537 .data = .{
...@@ -4633,7 +5544,7 @@ fn genInlineMemcpy(...@@ -4633,7 +5544,7 @@ fn genInlineMemcpy(
4633 });5544 });
46345545
4635 // jump back to start of loop5546 // jump back to start of loop
4636 _ = try self.addInst(.{5547 _ = try func.addInst(.{
4637 .tag = .pseudo,5548 .tag = .pseudo,
4638 .ops = .pseudo_j,5549 .ops = .pseudo_j,
4639 .data = .{5550 .data = .{
...@@ -4643,25 +5554,29 @@ fn genInlineMemcpy(...@@ -4643,25 +5554,29 @@ fn genInlineMemcpy(
4643}5554}
46445555
4645/// Sets the value of `src_mcv` into `reg`. Assumes you have a lock on it.5556/// Sets the value of `src_mcv` into `reg`. Assumes you have a lock on it.
4646fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!void {5557fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!void {
4647 const zcu = self.bin_file.comp.module.?;5558 const zcu = func.bin_file.comp.module.?;
4648 const abi_size: u32 = @intCast(ty.abiSize(zcu));5559 const abi_size: u32 = @intCast(ty.abiSize(zcu));
46495560
4650 if (abi_size > 8) return self.fail("tried to set reg with size {}", .{abi_size});5561 if (abi_size > 8) return std.debug.panic("tried to set reg with size {}", .{abi_size});
5562
5563 const dst_reg_class = reg.class();
46515564
4652 switch (src_mcv) {5565 switch (src_mcv) {
4653 .dead => unreachable,5566 .dead => unreachable,
4654 .unreach, .none => return, // Nothing to do.5567 .unreach, .none => return, // Nothing to do.
4655 .undef => {5568 .undef => {
4656 if (!self.wantSafety())5569 if (!func.wantSafety())
4657 return; // The already existing value will do just fine.5570 return; // The already existing value will do just fine.
4658 // Write the debug undefined value.5571 // Write the debug undefined value.
4659 return self.genSetReg(ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa });5572 return func.genSetReg(ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa });
4660 },5573 },
4661 .immediate => |unsigned_x| {5574 .immediate => |unsigned_x| {
5575 assert(dst_reg_class == .int);
5576
4662 const x: i64 = @bitCast(unsigned_x);5577 const x: i64 = @bitCast(unsigned_x);
4663 if (math.minInt(i12) <= x and x <= math.maxInt(i12)) {5578 if (math.minInt(i12) <= x and x <= math.maxInt(i12)) {
4664 _ = try self.addInst(.{5579 _ = try func.addInst(.{
4665 .tag = .addi,5580 .tag = .addi,
4666 .ops = .rri,5581 .ops = .rri,
4667 .data = .{ .i_type = .{5582 .data = .{ .i_type = .{
...@@ -4675,7 +5590,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -4675,7 +5590,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
4675 const carry: i32 = if (lo12 < 0) 1 else 0;5590 const carry: i32 = if (lo12 < 0) 1 else 0;
4676 const hi20: i20 = @truncate((x >> 12) +% carry);5591 const hi20: i20 = @truncate((x >> 12) +% carry);
46775592
4678 _ = try self.addInst(.{5593 _ = try func.addInst(.{
4679 .tag = .lui,5594 .tag = .lui,
4680 .ops = .ri,5595 .ops = .ri,
4681 .data = .{ .u_type = .{5596 .data = .{ .u_type = .{
...@@ -4683,7 +5598,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -4683,7 +5598,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
4683 .imm20 = Immediate.s(hi20),5598 .imm20 = Immediate.s(hi20),
4684 } },5599 } },
4685 });5600 });
4686 _ = try self.addInst(.{5601 _ = try func.addInst(.{
4687 .tag = .addi,5602 .tag = .addi,
4688 .ops = .rri,5603 .ops = .rri,
4689 .data = .{ .i_type = .{5604 .data = .{ .i_type = .{
...@@ -4696,27 +5611,27 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -4696,27 +5611,27 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
4696 // TODO: use a more advanced myriad seq to do this without a reg.5611 // TODO: use a more advanced myriad seq to do this without a reg.
4697 // see: https://github.com/llvm/llvm-project/blob/081a66ffacfe85a37ff775addafcf3371e967328/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp#L2245612 // see: https://github.com/llvm/llvm-project/blob/081a66ffacfe85a37ff775addafcf3371e967328/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp#L224
46985613
4699 const temp, const temp_lock = try self.allocReg();5614 const temp, const temp_lock = try func.allocReg(.int);
4700 defer self.register_manager.unlockReg(temp_lock);5615 defer func.register_manager.unlockReg(temp_lock);
47015616
4702 const lo32: i32 = @truncate(x);5617 const lo32: i32 = @truncate(x);
4703 const carry: i32 = if (lo32 < 0) 1 else 0;5618 const carry: i32 = if (lo32 < 0) 1 else 0;
4704 const hi32: i32 = @truncate((x >> 32) +% carry);5619 const hi32: i32 = @truncate((x >> 32) +% carry);
47055620
4706 try self.genSetReg(Type.i32, temp, .{ .immediate = @bitCast(@as(i64, lo32)) });5621 try func.genSetReg(Type.i32, temp, .{ .immediate = @bitCast(@as(i64, lo32)) });
4707 try self.genSetReg(Type.i32, reg, .{ .immediate = @bitCast(@as(i64, hi32)) });5622 try func.genSetReg(Type.i32, reg, .{ .immediate = @bitCast(@as(i64, hi32)) });
47085623
4709 _ = try self.addInst(.{5624 _ = try func.addInst(.{
4710 .tag = .slli,5625 .tag = .slli,
4711 .ops = .rri,5626 .ops = .rri,
4712 .data = .{ .i_type = .{5627 .data = .{ .i_type = .{
4713 .rd = reg,5628 .rd = reg,
4714 .rs1 = reg,5629 .rs1 = reg,
4715 .imm12 = Immediate.s(32),5630 .imm12 = Immediate.u(32),
4716 } },5631 } },
4717 });5632 });
47185633
4719 _ = try self.addInst(.{5634 _ = try func.addInst(.{
4720 .tag = .add,5635 .tag = .add,
4721 .ops = .rrr,5636 .ops = .rrr,
4722 .data = .{ .r_type = .{5637 .data = .{ .r_type = .{
...@@ -4732,8 +5647,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -4732,8 +5647,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
4732 if (src_reg.id() == reg.id())5647 if (src_reg.id() == reg.id())
4733 return;5648 return;
47345649
4735 // mov reg, src_reg5650 const src_reg_class = src_reg.class();
4736 _ = try self.addInst(.{5651
5652 if (src_reg_class == .float and dst_reg_class == .int) {
5653 // to move from float -> int, we use FMV.X.W
5654 return func.fail("TODO: genSetReg float -> int", .{});
5655 }
5656
5657 // mv reg, src_reg
5658 _ = try func.addInst(.{
4737 .tag = .pseudo,5659 .tag = .pseudo,
4738 .ops = .pseudo_mv,5660 .ops = .pseudo_mv,
4739 .data = .{ .rr = .{5661 .data = .{ .rr = .{
...@@ -4742,22 +5664,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -4742,22 +5664,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
4742 } },5664 } },
4743 });5665 });
4744 },5666 },
4745 .register_pair => |pair| try self.genSetReg(ty, reg, .{ .register = pair[0] }),5667 .register_pair => return func.fail("genSetReg should we allow reg -> reg_pair?", .{}),
4746 .memory => |addr| {
4747 try self.genSetReg(ty, reg, .{ .immediate = addr });
4748
4749 _ = try self.addInst(.{
4750 .tag = .ld,
4751 .ops = .rri,
4752 .data = .{ .i_type = .{
4753 .rd = reg,
4754 .rs1 = reg,
4755 .imm12 = Immediate.s(0),
4756 } },
4757 });
4758 },
4759 .load_frame => |frame| {5668 .load_frame => |frame| {
4760 _ = try self.addInst(.{5669 _ = try func.addInst(.{
4761 .tag = .pseudo,5670 .tag = .pseudo,
4762 .ops = .pseudo_load_rm,5671 .ops = .pseudo_load_rm,
4763 .data = .{ .rm = .{5672 .data = .{ .rm = .{
...@@ -4765,47 +5674,73 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -4765,47 +5674,73 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
4765 .m = .{5674 .m = .{
4766 .base = .{ .frame = frame.index },5675 .base = .{ .frame = frame.index },
4767 .mod = .{5676 .mod = .{
4768 .rm = .{5677 .size = func.memSize(ty),
4769 .size = self.memSize(ty),5678 .unsigned = ty.isUnsignedInt(zcu),
4770 .disp = frame.off,5679 .disp = frame.off,
4771 },
4772 },5680 },
4773 },5681 },
4774 } },5682 } },
4775 });5683 });
4776 },5684 },
4777 .lea_frame => |frame| {5685 .memory => |addr| {
4778 _ = try self.addInst(.{5686 try func.genSetReg(ty, reg, .{ .immediate = addr });
5687
5688 _ = try func.addInst(.{
5689 .tag = .ld,
5690 .ops = .rri,
5691 .data = .{ .i_type = .{
5692 .rd = reg,
5693 .rs1 = reg,
5694 .imm12 = Immediate.u(0),
5695 } },
5696 });
5697 },
5698 .lea_frame, .register_offset => {
5699 _ = try func.addInst(.{
4779 .tag = .pseudo,5700 .tag = .pseudo,
4780 .ops = .pseudo_lea_rm,5701 .ops = .pseudo_lea_rm,
4781 .data = .{ .rm = .{5702 .data = .{ .rm = .{
4782 .r = reg,5703 .r = reg,
4783 .m = .{5704 .m = switch (src_mcv) {
4784 .base = .{ .frame = frame.index },5705 .register_offset => |reg_off| .{
4785 .mod = .{5706 .base = .{ .reg = reg_off.reg },
4786 .rm = .{5707 .mod = .{
4787 .size = self.memSize(ty),5708 .size = func.memSize(ty),
5709 .disp = reg_off.off,
5710 .unsigned = false,
5711 },
5712 },
5713 .lea_frame => |frame| .{
5714 .base = .{ .frame = frame.index },
5715 .mod = .{
5716 .size = func.memSize(ty),
4788 .disp = frame.off,5717 .disp = frame.off,
5718 .unsigned = false,
4789 },5719 },
4790 },5720 },
5721 else => unreachable,
4791 },5722 },
4792 } },5723 } },
4793 });5724 });
4794 },5725 },
4795 .load_symbol => {
4796 try self.genSetReg(ty, reg, src_mcv.address());
4797 try self.genSetReg(ty, reg, .{ .indirect = .{ .reg = reg } });
4798 },
4799 .indirect => |reg_off| {5726 .indirect => |reg_off| {
5727 const float_class = dst_reg_class == .float;
5728
4800 const load_tag: Mir.Inst.Tag = switch (abi_size) {5729 const load_tag: Mir.Inst.Tag = switch (abi_size) {
4801 1 => .lb,5730 1 => if (float_class)
4802 2 => .lh,5731 unreachable // Zig does not support 8-bit floats
4803 4 => .lw,5732 else
4804 8 => .ld,5733 .lb,
4805 else => return self.fail("TODO: genSetReg for size {d}", .{abi_size}),5734 2 => if (float_class)
5735 return func.fail("TODO: genSetReg indirect 16-bit float", .{})
5736 else
5737 .lh,
5738 4 => if (float_class) .flw else .lw,
5739 8 => if (float_class) .fld else .ld,
5740 else => return std.debug.panic("TODO: genSetReg for size {d}", .{abi_size}),
4806 };5741 };
48075742
4808 _ = try self.addInst(.{5743 _ = try func.addInst(.{
4809 .tag = load_tag,5744 .tag = load_tag,
4810 .ops = .rri,5745 .ops = .rri,
4811 .data = .{ .i_type = .{5746 .data = .{ .i_type = .{
...@@ -4818,54 +5753,183 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -4818,54 +5753,183 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
4818 .lea_symbol => |sym_off| {5753 .lea_symbol => |sym_off| {
4819 assert(sym_off.off == 0);5754 assert(sym_off.off == 0);
48205755
4821 const atom_index = try self.symbolIndex();5756 const atom_index = try func.symbolIndex();
48225757
4823 _ = try self.addInst(.{5758 _ = try func.addInst(.{
4824 .tag = .pseudo,5759 .tag = .pseudo,
4825 .ops = .pseudo_load_symbol,5760 .ops = .pseudo_load_symbol,
4826 .data = .{ .payload = try self.addExtra(Mir.LoadSymbolPayload{5761 .data = .{ .payload = try func.addExtra(Mir.LoadSymbolPayload{
4827 .register = reg.id(),5762 .register = reg.encodeId(),
4828 .atom_index = atom_index,5763 .atom_index = atom_index,
4829 .sym_index = sym_off.sym,5764 .sym_index = sym_off.sym,
4830 }) },5765 }) },
4831 });5766 });
4832 },5767 },
4833 .air_ref => |ref| try self.genSetReg(ty, reg, try self.resolveInst(ref)),5768 .load_symbol => {
4834 else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),5769 const addr_reg, const addr_lock = try func.allocReg(.int);
5770 defer func.register_manager.unlockReg(addr_lock);
5771
5772 try func.genSetReg(ty, addr_reg, src_mcv.address());
5773 try func.genSetReg(ty, reg, .{ .indirect = .{ .reg = addr_reg } });
5774 },
5775 .air_ref => |ref| try func.genSetReg(ty, reg, try func.resolveInst(ref)),
5776 else => return func.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),
5777 }
5778}
5779
5780fn genSetMem(
5781 func: *Func,
5782 base: Memory.Base,
5783 disp: i32,
5784 ty: Type,
5785 src_mcv: MCValue,
5786) InnerError!void {
5787 const mod = func.bin_file.comp.module.?;
5788 const abi_size: u32 = @intCast(ty.abiSize(mod));
5789 const dst_ptr_mcv: MCValue = switch (base) {
5790 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
5791 .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },
5792 .reloc => |base_symbol| .{ .lea_symbol = .{ .sym = base_symbol.sym_index, .off = disp } },
5793 };
5794 switch (src_mcv) {
5795 .none,
5796 .unreach,
5797 .dead,
5798 .reserved_frame,
5799 => unreachable,
5800 .undef => try func.genInlineMemset(
5801 dst_ptr_mcv,
5802 src_mcv,
5803 .{ .immediate = abi_size },
5804 ),
5805 .register_offset,
5806 .memory,
5807 .indirect,
5808 .load_frame,
5809 .lea_frame,
5810 .load_symbol,
5811 .lea_symbol,
5812 => switch (abi_size) {
5813 0 => {},
5814 1, 2, 4, 8 => {
5815 // no matter what type, it should use an integer register
5816 const src_reg = try func.copyToTmpRegister(Type.usize, src_mcv);
5817 const src_lock = func.register_manager.lockRegAssumeUnused(src_reg);
5818 defer func.register_manager.unlockReg(src_lock);
5819
5820 try func.genSetMem(base, disp, ty, .{ .register = src_reg });
5821 },
5822 else => try func.genInlineMemcpy(
5823 dst_ptr_mcv,
5824 src_mcv.address(),
5825 .{ .immediate = abi_size },
5826 ),
5827 },
5828 .register => |reg| {
5829 const mem_size = switch (base) {
5830 .frame => |base_fi| mem_size: {
5831 assert(disp >= 0);
5832 const frame_abi_size = func.frame_allocs.items(.abi_size)[@intFromEnum(base_fi)];
5833 const frame_spill_pad = func.frame_allocs.items(.spill_pad)[@intFromEnum(base_fi)];
5834 assert(frame_abi_size - frame_spill_pad - disp >= abi_size);
5835 break :mem_size if (frame_abi_size - frame_spill_pad - disp == abi_size)
5836 frame_abi_size
5837 else
5838 abi_size;
5839 },
5840 else => abi_size,
5841 };
5842 const src_size = math.ceilPowerOfTwoAssert(u32, abi_size);
5843 const src_align = Alignment.fromNonzeroByteUnits(math.ceilPowerOfTwoAssert(u32, src_size));
5844 if (src_size > mem_size) {
5845 const frame_index = try func.allocFrameIndex(FrameAlloc.init(.{
5846 .size = src_size,
5847 .alignment = src_align,
5848 }));
5849 const frame_mcv: MCValue = .{ .load_frame = .{ .index = frame_index } };
5850 _ = try func.addInst(.{
5851 .tag = .pseudo,
5852 .ops = .pseudo_store_rm,
5853 .data = .{ .rm = .{
5854 .r = reg,
5855 .m = .{
5856 .base = .{ .frame = frame_index },
5857 .mod = .{
5858 .size = Memory.Size.fromByteSize(src_size),
5859 .unsigned = false,
5860 },
5861 },
5862 } },
5863 });
5864 try func.genSetMem(base, disp, ty, frame_mcv);
5865 try func.freeValue(frame_mcv);
5866 } else _ = try func.addInst(.{
5867 .tag = .pseudo,
5868 .ops = .pseudo_store_rm,
5869 .data = .{ .rm = .{
5870 .r = reg,
5871 .m = .{
5872 .base = base,
5873 .mod = .{
5874 .size = func.memSize(ty),
5875 .disp = disp,
5876 .unsigned = false,
5877 },
5878 },
5879 } },
5880 });
5881 },
5882 .register_pair => |src_regs| {
5883 var part_disp: i32 = disp;
5884 for (try func.splitType(ty), src_regs) |src_ty, src_reg| {
5885 try func.genSetMem(base, part_disp, src_ty, .{ .register = src_reg });
5886 part_disp += @intCast(src_ty.abiSize(mod));
5887 }
5888 },
5889 .immediate => {
5890 // TODO: remove this lock in favor of a copyToTmpRegister when we load 64 bit immediates with
5891 // a register allocation.
5892 const reg, const reg_lock = try func.promoteReg(ty, src_mcv);
5893 defer if (reg_lock) |lock| func.register_manager.unlockReg(lock);
5894
5895 return func.genSetMem(base, disp, ty, .{ .register = reg });
5896 },
5897 .air_ref => |src_ref| try func.genSetMem(base, disp, ty, try func.resolveInst(src_ref)),
4835 }5898 }
4836}5899}
48375900
4838fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void {5901fn airIntFromPtr(func: *Func, inst: Air.Inst.Index) !void {
4839 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;5902 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4840 const result = result: {5903 const result = result: {
4841 const src_mcv = try self.resolveInst(un_op);5904 const src_mcv = try func.resolveInst(un_op);
4842 if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;5905 const src_ty = func.typeOfIndex(inst);
5906 if (func.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;
48435907
4844 const dst_mcv = try self.allocRegOrMem(inst, true);5908 const dst_mcv = try func.allocRegOrMem(src_ty, inst, true);
4845 const dst_ty = self.typeOfIndex(inst);5909 const dst_ty = func.typeOfIndex(inst);
4846 try self.genCopy(dst_ty, dst_mcv, src_mcv);5910 try func.genCopy(dst_ty, dst_mcv, src_mcv);
4847 break :result dst_mcv;5911 break :result dst_mcv;
4848 };5912 };
4849 return self.finishAir(inst, result, .{ un_op, .none, .none });5913 return func.finishAir(inst, result, .{ un_op, .none, .none });
4850}5914}
48515915
4852fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {5916fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {
4853 const zcu = self.bin_file.comp.module.?;5917 const zcu = func.bin_file.comp.module.?;
48545918
4855 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5919 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
4856 const result = if (self.liveness.isUnused(inst)) .unreach else result: {5920 const result = if (func.liveness.isUnused(inst)) .unreach else result: {
4857 const src_mcv = try self.resolveInst(ty_op.operand);5921 const src_mcv = try func.resolveInst(ty_op.operand);
48585922
4859 const dst_ty = self.typeOfIndex(inst);5923 const dst_ty = func.typeOfIndex(inst);
4860 const src_ty = self.typeOf(ty_op.operand);5924 const src_ty = func.typeOf(ty_op.operand);
48615925
4862 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;5926 const src_lock = if (src_mcv.getReg()) |reg| func.register_manager.lockReg(reg) else null;
4863 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);5927 defer if (src_lock) |lock| func.register_manager.unlockReg(lock);
48645928
4865 const dst_mcv = if (dst_ty.abiSize(zcu) <= src_ty.abiSize(zcu) and5929 const dst_mcv = if (dst_ty.abiSize(zcu) <= src_ty.abiSize(zcu) and
4866 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {5930 func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
4867 const dst_mcv = try self.allocRegOrMem(inst, true);5931 const dst_mcv = try func.allocRegOrMem(dst_ty, inst, true);
4868 try self.genCopy(switch (math.order(dst_ty.abiSize(zcu), src_ty.abiSize(zcu))) {5932 try func.genCopy(switch (math.order(dst_ty.abiSize(zcu), src_ty.abiSize(zcu))) {
4869 .lt => dst_ty,5933 .lt => dst_ty,
4870 .eq => if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,5934 .eq => if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,
4871 .gt => src_ty,5935 .gt => src_ty,
...@@ -4880,230 +5944,440 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -4880,230 +5944,440 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
4880 const bit_size = dst_ty.bitSize(zcu);5944 const bit_size = dst_ty.bitSize(zcu);
4881 if (abi_size * 8 <= bit_size) break :result dst_mcv;5945 if (abi_size * 8 <= bit_size) break :result dst_mcv;
48825946
4883 return self.fail("TODO: airBitCast {} to {}", .{ src_ty.fmt(zcu), dst_ty.fmt(zcu) });5947 return func.fail("TODO: airBitCast {} to {}", .{ src_ty.fmt(zcu), dst_ty.fmt(zcu) });
4884 };5948 };
4885 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5949 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
4886}5950}
5951
5952fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {
5953 const zcu = func.bin_file.comp.module.?;
5954 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5955
5956 const slice_ty = func.typeOfIndex(inst);
5957 const ptr_ty = func.typeOf(ty_op.operand);
5958 const ptr = try func.resolveInst(ty_op.operand);
5959 const array_ty = ptr_ty.childType(zcu);
5960 const array_len = array_ty.arrayLen(zcu);
5961
5962 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(slice_ty, zcu));
5963 try func.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);
5964 try func.genSetMem(
5965 .{ .frame = frame_index },
5966 @intCast(ptr_ty.abiSize(zcu)),
5967 Type.usize,
5968 .{ .immediate = array_len },
5969 );
48875970
4888fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {5971 const result = MCValue{ .load_frame = .{ .index = frame_index } };
4889 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5972 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
4890 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airArrayToSlice for {}", .{
4891 self.target.cpu.arch,
4892 });
4893 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
4894}5973}
48955974
4896fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void {5975fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void {
4897 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5976 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
4898 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airFloatFromInt for {}", .{5977 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airFloatFromInt for {}", .{
4899 self.target.cpu.arch,5978 func.target.cpu.arch,
4900 });5979 });
4901 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5980 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
4902}5981}
49035982
4904fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void {5983fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {
4905 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5984 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
4906 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airIntFromFloat for {}", .{5985 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airIntFromFloat for {}", .{
4907 self.target.cpu.arch,5986 func.target.cpu.arch,
4908 });5987 });
4909 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5988 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
4910}5989}
49115990
4912fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {5991fn airCmpxchg(func: *Func, inst: Air.Inst.Index) !void {
4913 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;5992 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
4914 const extra = self.air.extraData(Air.Block, ty_pl.payload);5993 const extra = func.air.extraData(Air.Block, ty_pl.payload);
4915 _ = extra;5994 _ = extra;
4916 return self.fail("TODO implement airCmpxchg for {}", .{5995 return func.fail("TODO implement airCmpxchg for {}", .{
4917 self.target.cpu.arch,5996 func.target.cpu.arch,
4918 });5997 });
4919 // return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });5998 // return func.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });
4920}5999}
49216000
4922fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void {6001fn airAtomicRmw(func: *Func, inst: Air.Inst.Index) !void {
4923 _ = inst;6002 _ = inst;
4924 return self.fail("TODO implement airCmpxchg for {}", .{self.target.cpu.arch});6003 return func.fail("TODO implement airCmpxchg for {}", .{func.target.cpu.arch});
4925}6004}
49266005
4927fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void {6006fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void {
4928 _ = inst;6007 _ = inst;
4929 return self.fail("TODO implement airAtomicLoad for {}", .{self.target.cpu.arch});6008 return func.fail("TODO implement airAtomicLoad for {}", .{func.target.cpu.arch});
4930}6009}
49316010
4932fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void {6011fn airAtomicStore(func: *Func, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void {
4933 _ = inst;6012 _ = inst;
4934 _ = order;6013 _ = order;
4935 return self.fail("TODO implement airAtomicStore for {}", .{self.target.cpu.arch});6014 return func.fail("TODO implement airAtomicStore for {}", .{func.target.cpu.arch});
4936}6015}
49376016
4938fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {6017fn airMemset(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
4939 _ = inst;6018 const zcu = func.bin_file.comp.module.?;
4940 if (safety) {6019 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
4941 // TODO if the value is undef, write 0xaa bytes to dest6020
4942 } else {6021 result: {
4943 // TODO if the value is undef, don't lower this instruction6022 if (!safety and (try func.resolveInst(bin_op.rhs)) == .undef) break :result;
6023
6024 const dst_ptr = try func.resolveInst(bin_op.lhs);
6025 const dst_ptr_ty = func.typeOf(bin_op.lhs);
6026 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
6027 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
6028 else => null,
6029 };
6030 defer if (dst_ptr_lock) |lock| func.register_manager.unlockReg(lock);
6031
6032 const src_val = try func.resolveInst(bin_op.rhs);
6033 const elem_ty = func.typeOf(bin_op.rhs);
6034 const src_val_lock: ?RegisterLock = switch (src_val) {
6035 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
6036 else => null,
6037 };
6038 defer if (src_val_lock) |lock| func.register_manager.unlockReg(lock);
6039
6040 const elem_abi_size: u31 = @intCast(elem_ty.abiSize(zcu));
6041
6042 if (elem_abi_size == 1) {
6043 const ptr: MCValue = switch (dst_ptr_ty.ptrSize(zcu)) {
6044 // TODO: this only handles slices stored in the stack
6045 .Slice => dst_ptr,
6046 .One => dst_ptr,
6047 .C, .Many => unreachable,
6048 };
6049 const len: MCValue = switch (dst_ptr_ty.ptrSize(zcu)) {
6050 // TODO: this only handles slices stored in the stack
6051 .Slice => dst_ptr.address().offset(8).deref(),
6052 .One => .{ .immediate = dst_ptr_ty.childType(zcu).arrayLen(zcu) },
6053 .C, .Many => unreachable,
6054 };
6055 const len_lock: ?RegisterLock = switch (len) {
6056 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
6057 else => null,
6058 };
6059 defer if (len_lock) |lock| func.register_manager.unlockReg(lock);
6060
6061 try func.genInlineMemset(ptr, src_val, len);
6062 break :result;
6063 }
6064
6065 // Store the first element, and then rely on memcpy copying forwards.
6066 // Length zero requires a runtime check - so we handle arrays specially
6067 // here to elide it.
6068 switch (dst_ptr_ty.ptrSize(zcu)) {
6069 .Slice => return func.fail("TODO: airMemset Slices", .{}),
6070 .One => {
6071 const elem_ptr_ty = try zcu.singleMutPtrType(elem_ty);
6072
6073 const len = dst_ptr_ty.childType(zcu).arrayLen(zcu);
6074
6075 assert(len != 0); // prevented by Sema
6076 try func.store(dst_ptr, src_val, elem_ptr_ty, elem_ty);
6077
6078 const second_elem_ptr_reg, const second_elem_ptr_lock = try func.allocReg(.int);
6079 defer func.register_manager.unlockReg(second_elem_ptr_lock);
6080
6081 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };
6082
6083 try func.genSetReg(Type.usize, second_elem_ptr_reg, .{ .register_offset = .{
6084 .reg = try func.copyToTmpRegister(Type.usize, dst_ptr),
6085 .off = elem_abi_size,
6086 } });
6087
6088 const bytes_to_copy: MCValue = .{ .immediate = elem_abi_size * (len - 1) };
6089 try func.genInlineMemcpy(second_elem_ptr_mcv, dst_ptr, bytes_to_copy);
6090 },
6091 .C, .Many => unreachable,
6092 }
4944 }6093 }
4945 return self.fail("TODO implement airMemset for {}", .{self.target.cpu.arch});6094 return func.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
4946}6095}
49476096
4948fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {6097fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void {
4949 _ = inst;6098 _ = inst;
4950 return self.fail("TODO implement airMemcpy for {}", .{self.target.cpu.arch});6099 return func.fail("TODO implement airMemcpy for {}", .{func.target.cpu.arch});
4951}6100}
49526101
4953fn airTagName(self: *Self, inst: Air.Inst.Index) !void {6102fn airTagName(func: *Func, inst: Air.Inst.Index) !void {
4954 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;6103 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4955 const operand = try self.resolveInst(un_op);6104 const operand = try func.resolveInst(un_op);
4956 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else {6105 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else {
4957 _ = operand;6106 _ = operand;
4958 return self.fail("TODO implement airTagName for riscv64", .{});6107 return func.fail("TODO implement airTagName for riscv64", .{});
4959 };6108 };
4960 return self.finishAir(inst, result, .{ un_op, .none, .none });6109 return func.finishAir(inst, result, .{ un_op, .none, .none });
4961}6110}
49626111
4963fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {6112fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {
4964 const zcu = self.bin_file.comp.module.?;6113 const zcu = func.bin_file.comp.module.?;
4965 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;6114 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
49666115
4967 const err_ty = self.typeOf(un_op);6116 const err_ty = func.typeOf(un_op);
4968 const err_mcv = try self.resolveInst(un_op);6117 const err_mcv = try func.resolveInst(un_op);
49696118
4970 const err_reg = try self.copyToTmpRegister(err_ty, err_mcv);6119 const err_reg = try func.copyToTmpRegister(err_ty, err_mcv);
4971 const err_lock = self.register_manager.lockRegAssumeUnused(err_reg);6120 const err_lock = func.register_manager.lockRegAssumeUnused(err_reg);
4972 defer self.register_manager.unlockReg(err_lock);6121 defer func.register_manager.unlockReg(err_lock);
49736122
4974 const addr_reg, const addr_lock = try self.allocReg();6123 const addr_reg, const addr_lock = try func.allocReg(.int);
4975 defer self.register_manager.unlockReg(addr_lock);6124 defer func.register_manager.unlockReg(addr_lock);
49766125
6126 // this is now the base address of the error name table
4977 const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, zcu);6127 const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, zcu);
4978 if (self.bin_file.cast(link.File.Elf)) |elf_file| {6128 if (func.bin_file.cast(link.File.Elf)) |elf_file| {
4979 const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, lazy_sym) catch |err|6129 const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, lazy_sym) catch |err|
4980 return self.fail("{s} creating lazy symbol", .{@errorName(err)});6130 return func.fail("{s} creating lazy symbol", .{@errorName(err)});
4981 const sym = elf_file.symbol(sym_index);6131 const sym = elf_file.symbol(sym_index);
4982 try self.genSetReg(Type.usize, addr_reg, .{ .load_symbol = .{ .sym = sym.esym_index } });6132 try func.genSetReg(Type.usize, addr_reg, .{ .load_symbol = .{ .sym = sym.esym_index } });
4983 } else {6133 } else {
4984 return self.fail("TODO: riscv non-elf", .{});6134 return func.fail("TODO: riscv non-elf", .{});
4985 }6135 }
49866136
4987 const start_reg, const start_lock = try self.allocReg();6137 const start_reg, const start_lock = try func.allocReg(.int);
4988 defer self.register_manager.unlockReg(start_lock);6138 defer func.register_manager.unlockReg(start_lock);
6139
6140 const end_reg, const end_lock = try func.allocReg(.int);
6141 defer func.register_manager.unlockReg(end_lock);
6142
6143 // const tmp_reg, const tmp_lock = try func.allocReg(.int);
6144 // defer func.register_manager.unlockReg(tmp_lock);
6145
6146 // we move the base address forward by the following formula: base + (errno * 8)
6147
6148 // shifting left by 4 is the same as multiplying by 8
6149 _ = try func.addInst(.{
6150 .tag = .slli,
6151 .ops = .rri,
6152 .data = .{ .i_type = .{
6153 .imm12 = Immediate.u(4),
6154 .rd = err_reg,
6155 .rs1 = err_reg,
6156 } },
6157 });
6158
6159 _ = try func.addInst(.{
6160 .tag = .add,
6161 .ops = .rrr,
6162 .data = .{ .r_type = .{
6163 .rd = addr_reg,
6164 .rs1 = addr_reg,
6165 .rs2 = err_reg,
6166 } },
6167 });
6168
6169 _ = try func.addInst(.{
6170 .tag = .pseudo,
6171 .ops = .pseudo_load_rm,
6172 .data = .{
6173 .rm = .{
6174 .r = start_reg,
6175 .m = .{
6176 .base = .{ .reg = addr_reg },
6177 .mod = .{ .size = .dword, .unsigned = true },
6178 },
6179 },
6180 },
6181 });
6182
6183 _ = try func.addInst(.{
6184 .tag = .pseudo,
6185 .ops = .pseudo_load_rm,
6186 .data = .{
6187 .rm = .{
6188 .r = end_reg,
6189 .m = .{
6190 .base = .{ .reg = addr_reg },
6191 .mod = .{ .size = .dword, .unsigned = true },
6192 },
6193 },
6194 },
6195 });
49896196
4990 const end_reg, const end_lock = try self.allocReg();6197 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, false);
4991 defer self.register_manager.unlockReg(end_lock);6198 const frame = dst_mcv.load_frame;
6199 try func.genSetMem(
6200 .{ .frame = frame.index },
6201 frame.off,
6202 Type.usize,
6203 .{ .register = start_reg },
6204 );
49926205
4993 _ = start_reg;6206 try func.genSetMem(
4994 _ = end_reg;6207 .{ .frame = frame.index },
6208 frame.off + 8,
6209 Type.usize,
6210 .{ .register = end_reg },
6211 );
49956212
4996 return self.fail("TODO: airErrorName", .{});6213 return func.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
4997}6214}
49986215
4999fn airSplat(self: *Self, inst: Air.Inst.Index) !void {6216fn airSplat(func: *Func, inst: Air.Inst.Index) !void {
5000 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;6217 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5001 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airSplat for riscv64", .{});6218 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airSplat for riscv64", .{});
5002 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });6219 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
5003}6220}
50046221
5005fn airSelect(self: *Self, inst: Air.Inst.Index) !void {6222fn airSelect(func: *Func, inst: Air.Inst.Index) !void {
5006 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;6223 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
5007 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;6224 const extra = func.air.extraData(Air.Bin, pl_op.payload).data;
5008 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airSelect for riscv64", .{});6225 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airSelect for riscv64", .{});
5009 return self.finishAir(inst, result, .{ pl_op.operand, extra.lhs, extra.rhs });6226 return func.finishAir(inst, result, .{ pl_op.operand, extra.lhs, extra.rhs });
5010}6227}
50116228
5012fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {6229fn airShuffle(func: *Func, inst: Air.Inst.Index) !void {
5013 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;6230 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5014 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airShuffle for riscv64", .{});6231 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShuffle for riscv64", .{});
5015 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });6232 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
5016}6233}
50176234
5018fn airReduce(self: *Self, inst: Air.Inst.Index) !void {6235fn airReduce(func: *Func, inst: Air.Inst.Index) !void {
5019 const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce;6236 const reduce = func.air.instructions.items(.data)[@intFromEnum(inst)].reduce;
5020 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airReduce for riscv64", .{});6237 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airReduce for riscv64", .{});
5021 return self.finishAir(inst, result, .{ reduce.operand, .none, .none });6238 return func.finishAir(inst, result, .{ reduce.operand, .none, .none });
5022}6239}
50236240
5024fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {6241fn airAggregateInit(func: *Func, inst: Air.Inst.Index) !void {
5025 const zcu = self.bin_file.comp.module.?;6242 const zcu = func.bin_file.comp.module.?;
5026 const result_ty = self.typeOfIndex(inst);6243 const result_ty = func.typeOfIndex(inst);
5027 const len: usize = @intCast(result_ty.arrayLen(zcu));6244 const len: usize = @intCast(result_ty.arrayLen(zcu));
5028 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;6245 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
5029 const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]);6246 const elements: []const Air.Inst.Ref = @ptrCast(func.air.extra[ty_pl.payload..][0..len]);
6247
5030 const result: MCValue = result: {6248 const result: MCValue = result: {
5031 switch (result_ty.zigTypeTag(zcu)) {6249 switch (result_ty.zigTypeTag(zcu)) {
5032 .Struct => {6250 .Struct => {
5033 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, zcu));6251 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(result_ty, zcu));
6252 if (result_ty.containerLayout(zcu) == .@"packed") {
6253 const struct_obj = zcu.typeToStruct(result_ty).?;
6254 try func.genInlineMemset(
6255 .{ .lea_frame = .{ .index = frame_index } },
6256 .{ .immediate = 0 },
6257 .{ .immediate = result_ty.abiSize(zcu) },
6258 );
50346259
5035 if (result_ty.containerLayout(zcu) == .@"packed") {} else for (elements, 0..) |elem, elem_i| {6260 for (elements, 0..) |elem, elem_i_usize| {
6261 const elem_i: u32 = @intCast(elem_i_usize);
6262 if ((try result_ty.structFieldValueComptime(zcu, elem_i)) != null) continue;
6263
6264 const elem_ty = result_ty.structFieldType(elem_i, zcu);
6265 const elem_bit_size: u32 = @intCast(elem_ty.bitSize(zcu));
6266 if (elem_bit_size > 64) {
6267 return func.fail(
6268 "TODO airAggregateInit implement packed structs with large fields",
6269 .{},
6270 );
6271 }
6272
6273 const elem_abi_size: u32 = @intCast(elem_ty.abiSize(zcu));
6274 const elem_abi_bits = elem_abi_size * 8;
6275 const elem_off = zcu.structPackedFieldBitOffset(struct_obj, elem_i);
6276 const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);
6277 const elem_bit_off = elem_off % elem_abi_bits;
6278 const elem_mcv = try func.resolveInst(elem);
6279
6280 _ = elem_byte_off;
6281 _ = elem_bit_off;
6282
6283 const elem_lock = switch (elem_mcv) {
6284 .register => |reg| func.register_manager.lockReg(reg),
6285 .immediate => |imm| lock: {
6286 if (imm == 0) continue;
6287 break :lock null;
6288 },
6289 else => null,
6290 };
6291 defer if (elem_lock) |lock| func.register_manager.unlockReg(lock);
6292
6293 return func.fail("TODO: airAggregateInit packed structs", .{});
6294 }
6295 } else for (elements, 0..) |elem, elem_i| {
5036 if ((try result_ty.structFieldValueComptime(zcu, elem_i)) != null) continue;6296 if ((try result_ty.structFieldValueComptime(zcu, elem_i)) != null) continue;
50376297
5038 const elem_ty = result_ty.structFieldType(elem_i, zcu);6298 const elem_ty = result_ty.structFieldType(elem_i, zcu);
5039 const elem_off: i32 = @intCast(result_ty.structFieldOffset(elem_i, zcu));6299 const elem_off: i32 = @intCast(result_ty.structFieldOffset(elem_i, zcu));
5040 const elem_mcv = try self.resolveInst(elem);6300 const elem_mcv = try func.resolveInst(elem);
50416301 try func.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, elem_mcv);
5042 const elem_frame: FrameAddr = .{6302 }
5043 .index = frame_index,6303 break :result .{ .load_frame = .{ .index = frame_index } };
5044 .off = elem_off,6304 },
5045 };6305 .Array => {
5046 try self.genSetStack(6306 const elem_ty = result_ty.childType(zcu);
6307 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(result_ty, zcu));
6308 const elem_size: u32 = @intCast(elem_ty.abiSize(zcu));
6309
6310 for (elements, 0..) |elem, elem_i| {
6311 const elem_mcv = try func.resolveInst(elem);
6312 const elem_off: i32 = @intCast(elem_size * elem_i);
6313 try func.genSetMem(
6314 .{ .frame = frame_index },
6315 elem_off,
5047 elem_ty,6316 elem_ty,
5048 elem_frame,
5049 elem_mcv,6317 elem_mcv,
5050 );6318 );
5051 }6319 }
6320 if (result_ty.sentinel(zcu)) |sentinel| try func.genSetMem(
6321 .{ .frame = frame_index },
6322 @intCast(elem_size * elements.len),
6323 elem_ty,
6324 try func.genTypedValue(sentinel),
6325 );
6326 break :result .{ .load_frame = .{ .index = frame_index } };
5052 },6327 },
5053 else => return self.fail("TODO: airAggregateInit {}", .{result_ty.fmt(zcu)}),6328 else => return func.fail("TODO: airAggregate {}", .{result_ty.fmt(zcu)}),
5054 }6329 }
5055 break :result .{ .register = .zero };
5056 };6330 };
50576331
5058 if (elements.len <= Liveness.bpi - 1) {6332 if (elements.len <= Liveness.bpi - 1) {
5059 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);6333 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);
5060 @memcpy(buf[0..elements.len], elements);6334 @memcpy(buf[0..elements.len], elements);
5061 return self.finishAir(inst, result, buf);6335 return func.finishAir(inst, result, buf);
5062 }6336 }
5063 var bt = self.liveness.iterateBigTomb(inst);6337 var bt = func.liveness.iterateBigTomb(inst);
5064 for (elements) |elem| try self.feed(&bt, elem);6338 for (elements) |elem| try func.feed(&bt, elem);
5065 return self.finishAirResult(inst, result);6339 return func.finishAirResult(inst, result);
5066}6340}
50676341
5068fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {6342fn airUnionInit(func: *Func, inst: Air.Inst.Index) !void {
5069 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;6343 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
5070 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;6344 const extra = func.air.extraData(Air.UnionInit, ty_pl.payload).data;
5071 _ = extra;6345 _ = extra;
5072 return self.fail("TODO implement airUnionInit for riscv64", .{});6346 return func.fail("TODO implement airUnionInit for riscv64", .{});
5073 // return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });6347 // return func.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });
5074}6348}
50756349
5076fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {6350fn airPrefetch(func: *Func, inst: Air.Inst.Index) !void {
5077 const prefetch = self.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;6351 const prefetch = func.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;
5078 // TODO: RISC-V does have prefetch instruction variants.6352 // TODO: RISC-V does have prefetch instruction variants.
5079 // see here: https://raw.githubusercontent.com/riscv/riscv-CMOs/master/specifications/cmobase-v1.0.1.pdf6353 // see here: https://raw.githubusercontent.com/riscv/riscv-CMOs/master/specifications/cmobase-v1.0.1.pdf
5080 return self.finishAir(inst, .unreach, .{ prefetch.ptr, .none, .none });6354 return func.finishAir(inst, .unreach, .{ prefetch.ptr, .none, .none });
5081}6355}
50826356
5083fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {6357fn airMulAdd(func: *Func, inst: Air.Inst.Index) !void {
5084 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;6358 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
5085 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;6359 const extra = func.air.extraData(Air.Bin, pl_op.payload).data;
5086 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else {6360 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else {
5087 return self.fail("TODO implement airMulAdd for riscv64", .{});6361 return func.fail("TODO implement airMulAdd for riscv64", .{});
5088 };6362 };
5089 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });6363 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });
5090}6364}
50916365
5092fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {6366fn resolveInst(func: *Func, ref: Air.Inst.Ref) InnerError!MCValue {
5093 const zcu = self.bin_file.comp.module.?;6367 const zcu = func.bin_file.comp.module.?;
50946368
5095 // If the type has no codegen bits, no need to store it.6369 // If the type has no codegen bits, no need to store it.
5096 const inst_ty = self.typeOf(ref);6370 const inst_ty = func.typeOf(ref);
5097 if (!inst_ty.hasRuntimeBits(zcu))6371 if (!inst_ty.hasRuntimeBits(zcu))
5098 return .none;6372 return .none;
50996373
5100 const mcv = if (ref.toIndex()) |inst| mcv: {6374 const mcv = if (ref.toIndex()) |inst| mcv: {
5101 break :mcv self.inst_tracking.getPtr(inst).?.short;6375 break :mcv func.inst_tracking.getPtr(inst).?.short;
5102 } else mcv: {6376 } else mcv: {
5103 const ip_index = ref.toInterned().?;6377 const ip_index = ref.toInterned().?;
5104 const gop = try self.const_tracking.getOrPut(self.gpa, ip_index);6378 const gop = try func.const_tracking.getOrPut(func.gpa, ip_index);
5105 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(6379 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(
5106 try self.genTypedValue(Value.fromInterned(ip_index)),6380 try func.genTypedValue(Value.fromInterned(ip_index)),
5107 );6381 );
5108 break :mcv gop.value_ptr.short;6382 break :mcv gop.value_ptr.short;
5109 };6383 };
...@@ -5111,21 +6385,21 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -5111,21 +6385,21 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
5111 return mcv;6385 return mcv;
5112}6386}
51136387
5114fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking {6388fn getResolvedInstValue(func: *Func, inst: Air.Inst.Index) *InstTracking {
5115 const tracking = self.inst_tracking.getPtr(inst).?;6389 const tracking = func.inst_tracking.getPtr(inst).?;
5116 return switch (tracking.short) {6390 return switch (tracking.short) {
5117 .none, .unreach, .dead => unreachable,6391 .none, .unreach, .dead => unreachable,
5118 else => tracking,6392 else => tracking,
5119 };6393 };
5120}6394}
51216395
5122fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {6396fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
5123 const zcu = self.bin_file.comp.module.?;6397 const zcu = func.bin_file.comp.module.?;
5124 const result = try codegen.genTypedValue(6398 const result = try codegen.genTypedValue(
5125 self.bin_file,6399 func.bin_file,
5126 self.src_loc,6400 func.src_loc,
5127 val,6401 val,
5128 zcu.funcOwnerDeclIndex(self.func_index),6402 zcu.funcOwnerDeclIndex(func.func_index),
5129 );6403 );
5130 const mcv: MCValue = switch (result) {6404 const mcv: MCValue = switch (result) {
5131 .mcv => |mcv| switch (mcv) {6405 .mcv => |mcv| switch (mcv) {
...@@ -5135,11 +6409,11 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {...@@ -5135,11 +6409,11 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
5135 .immediate => |imm| .{ .immediate = imm },6409 .immediate => |imm| .{ .immediate = imm },
5136 .memory => |addr| .{ .memory = addr },6410 .memory => |addr| .{ .memory = addr },
5137 .load_got, .load_direct, .load_tlv => {6411 .load_got, .load_direct, .load_tlv => {
5138 return self.fail("TODO: genTypedValue {s}", .{@tagName(mcv)});6412 return func.fail("TODO: genTypedValue {s}", .{@tagName(mcv)});
5139 },6413 },
5140 },6414 },
5141 .fail => |msg| {6415 .fail => |msg| {
5142 self.err_msg = msg;6416 func.err_msg = msg;
5143 return error.CodegenFail;6417 return error.CodegenFail;
5144 },6418 },
5145 };6419 };
...@@ -5152,36 +6426,39 @@ const CallMCValues = struct {...@@ -5152,36 +6426,39 @@ const CallMCValues = struct {
5152 stack_byte_count: u31,6426 stack_byte_count: u31,
5153 stack_align: Alignment,6427 stack_align: Alignment,
51546428
5155 fn deinit(self: *CallMCValues, func: *Self) void {6429 fn deinit(call: *CallMCValues, func: *Func) void {
5156 func.gpa.free(self.args);6430 func.gpa.free(call.args);
5157 self.* = undefined;6431 call.* = undefined;
5158 }6432 }
5159};6433};
51606434
5161/// Caller must call `CallMCValues.deinit`.6435/// Caller must call `CallMCValues.deinit`.
5162fn resolveCallingConventionValues(6436fn resolveCallingConventionValues(
5163 self: *Self,6437 func: *Func,
5164 fn_info: InternPool.Key.FuncType,6438 fn_info: InternPool.Key.FuncType,
6439 var_args: []const Type,
5165) !CallMCValues {6440) !CallMCValues {
5166 const zcu = self.bin_file.comp.module.?;6441 const zcu = func.bin_file.comp.module.?;
5167 const ip = &zcu.intern_pool;6442 const ip = &zcu.intern_pool;
51686443
5169 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len);6444 const param_types = try func.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
5170 defer self.gpa.free(param_types);6445 defer func.gpa.free(param_types);
51716446
5172 for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src| {6447 for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src| {
5173 dest.* = Type.fromInterned(src);6448 dest.* = Type.fromInterned(src);
5174 }6449 }
6450 for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg_ty|
6451 param_ty.* = func.promoteVarArg(arg_ty);
51756452
5176 const cc = fn_info.cc;6453 const cc = fn_info.cc;
5177 var result: CallMCValues = .{6454 var result: CallMCValues = .{
5178 .args = try self.gpa.alloc(MCValue, param_types.len),6455 .args = try func.gpa.alloc(MCValue, param_types.len),
5179 // These undefined values must be populated before returning from this function.6456 // These undefined values must be populated before returning from this function.
5180 .return_value = undefined,6457 .return_value = undefined,
5181 .stack_byte_count = 0,6458 .stack_byte_count = 0,
5182 .stack_align = undefined,6459 .stack_align = undefined,
5183 };6460 };
5184 errdefer self.gpa.free(result.args);6461 errdefer func.gpa.free(result.args);
51856462
5186 const ret_ty = Type.fromInterned(fn_info.return_type);6463 const ret_ty = Type.fromInterned(fn_info.return_type);
51876464
...@@ -5193,7 +6470,7 @@ fn resolveCallingConventionValues(...@@ -5193,7 +6470,7 @@ fn resolveCallingConventionValues(
5193 },6470 },
5194 .C, .Unspecified => {6471 .C, .Unspecified => {
5195 if (result.args.len > 8) {6472 if (result.args.len > 8) {
5196 return self.fail("RISC-V calling convention does not support more than 8 arguments", .{});6473 return func.fail("RISC-V calling convention does not support more than 8 arguments", .{});
5197 }6474 }
51986475
5199 var ret_int_reg_i: u32 = 0;6476 var ret_int_reg_i: u32 = 0;
...@@ -5209,21 +6486,29 @@ fn resolveCallingConventionValues(...@@ -5209,21 +6486,29 @@ fn resolveCallingConventionValues(
5209 } else {6486 } else {
5210 var ret_tracking: [2]InstTracking = undefined;6487 var ret_tracking: [2]InstTracking = undefined;
5211 var ret_tracking_i: usize = 0;6488 var ret_tracking_i: usize = 0;
6489 var ret_float_reg_i: usize = 0;
52126490
5213 const classes = mem.sliceTo(&abi.classifySystem(ret_ty, zcu), .none);6491 const classes = mem.sliceTo(&abi.classifySystem(ret_ty, zcu), .none);
52146492
5215 for (classes) |class| switch (class) {6493 for (classes) |class| switch (class) {
5216 .integer => {6494 .integer => {
5217 const ret_int_reg = abi.function_ret_regs[ret_int_reg_i];6495 const ret_int_reg = abi.Registers.Integer.function_ret_regs[ret_int_reg_i];
5218 ret_int_reg_i += 1;6496 ret_int_reg_i += 1;
52196497
5220 ret_tracking[ret_tracking_i] = InstTracking.init(.{ .register = ret_int_reg });6498 ret_tracking[ret_tracking_i] = InstTracking.init(.{ .register = ret_int_reg });
5221 ret_tracking_i += 1;6499 ret_tracking_i += 1;
5222 },6500 },
6501 .float => {
6502 const ret_float_reg = abi.Registers.Float.function_ret_regs[ret_float_reg_i];
6503 ret_float_reg_i += 1;
6504
6505 ret_tracking[ret_tracking_i] = InstTracking.init(.{ .register = ret_float_reg });
6506 ret_tracking_i += 1;
6507 },
5223 .memory => {6508 .memory => {
5224 const ret_int_reg = abi.function_ret_regs[ret_int_reg_i];6509 const ret_int_reg = abi.Registers.Integer.function_ret_regs[ret_int_reg_i];
5225 ret_int_reg_i += 1;6510 ret_int_reg_i += 1;
5226 const ret_indirect_reg = abi.function_arg_regs[param_int_reg_i];6511 const ret_indirect_reg = abi.Registers.Integer.function_arg_regs[param_int_reg_i];
5227 param_int_reg_i += 1;6512 param_int_reg_i += 1;
52286513
5229 ret_tracking[ret_tracking_i] = .{6514 ret_tracking[ret_tracking_i] = .{
...@@ -5232,11 +6517,11 @@ fn resolveCallingConventionValues(...@@ -5232,11 +6517,11 @@ fn resolveCallingConventionValues(
5232 };6517 };
5233 ret_tracking_i += 1;6518 ret_tracking_i += 1;
5234 },6519 },
5235 else => return self.fail("TODO: C calling convention return class {}", .{class}),6520 else => return func.fail("TODO: C calling convention return class {}", .{class}),
5236 };6521 };
52376522
5238 result.return_value = switch (ret_tracking_i) {6523 result.return_value = switch (ret_tracking_i) {
5239 else => return self.fail("ty {} took {} tracking return indices", .{ ret_ty.fmt(zcu), ret_tracking_i }),6524 else => return func.fail("ty {} took {} tracking return indices", .{ ret_ty.fmt(zcu), ret_tracking_i }),
5240 1 => ret_tracking[0],6525 1 => ret_tracking[0],
5241 2 => InstTracking.init(.{ .register_pair = .{6526 2 => InstTracking.init(.{ .register_pair = .{
5242 ret_tracking[0].short.register, ret_tracking[1].short.register,6527 ret_tracking[0].short.register, ret_tracking[1].short.register,
...@@ -5244,8 +6529,14 @@ fn resolveCallingConventionValues(...@@ -5244,8 +6529,14 @@ fn resolveCallingConventionValues(
5244 };6529 };
5245 }6530 }
52466531
6532 var param_float_reg_i: usize = 0;
6533
5247 for (param_types, result.args) |ty, *arg| {6534 for (param_types, result.args) |ty, *arg| {
5248 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));6535 if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) {
6536 assert(cc == .Unspecified);
6537 arg.* = .none;
6538 continue;
6539 }
52496540
5250 var arg_mcv: [2]MCValue = undefined;6541 var arg_mcv: [2]MCValue = undefined;
5251 var arg_mcv_i: usize = 0;6542 var arg_mcv_i: usize = 0;
...@@ -5254,7 +6545,7 @@ fn resolveCallingConventionValues(...@@ -5254,7 +6545,7 @@ fn resolveCallingConventionValues(
52546545
5255 for (classes) |class| switch (class) {6546 for (classes) |class| switch (class) {
5256 .integer => {6547 .integer => {
5257 const param_int_regs = abi.function_arg_regs;6548 const param_int_regs = abi.Registers.Integer.function_arg_regs;
5258 if (param_int_reg_i >= param_int_regs.len) break;6549 if (param_int_reg_i >= param_int_regs.len) break;
52596550
5260 const param_int_reg = param_int_regs[param_int_reg_i];6551 const param_int_reg = param_int_regs[param_int_reg_i];
...@@ -5263,36 +6554,47 @@ fn resolveCallingConventionValues(...@@ -5263,36 +6554,47 @@ fn resolveCallingConventionValues(
5263 arg_mcv[arg_mcv_i] = .{ .register = param_int_reg };6554 arg_mcv[arg_mcv_i] = .{ .register = param_int_reg };
5264 arg_mcv_i += 1;6555 arg_mcv_i += 1;
5265 },6556 },
6557 .float => {
6558 const param_float_regs = abi.Registers.Float.function_arg_regs;
6559 if (param_float_reg_i >= param_float_regs.len) break;
6560
6561 const param_float_reg = param_float_regs[param_float_reg_i];
6562 param_float_reg_i += 1;
6563
6564 arg_mcv[arg_mcv_i] = .{ .register = param_float_reg };
6565 arg_mcv_i += 1;
6566 },
5266 .memory => {6567 .memory => {
5267 const param_int_regs = abi.function_arg_regs;6568 const param_int_regs = abi.Registers.Integer.function_arg_regs;
6569
5268 const param_int_reg = param_int_regs[param_int_reg_i];6570 const param_int_reg = param_int_regs[param_int_reg_i];
6571 param_int_reg_i += 1;
52696572
5270 arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } };6573 arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } };
5271 arg_mcv_i += 1;6574 arg_mcv_i += 1;
5272 },6575 },
5273 else => return self.fail("TODO: C calling convention arg class {}", .{class}),6576 else => return func.fail("TODO: C calling convention arg class {}", .{class}),
5274 } else {6577 } else {
5275 arg.* = switch (arg_mcv_i) {6578 arg.* = switch (arg_mcv_i) {
5276 else => return self.fail("ty {} took {} tracking arg indices", .{ ty.fmt(zcu), arg_mcv_i }),6579 else => return func.fail("ty {} took {} tracking arg indices", .{ ty.fmt(zcu), arg_mcv_i }),
5277 1 => arg_mcv[0],6580 1 => arg_mcv[0],
5278 2 => .{ .register_pair = .{ arg_mcv[0].register, arg_mcv[1].register } },6581 2 => .{ .register_pair = .{ arg_mcv[0].register, arg_mcv[1].register } },
5279 };6582 };
5280 continue;6583 continue;
5281 }6584 }
52826585
5283 return self.fail("TODO: pass args by stack", .{});6586 return func.fail("TODO: pass args by stack", .{});
5284 }6587 }
5285 },6588 },
5286 else => return self.fail("TODO implement function parameters for {} on riscv64", .{cc}),6589 else => return func.fail("TODO implement function parameters for {} on riscv64", .{cc}),
5287 }6590 }
52886591
5289 result.stack_byte_count = @intCast(result.stack_align.forward(result.stack_byte_count));6592 result.stack_byte_count = @intCast(result.stack_align.forward(result.stack_byte_count));
5290 return result;6593 return result;
5291}6594}
52926595
5293/// TODO support scope overrides. Also note this logic is duplicated with `Module.wantSafety`.6596fn wantSafety(func: *Func) bool {
5294fn wantSafety(self: *Self) bool {6597 return switch (func.mod.optimize_mode) {
5295 return switch (self.bin_file.comp.root_mod.optimize_mode) {
5296 .Debug => true,6598 .Debug => true,
5297 .ReleaseSafe => true,6599 .ReleaseSafe => true,
5298 .ReleaseFast => false,6600 .ReleaseFast => false,
...@@ -5300,39 +6602,36 @@ fn wantSafety(self: *Self) bool {...@@ -5300,39 +6602,36 @@ fn wantSafety(self: *Self) bool {
5300 };6602 };
5301}6603}
53026604
5303fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError {6605fn fail(func: *Func, comptime format: []const u8, args: anytype) InnerError {
5304 @setCold(true);6606 @setCold(true);
5305 assert(self.err_msg == null);6607 assert(func.err_msg == null);
5306 self.err_msg = try ErrorMsg.create(self.gpa, self.src_loc, format, args);6608 func.err_msg = try ErrorMsg.create(func.gpa, func.src_loc, format, args);
5307 return error.CodegenFail;6609 return error.CodegenFail;
5308}6610}
53096611
5310fn failSymbol(self: *Self, comptime format: []const u8, args: anytype) InnerError {6612fn failSymbol(func: *Func, comptime format: []const u8, args: anytype) InnerError {
5311 @setCold(true);6613 @setCold(true);
5312 assert(self.err_msg == null);6614 assert(func.err_msg == null);
5313 self.err_msg = try ErrorMsg.create(self.gpa, self.src_loc, format, args);6615 func.err_msg = try ErrorMsg.create(func.gpa, func.src_loc, format, args);
5314 return error.CodegenFail;6616 return error.CodegenFail;
5315}6617}
53166618
5317fn parseRegName(name: []const u8) ?Register {6619fn parseRegName(name: []const u8) ?Register {
5318 if (@hasDecl(Register, "parseRegName")) {
5319 return Register.parseRegName(name);
5320 }
5321 return std.meta.stringToEnum(Register, name);6620 return std.meta.stringToEnum(Register, name);
5322}6621}
53236622
5324fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {6623fn typeOf(func: *Func, inst: Air.Inst.Ref) Type {
5325 const zcu = self.bin_file.comp.module.?;6624 const zcu = func.bin_file.comp.module.?;
5326 return self.air.typeOf(inst, &zcu.intern_pool);6625 return func.air.typeOf(inst, &zcu.intern_pool);
5327}6626}
53286627
5329fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {6628fn typeOfIndex(func: *Func, inst: Air.Inst.Index) Type {
5330 const zcu = self.bin_file.comp.module.?;6629 const zcu = func.bin_file.comp.module.?;
5331 return self.air.typeOfIndex(inst, &zcu.intern_pool);6630 return func.air.typeOfIndex(inst, &zcu.intern_pool);
5332}6631}
53336632
5334fn hasFeature(self: *Self, feature: Target.riscv.Feature) bool {6633fn hasFeature(func: *Func, feature: Target.riscv.Feature) bool {
5335 return Target.riscv.featureSetHas(self.target.cpu.features, feature);6634 return Target.riscv.featureSetHas(func.target.cpu.features, feature);
5336}6635}
53376636
5338pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Module) u64 {6637pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Module) u64 {
...@@ -5356,3 +6655,33 @@ pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Module) u64 {...@@ -5356,3 +6655,33 @@ pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Module) u64 {
5356 return 0;6655 return 0;
5357 }6656 }
5358}6657}
6658
6659fn promoteInt(func: *Func, ty: Type) Type {
6660 const mod = func.bin_file.comp.module.?;
6661 const int_info: InternPool.Key.IntType = switch (ty.toIntern()) {
6662 .bool_type => .{ .signedness = .unsigned, .bits = 1 },
6663 else => if (ty.isAbiInt(mod)) ty.intInfo(mod) else return ty,
6664 };
6665 for ([_]Type{
6666 Type.c_int, Type.c_uint,
6667 Type.c_long, Type.c_ulong,
6668 Type.c_longlong, Type.c_ulonglong,
6669 }) |promote_ty| {
6670 const promote_info = promote_ty.intInfo(mod);
6671 if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue;
6672 if (int_info.bits + @intFromBool(int_info.signedness == .unsigned and
6673 promote_info.signedness == .signed) <= promote_info.bits) return promote_ty;
6674 }
6675 return ty;
6676}
6677
6678fn promoteVarArg(func: *Func, ty: Type) Type {
6679 if (!ty.isRuntimeFloat()) return func.promoteInt(ty);
6680 switch (ty.floatBits(func.target.*)) {
6681 32, 64 => return Type.f64,
6682 else => |float_bits| {
6683 assert(float_bits == func.target.c_type_bit_size(.longdouble));
6684 return Type.c_longdouble;
6685 },
6686 }
6687}
src/arch/riscv64/Emit.zig+20-1
...@@ -42,6 +42,12 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -42,6 +42,12 @@ pub fn emitMir(emit: *Emit) Error!void {
42 .enc = std.meta.activeTag(lowered_inst.encoding.data),42 .enc = std.meta.activeTag(lowered_inst.encoding.data),
43 }),43 }),
44 .load_symbol_reloc => |symbol| {44 .load_symbol_reloc => |symbol| {
45 const is_obj_or_static_lib = switch (emit.lower.output_mode) {
46 .Exe => false,
47 .Obj => true,
48 .Lib => emit.lower.link_mode == .static,
49 };
50
45 if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {51 if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
46 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;52 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
47 const sym_index = elf_file.zigObjectPtr().?.symbol(symbol.sym_index);53 const sym_index = elf_file.zigObjectPtr().?.symbol(symbol.sym_index);
...@@ -50,7 +56,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -50,7 +56,7 @@ pub fn emitMir(emit: *Emit) Error!void {
50 var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);56 var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
51 var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);57 var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);
5258
53 if (sym.flags.needs_zig_got) {59 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
54 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);60 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
5561
56 hi_r_type = Elf.R_ZIG_GOT_HI20;62 hi_r_type = Elf.R_ZIG_GOT_HI20;
...@@ -70,6 +76,19 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -70,6 +76,19 @@ pub fn emitMir(emit: *Emit) Error!void {
70 });76 });
71 } else return emit.fail("TODO: load_symbol_reloc non-ELF", .{});77 } else return emit.fail("TODO: load_symbol_reloc non-ELF", .{});
72 },78 },
79 .call_extern_fn_reloc => |symbol| {
80 if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
81 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
82
83 const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT);
84
85 try atom_ptr.addReloc(elf_file, .{
86 .r_offset = start_offset,
87 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,
88 .r_addend = 0,
89 });
90 } else return emit.fail("TODO: call_extern_fn_reloc non-ELF", .{});
91 },
73 };92 };
74 }93 }
75 std.debug.assert(lowered_relocs.len == 0);94 std.debug.assert(lowered_relocs.len == 0);
src/arch/riscv64/Encoding.zig+477-97
...@@ -1,7 +1,71 @@...@@ -1,7 +1,71 @@
1mnemonic: Mnemonic,1mnemonic: Mnemonic,
2data: Data,2data: Data,
33
4const OpCode = enum(u7) {
5 OP = 0b0110011,
6 OP_IMM = 0b0010011,
7 OP_IMM_32 = 0b0011011,
8 OP_32 = 0b0111011,
9
10 BRANCH = 0b1100011,
11 LOAD = 0b0000011,
12 STORE = 0b0100011,
13 SYSTEM = 0b1110011,
14
15 OP_FP = 0b1010011,
16 LOAD_FP = 0b0000111,
17 STORE_FP = 0b0100111,
18
19 JALR = 0b1100111,
20 AUIPC = 0b0010111,
21 LUI = 0b0110111,
22 JAL = 0b1101111,
23 NONE = 0b0000000,
24};
25
26const Fmt = enum(u2) {
27 /// 32-bit single-precision
28 S = 0b00,
29 /// 64-bit double-precision
30 D = 0b01,
31 _reserved = 0b10,
32 /// 128-bit quad-precision
33 Q = 0b11,
34};
35
36const Enc = struct {
37 opcode: OpCode,
38
39 data: union(enum) {
40 /// funct3 + funct7
41 ff: struct {
42 funct3: u3,
43 funct7: u7,
44 },
45 /// funct5 + rm + fmt
46 fmt: struct {
47 funct5: u5,
48 rm: u3,
49 fmt: Fmt,
50 },
51 /// funct3
52 f: struct {
53 funct3: u3,
54 },
55 /// typ + funct3 + has_5
56 sh: struct {
57 typ: u6,
58 funct3: u3,
59 has_5: bool,
60 },
61 /// U-type
62 none,
63 },
64};
65
4pub const Mnemonic = enum {66pub const Mnemonic = enum {
67 // base mnemonics
68
5 // I Type69 // I Type
6 ld,70 ld,
7 lw,71 lw,
...@@ -10,18 +74,25 @@ pub const Mnemonic = enum {...@@ -10,18 +74,25 @@ pub const Mnemonic = enum {
10 lhu,74 lhu,
11 lb,75 lb,
12 lbu,76 lbu,
77
13 sltiu,78 sltiu,
14 xori,79 xori,
15 andi,80 andi,
81
16 slli,82 slli,
17 srli,83 srli,
18 srai,84 srai,
1985
86 slliw,
87 srliw,
88 sraiw,
89
20 addi,90 addi,
21 jalr,91 jalr,
2292
23 // U Type93 // U Type
24 lui,94 lui,
95 auipc,
2596
26 // S Type97 // S Type
27 sd,98 sd,
...@@ -37,64 +108,265 @@ pub const Mnemonic = enum {...@@ -37,64 +108,265 @@ pub const Mnemonic = enum {
37108
38 // R Type109 // R Type
39 add,110 add,
40 @"and",111 addw,
41 sub,112 sub,
113 subw,
114 @"and",
115 @"or",
42 slt,116 slt,
43 mul,
44 sltu,117 sltu,
45 xor,118 xor,
46119
120 sll,
121 srl,
122 sra,
123
124 sllw,
125 srlw,
126 sraw,
127
47 // System128 // System
48 ecall,129 ecall,
49 ebreak,130 ebreak,
50 unimp,131 unimp,
51132
133 // M extension
134 mul,
135 mulw,
136
137 mulh,
138 mulhu,
139 mulhsu,
140
141 div,
142 divu,
143
144 divw,
145 divuw,
146
147 rem,
148 remu,
149
150 remw,
151 remuw,
152
153 // F extension (32-bit float)
154 fadds,
155 fsubs,
156 fmuls,
157 fdivs,
158
159 fmins,
160 fmaxs,
161
162 fsqrts,
163
164 flw,
165 fsw,
166
167 feqs,
168 flts,
169 fles,
170
171 fsgnjns,
172 fsgnjxs,
173
174 // D extension (64-bit float)
175 faddd,
176 fsubd,
177 fmuld,
178 fdivd,
179
180 fmind,
181 fmaxd,
182
183 fsqrtd,
184
185 fld,
186 fsd,
187
188 feqd,
189 fltd,
190 fled,
191
192 fsgnjnd,
193 fsgnjxd,
194
52 pub fn encoding(mnem: Mnemonic) Enc {195 pub fn encoding(mnem: Mnemonic) Enc {
53 return switch (mnem) {196 return switch (mnem) {
54 // zig fmt: off197 // zig fmt: off
55 .add => .{ .opcode = 0b0110011, .funct3 = 0b000, .funct7 = 0b0000000 },
56 .sltu => .{ .opcode = 0b0110011, .funct3 = 0b011, .funct7 = 0b0000000 },
57 .@"and" => .{ .opcode = 0b0110011, .funct3 = 0b111, .funct7 = 0b0000000 },
58 .sub => .{ .opcode = 0b0110011, .funct3 = 0b000, .funct7 = 0b0100000 },
59198
60 .ld => .{ .opcode = 0b0000011, .funct3 = 0b011, .funct7 = null },199 // OP
61 .lw => .{ .opcode = 0b0000011, .funct3 = 0b010, .funct7 = null },200
62 .lwu => .{ .opcode = 0b0000011, .funct3 = 0b110, .funct7 = null },201 .add => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } },
63 .lh => .{ .opcode = 0b0000011, .funct3 = 0b001, .funct7 = null },202 .sub => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } },
64 .lhu => .{ .opcode = 0b0000011, .funct3 = 0b101, .funct7 = null },203
65 .lb => .{ .opcode = 0b0000011, .funct3 = 0b000, .funct7 = null },204 .@"and" => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000000 } } },
66 .lbu => .{ .opcode = 0b0000011, .funct3 = 0b100, .funct7 = null },205 .@"or" => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000000 } } },
206 .xor => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000000 } } },
207
208 .sltu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000000 } } },
209 .slt => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000000 } } },
210
211 .mul => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } },
212 .mulh => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000001 } } },
213 .mulhsu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000001 } } },
214 .mulhu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000001 } } },
215
216 .div => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000001 } } },
217 .divu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000001 } } },
218
219 .rem => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000001 } } },
220 .remu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000001 } } },
221
222 .sll => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } },
223 .srl => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000000 } } },
224 .sra => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0100000 } } },
225
226
227 // OP_IMM
228
229 .addi => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b000 } } },
230 .andi => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b111 } } },
231 .xori => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b100 } } },
232
233 .sltiu => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b011 } } },
234
235 .slli => .{ .opcode = .OP_IMM, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b001, .has_5 = true } } },
236 .srli => .{ .opcode = .OP_IMM, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b101, .has_5 = true } } },
237 .srai => .{ .opcode = .OP_IMM, .data = .{ .sh = .{ .typ = 0b010000, .funct3 = 0b101, .has_5 = true } } },
238
239
240 // OP_IMM_32
241
242 .slliw => .{ .opcode = .OP_IMM_32, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b001, .has_5 = false } } },
243 .srliw => .{ .opcode = .OP_IMM_32, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b101, .has_5 = false } } },
244 .sraiw => .{ .opcode = .OP_IMM_32, .data = .{ .sh = .{ .typ = 0b010000, .funct3 = 0b101, .has_5 = false } } },
245
246
247 // OP_32
248
249 .addw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } },
250 .subw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } },
251 .mulw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } },
252
253 .divw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000001 } } },
254 .divuw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000001 } } },
255
256 .remw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000001 } } },
257 .remuw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000001 } } },
258
259 .sllw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } },
260 .srlw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000000 } } },
261 .sraw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0100000 } } },
262
263
264 // OP_FP
265
266 .fadds => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .S, .rm = 0b111 } } },
267 .faddd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .D, .rm = 0b111 } } },
268
269 .fsubs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .S, .rm = 0b111 } } },
270 .fsubd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .D, .rm = 0b111 } } },
271
272 .fmuls => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .S, .rm = 0b111 } } },
273 .fmuld => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .D, .rm = 0b111 } } },
274
275 .fdivs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .S, .rm = 0b111 } } },
276 .fdivd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .D, .rm = 0b111 } } },
277
278 .fmins => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b000 } } },
279 .fmind => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b000 } } },
280
281 .fmaxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b001 } } },
282 .fmaxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b001 } } },
283
284 .fsqrts => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .S, .rm = 0b111 } } },
285 .fsqrtd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .D, .rm = 0b111 } } },
286
287 .fles => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b000 } } },
288 .fled => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b000 } } },
289
290 .flts => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b001 } } },
291 .fltd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b001 } } },
292
293 .feqs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b010 } } },
294 .feqd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b010 } } },
295
296 .fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } },
297 .fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } },
298
299 .fsgnjxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b0010} } },
300 .fsgnjxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b0010} } },
301
302
303 // LOAD
304
305 .lb => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b000 } } },
306 .lh => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b001 } } },
307 .lw => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b010 } } },
308 .ld => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b011 } } },
309 .lbu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b100 } } },
310 .lhu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b101 } } },
311 .lwu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b110 } } },
312
313
314 // STORE
315
316 .sb => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b000 } } },
317 .sh => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b001 } } },
318 .sw => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b010 } } },
319 .sd => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b011 } } },
320
321
322 // LOAD_FP
67323
68 .sltiu => .{ .opcode = 0b0010011, .funct3 = 0b011, .funct7 = null },324 .flw => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },
325 .fld => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },
326
69327
70 .addi => .{ .opcode = 0b0010011, .funct3 = 0b000, .funct7 = null },328 // STORE_FP
71 .andi => .{ .opcode = 0b0010011, .funct3 = 0b111, .funct7 = null },
72 .xori => .{ .opcode = 0b0010011, .funct3 = 0b100, .funct7 = null },
73 .jalr => .{ .opcode = 0b1100111, .funct3 = 0b000, .funct7 = null },
74 .slli => .{ .opcode = 0b0010011, .funct3 = 0b001, .funct7 = null },
75 .srli => .{ .opcode = 0b0010011, .funct3 = 0b101, .funct7 = null },
76 .srai => .{ .opcode = 0b0010011, .funct3 = 0b101, .funct7 = null, .offset = 1 << 10 },
77329
78 .lui => .{ .opcode = 0b0110111, .funct3 = null, .funct7 = null },330 .fsw => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },
331 .fsd => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },
79332
80 .sd => .{ .opcode = 0b0100011, .funct3 = 0b011, .funct7 = null },
81 .sw => .{ .opcode = 0b0100011, .funct3 = 0b010, .funct7 = null },
82 .sh => .{ .opcode = 0b0100011, .funct3 = 0b001, .funct7 = null },
83 .sb => .{ .opcode = 0b0100011, .funct3 = 0b000, .funct7 = null },
84333
85 .jal => .{ .opcode = 0b1101111, .funct3 = null, .funct7 = null },334 // JALR
86335
87 .beq => .{ .opcode = 0b1100011, .funct3 = 0b000, .funct7 = null },336 .jalr => .{ .opcode = .JALR, .data = .{ .f = .{ .funct3 = 0b000 } } },
88337
89 .slt => .{ .opcode = 0b0110011, .funct3 = 0b010, .funct7 = 0b0000000 },
90338
91 .xor => .{ .opcode = 0b0110011, .funct3 = 0b100, .funct7 = 0b0000000 },339 // LUI
340
341 .lui => .{ .opcode = .LUI, .data = .{ .none = {} } },
342
343
344 // AUIPC
345
346 .auipc => .{ .opcode = .AUIPC, .data = .{ .none = {} } },
347
348
349 // JAL
350
351 .jal => .{ .opcode = .JAL, .data = .{ .none = {} } },
352
353
354 // BRANCH
355
356 .beq => .{ .opcode = .BRANCH, .data = .{ .f = .{ .funct3 = 0b000 } } },
357
358
359 // SYSTEM
360
361 .ecall => .{ .opcode = .SYSTEM, .data = .{ .f = .{ .funct3 = 0b000 } } },
362 .ebreak => .{ .opcode = .SYSTEM, .data = .{ .f = .{ .funct3 = 0b000 } } },
363
364
365 // NONE
366
367 .unimp => .{ .opcode = .NONE, .data = .{ .f = .{ .funct3 = 0b000 } } },
92368
93 .mul => .{ .opcode = 0b0110011, .funct3 = 0b000, .funct7 = 0b0000001 },
94369
95 .ecall => .{ .opcode = 0b1110011, .funct3 = 0b000, .funct7 = null },
96 .ebreak => .{ .opcode = 0b1110011, .funct3 = 0b000, .funct7 = null },
97 .unimp => .{ .opcode = 0b0000000, .funct3 = 0b000, .funct7 = null },
98 // zig fmt: on370 // zig fmt: on
99 };371 };
100 }372 }
...@@ -102,6 +374,7 @@ pub const Mnemonic = enum {...@@ -102,6 +374,7 @@ pub const Mnemonic = enum {
102374
103pub const InstEnc = enum {375pub const InstEnc = enum {
104 R,376 R,
377 R4,
105 I,378 I,
106 S,379 S,
107 B,380 B,
...@@ -114,29 +387,42 @@ pub const InstEnc = enum {...@@ -114,29 +387,42 @@ pub const InstEnc = enum {
114 pub fn fromMnemonic(mnem: Mnemonic) InstEnc {387 pub fn fromMnemonic(mnem: Mnemonic) InstEnc {
115 return switch (mnem) {388 return switch (mnem) {
116 .addi,389 .addi,
117 .ld,
118 .lw,
119 .lwu,
120 .lh,
121 .lhu,
122 .lb,
123 .lbu,
124 .jalr,390 .jalr,
125 .sltiu,391 .sltiu,
126 .xori,392 .xori,
127 .andi,393 .andi,
394
128 .slli,395 .slli,
129 .srli,396 .srli,
130 .srai,397 .srai,
398
399 .slliw,
400 .srliw,
401 .sraiw,
402
403 .ld,
404 .lw,
405 .lwu,
406 .lh,
407 .lhu,
408 .lb,
409 .lbu,
410
411 .flw,
412 .fld,
131 => .I,413 => .I,
132414
133 .lui,415 .lui,
416 .auipc,
134 => .U,417 => .U,
135418
136 .sd,419 .sd,
137 .sw,420 .sw,
138 .sh,421 .sh,
139 .sb,422 .sb,
423
424 .fsd,
425 .fsw,
140 => .S,426 => .S,
141427
142 .jal,428 .jal,
...@@ -147,11 +433,76 @@ pub const InstEnc = enum {...@@ -147,11 +433,76 @@ pub const InstEnc = enum {
147433
148 .slt,434 .slt,
149 .sltu,435 .sltu,
150 .mul,436
437 .sll,
438 .srl,
439 .sra,
440
441 .sllw,
442 .srlw,
443 .sraw,
444
445 .div,
446 .divu,
447 .divw,
448 .divuw,
449
450 .rem,
451 .remu,
452 .remw,
453 .remuw,
454
151 .xor,455 .xor,
456 .@"and",
457 .@"or",
458
152 .add,459 .add,
460 .addw,
461
153 .sub,462 .sub,
154 .@"and",463 .subw,
464
465 .mul,
466 .mulw,
467 .mulh,
468 .mulhu,
469 .mulhsu,
470
471 .fadds,
472 .faddd,
473
474 .fsubs,
475 .fsubd,
476
477 .fmuls,
478 .fmuld,
479
480 .fdivs,
481 .fdivd,
482
483 .fmins,
484 .fmind,
485
486 .fmaxs,
487 .fmaxd,
488
489 .fsqrts,
490 .fsqrtd,
491
492 .fles,
493 .fled,
494
495 .flts,
496 .fltd,
497
498 .feqs,
499 .feqd,
500
501 .fsgnjns,
502 .fsgnjnd,
503
504 .fsgnjxs,
505 .fsgnjxd,
155 => .R,506 => .R,
156507
157 .ecall,508 .ecall,
...@@ -161,16 +512,17 @@ pub const InstEnc = enum {...@@ -161,16 +512,17 @@ pub const InstEnc = enum {
161 };512 };
162 }513 }
163514
164 pub fn opsList(enc: InstEnc) [3]std.meta.FieldEnum(Operand) {515 pub fn opsList(enc: InstEnc) [4]std.meta.FieldEnum(Operand) {
165 return switch (enc) {516 return switch (enc) {
166 // zig fmt: off517 // zig fmt: off
167 .R => .{ .reg, .reg, .reg, },518 .R => .{ .reg, .reg, .reg, .none },
168 .I => .{ .reg, .reg, .imm, },519 .R4 => .{ .reg, .reg, .reg, .reg },
169 .S => .{ .reg, .reg, .imm, },520 .I => .{ .reg, .reg, .imm, .none },
170 .B => .{ .reg, .reg, .imm, },521 .S => .{ .reg, .reg, .imm, .none },
171 .U => .{ .reg, .imm, .none, },522 .B => .{ .reg, .reg, .imm, .none },
172 .J => .{ .reg, .imm, .none, },523 .U => .{ .reg, .imm, .none, .none },
173 .system => .{ .none, .none, .none, },524 .J => .{ .reg, .imm, .none, .none },
525 .system => .{ .none, .none, .none, .none },
174 // zig fmt: on526 // zig fmt: on
175 };527 };
176 }528 }
...@@ -185,6 +537,15 @@ pub const Data = union(InstEnc) {...@@ -185,6 +537,15 @@ pub const Data = union(InstEnc) {
185 rs2: u5,537 rs2: u5,
186 funct7: u7,538 funct7: u7,
187 },539 },
540 R4: packed struct {
541 opcode: u7,
542 rd: u5,
543 funct3: u3,
544 rs1: u5,
545 rs2: u5,
546 funct2: u2,
547 rs3: u5,
548 },
188 I: packed struct {549 I: packed struct {
189 opcode: u7,550 opcode: u7,
190 rd: u5,551 rd: u5,
...@@ -227,19 +588,21 @@ pub const Data = union(InstEnc) {...@@ -227,19 +588,21 @@ pub const Data = union(InstEnc) {
227588
228 pub fn toU32(self: Data) u32 {589 pub fn toU32(self: Data) u32 {
229 return switch (self) {590 return switch (self) {
230 .R => |v| @as(u32, @bitCast(v)),591 // zig fmt: off
231 .I => |v| @as(u32, @bitCast(v)),592 .R => |v| @bitCast(v),
232 .S => |v| @as(u32, @bitCast(v)),593 .R4 => |v| @bitCast(v),
233 .B => |v| @as(u32, @intCast(v.opcode)) + (@as(u32, @intCast(v.imm11)) << 7) + (@as(u32, @intCast(v.imm1_4)) << 8) + (@as(u32, @intCast(v.funct3)) << 12) + (@as(u32, @intCast(v.rs1)) << 15) + (@as(u32, @intCast(v.rs2)) << 20) + (@as(u32, @intCast(v.imm5_10)) << 25) + (@as(u32, @intCast(v.imm12)) << 31),594 .I => |v| @bitCast(v),
234 .U => |v| @as(u32, @bitCast(v)),595 .S => |v| @bitCast(v),
235 .J => |v| @as(u32, @bitCast(v)),596 .B => |v| @as(u32, @intCast(v.opcode)) + (@as(u32, @intCast(v.imm11)) << 7) + (@as(u32, @intCast(v.imm1_4)) << 8) + (@as(u32, @intCast(v.funct3)) << 12) + (@as(u32, @intCast(v.rs1)) << 15) + (@as(u32, @intCast(v.rs2)) << 20) + (@as(u32, @intCast(v.imm5_10)) << 25) + (@as(u32, @intCast(v.imm12)) << 31),
597 .U => |v| @bitCast(v),
598 .J => |v| @bitCast(v),
236 .system => unreachable,599 .system => unreachable,
600 // zig fmt: on
237 };601 };
238 }602 }
239603
240 pub fn construct(mnem: Mnemonic, ops: []const Operand) !Data {604 pub fn construct(mnem: Mnemonic, ops: []const Operand) !Data {
241 const inst_enc = InstEnc.fromMnemonic(mnem);605 const inst_enc = InstEnc.fromMnemonic(mnem);
242
243 const enc = mnem.encoding();606 const enc = mnem.encoding();
244607
245 // special mnemonics608 // special mnemonics
...@@ -251,17 +614,17 @@ pub const Data = union(InstEnc) {...@@ -251,17 +614,17 @@ pub const Data = union(InstEnc) {
251 assert(ops.len == 0);614 assert(ops.len == 0);
252 return .{615 return .{
253 .I = .{616 .I = .{
254 .rd = Register.zero.id(),617 .rd = Register.zero.encodeId(),
255 .rs1 = Register.zero.id(),618 .rs1 = Register.zero.encodeId(),
256 .imm0_11 = switch (mnem) {619 .imm0_11 = switch (mnem) {
257 .ecall => 0x000,620 .ecall => 0x000,
258 .ebreak => 0x001,621 .ebreak => 0x001,
259 .unimp => 0,622 .unimp => 0x000,
260 else => unreachable,623 else => unreachable,
261 },624 },
262625
263 .opcode = enc.opcode,626 .opcode = @intFromEnum(enc.opcode),
264 .funct3 = enc.funct3.?,627 .funct3 = enc.data.f.funct3,
265 },628 },
266 };629 };
267 },630 },
...@@ -272,14 +635,26 @@ pub const Data = union(InstEnc) {...@@ -272,14 +635,26 @@ pub const Data = union(InstEnc) {
272 .R => {635 .R => {
273 assert(ops.len == 3);636 assert(ops.len == 3);
274 return .{637 return .{
275 .R = .{638 .R = switch (enc.data) {
276 .rd = ops[0].reg.id(),639 .ff => |ff| .{
277 .rs1 = ops[1].reg.id(),640 .rd = ops[0].reg.encodeId(),
278 .rs2 = ops[2].reg.id(),641 .rs1 = ops[1].reg.encodeId(),
279642 .rs2 = ops[2].reg.encodeId(),
280 .opcode = enc.opcode,643
281 .funct3 = enc.funct3.?,644 .opcode = @intFromEnum(enc.opcode),
282 .funct7 = enc.funct7.?,645 .funct3 = ff.funct3,
646 .funct7 = ff.funct7,
647 },
648 .fmt => |fmt| .{
649 .rd = ops[0].reg.encodeId(),
650 .rs1 = ops[1].reg.encodeId(),
651 .rs2 = ops[2].reg.encodeId(),
652
653 .opcode = @intFromEnum(enc.opcode),
654 .funct3 = fmt.rm,
655 .funct7 = (@as(u7, fmt.funct5) << 2) | @intFromEnum(fmt.fmt),
656 },
657 else => unreachable,
283 },658 },
284 };659 };
285 },660 },
...@@ -290,25 +665,37 @@ pub const Data = union(InstEnc) {...@@ -290,25 +665,37 @@ pub const Data = union(InstEnc) {
290 return .{665 return .{
291 .S = .{666 .S = .{
292 .imm0_4 = @truncate(umm),667 .imm0_4 = @truncate(umm),
293 .rs1 = ops[0].reg.id(),668 .rs1 = ops[0].reg.encodeId(),
294 .rs2 = ops[1].reg.id(),669 .rs2 = ops[1].reg.encodeId(),
295 .imm5_11 = @truncate(umm >> 5),670 .imm5_11 = @truncate(umm >> 5),
296671
297 .opcode = enc.opcode,672 .opcode = @intFromEnum(enc.opcode),
298 .funct3 = enc.funct3.?,673 .funct3 = enc.data.f.funct3,
299 },674 },
300 };675 };
301 },676 },
302 .I => {677 .I => {
303 assert(ops.len == 3);678 assert(ops.len == 3);
304 return .{679 return .{
305 .I = .{680 .I = switch (enc.data) {
306 .rd = ops[0].reg.id(),681 .f => |f| .{
307 .rs1 = ops[1].reg.id(),682 .rd = ops[0].reg.encodeId(),
308 .imm0_11 = ops[2].imm.asBits(u12) + enc.offset,683 .rs1 = ops[1].reg.encodeId(),
309684 .imm0_11 = ops[2].imm.asBits(u12),
310 .opcode = enc.opcode,685
311 .funct3 = enc.funct3.?,686 .opcode = @intFromEnum(enc.opcode),
687 .funct3 = f.funct3,
688 },
689 .sh => |sh| .{
690 .rd = ops[0].reg.encodeId(),
691 .rs1 = ops[1].reg.encodeId(),
692 .imm0_11 = (@as(u12, sh.typ) << 6) |
693 if (sh.has_5) ops[2].imm.asBits(u6) else (@as(u6, 0) | ops[2].imm.asBits(u5)),
694
695 .opcode = @intFromEnum(enc.opcode),
696 .funct3 = sh.funct3,
697 },
698 else => unreachable,
312 },699 },
313 };700 };
314 },701 },
...@@ -316,10 +703,10 @@ pub const Data = union(InstEnc) {...@@ -316,10 +703,10 @@ pub const Data = union(InstEnc) {
316 assert(ops.len == 2);703 assert(ops.len == 2);
317 return .{704 return .{
318 .U = .{705 .U = .{
319 .rd = ops[0].reg.id(),706 .rd = ops[0].reg.encodeId(),
320 .imm12_31 = ops[1].imm.asBits(u20),707 .imm12_31 = ops[1].imm.asBits(u20),
321708
322 .opcode = enc.opcode,709 .opcode = @intFromEnum(enc.opcode),
323 },710 },
324 };711 };
325 },712 },
...@@ -331,13 +718,13 @@ pub const Data = union(InstEnc) {...@@ -331,13 +718,13 @@ pub const Data = union(InstEnc) {
331718
332 return .{719 return .{
333 .J = .{720 .J = .{
334 .rd = ops[0].reg.id(),721 .rd = ops[0].reg.encodeId(),
335 .imm1_10 = @truncate(umm >> 1),722 .imm1_10 = @truncate(umm >> 1),
336 .imm11 = @truncate(umm >> 11),723 .imm11 = @truncate(umm >> 11),
337 .imm12_19 = @truncate(umm >> 12),724 .imm12_19 = @truncate(umm >> 12),
338 .imm20 = @truncate(umm >> 20),725 .imm20 = @truncate(umm >> 20),
339726
340 .opcode = enc.opcode,727 .opcode = @intFromEnum(enc.opcode),
341 },728 },
342 };729 };
343 },730 },
...@@ -349,15 +736,15 @@ pub const Data = union(InstEnc) {...@@ -349,15 +736,15 @@ pub const Data = union(InstEnc) {
349736
350 return .{737 return .{
351 .B = .{738 .B = .{
352 .rs1 = ops[0].reg.id(),739 .rs1 = ops[0].reg.encodeId(),
353 .rs2 = ops[1].reg.id(),740 .rs2 = ops[1].reg.encodeId(),
354 .imm1_4 = @truncate(umm >> 1),741 .imm1_4 = @truncate(umm >> 1),
355 .imm5_10 = @truncate(umm >> 5),742 .imm5_10 = @truncate(umm >> 5),
356 .imm11 = @truncate(umm >> 11),743 .imm11 = @truncate(umm >> 11),
357 .imm12 = @truncate(umm >> 12),744 .imm12 = @truncate(umm >> 12),
358745
359 .opcode = enc.opcode,746 .opcode = @intFromEnum(enc.opcode),
360 .funct3 = enc.funct3.?,747 .funct3 = enc.data.f.funct3,
361 },748 },
362 };749 };
363 },750 },
...@@ -376,13 +763,6 @@ pub fn findByMnemonic(mnem: Mnemonic, ops: []const Operand) !?Encoding {...@@ -376,13 +763,6 @@ pub fn findByMnemonic(mnem: Mnemonic, ops: []const Operand) !?Encoding {
376 };763 };
377}764}
378765
379const Enc = struct {
380 opcode: u7,
381 funct3: ?u3,
382 funct7: ?u7,
383 offset: u12 = 0,
384};
385
386fn verifyOps(mnem: Mnemonic, ops: []const Operand) bool {766fn verifyOps(mnem: Mnemonic, ops: []const Operand) bool {
387 const inst_enc = InstEnc.fromMnemonic(mnem);767 const inst_enc = InstEnc.fromMnemonic(mnem);
388 const list = std.mem.sliceTo(&inst_enc.opsList(), .none);768 const list = std.mem.sliceTo(&inst_enc.opsList(), .none);
src/arch/riscv64/Lower.zig+260-93
...@@ -14,7 +14,7 @@ result_relocs_len: u8 = undefined,...@@ -14,7 +14,7 @@ result_relocs_len: u8 = undefined,
14result_insts: [14result_insts: [
15 @max(15 @max(
16 1, // non-pseudo instruction16 1, // non-pseudo instruction
17 abi.callee_preserved_regs.len, // spill / restore regs,17 abi.Registers.all_preserved.len, // spill / restore regs,
18 )18 )
19]Instruction = undefined,19]Instruction = undefined,
20result_relocs: [1]Reloc = undefined,20result_relocs: [1]Reloc = undefined,
...@@ -32,8 +32,10 @@ pub const Reloc = struct {...@@ -32,8 +32,10 @@ pub const Reloc = struct {
32 const Target = union(enum) {32 const Target = union(enum) {
33 inst: Mir.Inst.Index,33 inst: Mir.Inst.Index,
3434
35 /// Relocs the lowered_inst_index and the next one.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 instruction.
38 call_extern_fn_reloc: bits.Symbol,
37 };39 };
38};40};
3941
...@@ -42,6 +44,8 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -42,6 +44,8 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
42 insts: []const Instruction,44 insts: []const Instruction,
43 relocs: []const Reloc,45 relocs: []const Reloc,
44} {46} {
47 const zcu = lower.bin_file.comp.module.?;
48
45 lower.result_insts = undefined;49 lower.result_insts = undefined;
46 lower.result_relocs = undefined;50 lower.result_relocs = undefined;
47 errdefer lower.result_insts = undefined;51 errdefer lower.result_insts = undefined;
...@@ -69,11 +73,25 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -69,11 +73,25 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
6973
70 switch (inst.ops) {74 switch (inst.ops) {
71 .pseudo_load_rm => {75 .pseudo_load_rm => {
72 const tag: Encoding.Mnemonic = switch (rm.m.mod.rm.size) {76 const dest_reg = rm.r;
73 .byte => .lb,77 const dest_reg_class = dest_reg.class();
74 .hword => .lh,78 const float = dest_reg_class == .float;
75 .word => .lw,79
76 .dword => .ld,80 const src_size = rm.m.mod.size;
81 const unsigned = rm.m.mod.unsigned;
82
83 const tag: Encoding.Mnemonic = if (!float)
84 switch (src_size) {
85 .byte => if (unsigned) .lbu else .lb,
86 .hword => if (unsigned) .lhu else .lh,
87 .word => if (unsigned) .lwu else .lw,
88 .dword => .ld,
89 }
90 else switch (src_size) {
91 .byte => unreachable, // Zig does not support 8-bit floats
92 .hword => return lower.fail("TODO: lowerMir pseudo_load_rm support 16-bit floats", .{}),
93 .word => .flw,
94 .dword => .fld,
77 };95 };
7896
79 try lower.emit(tag, &.{97 try lower.emit(tag, &.{
...@@ -83,11 +101,25 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -83,11 +101,25 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
83 });101 });
84 },102 },
85 .pseudo_store_rm => {103 .pseudo_store_rm => {
86 const tag: Encoding.Mnemonic = switch (rm.m.mod.rm.size) {104 const src_reg = rm.r;
87 .byte => .sb,105 const src_reg_class = src_reg.class();
88 .hword => .sh,106 const float = src_reg_class == .float;
89 .word => .sw,107
90 .dword => .sd,108 // TODO: do we actually need this? are all stores not usize?
109 const dest_size = rm.m.mod.size;
110
111 const tag: Encoding.Mnemonic = if (!float)
112 switch (dest_size) {
113 .byte => .sb,
114 .hword => .sh,
115 .word => .sw,
116 .dword => .sd,
117 }
118 else switch (dest_size) {
119 .byte => unreachable, // Zig does not support 8-bit floats
120 .hword => return lower.fail("TODO: lowerMir pseudo_load_rm support 16-bit floats", .{}),
121 .word => .fsw,
122 .dword => .fsd,
91 };123 };
92124
93 try lower.emit(tag, &.{125 try lower.emit(tag, &.{
...@@ -103,11 +135,27 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -103,11 +135,27 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
103 .pseudo_mv => {135 .pseudo_mv => {
104 const rr = inst.data.rr;136 const rr = inst.data.rr;
105137
106 try lower.emit(.addi, &.{138 const dst_class = rr.rd.class();
107 .{ .reg = rr.rd },139 const src_class = rr.rs.class();
108 .{ .reg = rr.rs },140
109 .{ .imm = Immediate.s(0) },141 assert(dst_class == src_class);
110 });142
143 switch (dst_class) {
144 .float => {
145 try lower.emit(if (lower.hasFeature(.d)) .fsgnjnd else .fsgnjns, &.{
146 .{ .reg = rr.rd },
147 .{ .reg = rr.rs },
148 .{ .reg = rr.rs },
149 });
150 },
151 .int => {
152 try lower.emit(.addi, &.{
153 .{ .reg = rr.rd },
154 .{ .reg = rr.rs },
155 .{ .imm = Immediate.s(0) },
156 });
157 },
158 }
111 },159 },
112160
113 .pseudo_ret => {161 .pseudo_ret => {
...@@ -131,25 +179,31 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -131,25 +179,31 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
131 .pseudo_load_symbol => {179 .pseudo_load_symbol => {
132 const payload = inst.data.payload;180 const payload = inst.data.payload;
133 const data = lower.mir.extraData(Mir.LoadSymbolPayload, payload).data;181 const data = lower.mir.extraData(Mir.LoadSymbolPayload, payload).data;
182 const dst_reg: bits.Register = @enumFromInt(data.register);
183 assert(dst_reg.class() == .int);
134184
135 try lower.emit(.lui, &.{185 try lower.emit(.lui, &.{
136 .{ .reg = @enumFromInt(data.register) },186 .{ .reg = dst_reg },
137 .{ .imm = lower.reloc(.{ .load_symbol_reloc = .{187 .{ .imm = lower.reloc(.{
138 .atom_index = data.atom_index,188 .load_symbol_reloc = .{
139 .sym_index = data.sym_index,189 .atom_index = data.atom_index,
140 } }) },190 .sym_index = data.sym_index,
191 },
192 }) },
141 });193 });
142194
143 // the above reloc implies this one195 // the above reloc implies this one
144 try lower.emit(.addi, &.{196 try lower.emit(.addi, &.{
145 .{ .reg = @enumFromInt(data.register) },197 .{ .reg = dst_reg },
146 .{ .reg = @enumFromInt(data.register) },198 .{ .reg = dst_reg },
147 .{ .imm = Immediate.s(0) },199 .{ .imm = Immediate.s(0) },
148 });200 });
149 },201 },
150202
151 .pseudo_lea_rm => {203 .pseudo_lea_rm => {
152 const rm = inst.data.rm;204 const rm = inst.data.rm;
205 assert(rm.r.class() == .int);
206
153 const frame = rm.m.toFrameLoc(lower.mir);207 const frame = rm.m.toFrameLoc(lower.mir);
154208
155 try lower.emit(.addi, &.{209 try lower.emit(.addi, &.{
...@@ -159,6 +213,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -159,6 +213,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
159 });213 });
160 },214 },
161215
216 .pseudo_fabs => {
217 const fabs = inst.data.fabs;
218 assert(fabs.rs.class() == .float and fabs.rd.class() == .float);
219
220 const mnem: Encoding.Mnemonic = switch (fabs.bits) {
221 16 => return lower.fail("TODO: airAbs Float 16", .{}),
222 32 => .fsgnjxs,
223 64 => .fsgnjxd,
224 80 => return lower.fail("TODO: airAbs Float 80", .{}),
225 128 => return lower.fail("TODO: airAbs Float 128", .{}),
226 else => unreachable,
227 };
228
229 try lower.emit(mnem, &.{
230 .{ .reg = fabs.rs },
231 .{ .reg = fabs.rd },
232 .{ .reg = fabs.rd },
233 });
234 },
235
162 .pseudo_compare => {236 .pseudo_compare => {
163 const compare = inst.data.compare;237 const compare = inst.data.compare;
164 const op = compare.op;238 const op = compare.op;
...@@ -167,78 +241,142 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -167,78 +241,142 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
167 const rs1 = compare.rs1;241 const rs1 = compare.rs1;
168 const rs2 = compare.rs2;242 const rs2 = compare.rs2;
169243
170 switch (op) {244 const class = rs1.class();
171 .eq => {245 const ty = compare.ty;
172 try lower.emit(.xor, &.{246 const size = std.math.ceilPowerOfTwo(u64, ty.bitSize(zcu)) catch {
173 .{ .reg = rd },247 return lower.fail("pseudo_compare size {}", .{ty.bitSize(zcu)});
174 .{ .reg = rs1 },248 };
175 .{ .reg = rs2 },249
176 });250 const is_unsigned = ty.isUnsignedInt(zcu);
177251
178 try lower.emit(.sltiu, &.{252 const less_than: Encoding.Mnemonic = if (is_unsigned) .sltu else .slt;
179 .{ .reg = rd },253
180 .{ .reg = rd },254 switch (class) {
181 .{ .imm = Immediate.s(1) },255 .int => switch (op) {
182 });256 .eq => {
257 try lower.emit(.xor, &.{
258 .{ .reg = rd },
259 .{ .reg = rs1 },
260 .{ .reg = rs2 },
261 });
262
263 try lower.emit(.sltiu, &.{
264 .{ .reg = rd },
265 .{ .reg = rd },
266 .{ .imm = Immediate.s(1) },
267 });
268 },
269 .neq => {
270 try lower.emit(.xor, &.{
271 .{ .reg = rd },
272 .{ .reg = rs1 },
273 .{ .reg = rs2 },
274 });
275
276 try lower.emit(.sltu, &.{
277 .{ .reg = rd },
278 .{ .reg = .zero },
279 .{ .reg = rd },
280 });
281 },
282 .gt => {
283 try lower.emit(less_than, &.{
284 .{ .reg = rd },
285 .{ .reg = rs1 },
286 .{ .reg = rs2 },
287 });
288 },
289 .gte => {
290 try lower.emit(less_than, &.{
291 .{ .reg = rd },
292 .{ .reg = rs1 },
293 .{ .reg = rs2 },
294 });
295
296 try lower.emit(.xori, &.{
297 .{ .reg = rd },
298 .{ .reg = rd },
299 .{ .imm = Immediate.s(1) },
300 });
301 },
302 .lt => {
303 try lower.emit(less_than, &.{
304 .{ .reg = rd },
305 .{ .reg = rs1 },
306 .{ .reg = rs2 },
307 });
308 },
309 .lte => {
310 try lower.emit(less_than, &.{
311 .{ .reg = rd },
312 .{ .reg = rs2 },
313 .{ .reg = rs1 },
314 });
315
316 try lower.emit(.xori, &.{
317 .{ .reg = rd },
318 .{ .reg = rd },
319 .{ .imm = Immediate.s(1) },
320 });
321 },
183 },322 },
184 .neq => {323 .float => switch (op) {
185 try lower.emit(.xor, &.{324 // eq
186 .{ .reg = rd },325 .eq => {
187 .{ .reg = rs1 },326 try lower.emit(if (size == 64) .feqd else .feqs, &.{
188 .{ .reg = rs2 },327 .{ .reg = rd },
189 });328 .{ .reg = rs1 },
190329 .{ .reg = rs2 },
191 try lower.emit(.sltu, &.{330 });
192 .{ .reg = rd },331 },
193 .{ .reg = .zero },332 // !(eq)
194 .{ .reg = rd },333 .neq => {
195 });334 try lower.emit(if (size == 64) .feqd else .feqs, &.{
196 },335 .{ .reg = rd },
197 .gt => {336 .{ .reg = rs1 },
198 try lower.emit(.sltu, &.{337 .{ .reg = rs2 },
199 .{ .reg = rd },338 });
200 .{ .reg = rs1 },339 try lower.emit(.xori, &.{
201 .{ .reg = rs2 },340 .{ .reg = rd },
202 });341 .{ .reg = rd },
203 },342 .{ .imm = Immediate.s(1) },
204 .gte => {343 });
205 try lower.emit(.sltu, &.{344 },
206 .{ .reg = rd },345 .lt => {
207 .{ .reg = rs1 },346 try lower.emit(if (size == 64) .fltd else .flts, &.{
208 .{ .reg = rs2 },347 .{ .reg = rd },
209 });348 .{ .reg = rs1 },
210349 .{ .reg = rs2 },
211 try lower.emit(.xori, &.{350 });
212 .{ .reg = rd },351 },
213 .{ .reg = rd },352 .lte => {
214 .{ .imm = Immediate.s(1) },353 try lower.emit(if (size == 64) .fled else .fles, &.{
215 });354 .{ .reg = rd },
216 },355 .{ .reg = rs1 },
217 .lt => {356 .{ .reg = rs2 },
218 try lower.emit(.slt, &.{357 });
219 .{ .reg = rd },358 },
220 .{ .reg = rs1 },359 .gt => {
221 .{ .reg = rs2 },360 try lower.emit(if (size == 64) .fltd else .flts, &.{
222 });361 .{ .reg = rd },
223 },362 .{ .reg = rs2 },
224 .lte => {363 .{ .reg = rs1 },
225 try lower.emit(.slt, &.{364 });
226 .{ .reg = rd },365 },
227 .{ .reg = rs2 },366 .gte => {
228 .{ .reg = rs1 },367 try lower.emit(if (size == 64) .fled else .fles, &.{
229 });368 .{ .reg = rd },
230369 .{ .reg = rs2 },
231 try lower.emit(.xori, &.{370 .{ .reg = rs1 },
232 .{ .reg = rd },371 });
233 .{ .reg = rd },372 },
234 .{ .imm = Immediate.s(1) },
235 });
236 },373 },
237 }374 }
238 },375 },
239376
240 .pseudo_not => {377 .pseudo_not => {
241 const rr = inst.data.rr;378 const rr = inst.data.rr;
379 assert(rr.rs.class() == .int and rr.rd.class() == .int);
242380
243 try lower.emit(.xori, &.{381 try lower.emit(.xori, &.{
244 .{ .reg = rr.rd },382 .{ .reg = rr.rd },
...@@ -247,6 +385,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -247,6 +385,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
247 });385 });
248 },386 },
249387
388 .pseudo_extern_fn_reloc => {
389 const inst_reloc = inst.data.reloc;
390
391 try lower.emit(.auipc, &.{
392 .{ .reg = .ra },
393 .{ .imm = lower.reloc(
394 .{ .call_extern_fn_reloc = .{
395 .atom_index = inst_reloc.atom_index,
396 .sym_index = inst_reloc.sym_index,
397 } },
398 ) },
399 });
400
401 try lower.emit(.jalr, &.{
402 .{ .reg = .ra },
403 .{ .reg = .ra },
404 .{ .imm = Immediate.s(0) },
405 });
406 },
407
250 else => return lower.fail("TODO lower: psuedo {s}", .{@tagName(inst.ops)}),408 else => return lower.fail("TODO lower: psuedo {s}", .{@tagName(inst.ops)}),
251 },409 },
252 }410 }
...@@ -314,16 +472,19 @@ fn pushPopRegList(lower: *Lower, comptime spilling: bool, reg_list: Mir.Register...@@ -314,16 +472,19 @@ fn pushPopRegList(lower: *Lower, comptime spilling: bool, reg_list: Mir.Register
314 var reg_i: u31 = 0;472 var reg_i: u31 = 0;
315 while (it.next()) |i| {473 while (it.next()) |i| {
316 const frame = lower.mir.frame_locs.get(@intFromEnum(bits.FrameIndex.spill_frame));474 const frame = lower.mir.frame_locs.get(@intFromEnum(bits.FrameIndex.spill_frame));
475 const reg = abi.Registers.all_preserved[i];
476 const reg_class = reg.class();
477 const is_float_reg = reg_class == .float;
317478
318 if (spilling) {479 if (spilling) {
319 try lower.emit(.sd, &.{480 try lower.emit(if (is_float_reg) .fsd else .sd, &.{
320 .{ .reg = frame.base },481 .{ .reg = frame.base },
321 .{ .reg = abi.callee_preserved_regs[i] },482 .{ .reg = abi.Registers.all_preserved[i] },
322 .{ .imm = Immediate.s(frame.disp + reg_i) },483 .{ .imm = Immediate.s(frame.disp + reg_i) },
323 });484 });
324 } else {485 } else {
325 try lower.emit(.ld, &.{486 try lower.emit(if (is_float_reg) .fld else .ld, &.{
326 .{ .reg = abi.callee_preserved_regs[i] },487 .{ .reg = abi.Registers.all_preserved[i] },
327 .{ .reg = frame.base },488 .{ .reg = frame.base },
328 .{ .imm = Immediate.s(frame.disp + reg_i) },489 .{ .imm = Immediate.s(frame.disp + reg_i) },
329 });490 });
...@@ -340,6 +501,12 @@ pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {...@@ -340,6 +501,12 @@ pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {
340 return error.LowerFail;501 return error.LowerFail;
341}502}
342503
504fn hasFeature(lower: *Lower, feature: std.Target.riscv.Feature) bool {
505 const target = lower.bin_file.comp.module.?.getTarget();
506 const features = target.cpu.features;
507 return std.Target.riscv.featureSetHas(features, feature);
508}
509
343const Lower = @This();510const Lower = @This();
344511
345const abi = @import("abi.zig");512const abi = @import("abi.zig");
src/arch/riscv64/Mir.zig+93-47
...@@ -20,90 +20,119 @@ pub const Inst = struct {...@@ -20,90 +20,119 @@ pub const Inst = struct {
20 pub const Index = u32;20 pub const Index = u32;
2121
22 pub const Tag = enum(u16) {22 pub const Tag = enum(u16) {
23 /// Add immediate. Uses i_type payload.
24 addi,
2523
26 /// Add immediate and produce a sign-extended result.24 // base extension
27 ///25 addi,
28 /// Uses i-type payload.
29 addiw,26 addiw,
3027
31 jalr,28 jalr,
32 lui,29 lui,
33 mv,
3430
35 @"and",31 @"and",
32 andi,
33
36 xor,34 xor,
35 @"or",
3736
38 ebreak,37 ebreak,
39 ecall,38 ecall,
40 unimp,39 unimp,
4140
42 /// OR instruction. Uses r_type payload.
43 @"or",
44
45 /// Addition
46 add,41 add,
47 /// Subtraction42 addw,
48 sub,43 sub,
49 /// Multiply, uses r_type. Needs the M extension.44 subw,
50 mul,
51
52 /// Absolute Value, uses i_type payload.
53 abs,
5445
55 sltu,46 sltu,
56 slt,47 slt,
5748
58 /// Immediate Logical Right Shift, uses i_type payload
59 srli,
60 /// Immediate Logical Left Shift, uses i_type payload
61 slli,49 slli,
62 /// Immediate Arithmetic Right Shift, uses i_type payload.50 srli,
63 srai,51 srai,
64 /// Register Logical Left Shift, uses r_type payload52
53 slliw,
54 srliw,
55 sraiw,
56
57 sll,
58 srl,
59 sra,
60
65 sllw,61 sllw,
66 /// Register Logical Right Shit, uses r_type payload
67 srlw,62 srlw,
63 sraw,
6864
69 /// Jumps, but stores the address of the instruction following the
70 /// jump in `rd`.
71 ///
72 /// Uses j_type payload.
73 jal,65 jal,
7466
75 /// Immediate AND, uses i_type payload
76 andi,
77
78 /// Branch if equal, Uses b_type
79 beq,67 beq,
80 /// Branch if not equal, Uses b_type
81 bne,68 bne,
8269
83 /// Boolean NOT, Uses rr payload
84 not,
85
86 /// Generates a NO-OP, uses nop payload
87 nop,70 nop,
8871
89 /// Load double (64 bits), uses i_type payload
90 ld,72 ld,
91 /// Load word (32 bits), uses i_type payload
92 lw,73 lw,
93 /// Load half (16 bits), uses i_type payload
94 lh,74 lh,
95 /// Load byte (8 bits), uses i_type payload
96 lb,75 lb,
9776
98 /// Store double (64 bits), uses s_type payload
99 sd,77 sd,
100 /// Store word (32 bits), uses s_type payload
101 sw,78 sw,
102 /// Store half (16 bits), uses s_type payload
103 sh,79 sh,
104 /// Store byte (8 bits), uses s_type payload
105 sb,80 sb,
10681
82 // M extension
83 mul,
84 mulw,
85
86 div,
87 divu,
88 divw,
89 divuw,
90
91 rem,
92 remu,
93 remw,
94 remuw,
95
96 // F extension (32-bit float)
97 fadds,
98 fsubs,
99 fmuls,
100 fdivs,
101
102 fabss,
103
104 fmins,
105 fmaxs,
106
107 fsqrts,
108
109 flw,
110 fsw,
111
112 feqs,
113 flts,
114 fles,
115
116 // D extension (64-bit float)
117 faddd,
118 fsubd,
119 fmuld,
120 fdivd,
121
122 fabsd,
123
124 fmind,
125 fmaxd,
126
127 fsqrtd,
128
129 fld,
130 fsd,
131
132 feqd,
133 fltd,
134 fled,
135
107 /// A pseudo-instruction. Used for anything that isn't 1:1 with an136 /// A pseudo-instruction. Used for anything that isn't 1:1 with an
108 /// assembly instruction.137 /// assembly instruction.
109 pseudo,138 pseudo,
...@@ -192,6 +221,12 @@ pub const Inst = struct {...@@ -192,6 +221,12 @@ pub const Inst = struct {
192 rs: Register,221 rs: Register,
193 },222 },
194223
224 fabs: struct {
225 rd: Register,
226 rs: Register,
227 bits: u16,
228 },
229
195 compare: struct {230 compare: struct {
196 rd: Register,231 rd: Register,
197 rs1: Register,232 rs1: Register,
...@@ -204,6 +239,12 @@ pub const Inst = struct {...@@ -204,6 +239,12 @@ pub const Inst = struct {
204 lt,239 lt,
205 lte,240 lte,
206 },241 },
242 ty: Type,
243 },
244
245 reloc: struct {
246 atom_index: u32,
247 sym_index: u32,
207 },248 },
208 };249 };
209250
...@@ -217,10 +258,7 @@ pub const Inst = struct {...@@ -217,10 +258,7 @@ pub const Inst = struct {
217258
218 /// Two registers + immediate, uses the i_type payload.259 /// Two registers + immediate, uses the i_type payload.
219 rri,260 rri,
220 /// Two registers + Two Immediates261 //extern_fn_reloc/ Two registers + another instruction.
221 rrii,
222
223 /// Two registers + another instruction.
224 rr_inst,262 rr_inst,
225263
226 /// Register + Memory264 /// Register + Memory
...@@ -268,6 +306,9 @@ pub const Inst = struct {...@@ -268,6 +306,9 @@ pub const Inst = struct {
268 /// Jumps. Uses `inst` payload.306 /// Jumps. Uses `inst` payload.
269 pseudo_j,307 pseudo_j,
270308
309 /// Floating point absolute value.
310 pseudo_fabs,
311
271 /// Dead inst, ignored by the emitter.312 /// Dead inst, ignored by the emitter.
272 pseudo_dead,313 pseudo_dead,
273314
...@@ -286,6 +327,9 @@ pub const Inst = struct {...@@ -286,6 +327,9 @@ pub const Inst = struct {
286327
287 pseudo_compare,328 pseudo_compare,
288 pseudo_not,329 pseudo_not,
330
331 /// Generates an auipc + jalr pair, with a R_RISCV_CALL_PLT reloc
332 pseudo_extern_fn_reloc,
289 };333 };
290334
291 // Make sure we don't accidentally make instructions bigger than expected.335 // Make sure we don't accidentally make instructions bigger than expected.
...@@ -387,6 +431,8 @@ pub const RegisterList = struct {...@@ -387,6 +431,8 @@ pub const RegisterList = struct {
387const Mir = @This();431const Mir = @This();
388const std = @import("std");432const std = @import("std");
389const builtin = @import("builtin");433const builtin = @import("builtin");
434const Type = @import("../../type.zig").Type;
435
390const assert = std.debug.assert;436const assert = std.debug.assert;
391437
392const bits = @import("bits.zig");438const bits = @import("bits.zig");
src/arch/riscv64/abi.zig+99-57
...@@ -7,7 +7,7 @@ const InternPool = @import("../../InternPool.zig");...@@ -7,7 +7,7 @@ const InternPool = @import("../../InternPool.zig");
7const Module = @import("../../Module.zig");7const Module = @import("../../Module.zig");
8const assert = std.debug.assert;8const assert = std.debug.assert;
99
10pub const Class = enum { memory, byval, integer, double_integer, fields, none };10pub const Class = enum { memory, byval, integer, double_integer, fields };
1111
12pub fn classifyType(ty: Type, mod: *Module) Class {12pub fn classifyType(ty: Type, mod: *Module) Class {
13 const target = mod.getTarget();13 const target = mod.getTarget();
...@@ -93,11 +93,13 @@ pub fn classifyType(ty: Type, mod: *Module) Class {...@@ -93,11 +93,13 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
93 }93 }
94}94}
9595
96pub const SystemClass = enum { integer, float, memory, none };
97
96/// There are a maximum of 8 possible return slots. Returned values are in98/// There are a maximum of 8 possible return slots. Returned values are in
97/// the beginning of the array; unused slots are filled with .none.99/// the beginning of the array; unused slots are filled with .none.
98pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {100pub fn classifySystem(ty: Type, zcu: *Module) [8]SystemClass {
99 var result = [1]Class{.none} ** 8;101 var result = [1]SystemClass{.none} ** 8;
100 const memory_class = [_]Class{102 const memory_class = [_]SystemClass{
101 .memory, .none, .none, .none,103 .memory, .none, .none, .none,
102 .none, .none, .none, .none,104 .none, .none, .none, .none,
103 };105 };
...@@ -123,6 +125,7 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {...@@ -123,6 +125,7 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {
123 return result;125 return result;
124 }126 }
125 result[0] = .integer;127 result[0] = .integer;
128 if (ty.optionalChild(zcu).abiSize(zcu) == 0) return result;
126 result[1] = .integer;129 result[1] = .integer;
127 return result;130 return result;
128 },131 },
...@@ -139,6 +142,18 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {...@@ -139,6 +142,18 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {
139 }142 }
140 unreachable; // support > 128 bit int arguments143 unreachable; // support > 128 bit int arguments
141 },144 },
145 .Float => {
146 const target = zcu.getTarget();
147 const features = target.cpu.features;
148
149 const float_bits = ty.floatBits(zcu.getTarget());
150 const float_reg_size: u32 = if (std.Target.riscv.featureSetHas(features, .d)) 64 else 32;
151 if (float_bits <= float_reg_size) {
152 result[0] = .float;
153 return result;
154 }
155 unreachable; // support split float args
156 },
142 .ErrorUnion => {157 .ErrorUnion => {
143 const payload_ty = ty.errorUnionPayload(zcu);158 const payload_ty = ty.errorUnionPayload(zcu);
144 const payload_bits = payload_ty.bitSize(zcu);159 const payload_bits = payload_ty.bitSize(zcu);
...@@ -149,12 +164,7 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {...@@ -149,12 +164,7 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {
149 // anyerror!void can fit into one register164 // anyerror!void can fit into one register
150 if (payload_bits == 0) return result;165 if (payload_bits == 0) return result;
151166
152 if (payload_bits <= 64) {167 return memory_class;
153 result[1] = .integer;
154 return result;
155 }
156
157 std.debug.panic("TODO: classifySystem ErrorUnion > 64 bit payload", .{});
158 },168 },
159 .Struct => {169 .Struct => {
160 const layout = ty.containerLayout(zcu);170 const layout = ty.containerLayout(zcu);
...@@ -169,6 +179,19 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {...@@ -169,6 +179,19 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {
169179
170 return memory_class;180 return memory_class;
171 },181 },
182 .Array => {
183 const ty_size = ty.abiSize(zcu);
184 if (ty_size <= 8) {
185 result[0] = .integer;
186 return result;
187 }
188 if (ty_size <= 16) {
189 result[0] = .integer;
190 result[1] = .integer;
191 return result;
192 }
193 return memory_class;
194 },
172 else => |bad_ty| std.debug.panic("classifySystem {s}", .{@tagName(bad_ty)}),195 else => |bad_ty| std.debug.panic("classifySystem {s}", .{@tagName(bad_ty)}),
173 }196 }
174}197}
...@@ -230,62 +253,81 @@ fn classifyStruct(...@@ -230,62 +253,81 @@ fn classifyStruct(
230 }253 }
231}254}
232255
233pub const callee_preserved_regs = [_]Register{256const allocatable_registers = Registers.Integer.all_regs ++ Registers.Float.all_regs;
234 // .s0 is ommited to be used as a frame pointer257pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register, &allocatable_registers);
235 .s1, .s2, .s3, .s4, .s5, .s6, .s7, .s8, .s9, .s10, .s11,
236};
237258
238pub const function_arg_regs = [_]Register{259// Register classes
239 .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7,260const RegisterBitSet = RegisterManager.RegisterBitSet;
240};
241261
242pub const function_ret_regs = [_]Register{262pub const RegisterClass = enum {
243 .a0, .a1,263 int,
264 float,
244};265};
245266
246pub const temporary_regs = [_]Register{267pub const Registers = struct {
247 .t0, .t1, .t2, .t3, .t4, .t5, .t6,268 pub const all_preserved = Integer.callee_preserved_regs ++ Float.callee_preserved_regs;
248};
249269
250const allocatable_registers = callee_preserved_regs ++ function_arg_regs ++ temporary_regs;270 pub const Integer = struct {
251pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register, &allocatable_registers);271 // zig fmt: off
272 pub const general_purpose = initRegBitSet(0, callee_preserved_regs.len);
273 pub const function_arg = initRegBitSet(callee_preserved_regs.len, function_arg_regs.len);
274 pub const function_ret = initRegBitSet(callee_preserved_regs.len, function_ret_regs.len);
275 pub const temporary = initRegBitSet(callee_preserved_regs.len + function_arg_regs.len, temporary_regs.len);
276 // zig fmt: on
252277
253// Register classes278 pub const callee_preserved_regs = [_]Register{
254const RegisterBitSet = RegisterManager.RegisterBitSet;279 // .s0 is omitted to be used as the frame pointer register
255pub const RegisterClass = struct {280 .s1, .s2, .s3, .s4, .s5, .s6, .s7, .s8, .s9, .s10, .s11,
256 pub const gp: RegisterBitSet = blk: {281 };
257 var set = RegisterBitSet.initEmpty();
258 set.setRangeValue(.{
259 .start = 0,
260 .end = callee_preserved_regs.len,
261 }, true);
262 break :blk set;
263 };
264282
265 pub const fa: RegisterBitSet = blk: {283 pub const function_arg_regs = [_]Register{
266 var set = RegisterBitSet.initEmpty();284 .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7,
267 set.setRangeValue(.{285 };
268 .start = callee_preserved_regs.len,286
269 .end = callee_preserved_regs.len + function_arg_regs.len,287 pub const function_ret_regs = [_]Register{
270 }, true);288 .a0, .a1,
271 break :blk set;289 };
272 };290
291 pub const temporary_regs = [_]Register{
292 .t0, .t1, .t2, .t3, .t4, .t5, .t6,
293 };
273294
274 pub const fr: RegisterBitSet = blk: {295 pub const all_regs = callee_preserved_regs ++ function_arg_regs ++ temporary_regs;
275 var set = RegisterBitSet.initEmpty();
276 set.setRangeValue(.{
277 .start = callee_preserved_regs.len,
278 .end = callee_preserved_regs.len + function_ret_regs.len,
279 }, true);
280 break :blk set;
281 };296 };
282297
283 pub const tp: RegisterBitSet = blk: {298 pub const Float = struct {
284 var set = RegisterBitSet.initEmpty();299 // zig fmt: off
285 set.setRangeValue(.{300 pub const general_purpose = initRegBitSet(Integer.all_regs.len, callee_preserved_regs.len);
286 .start = callee_preserved_regs.len + function_arg_regs.len,301 pub const function_arg = initRegBitSet(Integer.all_regs.len + callee_preserved_regs.len, function_arg_regs.len);
287 .end = callee_preserved_regs.len + function_arg_regs.len + temporary_regs.len,302 pub const function_ret = initRegBitSet(Integer.all_regs.len + callee_preserved_regs.len, function_ret_regs.len);
288 }, true);303 pub const temporary = initRegBitSet(Integer.all_regs.len + callee_preserved_regs.len + function_arg_regs.len, temporary_regs.len);
289 break :blk set;304 // zig fmt: on
305
306 pub const callee_preserved_regs = [_]Register{
307 .fs0, .fs1, .fs2, .fs3, .fs4, .fs5, .fs6, .fs7, .fs8, .fs9, .fs10, .fs11,
308 };
309
310 pub const function_arg_regs = [_]Register{
311 .fa0, .fa1, .fa2, .fa3, .fa4, .fa5, .fa6, .fa7,
312 };
313
314 pub const function_ret_regs = [_]Register{
315 .fa0, .fa1,
316 };
317
318 pub const temporary_regs = [_]Register{
319 .ft0, .ft1, .ft2, .ft3, .ft4, .ft5, .ft6, .ft7, .ft8, .ft9, .ft10, .ft11,
320 };
321
322 pub const all_regs = callee_preserved_regs ++ function_arg_regs ++ temporary_regs;
290 };323 };
291};324};
325
326fn initRegBitSet(start: usize, length: usize) RegisterBitSet {
327 var set = RegisterBitSet.initEmpty();
328 set.setRangeValue(.{
329 .start = start,
330 .end = start + length,
331 }, true);
332 return set;
333}
src/arch/riscv64/bits.zig+86-42
...@@ -2,8 +2,12 @@ const std = @import("std");...@@ -2,8 +2,12 @@ const std = @import("std");
2const DW = std.dwarf;2const DW = std.dwarf;
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const testing = std.testing;4const testing = std.testing;
5const Target = std.Target;
6
7const Module = @import("../../Module.zig");
5const Encoding = @import("Encoding.zig");8const Encoding = @import("Encoding.zig");
6const Mir = @import("Mir.zig");9const Mir = @import("Mir.zig");
10const abi = @import("abi.zig");
711
8pub const Memory = struct {12pub const Memory = struct {
9 base: Base,13 base: Base,
...@@ -15,12 +19,10 @@ pub const Memory = struct {...@@ -15,12 +19,10 @@ pub const Memory = struct {
15 reloc: Symbol,19 reloc: Symbol,
16 };20 };
1721
18 pub const Mod = union(enum(u1)) {22 pub const Mod = struct {
19 rm: struct {23 size: Size,
20 size: Size,24 unsigned: bool,
21 disp: i32 = 0,25 disp: i32 = 0,
22 },
23 off: i32,
24 };26 };
2527
26 pub const Size = enum(u4) {28 pub const Size = enum(u4) {
...@@ -35,10 +37,10 @@ pub const Memory = struct {...@@ -35,10 +37,10 @@ pub const Memory = struct {
3537
36 pub fn fromByteSize(size: u64) Size {38 pub fn fromByteSize(size: u64) Size {
37 return switch (size) {39 return switch (size) {
38 1 => .byte,40 1...1 => .byte,
39 2 => .hword,41 2...2 => .hword,
40 4 => .word,42 3...4 => .word,
41 8 => .dword,43 5...8 => .dword,
42 else => unreachable,44 else => unreachable,
43 };45 };
44 }46 }
...@@ -65,10 +67,7 @@ pub const Memory = struct {...@@ -65,10 +67,7 @@ pub const Memory = struct {
6567
66 /// Asserts `mem` can be represented as a `FrameLoc`.68 /// Asserts `mem` can be represented as a `FrameLoc`.
67 pub fn toFrameLoc(mem: Memory, mir: Mir) Mir.FrameLoc {69 pub fn toFrameLoc(mem: Memory, mir: Mir) Mir.FrameLoc {
68 const offset: i32 = switch (mem.mod) {70 const offset: i32 = mem.mod.disp;
69 .off => |off| off,
70 .rm => |rm| rm.disp,
71 };
7271
73 switch (mem.base) {72 switch (mem.base) {
74 .reg => |reg| {73 .reg => |reg| {
...@@ -91,7 +90,7 @@ pub const Memory = struct {...@@ -91,7 +90,7 @@ pub const Memory = struct {
9190
92pub const Immediate = union(enum) {91pub const Immediate = union(enum) {
93 signed: i32,92 signed: i32,
94 unsigned: u32,93 unsigned: u64,
9594
96 pub fn u(x: u64) Immediate {95 pub fn u(x: u64) Immediate {
97 return .{ .unsigned = x };96 return .{ .unsigned = x };
...@@ -119,24 +118,6 @@ pub const Immediate = union(enum) {...@@ -119,24 +118,6 @@ pub const Immediate = union(enum) {
119 };118 };
120 }119 }
121120
122 pub fn asUnsigned(imm: Immediate, bit_size: u64) u64 {
123 return switch (imm) {
124 .signed => |x| switch (bit_size) {
125 1, 8 => @as(u8, @bitCast(@as(i8, @intCast(x)))),
126 16 => @as(u16, @bitCast(@as(i16, @intCast(x)))),
127 32, 64 => @as(u32, @bitCast(x)),
128 else => unreachable,
129 },
130 .unsigned => |x| switch (bit_size) {
131 1, 8 => @as(u8, @intCast(x)),
132 16 => @as(u16, @intCast(x)),
133 32 => @as(u32, @intCast(x)),
134 64 => x,
135 else => unreachable,
136 },
137 };
138 }
139
140 pub fn asBits(imm: Immediate, comptime T: type) T {121 pub fn asBits(imm: Immediate, comptime T: type) T {
141 const int_info = @typeInfo(T).Int;122 const int_info = @typeInfo(T).Int;
142 if (int_info.signedness != .unsigned) @compileError("Immediate.asBits needs unsigned T");123 if (int_info.signedness != .unsigned) @compileError("Immediate.asBits needs unsigned T");
...@@ -147,12 +128,10 @@ pub const Immediate = union(enum) {...@@ -147,12 +128,10 @@ pub const Immediate = union(enum) {
147 }128 }
148};129};
149130
150pub const Register = enum(u6) {131pub const Register = enum(u8) {
151 // zig fmt: off132 // zig fmt: off
152 x0, x1, x2, x3, x4, x5, x6, x7,133
153 x8, x9, x10, x11, x12, x13, x14, x15,134 // base extension registers
154 x16, x17, x18, x19, x20, x21, x22, x23,
155 x24, x25, x26, x27, x28, x29, x30, x31,
156135
157 zero, // zero136 zero, // zero
158 ra, // return address. caller saved137 ra, // return address. caller saved
...@@ -166,17 +145,82 @@ pub const Register = enum(u6) {...@@ -166,17 +145,82 @@ pub const Register = enum(u6) {
166 a2, a3, a4, a5, a6, a7, // fn args. caller saved.145 a2, a3, a4, a5, a6, a7, // fn args. caller saved.
167 s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, // saved registers. callee saved.146 s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, // saved registers. callee saved.
168 t3, t4, t5, t6, // caller saved147 t3, t4, t5, t6, // caller saved
148
149 x0, x1, x2, x3, x4, x5, x6, x7,
150 x8, x9, x10, x11, x12, x13, x14, x15,
151 x16, x17, x18, x19, x20, x21, x22, x23,
152 x24, x25, x26, x27, x28, x29, x30, x31,
153
154
155 // F extension registers
156
157 ft0, ft1, ft2, ft3, ft4, ft5, ft6, ft7, // float temporaries. caller saved.
158 fs0, fs1, // float saved. callee saved.
159 fa0, fa1, // float arg/ret. caller saved.
160 fa2, fa3, fa4, fa5, fa6, fa7, // float arg. called saved.
161 fs2, fs3, fs4, fs5, fs6, fs7, fs8, fs9, fs10, fs11, // float saved. callee saved.
162 ft8, ft9, ft10, ft11, // foat temporaries. calller saved.
163
164 // this register is accessed only through API instructions instead of directly
165 // fcsr,
166
167 f0, f1, f2, f3, f4, f5, f6, f7,
168 f8, f9, f10, f11, f12, f13, f14, f15,
169 f16, f17, f18, f19, f20, f21, f22, f23,
170 f24, f25, f26, f27, f28, f29, f30, f31,
171
169 // zig fmt: on172 // zig fmt: on
170173
171 /// Returns the unique 5-bit ID of this register which is used in174 /// in RISC-V registers are stored as 5 bit IDs and a register can have
172 /// the machine code175 /// two names. Example being `zero` and `x0` are the same register and have the
173 pub fn id(self: Register) u5 {176 /// same ID, but are two different entries in the enum. We store floating point
174 return @as(u5, @truncate(@intFromEnum(self)));177 /// registers in the same enum. RISC-V uses the same IDs for `f0` and `x0` by
178 /// infering which register is being talked about given the instruction it's in.
179 ///
180 /// The goal of this function is to return the same ID for `zero` and `x0` but two
181 /// seperate IDs for `x0` and `f0`. We will assume that each register set has 32 registers
182 /// and is repeated twice, once for the named version, once for the number version.
183 pub fn id(reg: Register) u7 {
184 const base = switch (@intFromEnum(reg)) {
185 // zig fmt: off
186 @intFromEnum(Register.zero) ... @intFromEnum(Register.x31) => @intFromEnum(Register.zero),
187 @intFromEnum(Register.ft0) ... @intFromEnum(Register.f31) => @intFromEnum(Register.ft0),
188 else => unreachable,
189 // zig fmt: on
190 };
191
192 return @intCast(base + reg.encodeId());
193 }
194
195 pub fn encodeId(reg: Register) u5 {
196 return @truncate(@intFromEnum(reg));
175 }197 }
176198
177 pub fn dwarfLocOp(reg: Register) u8 {199 pub fn dwarfLocOp(reg: Register) u8 {
178 return @as(u8, reg.id());200 return @as(u8, reg.id());
179 }201 }
202
203 pub fn bitSize(reg: Register, zcu: *const Module) u32 {
204 const features = zcu.getTarget().cpu.features;
205
206 return switch (@intFromEnum(reg)) {
207 // zig fmt: off
208 @intFromEnum(Register.zero) ... @intFromEnum(Register.x31) => 64,
209 @intFromEnum(Register.ft0) ... @intFromEnum(Register.f31) => if (Target.riscv.featureSetHas(features, .d)) 64 else 32,
210 else => unreachable,
211 // zig fmt: on
212 };
213 }
214
215 pub fn class(reg: Register) abi.RegisterClass {
216 return switch (@intFromEnum(reg)) {
217 // zig fmt: off
218 @intFromEnum(Register.zero) ... @intFromEnum(Register.x31) => .int,
219 @intFromEnum(Register.ft0) ... @intFromEnum(Register.f31) => .float,
220 else => unreachable,
221 // zig fmt: on
222 };
223 }
180};224};
181225
182pub const FrameIndex = enum(u32) {226pub const FrameIndex = enum(u32) {
src/arch/riscv64/encoder.zig+26-2
...@@ -11,12 +11,11 @@ pub const Instruction = struct {...@@ -11,12 +11,11 @@ pub const Instruction = struct {
1111
12 pub fn new(mnemonic: Encoding.Mnemonic, ops: []const Operand) !Instruction {12 pub fn new(mnemonic: Encoding.Mnemonic, ops: []const Operand) !Instruction {
13 const encoding = (try Encoding.findByMnemonic(mnemonic, ops)) orelse {13 const encoding = (try Encoding.findByMnemonic(mnemonic, ops)) orelse {
14 std.log.err("no encoding found for: {s} {s} {s} {s} {s}", .{14 std.log.err("no encoding found for: {s} [{s} {s} {s}]", .{
15 @tagName(mnemonic),15 @tagName(mnemonic),
16 @tagName(if (ops.len > 0) ops[0] else .none),16 @tagName(if (ops.len > 0) ops[0] else .none),
17 @tagName(if (ops.len > 1) ops[1] else .none),17 @tagName(if (ops.len > 1) ops[1] else .none),
18 @tagName(if (ops.len > 2) ops[2] else .none),18 @tagName(if (ops.len > 2) ops[2] else .none),
19 @tagName(if (ops.len > 3) ops[3] else .none),
20 });19 });
21 return error.InvalidInstruction;20 return error.InvalidInstruction;
22 };21 };
...@@ -33,6 +32,31 @@ pub const Instruction = struct {...@@ -33,6 +32,31 @@ pub const Instruction = struct {
33 pub fn encode(inst: Instruction, writer: anytype) !void {32 pub fn encode(inst: Instruction, writer: anytype) !void {
34 try writer.writeInt(u32, inst.encoding.data.toU32(), .little);33 try writer.writeInt(u32, inst.encoding.data.toU32(), .little);
35 }34 }
35
36 pub fn format(
37 inst: Instruction,
38 comptime fmt: []const u8,
39 _: std.fmt.FormatOptions,
40 writer: anytype,
41 ) !void {
42 std.debug.assert(fmt.len == 0);
43
44 const encoding = inst.encoding;
45
46 try writer.print("{s} ", .{@tagName(encoding.mnemonic)});
47
48 var i: u32 = 0;
49 while (i < inst.ops.len and inst.ops[i] != .none) : (i += 1) {
50 if (i != inst.ops.len and i != 0) try writer.writeAll(", ");
51
52 switch (@as(Instruction.Operand, inst.ops[i])) {
53 .none => unreachable, // it's sliced out above
54 .reg => |reg| try writer.writeAll(@tagName(reg)),
55 .imm => |imm| try writer.print("{d}", .{imm.asSigned(64)}),
56 .mem => unreachable, // there is no "mem" operand in the actual instructions
57 }
58 }
59 }
36};60};
3761
38const std = @import("std");62const std = @import("std");
src/codegen/llvm.zig-2
...@@ -11151,7 +11151,6 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu...@@ -11151,7 +11151,6 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu
11151 }11151 }
11152 return o.builder.structType(.normal, types[0..types_len]);11152 return o.builder.structType(.normal, types[0..types_len]);
11153 },11153 },
11154 .none => unreachable,
11155 }11154 }
11156 },11155 },
11157 // TODO investigate C ABI for other architectures11156 // TODO investigate C ABI for other architectures
...@@ -11409,7 +11408,6 @@ const ParamTypeIterator = struct {...@@ -11409,7 +11408,6 @@ const ParamTypeIterator = struct {
11409 it.llvm_index += it.types_len - 1;11408 it.llvm_index += it.types_len - 1;
11410 return .multiple_llvm_types;11409 return .multiple_llvm_types;
11411 },11410 },
11412 .none => unreachable,
11413 }11411 }
11414 },11412 },
11415 // TODO investigate C ABI for other architectures11413 // TODO investigate C ABI for other architectures
src/link/Elf.zig+2-1
...@@ -5842,7 +5842,8 @@ pub fn tpAddress(self: *Elf) i64 {...@@ -5842,7 +5842,8 @@ pub fn tpAddress(self: *Elf) i64 {
5842 const addr = switch (self.getTarget().cpu.arch) {5842 const addr = switch (self.getTarget().cpu.arch) {
5843 .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align),5843 .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align),
5844 .aarch64 => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align),5844 .aarch64 => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align),
5845 else => @panic("TODO implement getTpAddress for this arch"),5845 .riscv64 => phdr.p_vaddr,
5846 else => |arch| std.debug.panic("TODO implement getTpAddress for {s}", .{@tagName(arch)}),
5846 };5847 };
5847 return @intCast(addr);5848 return @intCast(addr);
5848}5849}
src/link/Elf/Atom.zig+46-17
...@@ -1409,11 +1409,11 @@ const x86_64 = struct {...@@ -1409,11 +1409,11 @@ const x86_64 = struct {
1409 .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little),1409 .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little),
1410 .SIZE32 => {1410 .SIZE32 => {
1411 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));1411 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));
1412 try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(size + A)))), .little);1412 try cwriter.writeInt(u32, @bitCast(@as(i32, @intCast(size + A))), .little);
1413 },1413 },
1414 .SIZE64 => {1414 .SIZE64 => {
1415 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));1415 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));
1416 try cwriter.writeInt(i64, @as(i64, @intCast(size + A)), .little);1416 try cwriter.writeInt(i64, @intCast(size + A), .little);
1417 },1417 },
1418 else => try atom.reportUnhandledRelocError(rel, elf_file),1418 else => try atom.reportUnhandledRelocError(rel, elf_file),
1419 }1419 }
...@@ -2001,26 +2001,25 @@ const riscv = struct {...@@ -2001,26 +2001,25 @@ const riscv = struct {
2001 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());2001 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());
20022002
2003 switch (r_type) {2003 switch (r_type) {
2004 .@"64" => {2004 .@"32" => try atom.scanReloc(symbol, rel, absRelocAction(symbol, elf_file), elf_file),
2005 try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);2005 .@"64" => try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file),
2006 },2006 .HI20 => try atom.scanReloc(symbol, rel, absRelocAction(symbol, elf_file), elf_file),
2007
2008 .HI20 => {
2009 try atom.scanReloc(symbol, rel, absRelocAction(symbol, elf_file), elf_file);
2010 },
20112007
2012 .CALL_PLT => if (symbol.flags.import) {2008 .CALL_PLT => if (symbol.flags.import) {
2013 symbol.flags.needs_plt = true;2009 symbol.flags.needs_plt = true;
2014 },2010 },
2011 .GOT_HI20 => symbol.flags.needs_got = true,
20152012
2016 .GOT_HI20 => {2013 .TPREL_HI20,
2017 symbol.flags.needs_got = true;2014 .TPREL_LO12_I,
2018 },2015 .TPREL_LO12_S,
2016 .TPREL_ADD,
20192017
2020 .PCREL_HI20,2018 .PCREL_HI20,
2021 .PCREL_LO12_I,2019 .PCREL_LO12_I,
2022 .PCREL_LO12_S,2020 .PCREL_LO12_S,
2023 .LO12_I,2021 .LO12_I,
2022 .LO12_S,
2024 .ADD32,2023 .ADD32,
2025 .SUB32,2024 .SUB32,
2026 => {},2025 => {},
...@@ -2058,6 +2057,8 @@ const riscv = struct {...@@ -2058,6 +2057,8 @@ const riscv = struct {
2058 switch (r_type) {2057 switch (r_type) {
2059 .NONE => unreachable,2058 .NONE => unreachable,
20602059
2060 .@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),
2061
2061 .@"64" => {2062 .@"64" => {
2062 try atom.resolveDynAbsReloc(2063 try atom.resolveDynAbsReloc(
2063 target,2064 target,
...@@ -2076,11 +2077,6 @@ const riscv = struct {...@@ -2076,11 +2077,6 @@ const riscv = struct {
2076 riscv_util.writeInstU(code[r_offset..][0..4], value);2077 riscv_util.writeInstU(code[r_offset..][0..4], value);
2077 },2078 },
20782079
2079 .LO12_I => {
2080 const value: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow);
2081 riscv_util.writeInstI(code[r_offset..][0..4], value);
2082 },
2083
2084 .GOT_HI20 => {2080 .GOT_HI20 => {
2085 assert(target.flags.has_got);2081 assert(target.flags.has_got);
2086 const disp: u32 = @bitCast(math.cast(i32, G + GOT + A - P) orelse return error.Overflow);2082 const disp: u32 = @bitCast(math.cast(i32, G + GOT + A - P) orelse return error.Overflow);
...@@ -2143,6 +2139,39 @@ const riscv = struct {...@@ -2143,6 +2139,39 @@ const riscv = struct {
2143 }2139 }
2144 },2140 },
21452141
2142 .LO12_I,
2143 .LO12_S,
2144 => {
2145 const disp: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow);
2146 switch (r_type) {
2147 .LO12_I => riscv_util.writeInstI(code[r_offset..][0..4], disp),
2148 .LO12_S => riscv_util.writeInstS(code[r_offset..][0..4], disp),
2149 else => unreachable,
2150 }
2151 },
2152
2153 .TPREL_HI20 => {
2154 const target_addr: u32 = @intCast(target.address(.{}, elf_file));
2155 const val: i32 = @intCast(S + A - target_addr);
2156 riscv_util.writeInstU(code[r_offset..][0..4], @bitCast(val));
2157 },
2158
2159 .TPREL_LO12_I,
2160 .TPREL_LO12_S,
2161 => {
2162 const target_addr: u32 = @intCast(target.address(.{}, elf_file));
2163 const val: i32 = @intCast(S + A - target_addr);
2164 switch (r_type) {
2165 .TPREL_LO12_I => riscv_util.writeInstI(code[r_offset..][0..4], @bitCast(val)),
2166 .TPREL_LO12_S => riscv_util.writeInstS(code[r_offset..][0..4], @bitCast(val)),
2167 else => unreachable,
2168 }
2169 },
2170
2171 .TPREL_ADD => {
2172 // TODO: annotates an ADD instruction that can be removed when TPREL is relaxed
2173 },
2174
2146 else => |x| switch (@intFromEnum(x)) {2175 else => |x| switch (@intFromEnum(x)) {
2147 // Zig custom relocations2176 // Zig custom relocations
2148 Elf.R_ZIG_GOT_HI20 => {2177 Elf.R_ZIG_GOT_HI20 => {
src/link/Elf/ZigObject.zig+4-1
...@@ -906,7 +906,9 @@ fn updateDeclCode(...@@ -906,7 +906,9 @@ fn updateDeclCode(
906906
907 log.debug("updateDeclCode {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl });907 log.debug("updateDeclCode {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl });
908908
909 const required_alignment = decl.getAlignment(mod);909 const required_alignment = decl.getAlignment(mod).max(
910 target_util.minFunctionAlignment(mod.getTarget()),
911 );
910912
911 const sym = elf_file.symbol(sym_index);913 const sym = elf_file.symbol(sym_index);
912 const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index];914 const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index];
...@@ -1634,6 +1636,7 @@ const log = std.log.scoped(.link);...@@ -1634,6 +1636,7 @@ const log = std.log.scoped(.link);
1634const mem = std.mem;1636const mem = std.mem;
1635const relocation = @import("relocation.zig");1637const relocation = @import("relocation.zig");
1636const trace = @import("../../tracy.zig").trace;1638const trace = @import("../../tracy.zig").trace;
1639const target_util = @import("../../target.zig");
1637const std = @import("std");1640const std = @import("std");
16381641
1639const Air = @import("../../Air.zig");1642const Air = @import("../../Air.zig");
src/target.zig+17
...@@ -431,6 +431,23 @@ pub fn defaultFunctionAlignment(target: std.Target) Alignment {...@@ -431,6 +431,23 @@ pub fn defaultFunctionAlignment(target: std.Target) Alignment {
431 };431 };
432}432}
433433
434pub fn minFunctionAlignment(target: std.Target) Alignment {
435 return switch (target.cpu.arch) {
436 .arm,
437 .armeb,
438 .aarch64,
439 .aarch64_32,
440 .aarch64_be,
441 .riscv32,
442 .riscv64,
443 .sparc,
444 .sparcel,
445 .sparc64,
446 => .@"2",
447 else => .@"1",
448 };
449}
450
434pub fn supportsFunctionAlignment(target: std.Target) bool {451pub fn supportsFunctionAlignment(target: std.Target) bool {
435 return switch (target.cpu.arch) {452 return switch (target.cpu.arch) {
436 .wasm32, .wasm64 => false,453 .wasm32, .wasm64 => false,
test/behavior/abs.zig+3-5
...@@ -6,7 +6,6 @@ test "@abs integers" {...@@ -6,7 +6,6 @@ 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;
109
11 try comptime testAbsIntegers();10 try comptime testAbsIntegers();
12 try testAbsIntegers();11 try testAbsIntegers();
...@@ -93,18 +92,17 @@ test "@abs floats" {...@@ -93,18 +92,17 @@ test "@abs floats" {
93 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO92 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO93 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
95 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;94 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
96 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
9795
98 try comptime testAbsFloats(f16);96 try comptime testAbsFloats(f16);
99 try testAbsFloats(f16);97 if (builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f16);
100 try comptime testAbsFloats(f32);98 try comptime testAbsFloats(f32);
101 try testAbsFloats(f32);99 try testAbsFloats(f32);
102 try comptime testAbsFloats(f64);100 try comptime testAbsFloats(f64);
103 try testAbsFloats(f64);101 try testAbsFloats(f64);
104 try comptime testAbsFloats(f80);102 try comptime testAbsFloats(f80);
105 if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f80);103 if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64 and builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f80);
106 try comptime testAbsFloats(f128);104 try comptime testAbsFloats(f128);
107 if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f128);105 if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64 and builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f128);
108}106}
109107
110fn testAbsFloats(comptime T: type) !void {108fn testAbsFloats(comptime T: type) !void {
test/behavior/align.zig-8
...@@ -54,7 +54,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {...@@ -54,7 +54,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
54}54}
5555
56test "@alignCast pointers" {56test "@alignCast pointers" {
57 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
58 var x: u32 align(4) = 1;57 var x: u32 align(4) = 1;
59 expectsOnly1(&x);58 expectsOnly1(&x);
60 try expect(x == 2);59 try expect(x == 2);
...@@ -238,7 +237,6 @@ fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {...@@ -238,7 +237,6 @@ fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
238}237}
239238
240test "specifying alignment allows pointer cast" {239test "specifying alignment allows pointer cast" {
241 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
242 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
243 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO241 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
244242
...@@ -251,7 +249,6 @@ fn testBytesAlign(b: u8) !void {...@@ -251,7 +249,6 @@ fn testBytesAlign(b: u8) !void {
251}249}
252250
253test "@alignCast slices" {251test "@alignCast slices" {
254 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
255 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;252 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
256 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;253 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
257 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO254 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -312,7 +309,6 @@ test "function alignment" {...@@ -312,7 +309,6 @@ test "function alignment" {
312 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;309 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
313 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;310 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
314 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO311 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
315 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
316312
317 // function alignment is a compile error on wasm32/wasm64313 // function alignment is a compile error on wasm32/wasm64
318 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;314 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
...@@ -426,7 +422,6 @@ test "function callconv expression depends on generic parameter" {...@@ -426,7 +422,6 @@ test "function callconv expression depends on generic parameter" {
426}422}
427423
428test "runtime-known array index has best alignment possible" {424test "runtime-known array index has best alignment possible" {
429 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
430 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO425 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
431426
432 // take full advantage of over-alignment427 // take full advantage of over-alignment
...@@ -562,7 +557,6 @@ test "align(@alignOf(T)) T does not force resolution of T" {...@@ -562,7 +557,6 @@ test "align(@alignOf(T)) T does not force resolution of T" {
562}557}
563558
564test "align(N) on functions" {559test "align(N) on functions" {
565 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
566 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO560 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
567 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO561 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
568 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO562 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -608,7 +602,6 @@ test "comptime alloc alignment" {...@@ -608,7 +602,6 @@ test "comptime alloc alignment" {
608}602}
609603
610test "@alignCast null" {604test "@alignCast null" {
611 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
612 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;605 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
613 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO606 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
614607
...@@ -624,7 +617,6 @@ test "alignment of slice element" {...@@ -624,7 +617,6 @@ test "alignment of slice element" {
624}617}
625618
626test "sub-aligned pointer field access" {619test "sub-aligned pointer field access" {
627 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
628 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;620 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
629 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;621 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
630 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;622 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
test/behavior/alignof.zig-2
...@@ -29,8 +29,6 @@ test "comparison of @alignOf(T) against zero" {...@@ -29,8 +29,6 @@ test "comparison of @alignOf(T) against zero" {
29}29}
3030
31test "correct alignment for elements and slices of aligned array" {31test "correct alignment for elements and slices of aligned array" {
32 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
33
34 var buf: [1024]u8 align(64) = undefined;32 var buf: [1024]u8 align(64) = undefined;
35 var start: usize = 1;33 var start: usize = 1;
36 var end: usize = undefined;34 var end: usize = undefined;
test/behavior/array.zig-19
...@@ -50,7 +50,6 @@ fn getArrayLen(a: []const u32) usize {...@@ -50,7 +50,6 @@ fn getArrayLen(a: []const u32) usize {
50test "array concat with undefined" {50test "array concat with undefined" {
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_sparc64) return error.SkipZigTest; // TODO52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
53 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5453
55 const S = struct {54 const S = struct {
56 fn doTheTest() !void {55 fn doTheTest() !void {
...@@ -89,7 +88,6 @@ test "array concat with tuple" {...@@ -89,7 +88,6 @@ test "array concat with tuple" {
8988
90test "array init with concat" {89test "array init with concat" {
91 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO90 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
92 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
9391
94 const a = 'a';92 const a = 'a';
95 var i: [4]u8 = [2]u8{ a, 'b' } ++ [2]u8{ 'c', 'd' };93 var i: [4]u8 = [2]u8{ a, 'b' } ++ [2]u8{ 'c', 'd' };
...@@ -99,7 +97,6 @@ test "array init with concat" {...@@ -99,7 +97,6 @@ test "array init with concat" {
99test "array init with mult" {97test "array init with mult" {
100 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;98 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO99 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
103100
104 const a = 'a';101 const a = 'a';
105 var i: [8]u8 = [2]u8{ a, 'b' } ** 4;102 var i: [8]u8 = [2]u8{ a, 'b' } ** 4;
...@@ -231,7 +228,6 @@ test "nested arrays of integers" {...@@ -231,7 +228,6 @@ test "nested arrays of integers" {
231test "implicit comptime in array type size" {228test "implicit comptime in array type size" {
232 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;229 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO230 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
234 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
235231
236 var arr: [plusOne(10)]bool = undefined;232 var arr: [plusOne(10)]bool = undefined;
237 _ = &arr;233 _ = &arr;
...@@ -245,7 +241,6 @@ fn plusOne(x: u32) u32 {...@@ -245,7 +241,6 @@ fn plusOne(x: u32) u32 {
245test "single-item pointer to array indexing and slicing" {241test "single-item pointer to array indexing and slicing" {
246 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;242 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO243 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
248 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
249244
250 try testSingleItemPtrArrayIndexSlice();245 try testSingleItemPtrArrayIndexSlice();
251 try comptime testSingleItemPtrArrayIndexSlice();246 try comptime testSingleItemPtrArrayIndexSlice();
...@@ -271,7 +266,6 @@ fn doSomeMangling(array: *[4]u8) void {...@@ -271,7 +266,6 @@ fn doSomeMangling(array: *[4]u8) void {
271266
272test "implicit cast zero sized array ptr to slice" {267test "implicit cast zero sized array ptr to slice" {
273 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO268 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
274 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
275269
276 {270 {
277 var b = "".*;271 var b = "".*;
...@@ -310,7 +304,6 @@ const Str = struct { a: []Sub };...@@ -310,7 +304,6 @@ const Str = struct { a: []Sub };
310test "set global var array via slice embedded in struct" {304test "set global var array via slice embedded in struct" {
311 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;305 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
312 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO306 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
313 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
314307
315 var s = Str{ .a = s_array[0..] };308 var s = Str{ .a = s_array[0..] };
316309
...@@ -347,7 +340,6 @@ test "read/write through global variable array of struct fields initialized via...@@ -347,7 +340,6 @@ test "read/write through global variable array of struct fields initialized via
347test "implicit cast single-item pointer" {340test "implicit cast single-item pointer" {
348 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;341 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
349 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO342 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
350 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
351343
352 try testImplicitCastSingleItemPtr();344 try testImplicitCastSingleItemPtr();
353 try comptime testImplicitCastSingleItemPtr();345 try comptime testImplicitCastSingleItemPtr();
...@@ -378,7 +370,6 @@ test "comptime evaluating function that takes array by value" {...@@ -378,7 +370,6 @@ test "comptime evaluating function that takes array by value" {
378test "runtime initialize array elem and then implicit cast to slice" {370test "runtime initialize array elem and then implicit cast to slice" {
379 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;371 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
380 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO372 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
381 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
382373
383 var two: i32 = 2;374 var two: i32 = 2;
384 _ = &two;375 _ = &two;
...@@ -389,7 +380,6 @@ test "runtime initialize array elem and then implicit cast to slice" {...@@ -389,7 +380,6 @@ test "runtime initialize array elem and then implicit cast to slice" {
389test "array literal as argument to function" {380test "array literal as argument to function" {
390 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
391 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO382 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
392 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
393383
394 const S = struct {384 const S = struct {
395 fn entry(two: i32) !void {385 fn entry(two: i32) !void {
...@@ -418,7 +408,6 @@ test "double nested array to const slice cast in array literal" {...@@ -418,7 +408,6 @@ test "double nested array to const slice cast in array literal" {
418 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;408 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
419 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO409 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
420 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO410 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
421 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
422411
423 const S = struct {412 const S = struct {
424 fn entry(two: i32) !void {413 fn entry(two: i32) !void {
...@@ -505,7 +494,6 @@ test "anonymous literal in array" {...@@ -505,7 +494,6 @@ test "anonymous literal in array" {
505test "access the null element of a null terminated array" {494test "access the null element of a null terminated array" {
506 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;495 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
507 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO496 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
508 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
509497
510 const S = struct {498 const S = struct {
511 fn doTheTest() !void {499 fn doTheTest() !void {
...@@ -525,7 +513,6 @@ test "type deduction for array subscript expression" {...@@ -525,7 +513,6 @@ test "type deduction for array subscript expression" {
525 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;513 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
526 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO514 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
527 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO515 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
528 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
529516
530 const S = struct {517 const S = struct {
531 fn doTheTest() !void {518 fn doTheTest() !void {
...@@ -716,7 +703,6 @@ test "array of array agregate init" {...@@ -716,7 +703,6 @@ test "array of array agregate init" {
716 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO703 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
717 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO704 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
718 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO705 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
719 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
720706
721 var a = [1]u32{11} ** 10;707 var a = [1]u32{11} ** 10;
722 var b = [1][10]u32{a} ** 2;708 var b = [1][10]u32{a} ** 2;
...@@ -767,7 +753,6 @@ test "slicing array of zero-sized values" {...@@ -767,7 +753,6 @@ test "slicing array of zero-sized values" {
767 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;753 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
768 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;754 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
769 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;755 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
770 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
771 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;756 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
772757
773 var arr: [32]u0 = undefined;758 var arr: [32]u0 = undefined;
...@@ -778,8 +763,6 @@ test "slicing array of zero-sized values" {...@@ -778,8 +763,6 @@ test "slicing array of zero-sized values" {
778}763}
779764
780test "array init with no result pointer sets field result types" {765test "array init with no result pointer sets field result types" {
781 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
782
783 const S = struct {766 const S = struct {
784 // A function parameter has a result type, but no result pointer.767 // A function parameter has a result type, but no result pointer.
785 fn f(arr: [1]u32) u32 {768 fn f(arr: [1]u32) u32 {
...@@ -964,7 +947,6 @@ test "array initialized with string literal" {...@@ -964,7 +947,6 @@ test "array initialized with string literal" {
964947
965test "array initialized with array with sentinel" {948test "array initialized with array with sentinel" {
966 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO949 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
967 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
968950
969 const S = struct {951 const S = struct {
970 a: u32,952 a: u32,
...@@ -1051,7 +1033,6 @@ test "union that needs padding bytes inside an array" {...@@ -1051,7 +1033,6 @@ test "union that needs padding bytes inside an array" {
10511033
1052test "runtime index of array of zero-bit values" {1034test "runtime index of array of zero-bit values" {
1053 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1035 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1054 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10551036
1056 var runtime: struct { array: [1]void, index: usize } = undefined;1037 var runtime: struct { array: [1]void, index: usize } = undefined;
1057 runtime = .{ .array = .{{}}, .index = 0 };1038 runtime = .{ .array = .{{}}, .index = 0 };
test/behavior/basic.zig-17
...@@ -483,7 +483,6 @@ fn testStructInFn() !void {...@@ -483,7 +483,6 @@ fn testStructInFn() !void {
483483
484test "fn call returning scalar optional in equality expression" {484test "fn call returning scalar optional in equality expression" {
485 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO485 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
486 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
487 try expect(getNull() == null);486 try expect(getNull() == null);
488}487}
489488
...@@ -494,7 +493,6 @@ fn getNull() ?*i32 {...@@ -494,7 +493,6 @@ fn getNull() ?*i32 {
494test "global variable assignment with optional unwrapping with var initialized to undefined" {493test "global variable assignment with optional unwrapping with var initialized to undefined" {
495 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;494 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
496 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO495 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
497 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
498496
499 const S = struct {497 const S = struct {
500 var data: i32 = 1234;498 var data: i32 = 1234;
...@@ -513,7 +511,6 @@ var global_foo: *i32 = undefined;...@@ -513,7 +511,6 @@ var global_foo: *i32 = undefined;
513test "peer result location with typed parent, runtime condition, comptime prongs" {511test "peer result location with typed parent, runtime condition, comptime prongs" {
514 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;512 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
515 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO513 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
516 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
517514
518 const S = struct {515 const S = struct {
519 fn doTheTest(arg: i32) i32 {516 fn doTheTest(arg: i32) i32 {
...@@ -593,7 +590,6 @@ test "equality compare fn ptrs" {...@@ -593,7 +590,6 @@ test "equality compare fn ptrs" {
593590
594test "self reference through fn ptr field" {591test "self reference through fn ptr field" {
595 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;592 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
596 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
597593
598 const S = struct {594 const S = struct {
599 const A = struct {595 const A = struct {
...@@ -690,7 +686,6 @@ test "string concatenation" {...@@ -690,7 +686,6 @@ test "string concatenation" {
690 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;686 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
691 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;687 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
692 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO688 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
693 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
694689
695 const a = "OK" ++ " IT " ++ "WORKED";690 const a = "OK" ++ " IT " ++ "WORKED";
696 const b = "OK IT WORKED";691 const b = "OK IT WORKED";
...@@ -714,7 +709,6 @@ test "result location is optional inside error union" {...@@ -714,7 +709,6 @@ test "result location is optional inside error union" {
714 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO709 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
715 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO710 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
716 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO711 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
717 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
718712
719 const x = maybe(true) catch unreachable;713 const x = maybe(true) catch unreachable;
720 try expect(x.? == 42);714 try expect(x.? == 42);
...@@ -730,7 +724,6 @@ fn maybe(x: bool) anyerror!?u32 {...@@ -730,7 +724,6 @@ fn maybe(x: bool) anyerror!?u32 {
730test "auto created variables have correct alignment" {724test "auto created variables have correct alignment" {
731 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO725 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
732 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO726 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
733 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
734727
735 const S = struct {728 const S = struct {
736 fn foo(str: [*]const u8) u32 {729 fn foo(str: [*]const u8) u32 {
...@@ -838,7 +831,6 @@ test "labeled block implicitly ends in a break" {...@@ -838,7 +831,6 @@ test "labeled block implicitly ends in a break" {
838test "catch in block has correct result location" {831test "catch in block has correct result location" {
839 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;832 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
840 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO833 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
841 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
842834
843 const S = struct {835 const S = struct {
844 fn open() error{A}!@This() {836 fn open() error{A}!@This() {
...@@ -870,7 +862,6 @@ test "labeled block with runtime branch forwards its result location type to bre...@@ -870,7 +862,6 @@ test "labeled block with runtime branch forwards its result location type to bre
870862
871test "try in labeled block doesn't cast to wrong type" {863test "try in labeled block doesn't cast to wrong type" {
872 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO864 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
873 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
874865
875 const S = struct {866 const S = struct {
876 a: u32,867 a: u32,
...@@ -897,7 +888,6 @@ test "weird array and tuple initializations" {...@@ -897,7 +888,6 @@ test "weird array and tuple initializations" {
897 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO888 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
898 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO889 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
899 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO890 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
900 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
901891
902 const E = enum { a, b };892 const E = enum { a, b };
903 const S = struct { e: E };893 const S = struct { e: E };
...@@ -1016,7 +1006,6 @@ comptime {...@@ -1016,7 +1006,6 @@ comptime {
10161006
1017test "switch inside @as gets correct type" {1007test "switch inside @as gets correct type" {
1018 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1008 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1019 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10201009
1021 var a: u32 = 0;1010 var a: u32 = 0;
1022 _ = &a;1011 _ = &a;
...@@ -1101,8 +1090,6 @@ test "orelse coercion as function argument" {...@@ -1101,8 +1090,6 @@ test "orelse coercion as function argument" {
1101}1090}
11021091
1103test "runtime-known globals initialized with undefined" {1092test "runtime-known globals initialized with undefined" {
1104 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1105
1106 const S = struct {1093 const S = struct {
1107 var array: [10]u32 = [_]u32{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };1094 var array: [10]u32 = [_]u32{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
1108 var vp: [*]u32 = undefined;1095 var vp: [*]u32 = undefined;
...@@ -1246,8 +1233,6 @@ test "pointer to tuple field can be dereferenced at comptime" {...@@ -1246,8 +1233,6 @@ test "pointer to tuple field can be dereferenced at comptime" {
1246}1233}
12471234
1248test "proper value is returned from labeled block" {1235test "proper value is returned from labeled block" {
1249 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1250
1251 const S = struct {1236 const S = struct {
1252 fn hash(v: *u32, key: anytype) void {1237 fn hash(v: *u32, key: anytype) void {
1253 const Key = @TypeOf(key);1238 const Key = @TypeOf(key);
...@@ -1385,8 +1370,6 @@ test "allocation and looping over 3-byte integer" {...@@ -1385,8 +1370,6 @@ test "allocation and looping over 3-byte integer" {
1385}1370}
13861371
1387test "loading array from struct is not optimized away" {1372test "loading array from struct is not optimized away" {
1388 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1389
1390 const S = struct {1373 const S = struct {
1391 arr: [1]u32 = .{0},1374 arr: [1]u32 = .{0},
1392 fn doTheTest(self: *@This()) !void {1375 fn doTheTest(self: *@This()) !void {
test/behavior/bitcast.zig-5
...@@ -250,7 +250,6 @@ test "bitcast packed struct to integer and back" {...@@ -250,7 +250,6 @@ test "bitcast packed struct to integer and back" {
250test "implicit cast to error union by returning" {250test "implicit cast to error union by returning" {
251 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;251 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
252 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO252 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
253 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
254253
255 const S = struct {254 const S = struct {
256 fn entry() !void {255 fn entry() !void {
...@@ -280,8 +279,6 @@ test "comptime bitcast used in expression has the correct type" {...@@ -280,8 +279,6 @@ test "comptime bitcast used in expression has the correct type" {
280}279}
281280
282test "bitcast passed as tuple element" {281test "bitcast passed as tuple element" {
283 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
284
285 const S = struct {282 const S = struct {
286 fn foo(args: anytype) !void {283 fn foo(args: anytype) !void {
287 comptime assert(@TypeOf(args[0]) == f32);284 comptime assert(@TypeOf(args[0]) == f32);
...@@ -292,8 +289,6 @@ test "bitcast passed as tuple element" {...@@ -292,8 +289,6 @@ test "bitcast passed as tuple element" {
292}289}
293290
294test "triple level result location with bitcast sandwich passed as tuple element" {291test "triple level result location with bitcast sandwich passed as tuple element" {
295 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
296
297 const S = struct {292 const S = struct {
298 fn foo(args: anytype) !void {293 fn foo(args: anytype) !void {
299 comptime assert(@TypeOf(args[0]) == f64);294 comptime assert(@TypeOf(args[0]) == f64);
test/behavior/byteswap.zig+1
...@@ -100,6 +100,7 @@ test "@byteSwap vectors u8" {...@@ -100,6 +100,7 @@ test "@byteSwap vectors u8" {
100 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;100 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;102 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
103 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
103104
104 try comptime vector8();105 try comptime vector8();
105 try vector8();106 try vector8();
test/behavior/byval_arg_var.zig-1
...@@ -5,7 +5,6 @@ var result: []const u8 = "wrong";...@@ -5,7 +5,6 @@ var result: []const u8 = "wrong";
55
6test "pass string literal byvalue to a generic var param" {6test "pass string literal byvalue to a generic var param" {
7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
109
11 start();10 start();
test/behavior/call.zig-6
...@@ -60,7 +60,6 @@ test "tuple parameters" {...@@ -60,7 +60,6 @@ test "tuple parameters" {
60 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO60 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
61 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO61 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
62 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;62 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
63 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
6463
65 const add = struct {64 const add = struct {
66 fn add(a: i32, b: i32) i32 {65 fn add(a: i32, b: i32) i32 {
...@@ -94,7 +93,6 @@ test "result location of function call argument through runtime condition and st...@@ -94,7 +93,6 @@ test "result location of function call argument through runtime condition and st
94 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO93 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
95 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO94 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
96 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO95 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
97 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
9896
99 const E = enum { a, b };97 const E = enum { a, b };
100 const S = struct {98 const S = struct {
...@@ -411,7 +409,6 @@ test "recursive inline call with comptime known argument" {...@@ -411,7 +409,6 @@ test "recursive inline call with comptime known argument" {
411test "inline while with @call" {409test "inline while with @call" {
412 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO410 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
413 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO411 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
414 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
415412
416 const S = struct {413 const S = struct {
417 fn inc(a: *u32) void {414 fn inc(a: *u32) void {
...@@ -427,8 +424,6 @@ test "inline while with @call" {...@@ -427,8 +424,6 @@ test "inline while with @call" {
427}424}
428425
429test "method call as parameter type" {426test "method call as parameter type" {
430 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
431
432 const S = struct {427 const S = struct {
433 fn foo(x: anytype, y: @TypeOf(x).Inner()) @TypeOf(y) {428 fn foo(x: anytype, y: @TypeOf(x).Inner()) @TypeOf(y) {
434 return y;429 return y;
...@@ -477,7 +472,6 @@ test "argument to generic function has correct result type" {...@@ -477,7 +472,6 @@ test "argument to generic function has correct result type" {
477 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO472 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
478 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO473 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
479 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO474 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
480 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
481475
482 const S = struct {476 const S = struct {
483 fn foo(_: anytype, e: enum { a, b }) bool {477 fn foo(_: anytype, e: enum { a, b }) bool {
test/behavior/cast.zig-54
...@@ -57,8 +57,6 @@ test "@intCast to comptime_int" {...@@ -57,8 +57,6 @@ test "@intCast to comptime_int" {
57}57}
5858
59test "implicit cast comptime numbers to any type when the value fits" {59test "implicit cast comptime numbers to any type when the value fits" {
60 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
61
62 const a: u64 = 255;60 const a: u64 = 255;
63 var b: u8 = a;61 var b: u8 = a;
64 _ = &b;62 _ = &b;
...@@ -188,7 +186,6 @@ fn expectIntFromFloat(comptime F: type, f: F, comptime I: type, i: I) !void {...@@ -188,7 +186,6 @@ fn expectIntFromFloat(comptime F: type, f: F, comptime I: type, i: I) !void {
188test "implicitly cast indirect pointer to maybe-indirect pointer" {186test "implicitly cast indirect pointer to maybe-indirect pointer" {
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 const S = struct {190 const S = struct {
194 const Self = @This();191 const Self = @This();
...@@ -249,7 +246,6 @@ test "coerce undefined to optional" {...@@ -249,7 +246,6 @@ test "coerce undefined to optional" {
249 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;246 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
250 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;247 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO248 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
252 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
253249
254 try expect(MakeType(void).getNull() == null);250 try expect(MakeType(void).getNull() == null);
255 try expect(MakeType(void).getNonNull() != null);251 try expect(MakeType(void).getNonNull() != null);
...@@ -270,7 +266,6 @@ fn MakeType(comptime T: type) type {...@@ -270,7 +266,6 @@ fn MakeType(comptime T: type) type {
270test "implicit cast from *[N]T to [*c]T" {266test "implicit cast from *[N]T to [*c]T" {
271 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;267 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
272 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO268 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
273 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
274269
275 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };270 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
276 var y: [*c]u16 = &x;271 var y: [*c]u16 = &x;
...@@ -347,7 +342,6 @@ test "array coercion to undefined at runtime" {...@@ -347,7 +342,6 @@ test "array coercion to undefined at runtime" {
347 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;342 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
348 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO343 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
349 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;344 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
350 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
351345
352 @setRuntimeSafety(true);346 @setRuntimeSafety(true);
353347
...@@ -413,7 +407,6 @@ test "peer type unsigned int to signed" {...@@ -413,7 +407,6 @@ test "peer type unsigned int to signed" {
413test "expected [*c]const u8, found [*:0]const u8" {407test "expected [*c]const u8, found [*:0]const u8" {
414 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;408 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
415 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO409 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
416 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
417410
418 var a: [*:0]const u8 = "hello";411 var a: [*:0]const u8 = "hello";
419 _ = &a;412 _ = &a;
...@@ -483,7 +476,6 @@ fn castToOptionalTypeError(z: i32) !void {...@@ -483,7 +476,6 @@ fn castToOptionalTypeError(z: i32) !void {
483test "implicitly cast from [0]T to anyerror![]T" {476test "implicitly cast from [0]T to anyerror![]T" {
484 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;477 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
485 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO478 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
486 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
487479
488 try testCastZeroArrayToErrSliceMut();480 try testCastZeroArrayToErrSliceMut();
489 try comptime testCastZeroArrayToErrSliceMut();481 try comptime testCastZeroArrayToErrSliceMut();
...@@ -501,7 +493,6 @@ test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {...@@ -501,7 +493,6 @@ test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
501 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;493 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
502 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO494 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
503 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO495 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
504 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
505496
506 const S = struct {497 const S = struct {
507 fn doTheTest() anyerror!void {498 fn doTheTest() anyerror!void {
...@@ -558,7 +549,6 @@ fn testCastConstArrayRefToConstSlice() !void {...@@ -558,7 +549,6 @@ fn testCastConstArrayRefToConstSlice() !void {
558test "peer type resolution: error and [N]T" {549test "peer type resolution: error and [N]T" {
559 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;550 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
560 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO551 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
561 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
562552
563 try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));553 try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
564 comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));554 comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
...@@ -583,7 +573,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {...@@ -583,7 +573,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
583test "single-item pointer of array to slice to unknown length pointer" {573test "single-item pointer of array to slice to unknown length pointer" {
584 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;574 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
585 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO575 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
586 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
587576
588 try testCastPtrOfArrayToSliceAndPtr();577 try testCastPtrOfArrayToSliceAndPtr();
589 try comptime testCastPtrOfArrayToSliceAndPtr();578 try comptime testCastPtrOfArrayToSliceAndPtr();
...@@ -841,7 +830,6 @@ test "peer cast *[0]T to E![]const T" {...@@ -841,7 +830,6 @@ test "peer cast *[0]T to E![]const T" {
841 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;830 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
842 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;831 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
843 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO832 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
844 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
845833
846 var buffer: [5]u8 = "abcde".*;834 var buffer: [5]u8 = "abcde".*;
847 const buf: anyerror![]const u8 = buffer[0..];835 const buf: anyerror![]const u8 = buffer[0..];
...@@ -857,7 +845,6 @@ test "peer cast *[0]T to []const T" {...@@ -857,7 +845,6 @@ test "peer cast *[0]T to []const T" {
857 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;845 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
858 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;846 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
859 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO847 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
860 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
861848
862 var buffer: [5]u8 = "abcde".*;849 var buffer: [5]u8 = "abcde".*;
863 const buf: []const u8 = buffer[0..];850 const buf: []const u8 = buffer[0..];
...@@ -881,7 +868,6 @@ test "peer resolution of string literals" {...@@ -881,7 +868,6 @@ test "peer resolution of string literals" {
881 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;868 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
882 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO869 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
883 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO870 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
884 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
885871
886 const S = struct {872 const S = struct {
887 const E = enum { a, b, c, d };873 const E = enum { a, b, c, d };
...@@ -903,7 +889,6 @@ test "peer resolution of string literals" {...@@ -903,7 +889,6 @@ test "peer resolution of string literals" {
903test "peer cast [:x]T to []T" {889test "peer cast [:x]T to []T" {
904 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;890 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
905 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO891 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
906 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
907892
908 const S = struct {893 const S = struct {
909 fn doTheTest() !void {894 fn doTheTest() !void {
...@@ -920,7 +905,6 @@ test "peer cast [:x]T to []T" {...@@ -920,7 +905,6 @@ test "peer cast [:x]T to []T" {
920test "peer cast [N:x]T to [N]T" {905test "peer cast [N:x]T to [N]T" {
921 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;906 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
922 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO907 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
923 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
924908
925 const S = struct {909 const S = struct {
926 fn doTheTest() !void {910 fn doTheTest() !void {
...@@ -937,7 +921,6 @@ test "peer cast [N:x]T to [N]T" {...@@ -937,7 +921,6 @@ test "peer cast [N:x]T to [N]T" {
937test "peer cast *[N:x]T to *[N]T" {921test "peer cast *[N:x]T to *[N]T" {
938 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO922 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
939 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO923 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
940 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
941924
942 const S = struct {925 const S = struct {
943 fn doTheTest() !void {926 fn doTheTest() !void {
...@@ -995,7 +978,6 @@ test "peer cast [:x]T to [*:x]T" {...@@ -995,7 +978,6 @@ test "peer cast [:x]T to [*:x]T" {
995test "peer type resolution implicit cast to return type" {978test "peer type resolution implicit cast to return type" {
996 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;979 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
997 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO980 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
998 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
999981
1000 const S = struct {982 const S = struct {
1001 fn doTheTest() !void {983 fn doTheTest() !void {
...@@ -1016,7 +998,6 @@ test "peer type resolution implicit cast to return type" {...@@ -1016,7 +998,6 @@ test "peer type resolution implicit cast to return type" {
1016test "peer type resolution implicit cast to variable type" {998test "peer type resolution implicit cast to variable type" {
1017 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;999 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1018 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1000 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1019 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10201001
1021 const S = struct {1002 const S = struct {
1022 fn doTheTest() !void {1003 fn doTheTest() !void {
...@@ -1060,7 +1041,6 @@ test "cast between C pointer with different but compatible types" {...@@ -1060,7 +1041,6 @@ test "cast between C pointer with different but compatible types" {
1060test "peer type resolve string lit with sentinel-terminated mutable slice" {1041test "peer type resolve string lit with sentinel-terminated mutable slice" {
1061 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1042 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1062 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1043 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1063 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10641044
1065 var array: [4:0]u8 = undefined;1045 var array: [4:0]u8 = undefined;
1066 array[4] = 0; // TODO remove this when #4372 is solved1046 array[4] = 0; // TODO remove this when #4372 is solved
...@@ -1127,7 +1107,6 @@ test "implicit cast from [*]T to ?*anyopaque" {...@@ -1127,7 +1107,6 @@ test "implicit cast from [*]T to ?*anyopaque" {
1127 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1107 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1128 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1108 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1129 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1109 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1130 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11311110
1132 var a = [_]u8{ 3, 2, 1 };1111 var a = [_]u8{ 3, 2, 1 };
1133 var runtime_zero: usize = 0;1112 var runtime_zero: usize = 0;
...@@ -1158,7 +1137,6 @@ fn foobar(func: PFN_void) !void {...@@ -1158,7 +1137,6 @@ fn foobar(func: PFN_void) !void {
11581137
1159test "cast function with an opaque parameter" {1138test "cast function with an opaque parameter" {
1160 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1139 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1161 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11621140
1163 if (builtin.zig_backend == .stage2_c) {1141 if (builtin.zig_backend == .stage2_c) {
1164 // https://github.com/ziglang/zig/issues/168451142 // https://github.com/ziglang/zig/issues/16845
...@@ -1191,7 +1169,6 @@ test "implicit ptr to *anyopaque" {...@@ -1191,7 +1169,6 @@ test "implicit ptr to *anyopaque" {
1191 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1169 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1192 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1170 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1193 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1171 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1194 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11951172
1196 var a: u32 = 1;1173 var a: u32 = 1;
1197 const ptr: *align(@alignOf(u32)) anyopaque = &a;1174 const ptr: *align(@alignOf(u32)) anyopaque = &a;
...@@ -1205,7 +1182,6 @@ test "implicit ptr to *anyopaque" {...@@ -1205,7 +1182,6 @@ test "implicit ptr to *anyopaque" {
1205test "return null from fn () anyerror!?&T" {1182test "return null from fn () anyerror!?&T" {
1206 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1183 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1207 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1184 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1208 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12091185
1210 const a = returnNullFromOptionalTypeErrorRef();1186 const a = returnNullFromOptionalTypeErrorRef();
1211 const b = returnNullLitFromOptionalTypeErrorRef();1187 const b = returnNullLitFromOptionalTypeErrorRef();
...@@ -1296,7 +1272,6 @@ test "implicit cast from *T to ?*anyopaque" {...@@ -1296,7 +1272,6 @@ test "implicit cast from *T to ?*anyopaque" {
1296 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1272 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1297 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1273 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1298 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1274 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1299 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13001275
1301 var a: u8 = 1;1276 var a: u8 = 1;
1302 incrementVoidPtrValue(&a);1277 incrementVoidPtrValue(&a);
...@@ -1310,7 +1285,6 @@ fn incrementVoidPtrValue(value: ?*anyopaque) void {...@@ -1310,7 +1285,6 @@ fn incrementVoidPtrValue(value: ?*anyopaque) void {
1310test "implicit cast *[0]T to E![]const u8" {1285test "implicit cast *[0]T to E![]const u8" {
1311 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1286 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1312 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1287 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1313 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13141288
1315 var x = @as(anyerror![]const u8, &[0]u8{});1289 var x = @as(anyerror![]const u8, &[0]u8{});
1316 _ = &x;1290 _ = &x;
...@@ -1332,7 +1306,6 @@ test "*const [N]null u8 to ?[]const u8" {...@@ -1332,7 +1306,6 @@ test "*const [N]null u8 to ?[]const u8" {
1332 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1306 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1333 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1307 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1334 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1308 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1335 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13361309
1337 const S = struct {1310 const S = struct {
1338 fn doTheTest() !void {1311 fn doTheTest() !void {
...@@ -1369,7 +1342,6 @@ test "assignment to optional pointer result loc" {...@@ -1369,7 +1342,6 @@ test "assignment to optional pointer result loc" {
1369 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1342 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1370 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1343 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1371 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1344 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1372 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13731345
1374 var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct };1346 var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct };
1375 _ = &foo;1347 _ = &foo;
...@@ -1377,7 +1349,6 @@ test "assignment to optional pointer result loc" {...@@ -1377,7 +1349,6 @@ test "assignment to optional pointer result loc" {
1377}1349}
13781350
1379test "cast between *[N]void and []void" {1351test "cast between *[N]void and []void" {
1380 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1381 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1352 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13821353
1383 var a: [4]void = undefined;1354 var a: [4]void = undefined;
...@@ -1445,7 +1416,6 @@ test "peer type resolution: unreachable, null, slice" {...@@ -1445,7 +1416,6 @@ test "peer type resolution: unreachable, null, slice" {
1445 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1416 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1446 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1417 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1447 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1418 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1448 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14491419
1450 const S = struct {1420 const S = struct {
1451 fn doTheTest(num: usize, word: []const u8) !void {1421 fn doTheTest(num: usize, word: []const u8) !void {
...@@ -1486,7 +1456,6 @@ test "cast compatible optional types" {...@@ -1486,7 +1456,6 @@ test "cast compatible optional types" {
1486 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1456 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1487 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1457 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1488 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1458 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1489 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14901459
1491 var a: ?[:0]const u8 = null;1460 var a: ?[:0]const u8 = null;
1492 _ = &a;1461 _ = &a;
...@@ -1497,7 +1466,6 @@ test "cast compatible optional types" {...@@ -1497,7 +1466,6 @@ test "cast compatible optional types" {
1497test "coerce undefined single-item pointer of array to error union of slice" {1466test "coerce undefined single-item pointer of array to error union of slice" {
1498 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1467 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1499 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1468 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1500 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15011469
1502 const a = @as([*]u8, undefined)[0..0];1470 const a = @as([*]u8, undefined)[0..0];
1503 var b: error{a}![]const u8 = a;1471 var b: error{a}![]const u8 = a;
...@@ -1600,7 +1568,6 @@ test "bitcast packed struct with u0" {...@@ -1600,7 +1568,6 @@ test "bitcast packed struct with u0" {
16001568
1601test "optional pointer coerced to optional allowzero pointer" {1569test "optional pointer coerced to optional allowzero pointer" {
1602 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1570 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1603 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
16041571
1605 var p: ?*u32 = undefined;1572 var p: ?*u32 = undefined;
1606 var q: ?*allowzero u32 = undefined;1573 var q: ?*allowzero u32 = undefined;
...@@ -1617,8 +1584,6 @@ test "optional slice coerced to allowzero many pointer" {...@@ -1617,8 +1584,6 @@ test "optional slice coerced to allowzero many pointer" {
1617}1584}
16181585
1619test "optional slice passed as parameter coerced to allowzero many pointer" {1586test "optional slice passed as parameter coerced to allowzero many pointer" {
1620 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1621
1622 const ns = struct {1587 const ns = struct {
1623 const Color = struct {1588 const Color = struct {
1624 r: u8,1589 r: u8,
...@@ -1638,8 +1603,6 @@ test "optional slice passed as parameter coerced to allowzero many pointer" {...@@ -1638,8 +1603,6 @@ test "optional slice passed as parameter coerced to allowzero many pointer" {
1638}1603}
16391604
1640test "single item pointer to pointer to array to slice" {1605test "single item pointer to pointer to array to slice" {
1641 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1642
1643 var x: i32 = 1234;1606 var x: i32 = 1234;
1644 try expect(@as([]const i32, @as(*[1]i32, &x))[0] == 1234);1607 try expect(@as([]const i32, @as(*[1]i32, &x))[0] == 1234);
1645 const z1 = @as([]const i32, @as(*[1]i32, &x));1608 const z1 = @as([]const i32, @as(*[1]i32, &x));
...@@ -1682,8 +1645,6 @@ test "@volatileCast without a result location" {...@@ -1682,8 +1645,6 @@ test "@volatileCast without a result location" {
1682}1645}
16831646
1684test "coercion from single-item pointer to @as to slice" {1647test "coercion from single-item pointer to @as to slice" {
1685 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1686
1687 var x: u32 = 1;1648 var x: u32 = 1;
16881649
1689 // Why the following line gets a compile error?1650 // Why the following line gets a compile error?
...@@ -1696,7 +1657,6 @@ test "peer type resolution: const sentinel slice and mutable non-sentinel slice"...@@ -1696,7 +1657,6 @@ test "peer type resolution: const sentinel slice and mutable non-sentinel slice"
1696 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1657 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1697 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1658 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1698 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1659 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1699 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
17001660
1701 const S = struct {1661 const S = struct {
1702 fn doTheTest(comptime T: type, comptime s: T) !void {1662 fn doTheTest(comptime T: type, comptime s: T) !void {
...@@ -1727,7 +1687,6 @@ test "peer type resolution: float and comptime-known fixed-width integer" {...@@ -1727,7 +1687,6 @@ test "peer type resolution: float and comptime-known fixed-width integer" {
1727 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1687 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1728 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1688 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1729 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;1689 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1730 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
17311690
1732 const i: u8 = 100;1691 const i: u8 = 100;
1733 var f: f32 = 1.234;1692 var f: f32 = 1.234;
...@@ -1750,7 +1709,6 @@ test "peer type resolution: same array type with sentinel" {...@@ -1750,7 +1709,6 @@ test "peer type resolution: same array type with sentinel" {
1750 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1709 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1751 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1710 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1752 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1711 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1753 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
17541712
1755 var a: [2:0]u32 = .{ 0, 1 };1713 var a: [2:0]u32 = .{ 0, 1 };
1756 var b: [2:0]u32 = .{ 2, 3 };1714 var b: [2:0]u32 = .{ 2, 3 };
...@@ -1773,7 +1731,6 @@ test "peer type resolution: array with sentinel and array without sentinel" {...@@ -1773,7 +1731,6 @@ test "peer type resolution: array with sentinel and array without sentinel" {
1773 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1731 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1774 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1732 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1775 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1733 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1776 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
17771734
1778 var a: [2:0]u32 = .{ 0, 1 };1735 var a: [2:0]u32 = .{ 0, 1 };
1779 var b: [2]u32 = .{ 2, 3 };1736 var b: [2]u32 = .{ 2, 3 };
...@@ -1843,7 +1800,6 @@ test "peer type resolution: error union and optional of same type" {...@@ -1843,7 +1800,6 @@ test "peer type resolution: error union and optional of same type" {
1843 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1800 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1844 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1801 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1845 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1802 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1846 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
18471803
1848 const E = error{Foo};1804 const E = error{Foo};
1849 var a: E!*u8 = error.Foo;1805 var a: E!*u8 = error.Foo;
...@@ -1867,7 +1823,6 @@ test "peer type resolution: C pointer and @TypeOf(null)" {...@@ -1867,7 +1823,6 @@ test "peer type resolution: C pointer and @TypeOf(null)" {
1867 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1823 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1868 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1824 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1869 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1825 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1870 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
18711826
1872 var a: [*c]c_int = 0x1000;1827 var a: [*c]c_int = 0x1000;
1873 _ = &a;1828 _ = &a;
...@@ -1981,7 +1936,6 @@ test "peer type resolution: array and tuple" {...@@ -1981,7 +1936,6 @@ test "peer type resolution: array and tuple" {
1981 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1936 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1982 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1937 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1983 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1938 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1984 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19851939
1986 var arr: [3]i32 = .{ 1, 2, 3 };1940 var arr: [3]i32 = .{ 1, 2, 3 };
1987 _ = &arr;1941 _ = &arr;
...@@ -2116,7 +2070,6 @@ test "peer type resolution: tuple pointer and optional slice" {...@@ -2116,7 +2070,6 @@ test "peer type resolution: tuple pointer and optional slice" {
2116 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2070 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2071 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2118 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2072 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2119 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2120 // Miscompilation on Intel's OpenCL CPU runtime.2073 // Miscompilation on Intel's OpenCL CPU runtime.
2121 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky2074 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky
21222075
...@@ -2209,7 +2162,6 @@ test "peer type resolution: tuples with comptime fields" {...@@ -2209,7 +2162,6 @@ test "peer type resolution: tuples with comptime fields" {
2209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2162 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2210 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2163 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2211 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO2164 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
2212 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
22132165
2214 const a = .{ 1, 2 };2166 const a = .{ 1, 2 };
2215 const b = .{ @as(u32, 3), @as(i16, 4) };2167 const b = .{ @as(u32, 3), @as(i16, 4) };
...@@ -2241,7 +2193,6 @@ test "peer type resolution: C pointer and many pointer" {...@@ -2241,7 +2193,6 @@ test "peer type resolution: C pointer and many pointer" {
2241 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2193 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2242 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2194 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2243 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2195 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2244 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
22452196
2246 var buf = "hello".*;2197 var buf = "hello".*;
22472198
...@@ -2309,7 +2260,6 @@ test "peer type resolution: arrays of compatible types" {...@@ -2309,7 +2260,6 @@ test "peer type resolution: arrays of compatible types" {
2309 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2260 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2310 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2261 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2311 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2262 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2312 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
23132263
2314 var e0: u8 = 3;2264 var e0: u8 = 3;
2315 var e1: u8 = 2;2265 var e1: u8 = 2;
...@@ -2365,7 +2315,6 @@ test "cast builtins can wrap result in error union" {...@@ -2365,7 +2315,6 @@ test "cast builtins can wrap result in error union" {
2365 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2315 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2366 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2367 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2317 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2368 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
23692318
2370 const S = struct {2319 const S = struct {
2371 const MyEnum = enum(u32) { _ };2320 const MyEnum = enum(u32) { _ };
...@@ -2404,7 +2353,6 @@ test "cast builtins can wrap result in error union and optional" {...@@ -2404,7 +2353,6 @@ test "cast builtins can wrap result in error union and optional" {
2404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2353 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2405 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2354 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2406 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2355 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2407 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
24082356
2409 const S = struct {2357 const S = struct {
2410 const MyEnum = enum(u32) { _ };2358 const MyEnum = enum(u32) { _ };
...@@ -2600,7 +2548,6 @@ test "@intFromBool on vector" {...@@ -2600,7 +2548,6 @@ test "@intFromBool on vector" {
26002548
2601test "numeric coercions with undefined" {2549test "numeric coercions with undefined" {
2602 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;2550 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
2603 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
26042551
2605 const from: i32 = undefined;2552 const from: i32 = undefined;
2606 var to: f32 = from;2553 var to: f32 = from;
...@@ -2624,7 +2571,6 @@ test "@as does not corrupt values with incompatible representations" {...@@ -2624,7 +2571,6 @@ test "@as does not corrupt values with incompatible representations" {
2624 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2571 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2625 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2572 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2626 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;2573 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
2627 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
26282574
2629 const x: f32 = @as(f16, blk: {2575 const x: f32 = @as(f16, blk: {
2630 if (false) {2576 if (false) {
test/behavior/comptime_memory.zig-4
...@@ -408,8 +408,6 @@ test "mutate entire slice at comptime" {...@@ -408,8 +408,6 @@ test "mutate entire slice at comptime" {
408}408}
409409
410test "dereference undefined pointer to zero-bit type" {410test "dereference undefined pointer to zero-bit type" {
411 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
412
413 const p0: *void = undefined;411 const p0: *void = undefined;
414 try testing.expectEqual({}, p0.*);412 try testing.expectEqual({}, p0.*);
415413
...@@ -515,7 +513,5 @@ fn fieldPtrTest() u32 {...@@ -515,7 +513,5 @@ fn fieldPtrTest() u32 {
515 return a.value;513 return a.value;
516}514}
517test "pointer in aggregate field can mutate comptime state" {515test "pointer in aggregate field can mutate comptime state" {
518 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
519
520 try comptime std.testing.expect(fieldPtrTest() == 2);516 try comptime std.testing.expect(fieldPtrTest() == 2);
521}517}
test/behavior/defer.zig-3
...@@ -116,7 +116,6 @@ test "errdefer with payload" {...@@ -116,7 +116,6 @@ test "errdefer with payload" {
116 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO116 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
117 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO117 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
118 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;118 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
119 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
120119
121 const S = struct {120 const S = struct {
122 fn foo() !i32 {121 fn foo() !i32 {
...@@ -139,7 +138,6 @@ test "reference to errdefer payload" {...@@ -139,7 +138,6 @@ test "reference to errdefer payload" {
139 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO138 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
141 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO140 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
142 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
143141
144 const S = struct {142 const S = struct {
145 fn foo() !i32 {143 fn foo() !i32 {
...@@ -162,7 +160,6 @@ test "reference to errdefer payload" {...@@ -162,7 +160,6 @@ test "reference to errdefer payload" {
162test "simple else prong doesn't emit an error for unreachable else prong" {160test "simple else prong doesn't emit an error for unreachable else prong" {
163 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;161 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
165 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
166163
167 const S = struct {164 const S = struct {
168 fn foo() error{Foo}!void {165 fn foo() error{Foo}!void {
test/behavior/empty_union.zig-4
...@@ -48,8 +48,6 @@ test "empty extern union" {...@@ -48,8 +48,6 @@ test "empty extern union" {
48}48}
4949
50test "empty union passed as argument" {50test "empty union passed as argument" {
51 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
52
53 const U = union(enum) {51 const U = union(enum) {
54 fn f(u: @This()) void {52 fn f(u: @This()) void {
55 switch (u) {}53 switch (u) {}
...@@ -59,8 +57,6 @@ test "empty union passed as argument" {...@@ -59,8 +57,6 @@ test "empty union passed as argument" {
59}57}
6058
61test "empty enum passed as argument" {59test "empty enum passed as argument" {
62 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
63
64 const E = enum {60 const E = enum {
65 fn f(e: @This()) void {61 fn f(e: @This()) void {
66 switch (e) {}62 switch (e) {}
test/behavior/enum.zig-5
...@@ -610,7 +610,6 @@ fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {...@@ -610,7 +610,6 @@ fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {
610test "enum with specified tag values" {610test "enum with specified tag values" {
611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
612 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO612 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
613 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
614613
615 try testEnumWithSpecifiedTagValues(MultipleChoice.C);614 try testEnumWithSpecifiedTagValues(MultipleChoice.C);
616 try comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);615 try comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
...@@ -684,7 +683,6 @@ test "empty non-exhaustive enum" {...@@ -684,7 +683,6 @@ test "empty non-exhaustive enum" {
684test "single field non-exhaustive enum" {683test "single field non-exhaustive enum" {
685 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;684 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
686 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO685 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
687 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
688686
689 const S = struct {687 const S = struct {
690 const E = enum(u8) { a, _ };688 const E = enum(u8) { a, _ };
...@@ -749,7 +747,6 @@ test "cast integer literal to enum" {...@@ -749,7 +747,6 @@ test "cast integer literal to enum" {
749test "enum with specified and unspecified tag values" {747test "enum with specified and unspecified tag values" {
750 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;748 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
751 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO749 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
752 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
753750
754 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);751 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
755 try comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);752 try comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
...@@ -858,8 +855,6 @@ fn doALoopThing(id: EnumWithOneMember) void {...@@ -858,8 +855,6 @@ fn doALoopThing(id: EnumWithOneMember) void {
858}855}
859856
860test "comparison operator on enum with one member is comptime-known" {857test "comparison operator on enum with one member is comptime-known" {
861 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
862
863 doALoopThing(EnumWithOneMember.Eof);858 doALoopThing(EnumWithOneMember.Eof);
864}859}
865860
test/behavior/error.zig+1-25
...@@ -31,7 +31,6 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void {...@@ -31,7 +31,6 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
3131
32test "error binary operator" {32test "error binary operator" {
33 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO33 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
34 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3534
36 const a = errBinaryOperatorG(true) catch 3;35 const a = errBinaryOperatorG(true) catch 3;
37 const b = errBinaryOperatorG(false) catch 3;36 const b = errBinaryOperatorG(false) catch 3;
...@@ -63,14 +62,12 @@ pub fn baz() anyerror!i32 {...@@ -63,14 +62,12 @@ pub fn baz() anyerror!i32 {
6362
64test "error wrapping" {63test "error wrapping" {
65 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO64 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
6765
68 try expect((baz() catch unreachable) == 15);66 try expect((baz() catch unreachable) == 15);
69}67}
7068
71test "unwrap simple value from error" {69test "unwrap simple value from error" {
72 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO70 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
73 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7471
75 const i = unwrapSimpleValueFromErrorDo() catch unreachable;72 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
76 try expect(i == 13);73 try expect(i == 13);
...@@ -81,7 +78,6 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {...@@ -81,7 +78,6 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {
8178
82test "error return in assignment" {79test "error return in assignment" {
83 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO80 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8581
86 doErrReturnInAssignment() catch unreachable;82 doErrReturnInAssignment() catch unreachable;
87}83}
...@@ -104,7 +100,6 @@ test "syntax: optional operator in front of error union operator" {...@@ -104,7 +100,6 @@ test "syntax: optional operator in front of error union operator" {
104test "widen cast integer payload of error union function call" {100test "widen cast integer payload of error union function call" {
105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
106 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
107 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
108103
109 const S = struct {104 const S = struct {
110 fn errorable() !u64 {105 fn errorable() !u64 {
...@@ -129,7 +124,6 @@ test "debug info for optional error set" {...@@ -129,7 +124,6 @@ test "debug info for optional error set" {
129124
130test "implicit cast to optional to error union to return result loc" {125test "implicit cast to optional to error union to return result loc" {
131 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO126 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
132 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
133127
134 const S = struct {128 const S = struct {
135 fn entry() !void {129 fn entry() !void {
...@@ -241,8 +235,6 @@ fn testExplicitErrorSetCast(set1: Set1) !void {...@@ -241,8 +235,6 @@ fn testExplicitErrorSetCast(set1: Set1) !void {
241}235}
242236
243test "@errorCast on error unions" {237test "@errorCast on error unions" {
244 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
245
246 const S = struct {238 const S = struct {
247 fn doTheTest() !void {239 fn doTheTest() !void {
248 {240 {
...@@ -270,7 +262,6 @@ test "@errorCast on error unions" {...@@ -270,7 +262,6 @@ test "@errorCast on error unions" {
270262
271test "comptime test error for empty error set" {263test "comptime test error for empty error set" {
272 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO264 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
273 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
274265
275 try testComptimeTestErrorEmptySet(1234);266 try testComptimeTestErrorEmptySet(1234);
276 try comptime testComptimeTestErrorEmptySet(1234);267 try comptime testComptimeTestErrorEmptySet(1234);
...@@ -306,8 +297,6 @@ test "inferred empty error set comptime catch" {...@@ -306,8 +297,6 @@ test "inferred empty error set comptime catch" {
306}297}
307298
308test "error inference with an empty set" {299test "error inference with an empty set" {
309 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
310
311 const S = struct {300 const S = struct {
312 const Struct = struct {301 const Struct = struct {
313 pub fn func() (error{})!usize {302 pub fn func() (error{})!usize {
...@@ -362,7 +351,6 @@ fn quux_1() !i32 {...@@ -362,7 +351,6 @@ fn quux_1() !i32 {
362351
363test "error: Zero sized error set returned with value payload crash" {352test "error: Zero sized error set returned with value payload crash" {
364 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO353 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
365 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
366354
367 _ = try foo3(0);355 _ = try foo3(0);
368 _ = try comptime foo3(0);356 _ = try comptime foo3(0);
...@@ -376,7 +364,6 @@ fn foo3(b: usize) Error!usize {...@@ -376,7 +364,6 @@ fn foo3(b: usize) Error!usize {
376test "error: Infer error set from literals" {364test "error: Infer error set from literals" {
377 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO365 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
378 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;366 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
379 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
380367
381 _ = nullLiteral("n") catch |err| handleErrors(err);368 _ = nullLiteral("n") catch |err| handleErrors(err);
382 _ = floatLiteral("n") catch |err| handleErrors(err);369 _ = floatLiteral("n") catch |err| handleErrors(err);
...@@ -498,7 +485,6 @@ test "optional error set is the same size as error set" {...@@ -498,7 +485,6 @@ test "optional error set is the same size as error set" {
498test "nested catch" {485test "nested catch" {
499 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO486 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
500 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO487 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
501 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
502488
503 const S = struct {489 const S = struct {
504 fn entry() !void {490 fn entry() !void {
...@@ -524,7 +510,6 @@ test "nested catch" {...@@ -524,7 +510,6 @@ test "nested catch" {
524test "function pointer with return type that is error union with payload which is pointer of parent struct" {510test "function pointer with return type that is error union with payload which is pointer of parent struct" {
525 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO511 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
526 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;512 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
527 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
528513
529 const S = struct {514 const S = struct {
530 const Foo = struct {515 const Foo = struct {
...@@ -582,7 +567,6 @@ test "error payload type is correctly resolved" {...@@ -582,7 +567,6 @@ test "error payload type is correctly resolved" {
582 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO567 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
583 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO568 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
584 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO569 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
585 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
586570
587 const MyIntWrapper = struct {571 const MyIntWrapper = struct {
588 const Self = @This();572 const Self = @This();
...@@ -755,7 +739,6 @@ test "ret_ptr doesn't cause own inferred error set to be resolved" {...@@ -755,7 +739,6 @@ test "ret_ptr doesn't cause own inferred error set to be resolved" {
755739
756test "simple else prong allowed even when all errors handled" {740test "simple else prong allowed even when all errors handled" {
757 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO741 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
758 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
759742
760 const S = struct {743 const S = struct {
761 fn foo() !u8 {744 fn foo() !u8 {
...@@ -873,7 +856,6 @@ test "alignment of wrapping an error union payload" {...@@ -873,7 +856,6 @@ test "alignment of wrapping an error union payload" {
873856
874test "compare error union and error set" {857test "compare error union and error set" {
875 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO858 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
876 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
877859
878 var a: anyerror = error.Foo;860 var a: anyerror = error.Foo;
879 var b: anyerror!u32 = error.Bar;861 var b: anyerror!u32 = error.Bar;
...@@ -1039,7 +1021,6 @@ test "function called at runtime is properly analyzed for inferred error set" {...@@ -1039,7 +1021,6 @@ test "function called at runtime is properly analyzed for inferred error set" {
1039 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1021 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1040 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1022 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1041 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1023 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1042 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10431024
1044 const S = struct {1025 const S = struct {
1045 fn foo() !void {1026 fn foo() !void {
...@@ -1063,7 +1044,6 @@ test "generic type constructed from inferred error set of unresolved function" {...@@ -1063,7 +1044,6 @@ test "generic type constructed from inferred error set of unresolved function" {
1063 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1044 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1064 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1045 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1065 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1046 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1066 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10671047
1068 const S = struct {1048 const S = struct {
1069 fn write(_: void, bytes: []const u8) !usize {1049 fn write(_: void, bytes: []const u8) !usize {
...@@ -1079,8 +1059,6 @@ test "generic type constructed from inferred error set of unresolved function" {...@@ -1079,8 +1059,6 @@ test "generic type constructed from inferred error set of unresolved function" {
1079}1059}
10801060
1081test "errorCast to adhoc inferred error set" {1061test "errorCast to adhoc inferred error set" {
1082 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1083
1084 const S = struct {1062 const S = struct {
1085 inline fn baz() !i32 {1063 inline fn baz() !i32 {
1086 return @errorCast(err());1064 return @errorCast(err());
...@@ -1093,8 +1071,6 @@ test "errorCast to adhoc inferred error set" {...@@ -1093,8 +1071,6 @@ test "errorCast to adhoc inferred error set" {
1093}1071}
10941072
1095test "errorCast from error sets to error unions" {1073test "errorCast from error sets to error unions" {
1096 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1097
1098 const err_union: Set1!void = @errorCast(error.A);1074 const err_union: Set1!void = @errorCast(error.A);
1099 try expectError(error.A, err_union);1075 try expectError(error.A, err_union);
1100}1076}
...@@ -1103,8 +1079,8 @@ test "result location initialization of error union with OPV payload" {...@@ -1103,8 +1079,8 @@ test "result location initialization of error union with OPV payload" {
1103 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1079 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1104 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1080 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1105 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1081 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1106 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1107 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1082 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1083 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11081084
1109 const S = struct {1085 const S = struct {
1110 x: u0,1086 x: u0,
test/behavior/eval.zig-16
...@@ -73,7 +73,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {...@@ -73,7 +73,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
73test "constant expressions" {73test "constant expressions" {
74 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO74 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
75 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO75 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7776
78 var array: [array_size]u8 = undefined;77 var array: [array_size]u8 = undefined;
79 _ = &array;78 _ = &array;
...@@ -506,7 +505,6 @@ test "comptime shlWithOverflow" {...@@ -506,7 +505,6 @@ test "comptime shlWithOverflow" {
506test "const ptr to variable data changes at runtime" {505test "const ptr to variable data changes at runtime" {
507 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO506 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
508 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO507 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
509 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
510508
511 try expect(foo_ref.name[0] == 'a');509 try expect(foo_ref.name[0] == 'a');
512 foo_ref.name = "b";510 foo_ref.name = "b";
...@@ -549,7 +547,6 @@ test "static eval list init" {...@@ -549,7 +547,6 @@ test "static eval list init" {
549 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO547 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
550 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO548 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
551 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO549 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
552 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
553550
554 try expect(static_vec3.data[2] == 1.0);551 try expect(static_vec3.data[2] == 1.0);
555 try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);552 try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
...@@ -721,8 +718,6 @@ fn loopNTimes(comptime n: usize) void {...@@ -721,8 +718,6 @@ fn loopNTimes(comptime n: usize) void {
721}718}
722719
723test "variable inside inline loop that has different types on different iterations" {720test "variable inside inline loop that has different types on different iterations" {
724 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
725
726 try testVarInsideInlineLoop(.{ true, @as(u32, 42) });721 try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
727}722}
728723
...@@ -746,7 +741,6 @@ test "array concatenation of function calls" {...@@ -746,7 +741,6 @@ test "array concatenation of function calls" {
746 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;741 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
747 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;742 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
748 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO743 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
749 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
750744
751 var a = oneItem(3) ++ oneItem(4);745 var a = oneItem(3) ++ oneItem(4);
752 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));746 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
...@@ -756,7 +750,6 @@ test "array multiplication of function calls" {...@@ -756,7 +750,6 @@ test "array multiplication of function calls" {
756 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;750 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
757 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;751 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
758 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO752 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
759 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
760753
761 var a = oneItem(3) ** scalar(2);754 var a = oneItem(3) ** scalar(2);
762 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));755 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
...@@ -774,7 +767,6 @@ test "array concatenation peer resolves element types - value" {...@@ -774,7 +767,6 @@ test "array concatenation peer resolves element types - value" {
774 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;767 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
775 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;768 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
776 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO769 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
777 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
778770
779 var a = [2]u3{ 1, 7 };771 var a = [2]u3{ 1, 7 };
780 var b = [3]u8{ 200, 225, 255 };772 var b = [3]u8{ 200, 225, 255 };
...@@ -1088,7 +1080,6 @@ test "comptime break operand passing through runtime condition converted to runt...@@ -1088,7 +1080,6 @@ test "comptime break operand passing through runtime condition converted to runt
1088test "comptime break operand passing through runtime switch converted to runtime break" {1080test "comptime break operand passing through runtime switch converted to runtime break" {
1089 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1081 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1090 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1082 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1091 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10921083
1093 const S = struct {1084 const S = struct {
1094 fn doTheTest(runtime: u8) !void {1085 fn doTheTest(runtime: u8) !void {
...@@ -1556,7 +1547,6 @@ test "non-optional and optional array elements concatenated" {...@@ -1556,7 +1547,6 @@ test "non-optional and optional array elements concatenated" {
1556 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1547 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1557 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1548 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1558 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1549 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1559 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15601550
1561 const array = [1]u8{'A'} ++ [1]?u8{null};1551 const array = [1]u8{'A'} ++ [1]?u8{null};
1562 var index: usize = 0;1552 var index: usize = 0;
...@@ -1631,8 +1621,6 @@ test "struct in comptime false branch is not evaluated" {...@@ -1631,8 +1621,6 @@ test "struct in comptime false branch is not evaluated" {
1631}1621}
16321622
1633test "result of nested switch assigned to variable" {1623test "result of nested switch assigned to variable" {
1634 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1635
1636 var zds: u32 = 0;1624 var zds: u32 = 0;
1637 zds = switch (zds) {1625 zds = switch (zds) {
1638 0 => switch (zds) {1626 0 => switch (zds) {
...@@ -1647,8 +1635,6 @@ test "result of nested switch assigned to variable" {...@@ -1647,8 +1635,6 @@ test "result of nested switch assigned to variable" {
1647}1635}
16481636
1649test "inline for loop of functions returning error unions" {1637test "inline for loop of functions returning error unions" {
1650 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1651
1652 const T1 = struct {1638 const T1 = struct {
1653 fn v() error{}!usize {1639 fn v() error{}!usize {
1654 return 1;1640 return 1;
...@@ -1667,8 +1653,6 @@ test "inline for loop of functions returning error unions" {...@@ -1667,8 +1653,6 @@ test "inline for loop of functions returning error unions" {
1667}1653}
16681654
1669test "if inside a switch" {1655test "if inside a switch" {
1670 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1671
1672 var condition = true;1656 var condition = true;
1673 var wave_type: u32 = 0;1657 var wave_type: u32 = 0;
1674 _ = .{ &condition, &wave_type };1658 _ = .{ &condition, &wave_type };
test/behavior/extern.zig-2
...@@ -20,7 +20,6 @@ test "function extern symbol" {...@@ -20,7 +20,6 @@ test "function extern symbol" {
20 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;20 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;21 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;22 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
23 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2423
25 const a = @extern(*const fn () callconv(.C) i32, .{ .name = "a_mystery_function" });24 const a = @extern(*const fn () callconv(.C) i32, .{ .name = "a_mystery_function" });
26 try expect(a() == 4567);25 try expect(a() == 4567);
...@@ -34,7 +33,6 @@ test "function extern symbol matches extern decl" {...@@ -34,7 +33,6 @@ test "function extern symbol matches extern decl" {
34 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;33 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
35 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;34 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
36 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;35 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3836
39 const S = struct {37 const S = struct {
40 extern fn another_mystery_function() u32;38 extern fn another_mystery_function() u32;
test/behavior/floatop.zig-13
...@@ -22,8 +22,6 @@ test "add f16" {...@@ -22,8 +22,6 @@ test "add f16" {
22}22}
2323
24test "add f32/f64" {24test "add f32/f64" {
25 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
26
27 try testAdd(f32);25 try testAdd(f32);
28 try comptime testAdd(f32);26 try comptime testAdd(f32);
29 try testAdd(f64);27 try testAdd(f64);
...@@ -60,8 +58,6 @@ test "sub f16" {...@@ -60,8 +58,6 @@ test "sub f16" {
60}58}
6159
62test "sub f32/f64" {60test "sub f32/f64" {
63 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
64
65 try testSub(f32);61 try testSub(f32);
66 try comptime testSub(f32);62 try comptime testSub(f32);
67 try testSub(f64);63 try testSub(f64);
...@@ -98,8 +94,6 @@ test "mul f16" {...@@ -98,8 +94,6 @@ test "mul f16" {
98}94}
9995
100test "mul f32/f64" {96test "mul f32/f64" {
101 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
102
103 try testMul(f32);97 try testMul(f32);
104 try comptime testMul(f32);98 try comptime testMul(f32);
105 try testMul(f64);99 try testMul(f64);
...@@ -1005,7 +999,6 @@ test "@abs f32/f64" {...@@ -1005,7 +999,6 @@ test "@abs f32/f64" {
1005 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO999 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1006 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1000 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1007 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1001 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1008 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10091002
1010 try testFabs(f32);1003 try testFabs(f32);
1011 try comptime testFabs(f32);1004 try comptime testFabs(f32);
...@@ -1622,7 +1615,6 @@ test "comptime inf >= runtime 1" {...@@ -1622,7 +1615,6 @@ test "comptime inf >= runtime 1" {
1622test "comptime isNan(nan * 1)" {1615test "comptime isNan(nan * 1)" {
1623 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1616 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1624 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1617 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1625 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
16261618
1627 const nan_times_one = comptime std.math.nan(f64) * 1;1619 const nan_times_one = comptime std.math.nan(f64) * 1;
1628 try std.testing.expect(std.math.isNan(nan_times_one));1620 try std.testing.expect(std.math.isNan(nan_times_one));
...@@ -1630,7 +1622,6 @@ test "comptime isNan(nan * 1)" {...@@ -1630,7 +1622,6 @@ test "comptime isNan(nan * 1)" {
1630test "runtime isNan(nan * 1)" {1622test "runtime isNan(nan * 1)" {
1631 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1623 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1632 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1624 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1633 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
16341625
1635 const nan_times_one = std.math.nan(f64) * 1;1626 const nan_times_one = std.math.nan(f64) * 1;
1636 try std.testing.expect(std.math.isNan(nan_times_one));1627 try std.testing.expect(std.math.isNan(nan_times_one));
...@@ -1638,7 +1629,6 @@ test "runtime isNan(nan * 1)" {...@@ -1638,7 +1629,6 @@ test "runtime isNan(nan * 1)" {
1638test "comptime isNan(nan * 0)" {1629test "comptime isNan(nan * 0)" {
1639 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1630 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1640 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1631 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1641 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
16421632
1643 const nan_times_zero = comptime std.math.nan(f64) * 0;1633 const nan_times_zero = comptime std.math.nan(f64) * 0;
1644 try std.testing.expect(std.math.isNan(nan_times_zero));1634 try std.testing.expect(std.math.isNan(nan_times_zero));
...@@ -1648,7 +1638,6 @@ test "comptime isNan(nan * 0)" {...@@ -1648,7 +1638,6 @@ test "comptime isNan(nan * 0)" {
1648test "runtime isNan(nan * 0)" {1638test "runtime isNan(nan * 0)" {
1649 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1639 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1650 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1640 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1651 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
16521641
1653 const nan_times_zero = std.math.nan(f64) * 0;1642 const nan_times_zero = std.math.nan(f64) * 0;
1654 try std.testing.expect(std.math.isNan(nan_times_zero));1643 try std.testing.expect(std.math.isNan(nan_times_zero));
...@@ -1658,7 +1647,6 @@ test "runtime isNan(nan * 0)" {...@@ -1658,7 +1647,6 @@ test "runtime isNan(nan * 0)" {
1658test "comptime isNan(inf * 0)" {1647test "comptime isNan(inf * 0)" {
1659 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1648 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1660 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1649 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1661 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
16621650
1663 const inf_times_zero = comptime std.math.inf(f64) * 0;1651 const inf_times_zero = comptime std.math.inf(f64) * 0;
1664 try std.testing.expect(std.math.isNan(inf_times_zero));1652 try std.testing.expect(std.math.isNan(inf_times_zero));
...@@ -1668,7 +1656,6 @@ test "comptime isNan(inf * 0)" {...@@ -1668,7 +1656,6 @@ test "comptime isNan(inf * 0)" {
1668test "runtime isNan(inf * 0)" {1656test "runtime isNan(inf * 0)" {
1669 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1657 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1670 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1658 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1671 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
16721659
1673 const inf_times_zero = std.math.inf(f64) * 0;1660 const inf_times_zero = std.math.inf(f64) * 0;
1674 try std.testing.expect(std.math.isNan(inf_times_zero));1661 try std.testing.expect(std.math.isNan(inf_times_zero));
test/behavior/fn.zig-19
...@@ -71,7 +71,6 @@ fn outer(y: u32) *const fn (u32) u32 {...@@ -71,7 +71,6 @@ fn outer(y: u32) *const fn (u32) u32 {
7171
72test "return inner function which references comptime variable of outer function" {72test "return inner function which references comptime variable of outer function" {
73 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;73 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
74 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7574
76 const func = outer(10);75 const func = outer(10);
77 try expect(func(3) == 7);76 try expect(func(3) == 7);
...@@ -81,7 +80,6 @@ test "discard the result of a function that returns a struct" {...@@ -81,7 +80,6 @@ test "discard the result of a function that returns a struct" {
81 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;80 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
82 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;81 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
83 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO82 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8583
86 const S = struct {84 const S = struct {
87 fn entry() void {85 fn entry() void {
...@@ -106,7 +104,6 @@ test "inline function call that calls optional function pointer, return pointer...@@ -106,7 +104,6 @@ test "inline function call that calls optional function pointer, return pointer
106 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;104 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
107 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO105 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
108 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;106 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
109 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
110107
111 const S = struct {108 const S = struct {
112 field: u32,109 field: u32,
...@@ -191,7 +188,6 @@ test "function with complex callconv and return type expressions" {...@@ -191,7 +188,6 @@ test "function with complex callconv and return type expressions" {
191188
192test "pass by non-copying value" {189test "pass by non-copying value" {
193 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO190 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
194 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
195191
196 try expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);192 try expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
197}193}
...@@ -207,7 +203,6 @@ fn addPointCoords(pt: Point) i32 {...@@ -207,7 +203,6 @@ fn addPointCoords(pt: Point) i32 {
207203
208test "pass by non-copying value through var arg" {204test "pass by non-copying value through var arg" {
209 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
210 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
211206
212 try expect((try addPointCoordsVar(Point{ .x = 1, .y = 2 })) == 3);207 try expect((try addPointCoordsVar(Point{ .x = 1, .y = 2 })) == 3);
213}208}
...@@ -219,7 +214,6 @@ fn addPointCoordsVar(pt: anytype) !i32 {...@@ -219,7 +214,6 @@ fn addPointCoordsVar(pt: anytype) !i32 {
219214
220test "pass by non-copying value as method" {215test "pass by non-copying value as method" {
221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO216 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
222 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
223217
224 var pt = Point2{ .x = 1, .y = 2 };218 var pt = Point2{ .x = 1, .y = 2 };
225 try expect(pt.addPointCoords() == 3);219 try expect(pt.addPointCoords() == 3);
...@@ -236,7 +230,6 @@ const Point2 = struct {...@@ -236,7 +230,6 @@ const Point2 = struct {
236230
237test "pass by non-copying value as method, which is generic" {231test "pass by non-copying value as method, which is generic" {
238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO232 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
239 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
240233
241 var pt = Point3{ .x = 1, .y = 2 };234 var pt = Point3{ .x = 1, .y = 2 };
242 try expect(pt.addPointCoords(i32) == 3);235 try expect(pt.addPointCoords(i32) == 3);
...@@ -265,7 +258,6 @@ test "implicit cast fn call result to optional in field result" {...@@ -265,7 +258,6 @@ test "implicit cast fn call result to optional in field result" {
265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
266 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;259 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
267 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO260 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
268 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
269261
270 const S = struct {262 const S = struct {
271 fn entry() !void {263 fn entry() !void {
...@@ -292,7 +284,6 @@ test "implicit cast fn call result to optional in field result" {...@@ -292,7 +284,6 @@ test "implicit cast fn call result to optional in field result" {
292test "void parameters" {284test "void parameters" {
293 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;285 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
294 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;286 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
295 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
296287
297 try voidFun(1, void{}, 2, {});288 try voidFun(1, void{}, 2, {});
298}289}
...@@ -356,7 +347,6 @@ test "function call with anon list literal" {...@@ -356,7 +347,6 @@ test "function call with anon list literal" {
356 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO347 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
357 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO348 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
358 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO349 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
359 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
360350
361 const S = struct {351 const S = struct {
362 fn doTheTest() !void {352 fn doTheTest() !void {
...@@ -377,7 +367,6 @@ test "function call with anon list literal - 2D" {...@@ -377,7 +367,6 @@ test "function call with anon list literal - 2D" {
377 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO367 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
378 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO368 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
379 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO369 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
380 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
381370
382 const S = struct {371 const S = struct {
383 fn doTheTest() !void {372 fn doTheTest() !void {
...@@ -414,8 +403,6 @@ test "ability to give comptime types and non comptime types to same parameter" {...@@ -414,8 +403,6 @@ test "ability to give comptime types and non comptime types to same parameter" {
414}403}
415404
416test "function with inferred error set but returning no error" {405test "function with inferred error set but returning no error" {
417 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
418
419 const S = struct {406 const S = struct {
420 fn foo() !void {}407 fn foo() !void {}
421 };408 };
...@@ -426,7 +413,6 @@ test "function with inferred error set but returning no error" {...@@ -426,7 +413,6 @@ test "function with inferred error set but returning no error" {
426413
427test "import passed byref to function in return type" {414test "import passed byref to function in return type" {
428 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO415 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
429 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
430416
431 const S = struct {417 const S = struct {
432 fn get() @import("std").ArrayListUnmanaged(i32) {418 fn get() @import("std").ArrayListUnmanaged(i32) {
...@@ -485,7 +471,6 @@ test "method call with optional and error union first param" {...@@ -485,7 +471,6 @@ test "method call with optional and error union first param" {
485test "method call with optional pointer first param" {471test "method call with optional pointer first param" {
486 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
487 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO473 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
488 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
489474
490 const S = struct {475 const S = struct {
491 x: i32 = 1234,476 x: i32 = 1234,
...@@ -505,7 +490,6 @@ test "using @ptrCast on function pointers" {...@@ -505,7 +490,6 @@ test "using @ptrCast on function pointers" {
505 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO490 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
506 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO491 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
507 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;492 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
508 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
509493
510 const S = struct {494 const S = struct {
511 const A = struct { data: [4]u8 };495 const A = struct { data: [4]u8 };
...@@ -543,7 +527,6 @@ test "function returns function returning type" {...@@ -543,7 +527,6 @@ test "function returns function returning type" {
543527
544test "peer type resolution of inferred error set with non-void payload" {528test "peer type resolution of inferred error set with non-void payload" {
545 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO529 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
546 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
547530
548 const S = struct {531 const S = struct {
549 fn openDataFile(mode: enum { read, write }) !u32 {532 fn openDataFile(mode: enum { read, write }) !u32 {
...@@ -586,8 +569,6 @@ test "lazy values passed to anytype parameter" {...@@ -586,8 +569,6 @@ test "lazy values passed to anytype parameter" {
586}569}
587570
588test "pass and return comptime-only types" {571test "pass and return comptime-only types" {
589 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
590
591 const S = struct {572 const S = struct {
592 fn returnNull(comptime x: @Type(.Null)) @Type(.Null) {573 fn returnNull(comptime x: @Type(.Null)) @Type(.Null) {
593 return x;574 return x;
test/behavior/fn_delegation.zig-1
...@@ -34,7 +34,6 @@ fn custom(comptime T: type, comptime num: u64) fn (T) u64 {...@@ -34,7 +34,6 @@ fn custom(comptime T: type, comptime num: u64) fn (T) u64 {
34test "fn delegation" {34test "fn delegation" {
35 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO35 if (builtin.zig_backend == .stage2_arm) 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;
3837
39 const foo = Foo{};38 const foo = Foo{};
40 try expect(foo.one() == 11);39 try expect(foo.one() == 11);
test/behavior/for.zig-14
...@@ -69,7 +69,6 @@ test "basic for loop" {...@@ -69,7 +69,6 @@ test "basic for loop" {
69 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;69 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
70 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;70 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO71 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7372
74 const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;73 const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
7574
...@@ -134,7 +133,6 @@ test "for with null and T peer types and inferred result location type" {...@@ -134,7 +133,6 @@ test "for with null and T peer types and inferred result location type" {
134test "2 break statements and an else" {133test "2 break statements and an else" {
135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;134 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
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 S = struct {137 const S = struct {
140 fn entry(t: bool, f: bool) !void {138 fn entry(t: bool, f: bool) !void {
...@@ -183,7 +181,6 @@ fn mangleString(s: []u8) void {...@@ -183,7 +181,6 @@ fn mangleString(s: []u8) void {
183test "for copies its payload" {181test "for copies its payload" {
184 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
185 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO183 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
186 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
187184
188 const S = struct {185 const S = struct {
189 fn doTheTest() !void {186 fn doTheTest() !void {
...@@ -203,7 +200,6 @@ test "for on slice with allowzero ptr" {...@@ -203,7 +200,6 @@ test "for on slice with allowzero ptr" {
203 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO202 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
206 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
207203
208 const S = struct {204 const S = struct {
209 fn doTheTest(slice: []const u8) !void {205 fn doTheTest(slice: []const u8) !void {
...@@ -219,7 +215,6 @@ test "for on slice with allowzero ptr" {...@@ -219,7 +215,6 @@ test "for on slice with allowzero ptr" {
219test "else continue outer for" {215test "else continue outer for" {
220 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO217 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
222 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
223218
224 var i: usize = 6;219 var i: usize = 6;
225 var buf: [5]u8 = undefined;220 var buf: [5]u8 = undefined;
...@@ -283,7 +278,6 @@ test "two counters" {...@@ -283,7 +278,6 @@ test "two counters" {
283test "1-based counter and ptr to array" {278test "1-based counter and ptr to array" {
284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO279 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
285 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO280 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
286 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
287281
288 var ok: usize = 0;282 var ok: usize = 0;
289283
...@@ -317,7 +311,6 @@ test "slice and two counters, one is offset and one is runtime" {...@@ -317,7 +311,6 @@ test "slice and two counters, one is offset and one is runtime" {
317 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO311 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
318 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO312 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
319 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
320 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
321314
322 const slice: []const u8 = "blah";315 const slice: []const u8 = "blah";
323 var start: usize = 0;316 var start: usize = 0;
...@@ -347,7 +340,6 @@ test "two slices, one captured by-ref" {...@@ -347,7 +340,6 @@ test "two slices, one captured by-ref" {
347 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO340 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
348 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
349 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO342 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
350 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
351343
352 var buf: [10]u8 = undefined;344 var buf: [10]u8 = undefined;
353 const slice1: []const u8 = "blah";345 const slice1: []const u8 = "blah";
...@@ -367,7 +359,6 @@ test "raw pointer and slice" {...@@ -367,7 +359,6 @@ test "raw pointer and slice" {
367 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO359 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
368 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO360 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
369 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO361 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
370 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
371362
372 var buf: [10]u8 = undefined;363 var buf: [10]u8 = undefined;
373 const slice: []const u8 = "blah";364 const slice: []const u8 = "blah";
...@@ -387,7 +378,6 @@ test "raw pointer and counter" {...@@ -387,7 +378,6 @@ test "raw pointer and counter" {
387 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO378 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
388 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO379 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
389 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO380 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
390 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
391381
392 var buf: [10]u8 = undefined;382 var buf: [10]u8 = undefined;
393 const ptr: [*]u8 = &buf;383 const ptr: [*]u8 = &buf;
...@@ -406,7 +396,6 @@ test "inline for with slice as the comptime-known" {...@@ -406,7 +396,6 @@ test "inline for with slice as the comptime-known" {
406 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
407 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
408 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO398 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
409 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
410399
411 const comptime_slice = "hello";400 const comptime_slice = "hello";
412 var runtime_i: usize = 3;401 var runtime_i: usize = 3;
...@@ -438,7 +427,6 @@ test "inline for with counter as the comptime-known" {...@@ -438,7 +427,6 @@ test "inline for with counter as the comptime-known" {
438 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO427 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
439 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO428 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
440 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO429 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
441 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
442430
443 var runtime_slice = "hello";431 var runtime_slice = "hello";
444 var runtime_i: usize = 3;432 var runtime_i: usize = 3;
...@@ -471,7 +459,6 @@ test "inline for on tuple pointer" {...@@ -471,7 +459,6 @@ test "inline for on tuple pointer" {
471 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO459 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
472 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO460 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
473 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;461 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
474 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
475462
476 const S = struct { u32, u32, u32 };463 const S = struct { u32, u32, u32 };
477 var s: S = .{ 100, 200, 300 };464 var s: S = .{ 100, 200, 300 };
...@@ -487,7 +474,6 @@ test "ref counter that starts at zero" {...@@ -487,7 +474,6 @@ test "ref counter that starts at zero" {
487 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO474 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
488 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO475 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
489 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO476 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
490 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
491477
492 for ([_]usize{ 0, 1, 2 }, 0..) |i, j| {478 for ([_]usize{ 0, 1, 2 }, 0..) |i, j| {
493 try expectEqual(i, j);479 try expectEqual(i, j);
test/behavior/generics.zig-10
...@@ -117,7 +117,6 @@ test "function with return type type" {...@@ -117,7 +117,6 @@ test "function with return type type" {
117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
118 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;118 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
120 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
121120
122 var list: List(i32) = undefined;121 var list: List(i32) = undefined;
123 var list2: List(i32) = undefined;122 var list2: List(i32) = undefined;
...@@ -159,7 +158,6 @@ test "generic fn with implicit cast" {...@@ -159,7 +158,6 @@ test "generic fn with implicit cast" {
159 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;158 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
161 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO160 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
162 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
163161
164 try expect(getFirstByte(u8, &[_]u8{13}) == 13);162 try expect(getFirstByte(u8, &[_]u8{13}) == 13);
165 try expect(getFirstByte(u16, &[_]u16{163 try expect(getFirstByte(u16, &[_]u16{
...@@ -287,7 +285,6 @@ test "generic function instantiation turns into comptime call" {...@@ -287,7 +285,6 @@ test "generic function instantiation turns into comptime call" {
287285
288test "generic function with void and comptime parameter" {286test "generic function with void and comptime parameter" {
289 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO287 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
290 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
291288
292 const S = struct { x: i32 };289 const S = struct { x: i32 };
293 const namespace = struct {290 const namespace = struct {
...@@ -304,7 +301,6 @@ test "generic function with void and comptime parameter" {...@@ -304,7 +301,6 @@ test "generic function with void and comptime parameter" {
304test "anonymous struct return type referencing comptime parameter" {301test "anonymous struct return type referencing comptime parameter" {
305 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO302 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
306 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO303 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
307 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
308304
309 const S = struct {305 const S = struct {
310 pub fn extraData(comptime T: type, index: usize) struct { data: T, end: usize } {306 pub fn extraData(comptime T: type, index: usize) struct { data: T, end: usize } {
...@@ -323,7 +319,6 @@ test "generic function instantiation non-duplicates" {...@@ -323,7 +319,6 @@ test "generic function instantiation non-duplicates" {
323 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO319 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
324 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO320 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
325 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
326 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
327 if (builtin.os.tag == .wasi) return error.SkipZigTest;322 if (builtin.os.tag == .wasi) return error.SkipZigTest;
328323
329 const S = struct {324 const S = struct {
...@@ -395,7 +390,6 @@ test "extern function used as generic parameter" {...@@ -395,7 +390,6 @@ test "extern function used as generic parameter" {
395390
396test "generic struct as parameter type" {391test "generic struct as parameter type" {
397 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO392 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
398 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
399393
400 const S = struct {394 const S = struct {
401 fn doTheTest(comptime Int: type, thing: struct { int: Int }) !void {395 fn doTheTest(comptime Int: type, thing: struct { int: Int }) !void {
...@@ -436,7 +430,6 @@ test "null sentinel pointer passed as generic argument" {...@@ -436,7 +430,6 @@ test "null sentinel pointer passed as generic argument" {
436430
437test "generic function passed as comptime argument" {431test "generic function passed as comptime argument" {
438 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO432 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
439 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
440433
441 const S = struct {434 const S = struct {
442 fn doMath(comptime f: fn (type, i32, i32) error{Overflow}!i32, a: i32, b: i32) !void {435 fn doMath(comptime f: fn (type, i32, i32) error{Overflow}!i32, a: i32, b: i32) !void {
...@@ -449,7 +442,6 @@ test "generic function passed as comptime argument" {...@@ -449,7 +442,6 @@ test "generic function passed as comptime argument" {
449442
450test "return type of generic function is function pointer" {443test "return type of generic function is function pointer" {
451 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;444 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
452 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
453445
454 const S = struct {446 const S = struct {
455 fn b(comptime T: type) ?*const fn () error{}!T {447 fn b(comptime T: type) ?*const fn () error{}!T {
...@@ -462,7 +454,6 @@ test "return type of generic function is function pointer" {...@@ -462,7 +454,6 @@ test "return type of generic function is function pointer" {
462454
463test "coerced function body has inequal value with its uncoerced body" {455test "coerced function body has inequal value with its uncoerced body" {
464 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;456 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
465 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
466457
467 const S = struct {458 const S = struct {
468 const A = B(i32, c);459 const A = B(i32, c);
...@@ -547,7 +538,6 @@ test "call generic function with from function called by the generic function" {...@@ -547,7 +538,6 @@ test "call generic function with from function called by the generic function" {
547 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;538 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
548 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;539 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
549 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO540 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
550 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
551 if (builtin.zig_backend == .stage2_llvm and541 if (builtin.zig_backend == .stage2_llvm and
552 builtin.cpu.arch == .aarch64 and builtin.os.tag == .windows) return error.SkipZigTest;542 builtin.cpu.arch == .aarch64 and builtin.os.tag == .windows) return error.SkipZigTest;
553543
test/behavior/globals.zig-2
...@@ -7,7 +7,6 @@ test "store to global array" {...@@ -7,7 +7,6 @@ test "store to global array" {
7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
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_aarch64) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1110
12 try expect(pos[1] == 0.0);11 try expect(pos[1] == 0.0);
13 pos = [2]f32{ 0.0, 1.0 };12 pos = [2]f32{ 0.0, 1.0 };
...@@ -30,7 +29,6 @@ test "slices pointing at the same address as global array." {...@@ -30,7 +29,6 @@ test "slices pointing at the same address as global array." {
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_aarch64) return error.SkipZigTest;30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3432
35 const S = struct {33 const S = struct {
36 const a = [_]u8{ 1, 2, 3 };34 const a = [_]u8{ 1, 2, 3 };
test/behavior/if.zig-2
...@@ -45,7 +45,6 @@ var global_with_err: anyerror!u32 = error.SomeError;...@@ -45,7 +45,6 @@ var global_with_err: anyerror!u32 = error.SomeError;
4545
46test "unwrap mutable global var" {46test "unwrap mutable global var" {
47 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO47 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
48 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
4948
50 if (global_with_val) |v| {49 if (global_with_val) |v| {
51 try expect(v == 0);50 try expect(v == 0);
...@@ -139,7 +138,6 @@ test "if-else expression with runtime condition result location is inferred opti...@@ -139,7 +138,6 @@ test "if-else expression with runtime condition result location is inferred opti
139 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;138 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
140 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;139 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO140 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
142 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
143141
144 const A = struct { b: u64, c: u64 };142 const A = struct { b: u64, c: u64 };
145 var d: bool = true;143 var d: bool = true;
test/behavior/incomplete_struct_param_tld.zig-1
...@@ -23,7 +23,6 @@ fn foo(a: A) i32 {...@@ -23,7 +23,6 @@ fn foo(a: A) i32 {
2323
24test "incomplete struct param top level declaration" {24test "incomplete struct param top level declaration" {
25 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO25 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
26 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2726
28 const a = A{27 const a = A{
29 .b = B{28 .b = B{
test/behavior/inline_switch.zig-8
...@@ -5,7 +5,6 @@ const builtin = @import("builtin");...@@ -5,7 +5,6 @@ const builtin = @import("builtin");
5test "inline scalar prongs" {5test "inline scalar prongs" {
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_sparc64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
98
10 var x: usize = 0;9 var x: usize = 0;
11 switch (x) {10 switch (x) {
...@@ -21,7 +20,6 @@ test "inline scalar prongs" {...@@ -21,7 +20,6 @@ test "inline scalar prongs" {
21test "inline prong ranges" {20test "inline prong ranges" {
22 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2523
26 var x: usize = 0;24 var x: usize = 0;
27 _ = &x;25 _ = &x;
...@@ -37,7 +35,6 @@ const E = enum { a, b, c, d };...@@ -37,7 +35,6 @@ const E = enum { a, b, c, d };
37test "inline switch enums" {35test "inline switch enums" {
38 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO36 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
39 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO37 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
40 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
4138
42 var x: E = .a;39 var x: E = .a;
43 _ = &x;40 _ = &x;
...@@ -79,7 +76,6 @@ test "inline switch unions" {...@@ -79,7 +76,6 @@ test "inline switch unions" {
79test "inline else bool" {76test "inline else bool" {
80 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
81 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
82 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8379
84 var a = true;80 var a = true;
85 _ = &a;81 _ = &a;
...@@ -92,7 +88,6 @@ test "inline else bool" {...@@ -92,7 +88,6 @@ test "inline else bool" {
92test "inline else error" {88test "inline else error" {
93 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO89 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO90 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
95 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
9691
97 const Err = error{ a, b, c };92 const Err = error{ a, b, c };
98 var a = Err.a;93 var a = Err.a;
...@@ -106,7 +101,6 @@ test "inline else error" {...@@ -106,7 +101,6 @@ test "inline else error" {
106test "inline else enum" {101test "inline else enum" {
107 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
110104
111 const E2 = enum(u8) { a = 2, b = 3, c = 4, d = 5 };105 const E2 = enum(u8) { a = 2, b = 3, c = 4, d = 5 };
112 var a: E2 = .a;106 var a: E2 = .a;
...@@ -120,7 +114,6 @@ test "inline else enum" {...@@ -120,7 +114,6 @@ test "inline else enum" {
120test "inline else int with gaps" {114test "inline else int with gaps" {
121 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO115 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
122 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO116 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
123 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
124117
125 var a: u8 = 0;118 var a: u8 = 0;
126 _ = &a;119 _ = &a;
...@@ -139,7 +132,6 @@ test "inline else int with gaps" {...@@ -139,7 +132,6 @@ test "inline else int with gaps" {
139test "inline else int all values" {132test "inline else int all values" {
140 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO134 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
142 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
143135
144 var a: u2 = 0;136 var a: u2 = 0;
145 _ = &a;137 _ = &a;
test/behavior/ir_block_deps.zig-1
...@@ -21,7 +21,6 @@ test "ir block deps" {...@@ -21,7 +21,6 @@ test "ir block deps" {
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO23 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2524
26 try expect((foo(1) catch unreachable) == 0);25 try expect((foo(1) catch unreachable) == 0);
27 try expect((foo(2) catch unreachable) == 0);26 try expect((foo(2) catch unreachable) == 0);
test/behavior/lower_strlit_to_vector.zig-1
...@@ -6,7 +6,6 @@ test "strlit to vector" {...@@ -6,7 +6,6 @@ test "strlit to vector" {
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_sparc64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
109
11 const strlit = "0123456789abcdef0123456789ABCDEF";10 const strlit = "0123456789abcdef0123456789ABCDEF";
12 const vec_from_strlit: @Vector(32, u8) = strlit.*;11 const vec_from_strlit: @Vector(32, u8) = strlit.*;
test/behavior/math.zig-14
...@@ -236,7 +236,6 @@ test "float equality" {...@@ -236,7 +236,6 @@ test "float equality" {
236 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO236 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
239 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
240239
241 const x: f64 = 0.012;240 const x: f64 = 0.012;
242 const y: f64 = x + 1.0;241 const y: f64 = x + 1.0;
...@@ -593,8 +592,6 @@ fn testSignedWrappingEval(x: i32) !void {...@@ -593,8 +592,6 @@ fn testSignedWrappingEval(x: i32) !void {
593}592}
594593
595test "signed negation wrapping" {594test "signed negation wrapping" {
596 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
597
598 try testSignedNegationWrappingEval(minInt(i16));595 try testSignedNegationWrappingEval(minInt(i16));
599 try comptime testSignedNegationWrappingEval(minInt(i16));596 try comptime testSignedNegationWrappingEval(minInt(i16));
600}597}
...@@ -605,8 +602,6 @@ fn testSignedNegationWrappingEval(x: i16) !void {...@@ -605,8 +602,6 @@ fn testSignedNegationWrappingEval(x: i16) !void {
605}602}
606603
607test "unsigned negation wrapping" {604test "unsigned negation wrapping" {
608 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
609
610 try testUnsignedNegationWrappingEval(1);605 try testUnsignedNegationWrappingEval(1);
611 try comptime testUnsignedNegationWrappingEval(1);606 try comptime testUnsignedNegationWrappingEval(1);
612}607}
...@@ -667,8 +662,6 @@ test "bit shift a u1" {...@@ -667,8 +662,6 @@ test "bit shift a u1" {
667}662}
668663
669test "truncating shift right" {664test "truncating shift right" {
670 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
671
672 try testShrTrunc(maxInt(u16));665 try testShrTrunc(maxInt(u16));
673 try comptime testShrTrunc(maxInt(u16));666 try comptime testShrTrunc(maxInt(u16));
674}667}
...@@ -1436,8 +1429,6 @@ test "quad hex float literal parsing accurate" {...@@ -1436,8 +1429,6 @@ test "quad hex float literal parsing accurate" {
1436}1429}
14371430
1438test "truncating shift left" {1431test "truncating shift left" {
1439 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1440
1441 try testShlTrunc(maxInt(u16));1432 try testShlTrunc(maxInt(u16));
1442 try comptime testShlTrunc(maxInt(u16));1433 try comptime testShlTrunc(maxInt(u16));
1443}1434}
...@@ -1460,8 +1451,6 @@ fn testShlExact(x: u8) !void {...@@ -1460,8 +1451,6 @@ fn testShlExact(x: u8) !void {
1460}1451}
14611452
1462test "exact shift right" {1453test "exact shift right" {
1463 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1464
1465 try testShrExact(0b10110100);1454 try testShrExact(0b10110100);
1466 try comptime testShrExact(0b10110100);1455 try comptime testShrExact(0b10110100);
1467}1456}
...@@ -1471,8 +1460,6 @@ fn testShrExact(x: u8) !void {...@@ -1471,8 +1460,6 @@ fn testShrExact(x: u8) !void {
1471}1460}
14721461
1473test "shift left/right on u0 operand" {1462test "shift left/right on u0 operand" {
1474 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1475
1476 const S = struct {1463 const S = struct {
1477 fn doTheTest() !void {1464 fn doTheTest() !void {
1478 var x: u0 = 0;1465 var x: u0 = 0;
...@@ -1821,7 +1808,6 @@ test "absFloat" {...@@ -1821,7 +1808,6 @@ test "absFloat" {
1821 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1808 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1822 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1809 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1823 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1810 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1824 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
18251811
1826 try testAbsFloat();1812 try testAbsFloat();
1827 try comptime testAbsFloat();1813 try comptime testAbsFloat();
test/behavior/member_func.zig-2
...@@ -31,7 +31,6 @@ test "standard field calls" {...@@ -31,7 +31,6 @@ test "standard field calls" {
31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
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_spirv64) return error.SkipZigTest;33 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
34 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3534
36 try expect(HasFuncs.one(0) == 1);35 try expect(HasFuncs.one(0) == 1);
37 try expect(HasFuncs.two(0) == 2);36 try expect(HasFuncs.two(0) == 2);
...@@ -76,7 +75,6 @@ test "@field field calls" {...@@ -76,7 +75,6 @@ test "@field field calls" {
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;75 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO76 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;77 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
79 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8078
81 try expect(@field(HasFuncs, "one")(0) == 1);79 try expect(@field(HasFuncs, "one")(0) == 1);
82 try expect(@field(HasFuncs, "two")(0) == 2);80 try expect(@field(HasFuncs, "two")(0) == 2);
test/behavior/memset.zig-5
...@@ -7,7 +7,6 @@ test "@memset on array pointers" {...@@ -7,7 +7,6 @@ test "@memset on array pointers" {
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;8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
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 testMemsetArray();11 try testMemsetArray();
13 try comptime testMemsetArray();12 try comptime testMemsetArray();
...@@ -73,7 +72,6 @@ test "memset with bool element" {...@@ -73,7 +72,6 @@ test "memset with bool element" {
73 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;72 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
74 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;73 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
75 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;74 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
76 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7775
78 var buf: [5]bool = undefined;76 var buf: [5]bool = undefined;
79 @memset(&buf, true);77 @memset(&buf, true);
...@@ -86,7 +84,6 @@ test "memset with 1-byte struct element" {...@@ -86,7 +84,6 @@ test "memset with 1-byte struct element" {
86 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;84 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
87 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;85 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
88 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;86 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
89 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
9087
91 const S = struct { x: bool };88 const S = struct { x: bool };
92 var buf: [5]S = undefined;89 var buf: [5]S = undefined;
...@@ -100,7 +97,6 @@ test "memset with 1-byte array element" {...@@ -100,7 +97,6 @@ test "memset with 1-byte array element" {
100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;97 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;98 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
102 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;99 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
103 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
104100
105 const A = [1]bool;101 const A = [1]bool;
106 var buf: [5]A = undefined;102 var buf: [5]A = undefined;
...@@ -170,7 +166,6 @@ test "zero keys with @memset" {...@@ -170,7 +166,6 @@ test "zero keys with @memset" {
170 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO166 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
171 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO167 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
172 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;168 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
173 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
174169
175 const Keys = struct {170 const Keys = struct {
176 up: bool,171 up: bool,
test/behavior/merge_error_sets.zig-1
...@@ -13,7 +13,6 @@ fn foo() C!void {...@@ -13,7 +13,6 @@ fn foo() C!void {
1313
14test "merge error sets" {14test "merge error sets" {
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_riscv64) return error.SkipZigTest;
1716
18 if (foo()) {17 if (foo()) {
19 @panic("unexpected");18 @panic("unexpected");
test/behavior/nan.zig-1
...@@ -26,7 +26,6 @@ test "nan memory equality" {...@@ -26,7 +26,6 @@ test "nan memory equality" {
26 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;26 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
27 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;27 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
28 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;28 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
29 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3029
31 // signaled30 // signaled
32 try testing.expect(mem.eql(u8, mem.asBytes(&snan_u16), mem.asBytes(&snan_f16)));31 try testing.expect(mem.eql(u8, mem.asBytes(&snan_u16), mem.asBytes(&snan_f16)));
test/behavior/null.zig-3
...@@ -85,7 +85,6 @@ fn testTestNullRuntime(x: ?i32) !void {...@@ -85,7 +85,6 @@ fn testTestNullRuntime(x: ?i32) !void {
85test "optional void" {85test "optional void" {
86 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;86 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
87 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO87 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8988
90 try optionalVoidImpl();89 try optionalVoidImpl();
91 try comptime optionalVoidImpl();90 try comptime optionalVoidImpl();
...@@ -109,7 +108,6 @@ const Empty = struct {};...@@ -109,7 +108,6 @@ const Empty = struct {};
109test "optional struct{}" {108test "optional struct{}" {
110 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
111 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO110 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
112 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
113111
114 _ = try optionalEmptyStructImpl();112 _ = try optionalEmptyStructImpl();
115 _ = try comptime optionalEmptyStructImpl();113 _ = try comptime optionalEmptyStructImpl();
...@@ -135,7 +133,6 @@ test "null with default unwrap" {...@@ -135,7 +133,6 @@ test "null with default unwrap" {
135133
136test "optional pointer to 0 bit type null value at runtime" {134test "optional pointer to 0 bit type null value at runtime" {
137 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO135 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
138 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
139136
140 const EmptyStruct = struct {};137 const EmptyStruct = struct {};
141 var x: ?*EmptyStruct = null;138 var x: ?*EmptyStruct = null;
test/behavior/optional.zig-10
...@@ -29,7 +29,6 @@ pub const EmptyStruct = struct {};...@@ -29,7 +29,6 @@ pub const EmptyStruct = struct {};
2929
30test "optional pointer to size zero struct" {30test "optional pointer to size zero struct" {
31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3332
34 var e = EmptyStruct{};33 var e = EmptyStruct{};
35 const o: ?*EmptyStruct = &e;34 const o: ?*EmptyStruct = &e;
...@@ -60,7 +59,6 @@ fn testNullPtrsEql() !void {...@@ -60,7 +59,6 @@ fn testNullPtrsEql() !void {
60test "optional with zero-bit type" {59test "optional with zero-bit type" {
61 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;60 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
62 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;61 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
63 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
64 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;62 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
6563
66 const S = struct {64 const S = struct {
...@@ -241,7 +239,6 @@ test "compare optionals with modified payloads" {...@@ -241,7 +239,6 @@ test "compare optionals with modified payloads" {
241test "unwrap function call with optional pointer return value" {239test "unwrap function call with optional pointer return value" {
242 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO240 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
243 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO241 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
244 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
245242
246 const S = struct {243 const S = struct {
247 fn entry() !void {244 fn entry() !void {
...@@ -373,7 +370,6 @@ test "0-bit child type coerced to optional return ptr result location" {...@@ -373,7 +370,6 @@ test "0-bit child type coerced to optional return ptr result location" {
373test "0-bit child type coerced to optional" {370test "0-bit child type coerced to optional" {
374 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO371 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
375 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;372 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
376 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
377373
378 const S = struct {374 const S = struct {
379 fn doTheTest() !void {375 fn doTheTest() !void {
...@@ -492,7 +488,6 @@ const NoReturn = struct {...@@ -492,7 +488,6 @@ const NoReturn = struct {
492488
493test "optional of noreturn used with if" {489test "optional of noreturn used with if" {
494 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO490 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
495 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
496491
497 NoReturn.a = 64;492 NoReturn.a = 64;
498 if (NoReturn.loop()) |_| {493 if (NoReturn.loop()) |_| {
...@@ -504,7 +499,6 @@ test "optional of noreturn used with if" {...@@ -504,7 +499,6 @@ test "optional of noreturn used with if" {
504499
505test "optional of noreturn used with orelse" {500test "optional of noreturn used with orelse" {
506 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO501 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
507 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
508502
509 NoReturn.a = 64;503 NoReturn.a = 64;
510 const val = NoReturn.testOrelse();504 const val = NoReturn.testOrelse();
...@@ -601,7 +595,6 @@ test "cast slice to const slice nested in error union and optional" {...@@ -601,7 +595,6 @@ test "cast slice to const slice nested in error union and optional" {
601 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;595 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
602 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;596 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
603 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;597 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
604 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
605598
606 const S = struct {599 const S = struct {
607 fn inner() !?[]u8 {600 fn inner() !?[]u8 {
...@@ -615,8 +608,6 @@ test "cast slice to const slice nested in error union and optional" {...@@ -615,8 +608,6 @@ test "cast slice to const slice nested in error union and optional" {
615}608}
616609
617test "variable of optional of noreturn" {610test "variable of optional of noreturn" {
618 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
619
620 var null_opv: ?noreturn = null;611 var null_opv: ?noreturn = null;
621 _ = &null_opv;612 _ = &null_opv;
622 try std.testing.expectEqual(@as(?noreturn, null), null_opv);613 try std.testing.expectEqual(@as(?noreturn, null), null_opv);
...@@ -641,7 +632,6 @@ test "result location initialization of optional with OPV payload" {...@@ -641,7 +632,6 @@ test "result location initialization of optional with OPV payload" {
641 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO632 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
642 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO633 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
643 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO634 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
644 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
645 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;635 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
646636
647 const S = struct {637 const S = struct {
test/behavior/packed-struct.zig-4
...@@ -238,7 +238,6 @@ test "regular in irregular packed struct" {...@@ -238,7 +238,6 @@ test "regular in irregular packed struct" {
238 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;238 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
239 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO239 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
240 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;240 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
241 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
242241
243 const Irregular = packed struct {242 const Irregular = packed struct {
244 bar: Regular = Regular{},243 bar: Regular = Regular{},
...@@ -494,7 +493,6 @@ test "@intFromPtr on a packed struct field" {...@@ -494,7 +493,6 @@ test "@intFromPtr on a packed struct field" {
494 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;493 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
495 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO494 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
496 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;495 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
497 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
498 if (native_endian != .little) return error.SkipZigTest;496 if (native_endian != .little) return error.SkipZigTest;
499497
500 const S = struct {498 const S = struct {
...@@ -518,7 +516,6 @@ test "@intFromPtr on a packed struct field unaligned and nested" {...@@ -518,7 +516,6 @@ test "@intFromPtr on a packed struct field unaligned and nested" {
518 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;516 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
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_spirv64) return error.SkipZigTest;518 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
521 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
522 if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet519 if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet
523520
524 const S1 = packed struct {521 const S1 = packed struct {
...@@ -1191,7 +1188,6 @@ test "packed struct field pointer aligned properly" {...@@ -1191,7 +1188,6 @@ test "packed struct field pointer aligned properly" {
1191 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1188 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1192 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1189 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1193 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1190 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
1194 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11951191
1196 const Foo = packed struct {1192 const Foo = packed struct {
1197 a: i32,1193 a: i32,
test/behavior/pointers.zig-6
...@@ -174,7 +174,6 @@ test "implicit cast error unions with non-optional to optional pointer" {...@@ -174,7 +174,6 @@ test "implicit cast error unions with non-optional to optional pointer" {
174 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO174 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
175 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO175 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
176 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;176 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
177 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
178177
179 const S = struct {178 const S = struct {
180 fn doTheTest() !void {179 fn doTheTest() !void {
...@@ -202,7 +201,6 @@ test "allowzero pointer and slice" {...@@ -202,7 +201,6 @@ test "allowzero pointer and slice" {
202 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO201 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
203 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;202 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
204 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO203 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
205 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
206204
207 var ptr: [*]allowzero i32 = @ptrFromInt(0);205 var ptr: [*]allowzero i32 = @ptrFromInt(0);
208 const opt_ptr: ?[*]allowzero i32 = ptr;206 const opt_ptr: ?[*]allowzero i32 = ptr;
...@@ -222,7 +220,6 @@ test "assign null directly to C pointer and test null equality" {...@@ -222,7 +220,6 @@ test "assign null directly to C pointer and test null equality" {
222 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
223 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO221 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
224 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO222 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
225 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
226223
227 var x: [*c]i32 = null;224 var x: [*c]i32 = null;
228 _ = &x;225 _ = &x;
...@@ -442,7 +439,6 @@ test "indexing array with sentinel returns correct type" {...@@ -442,7 +439,6 @@ test "indexing array with sentinel returns correct type" {
442test "element pointer to slice" {439test "element pointer to slice" {
443 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO440 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
444 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO441 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
445 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
446442
447 const S = struct {443 const S = struct {
448 fn doTheTest() !void {444 fn doTheTest() !void {
...@@ -490,7 +486,6 @@ test "element pointer arithmetic to slice" {...@@ -490,7 +486,6 @@ test "element pointer arithmetic to slice" {
490486
491test "array slicing to slice" {487test "array slicing to slice" {
492 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO488 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
493 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
494489
495 const S = struct {490 const S = struct {
496 fn doTheTest() !void {491 fn doTheTest() !void {
...@@ -541,7 +536,6 @@ test "pointer alignment and element type include call expression" {...@@ -541,7 +536,6 @@ test "pointer alignment and element type include call expression" {
541536
542test "pointer to array has explicit alignment" {537test "pointer to array has explicit alignment" {
543 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO538 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
544 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
545539
546 const S = struct {540 const S = struct {
547 const Base = extern struct { a: u8 };541 const Base = extern struct { a: u8 };
test/behavior/prefetch.zig-1
...@@ -3,7 +3,6 @@ const std = @import("std");...@@ -3,7 +3,6 @@ const std = @import("std");
33
4test "@prefetch()" {4test "@prefetch()" {
5 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;5 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
6 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
76
8 var a: [2]u32 = .{ 42, 42 };7 var a: [2]u32 = .{ 42, 42 };
9 var a_len = a.len;8 var a_len = a.len;
test/behavior/ptrcast.zig-3
...@@ -58,7 +58,6 @@ fn testReinterpretStructWrappedBytesAsInteger() !void {...@@ -58,7 +58,6 @@ fn testReinterpretStructWrappedBytesAsInteger() !void {
58test "reinterpret bytes of an array into an extern struct" {58test "reinterpret bytes of an array into an extern struct" {
59 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO59 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
60 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO60 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
61 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
6261
63 try testReinterpretBytesAsExternStruct();62 try testReinterpretBytesAsExternStruct();
64 try comptime testReinterpretBytesAsExternStruct();63 try comptime testReinterpretBytesAsExternStruct();
...@@ -233,7 +232,6 @@ test "implicit optional pointer to optional anyopaque pointer" {...@@ -233,7 +232,6 @@ test "implicit optional pointer to optional anyopaque pointer" {
233 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO232 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
234 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
235 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO234 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
236 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
237235
238 var buf: [4]u8 = "aoeu".*;236 var buf: [4]u8 = "aoeu".*;
239 const x: ?[*]u8 = &buf;237 const x: ?[*]u8 = &buf;
...@@ -246,7 +244,6 @@ test "@ptrCast slice to slice" {...@@ -246,7 +244,6 @@ test "@ptrCast slice to slice" {
246 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO244 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
247 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO245 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
248 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO246 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
249 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
250247
251 const S = struct {248 const S = struct {
252 fn foo(slice: []u32) []i32 {249 fn foo(slice: []u32) []i32 {
test/behavior/ptrfromint.zig-5
...@@ -3,8 +3,6 @@ const builtin = @import("builtin");...@@ -3,8 +3,6 @@ const builtin = @import("builtin");
3const expectEqual = std.testing.expectEqual;3const expectEqual = std.testing.expectEqual;
44
5test "casting integer address to function pointer" {5test "casting integer address to function pointer" {
6 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7
8 addressToFunction();6 addressToFunction();
9 comptime addressToFunction();7 comptime addressToFunction();
10}8}
...@@ -19,7 +17,6 @@ test "mutate through ptr initialized with constant ptrFromInt value" {...@@ -19,7 +17,6 @@ test "mutate through ptr initialized with constant ptrFromInt value" {
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;17 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO19 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2320
24 forceCompilerAnalyzeBranchHardCodedPtrDereference(false);21 forceCompilerAnalyzeBranchHardCodedPtrDereference(false);
25}22}
...@@ -37,7 +34,6 @@ test "@ptrFromInt creates null pointer" {...@@ -37,7 +34,6 @@ test "@ptrFromInt creates null pointer" {
37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;34 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;35 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO36 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
40 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
4137
42 const ptr = @as(?*u32, @ptrFromInt(0));38 const ptr = @as(?*u32, @ptrFromInt(0));
43 try expectEqual(@as(?*u32, null), ptr);39 try expectEqual(@as(?*u32, null), ptr);
...@@ -47,7 +43,6 @@ test "@ptrFromInt creates allowzero zero pointer" {...@@ -47,7 +43,6 @@ test "@ptrFromInt creates allowzero zero pointer" {
47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;43 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
48 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;44 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
49 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO45 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
50 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5146
52 const ptr = @as(*allowzero u32, @ptrFromInt(0));47 const ptr = @as(*allowzero u32, @ptrFromInt(0));
53 try expectEqual(@as(usize, 0), @intFromPtr(ptr));48 try expectEqual(@as(usize, 0), @intFromPtr(ptr));
test/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig-1
...@@ -8,7 +8,6 @@ test "reference a variable in an if after an if in the 2nd switch prong" {...@@ -8,7 +8,6 @@ test "reference a variable in an if after an if in the 2nd switch prong" {
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_aarch64) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1211
13 try foo(true, Num.Two, false, "aoeu");12 try foo(true, Num.Two, false, "aoeu");
14 try expect(!ok);13 try expect(!ok);
test/behavior/return_address.zig-1
...@@ -10,7 +10,6 @@ test "return address" {...@@ -10,7 +10,6 @@ test "return address" {
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_spirv64) return error.SkipZigTest;12 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1413
15 _ = retAddr();14 _ = retAddr();
16 // TODO: #1493815 // TODO: #14938
test/behavior/sizeof_and_typeof.zig-5
...@@ -81,7 +81,6 @@ const P = packed struct {...@@ -81,7 +81,6 @@ const P = packed struct {
81test "@offsetOf" {81test "@offsetOf" {
82 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO82 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
83 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;83 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
84 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8584
86 // Packed structs have fixed memory layout85 // Packed structs have fixed memory layout
87 try expect(@offsetOf(P, "a") == 0);86 try expect(@offsetOf(P, "a") == 0);
...@@ -158,7 +157,6 @@ test "@TypeOf() has no runtime side effects" {...@@ -158,7 +157,6 @@ test "@TypeOf() has no runtime side effects" {
158157
159test "branching logic inside @TypeOf" {158test "branching logic inside @TypeOf" {
160 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;159 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
161 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
162160
163 const S = struct {161 const S = struct {
164 var data: i32 = 0;162 var data: i32 = 0;
...@@ -273,7 +271,6 @@ test "runtime instructions inside typeof in comptime only scope" {...@@ -273,7 +271,6 @@ test "runtime instructions inside typeof in comptime only scope" {
273 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;271 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
274 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;272 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
275 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO273 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
276 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
277274
278 {275 {
279 var y: i8 = 2;276 var y: i8 = 2;
...@@ -330,7 +327,6 @@ test "peer type resolution with @TypeOf doesn't trigger dependency loop check" {...@@ -330,7 +327,6 @@ test "peer type resolution with @TypeOf doesn't trigger dependency loop check" {
330 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO327 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
331 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO328 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
332 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO329 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
333 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
334330
335 const T = struct {331 const T = struct {
336 next: @TypeOf(null, @as(*const @This(), undefined)),332 next: @TypeOf(null, @as(*const @This(), undefined)),
...@@ -412,7 +408,6 @@ test "Extern function calls, dereferences and field access in @TypeOf" {...@@ -412,7 +408,6 @@ test "Extern function calls, dereferences and field access in @TypeOf" {
412 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;408 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
413 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO409 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
414 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;410 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
415 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
416411
417 const Test = struct {412 const Test = struct {
418 fn test_fn_1(a: c_long) @TypeOf(c_fopen("test", "r").*) {413 fn test_fn_1(a: c_long) @TypeOf(c_fopen("test", "r").*) {
test/behavior/slice.zig-20
...@@ -67,7 +67,6 @@ test "comptime slice of undefined pointer of length 0" {...@@ -67,7 +67,6 @@ test "comptime slice of undefined pointer of length 0" {
6767
68test "implicitly cast array of size 0 to slice" {68test "implicitly cast array of size 0 to slice" {
69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
70 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7170
72 var msg = [_]u8{};71 var msg = [_]u8{};
73 try assertLenIsZero(&msg);72 try assertLenIsZero(&msg);
...@@ -124,7 +123,6 @@ test "slice of type" {...@@ -124,7 +123,6 @@ test "slice of type" {
124123
125test "generic malloc free" {124test "generic malloc free" {
126 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO125 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
127 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
128126
129 const a = memAlloc(u8, 10) catch unreachable;127 const a = memAlloc(u8, 10) catch unreachable;
130 memFree(u8, a);128 memFree(u8, a);
...@@ -186,8 +184,6 @@ test "slicing zero length array" {...@@ -186,8 +184,6 @@ test "slicing zero length array" {
186}184}
187185
188test "slicing pointer by length" {186test "slicing pointer by length" {
189 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
190
191 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };187 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
192 const ptr: [*]const u8 = @as([*]const u8, @ptrCast(&array));188 const ptr: [*]const u8 = @as([*]const u8, @ptrCast(&array));
193 const slice = ptr[1..][0..5];189 const slice = ptr[1..][0..5];
...@@ -236,7 +232,6 @@ test "runtime safety lets us slice from len..len" {...@@ -236,7 +232,6 @@ test "runtime safety lets us slice from len..len" {
236 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;232 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;233 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO234 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
239 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
240235
241 var an_array = [_]u8{ 1, 2, 3 };236 var an_array = [_]u8{ 1, 2, 3 };
242 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));237 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
...@@ -249,7 +244,6 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {...@@ -249,7 +244,6 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
249test "C pointer" {244test "C pointer" {
250 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO245 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
251 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO246 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
252 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
253247
254 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";248 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
255 var len: u32 = 10;249 var len: u32 = 10;
...@@ -293,7 +287,6 @@ fn sliceSum(comptime q: []const u8) i32 {...@@ -293,7 +287,6 @@ fn sliceSum(comptime q: []const u8) i32 {
293test "slice type with custom alignment" {287test "slice type with custom alignment" {
294 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;288 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
295 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO289 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
296 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
297290
298 const LazilyResolvedType = struct {291 const LazilyResolvedType = struct {
299 anything: i32,292 anything: i32,
...@@ -307,7 +300,6 @@ test "slice type with custom alignment" {...@@ -307,7 +300,6 @@ test "slice type with custom alignment" {
307300
308test "obtaining a null terminated slice" {301test "obtaining a null terminated slice" {
309 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO302 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
310 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
311303
312 // here we have a normal array304 // here we have a normal array
313 var buf: [50]u8 = undefined;305 var buf: [50]u8 = undefined;
...@@ -352,7 +344,6 @@ test "empty array to slice" {...@@ -352,7 +344,6 @@ test "empty array to slice" {
352test "@ptrCast slice to pointer" {344test "@ptrCast slice to pointer" {
353 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;345 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
354 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO346 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
355 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
356347
357 const S = struct {348 const S = struct {
358 fn doTheTest() !void {349 fn doTheTest() !void {
...@@ -407,7 +398,6 @@ test "slice syntax resulting in pointer-to-array" {...@@ -407,7 +398,6 @@ test "slice syntax resulting in pointer-to-array" {
407 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO398 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
408 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO399 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
409 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO400 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
410 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
411 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;401 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
412402
413 const S = struct {403 const S = struct {
...@@ -627,7 +617,6 @@ test "slice syntax resulting in pointer-to-array" {...@@ -627,7 +617,6 @@ test "slice syntax resulting in pointer-to-array" {
627test "slice pointer-to-array null terminated" {617test "slice pointer-to-array null terminated" {
628 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO618 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
629 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO619 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
630 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
631620
632 comptime {621 comptime {
633 var array = [5:0]u8{ 1, 2, 3, 4, 5 };622 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
...@@ -646,7 +635,6 @@ test "slice pointer-to-array null terminated" {...@@ -646,7 +635,6 @@ test "slice pointer-to-array null terminated" {
646635
647test "slice pointer-to-array zero length" {636test "slice pointer-to-array zero length" {
648 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO637 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
649 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
650638
651 comptime {639 comptime {
652 {640 {
...@@ -681,7 +669,6 @@ test "type coercion of pointer to anon struct literal to pointer to slice" {...@@ -681,7 +669,6 @@ test "type coercion of pointer to anon struct literal to pointer to slice" {
681 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO669 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
682 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO670 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
683 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO671 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
684 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
685672
686 const S = struct {673 const S = struct {
687 const U = union {674 const U = union {
...@@ -773,7 +760,6 @@ test "slice sentinel access at comptime" {...@@ -773,7 +760,6 @@ test "slice sentinel access at comptime" {
773test "slicing array with sentinel as end index" {760test "slicing array with sentinel as end index" {
774 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;761 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
775 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO762 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
776 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
777763
778 const S = struct {764 const S = struct {
779 fn do() !void {765 fn do() !void {
...@@ -792,7 +778,6 @@ test "slicing array with sentinel as end index" {...@@ -792,7 +778,6 @@ test "slicing array with sentinel as end index" {
792test "slicing slice with sentinel as end index" {778test "slicing slice with sentinel as end index" {
793 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;779 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
794 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO780 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
795 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
796781
797 const S = struct {782 const S = struct {
798 fn do() !void {783 fn do() !void {
...@@ -863,7 +848,6 @@ test "global slice field access" {...@@ -863,7 +848,6 @@ test "global slice field access" {
863}848}
864849
865test "slice of void" {850test "slice of void" {
866 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
867 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;851 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
868852
869 var n: usize = 10;853 var n: usize = 10;
...@@ -874,8 +858,6 @@ test "slice of void" {...@@ -874,8 +858,6 @@ test "slice of void" {
874}858}
875859
876test "slice with dereferenced value" {860test "slice with dereferenced value" {
877 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
878
879 var a: usize = 0;861 var a: usize = 0;
880 const idx: *usize = &a;862 const idx: *usize = &a;
881 _ = blk: {863 _ = blk: {
...@@ -989,7 +971,6 @@ test "get address of element of zero-sized slice" {...@@ -989,7 +971,6 @@ test "get address of element of zero-sized slice" {
989 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO971 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
990 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO972 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
991 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO973 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
992 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
993 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;974 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
994975
995 const S = struct {976 const S = struct {
...@@ -1004,7 +985,6 @@ test "sentinel-terminated 0-length slices" {...@@ -1004,7 +985,6 @@ test "sentinel-terminated 0-length slices" {
1004 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO985 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
1005 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO986 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1006 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO987 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1007 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1008988
1009 const u32s: [4]u32 = [_]u32{ 0, 1, 2, 3 };989 const u32s: [4]u32 = [_]u32{ 0, 1, 2, 3 };
1010990
test/behavior/struct.zig-40
...@@ -92,7 +92,6 @@ test "structs" {...@@ -92,7 +92,6 @@ test "structs" {
92 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;92 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
93 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO93 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;94 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
95 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
9695
97 var foo: StructFoo = undefined;96 var foo: StructFoo = undefined;
98 @memset(@as([*]u8, @ptrCast(&foo))[0..@sizeOf(StructFoo)], 0);97 @memset(@as([*]u8, @ptrCast(&foo))[0..@sizeOf(StructFoo)], 0);
...@@ -111,7 +110,6 @@ fn testMutation(foo: *StructFoo) void {...@@ -111,7 +110,6 @@ fn testMutation(foo: *StructFoo) void {
111110
112test "struct byval assign" {111test "struct byval assign" {
113 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO112 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
114 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
115113
116 var foo1: StructFoo = undefined;114 var foo1: StructFoo = undefined;
117 var foo2: StructFoo = undefined;115 var foo2: StructFoo = undefined;
...@@ -176,7 +174,6 @@ const MemberFnTestFoo = struct {...@@ -176,7 +174,6 @@ const MemberFnTestFoo = struct {
176174
177test "call member function directly" {175test "call member function directly" {
178 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO176 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
179 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
180177
181 const instance = MemberFnTestFoo{ .x = 1234 };178 const instance = MemberFnTestFoo{ .x = 1234 };
182 const result = MemberFnTestFoo.member(instance);179 const result = MemberFnTestFoo.member(instance);
...@@ -185,7 +182,6 @@ test "call member function directly" {...@@ -185,7 +182,6 @@ test "call member function directly" {
185182
186test "store member function in variable" {183test "store member function in variable" {
187 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO184 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
188 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
189185
190 const instance = MemberFnTestFoo{ .x = 1234 };186 const instance = MemberFnTestFoo{ .x = 1234 };
191 const memberFn = MemberFnTestFoo.member;187 const memberFn = MemberFnTestFoo.member;
...@@ -207,7 +203,6 @@ const MemberFnRand = struct {...@@ -207,7 +203,6 @@ const MemberFnRand = struct {
207test "return struct byval from function" {203test "return struct byval from function" {
208 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;204 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
209 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
210 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
211206
212 const Bar = struct {207 const Bar = struct {
213 x: i32,208 x: i32,
...@@ -256,7 +251,6 @@ test "usingnamespace within struct scope" {...@@ -256,7 +251,6 @@ test "usingnamespace within struct scope" {
256test "struct field init with catch" {251test "struct field init with catch" {
257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;252 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
258 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO253 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
259 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
260254
261 const S = struct {255 const S = struct {
262 fn doTheTest() !void {256 fn doTheTest() !void {
...@@ -300,7 +294,6 @@ const Val = struct {...@@ -300,7 +294,6 @@ const Val = struct {
300test "struct point to self" {294test "struct point to self" {
301 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;295 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
302 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO296 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
303 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
304297
305 var root: Node = undefined;298 var root: Node = undefined;
306 root.val.x = 1;299 root.val.x = 1;
...@@ -355,7 +348,6 @@ test "self-referencing struct via array member" {...@@ -355,7 +348,6 @@ test "self-referencing struct via array member" {
355 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;348 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
356 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO349 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
357 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO350 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
358 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
359351
360 const T = struct {352 const T = struct {
361 children: [1]*@This(),353 children: [1]*@This(),
...@@ -403,7 +395,6 @@ test "packed struct" {...@@ -403,7 +395,6 @@ test "packed struct" {
403 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO395 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
404 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
405 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;397 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
406 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
407398
408 var foo = APackedStruct{399 var foo = APackedStruct{
409 .x = 1,400 .x = 1,
...@@ -633,7 +624,6 @@ fn getC(data: *const BitField1) u2 {...@@ -633,7 +624,6 @@ fn getC(data: *const BitField1) u2 {
633test "default struct initialization fields" {624test "default struct initialization fields" {
634 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;625 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
635 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO626 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
636 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
637627
638 const S = struct {628 const S = struct {
639 a: i32 = 1234,629 a: i32 = 1234,
...@@ -809,7 +799,6 @@ test "fn with C calling convention returns struct by value" {...@@ -809,7 +799,6 @@ test "fn with C calling convention returns struct by value" {
809 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO799 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
810 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO800 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
811 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO801 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
812 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
813802
814 const S = struct {803 const S = struct {
815 fn entry() !void {804 fn entry() !void {
...@@ -909,8 +898,6 @@ test "anonymous struct literal syntax" {...@@ -909,8 +898,6 @@ test "anonymous struct literal syntax" {
909}898}
910899
911test "fully anonymous struct" {900test "fully anonymous struct" {
912 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
913
914 const S = struct {901 const S = struct {
915 fn doTheTest() !void {902 fn doTheTest() !void {
916 try dump(.{903 try dump(.{
...@@ -933,8 +920,6 @@ test "fully anonymous struct" {...@@ -933,8 +920,6 @@ test "fully anonymous struct" {
933}920}
934921
935test "fully anonymous list literal" {922test "fully anonymous list literal" {
936 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
937
938 const S = struct {923 const S = struct {
939 fn doTheTest() !void {924 fn doTheTest() !void {
940 try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" });925 try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" });
...@@ -982,7 +967,6 @@ test "tuple element initialized with fn call" {...@@ -982,7 +967,6 @@ test "tuple element initialized with fn call" {
982 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO967 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
983 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO968 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
984 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO969 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
985 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
986970
987 const S = struct {971 const S = struct {
988 fn doTheTest() !void {972 fn doTheTest() !void {
...@@ -1023,7 +1007,6 @@ test "struct with 0-length union array field" {...@@ -1023,7 +1007,6 @@ test "struct with 0-length union array field" {
1023 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1007 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1024 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1008 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1025 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1009 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1026 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10271010
1028 const U = union {1011 const U = union {
1029 a: u32,1012 a: u32,
...@@ -1044,7 +1027,6 @@ test "type coercion of anon struct literal to struct" {...@@ -1044,7 +1027,6 @@ test "type coercion of anon struct literal to struct" {
1044 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1027 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1045 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1028 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1046 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1029 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1047 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10481030
1049 const S = struct {1031 const S = struct {
1050 const S2 = struct {1032 const S2 = struct {
...@@ -1084,7 +1066,6 @@ test "type coercion of pointer to anon struct literal to pointer to struct" {...@@ -1084,7 +1066,6 @@ test "type coercion of pointer to anon struct literal to pointer to struct" {
1084 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1066 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1085 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1067 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1086 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1068 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1087 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10881069
1089 const S = struct {1070 const S = struct {
1090 const S2 = struct {1071 const S2 = struct {
...@@ -1299,7 +1280,6 @@ test "initialize struct with empty literal" {...@@ -1299,7 +1280,6 @@ test "initialize struct with empty literal" {
12991280
1300test "loading a struct pointer perfoms a copy" {1281test "loading a struct pointer perfoms a copy" {
1301 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1282 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1302 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13031283
1304 const S = struct {1284 const S = struct {
1305 a: i32,1285 a: i32,
...@@ -1561,7 +1541,6 @@ test "discarded struct initialization works as expected" {...@@ -1561,7 +1541,6 @@ test "discarded struct initialization works as expected" {
1561test "function pointer in struct returns the struct" {1541test "function pointer in struct returns the struct" {
1562 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1542 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1563 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1543 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1564 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15651544
1566 const A = struct {1545 const A = struct {
1567 const A = @This();1546 const A = @This();
...@@ -1732,7 +1711,6 @@ test "extern struct field pointer has correct alignment" {...@@ -1732,7 +1711,6 @@ test "extern struct field pointer has correct alignment" {
1732 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1711 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1733 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1712 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1734 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1713 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1735 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
17361714
1737 const S = struct {1715 const S = struct {
1738 fn doTheTest() !void {1716 fn doTheTest() !void {
...@@ -1770,8 +1748,6 @@ test "extern struct field pointer has correct alignment" {...@@ -1770,8 +1748,6 @@ test "extern struct field pointer has correct alignment" {
1770}1748}
17711749
1772test "packed struct field in anonymous struct" {1750test "packed struct field in anonymous struct" {
1773 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1774
1775 const T = packed struct {1751 const T = packed struct {
1776 f1: bool = false,1752 f1: bool = false,
1777 };1753 };
...@@ -1783,8 +1759,6 @@ fn countFields(v: anytype) usize {...@@ -1783,8 +1759,6 @@ fn countFields(v: anytype) usize {
1783}1759}
17841760
1785test "struct init with no result pointer sets field result types" {1761test "struct init with no result pointer sets field result types" {
1786 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1787
1788 const S = struct {1762 const S = struct {
1789 // A function parameter has a result type, but no result pointer.1763 // A function parameter has a result type, but no result pointer.
1790 fn f(s: struct { x: u32 }) u32 {1764 fn f(s: struct { x: u32 }) u32 {
...@@ -1863,8 +1837,6 @@ test "comptimeness of optional and error union payload is analyzed properly" {...@@ -1863,8 +1837,6 @@ test "comptimeness of optional and error union payload is analyzed properly" {
1863}1837}
18641838
1865test "initializer uses own alignment" {1839test "initializer uses own alignment" {
1866 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1867
1868 const S = struct {1840 const S = struct {
1869 x: u32 = @alignOf(@This()) + 1,1841 x: u32 = @alignOf(@This()) + 1,
1870 };1842 };
...@@ -1876,8 +1848,6 @@ test "initializer uses own alignment" {...@@ -1876,8 +1848,6 @@ test "initializer uses own alignment" {
1876}1848}
18771849
1878test "initializer uses own size" {1850test "initializer uses own size" {
1879 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1880
1881 const S = struct {1851 const S = struct {
1882 x: u32 = @sizeOf(@This()) + 1,1852 x: u32 = @sizeOf(@This()) + 1,
1883 };1853 };
...@@ -1889,8 +1859,6 @@ test "initializer uses own size" {...@@ -1889,8 +1859,6 @@ test "initializer uses own size" {
1889}1859}
18901860
1891test "initializer takes a pointer to a variable inside its struct" {1861test "initializer takes a pointer to a variable inside its struct" {
1892 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1893
1894 const namespace = struct {1862 const namespace = struct {
1895 const S = struct {1863 const S = struct {
1896 s: *S = &S.instance,1864 s: *S = &S.instance,
...@@ -1909,8 +1877,6 @@ test "initializer takes a pointer to a variable inside its struct" {...@@ -1909,8 +1877,6 @@ test "initializer takes a pointer to a variable inside its struct" {
1909}1877}
19101878
1911test "circular dependency through pointer field of a struct" {1879test "circular dependency through pointer field of a struct" {
1912 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1913
1914 const S = struct {1880 const S = struct {
1915 const StructInner = extern struct {1881 const StructInner = extern struct {
1916 outer: StructOuter = std.mem.zeroes(StructOuter),1882 outer: StructOuter = std.mem.zeroes(StructOuter),
...@@ -1932,8 +1898,6 @@ test "circular dependency through pointer field of a struct" {...@@ -1932,8 +1898,6 @@ test "circular dependency through pointer field of a struct" {
1932}1898}
19331899
1934test "field calls do not force struct field init resolution" {1900test "field calls do not force struct field init resolution" {
1935 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1936
1937 const S = struct {1901 const S = struct {
1938 x: u32 = blk: {1902 x: u32 = blk: {
1939 _ = @TypeOf(make().dummyFn()); // runtime field call - S not fully resolved - dummyFn call should not force field init resolution1903 _ = @TypeOf(make().dummyFn()); // runtime field call - S not fully resolved - dummyFn call should not force field init resolution
...@@ -2067,7 +2031,6 @@ test "runtime value in nested initializer passed as pointer to function" {...@@ -2067,7 +2031,6 @@ test "runtime value in nested initializer passed as pointer to function" {
2067 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO2031 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
2068 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2032 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2069 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2033 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2070 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
20712034
2072 const Bar = struct {2035 const Bar = struct {
2073 b: u32,2036 b: u32,
...@@ -2142,7 +2105,6 @@ test "assignment of field with padding" {...@@ -2142,7 +2105,6 @@ test "assignment of field with padding" {
2142 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;2105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2143 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;2106 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2144 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2107 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2145 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
21462108
2147 const Mesh = extern struct {2109 const Mesh = extern struct {
2148 id: u32,2110 id: u32,
...@@ -2173,7 +2135,6 @@ test "initiate global variable with runtime value" {...@@ -2173,7 +2135,6 @@ test "initiate global variable with runtime value" {
2173 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;2135 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2174 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;2136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2175 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2137 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2176 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
21772138
2178 const S = struct {2139 const S = struct {
2179 field: i32,2140 field: i32,
...@@ -2192,7 +2153,6 @@ test "initiate global variable with runtime value" {...@@ -2192,7 +2153,6 @@ test "initiate global variable with runtime value" {
2192test "struct containing optional pointer to array of @This()" {2153test "struct containing optional pointer to array of @This()" {
2193 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;2154 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2194 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;2155 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2195 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
21962156
2197 const S = struct {2157 const S = struct {
2198 x: ?*const [1]@This(),2158 x: ?*const [1]@This(),
test/behavior/struct_contains_null_ptr_itself.zig-1
...@@ -5,7 +5,6 @@ const builtin = @import("builtin");...@@ -5,7 +5,6 @@ const builtin = @import("builtin");
5test "struct contains null pointer which contains original struct" {5test "struct contains null pointer which contains original struct" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
98
10 var x: ?*NodeLineComment = null;9 var x: ?*NodeLineComment = null;
11 _ = &x;10 _ = &x;
test/behavior/struct_contains_slice_of_itself.zig-2
...@@ -13,7 +13,6 @@ const NodeAligned = struct {...@@ -13,7 +13,6 @@ const NodeAligned = struct {
1313
14test "struct contains slice of itself" {14test "struct contains slice of itself" {
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_riscv64) return error.SkipZigTest;
1716
18 var other_nodes = [_]Node{17 var other_nodes = [_]Node{
19 Node{18 Node{
...@@ -54,7 +53,6 @@ test "struct contains slice of itself" {...@@ -54,7 +53,6 @@ test "struct contains slice of itself" {
54test "struct contains aligned slice of itself" {53test "struct contains aligned slice of itself" {
55 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5856
59 var other_nodes = [_]NodeAligned{57 var other_nodes = [_]NodeAligned{
60 NodeAligned{58 NodeAligned{
test/behavior/switch.zig+7-34
...@@ -7,7 +7,6 @@ const expectEqual = std.testing.expectEqual;...@@ -7,7 +7,6 @@ const expectEqual = std.testing.expectEqual;
77
8test "switch with numbers" {8test "switch with numbers" {
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_riscv64) return error.SkipZigTest;
1110
12 try testSwitchWithNumbers(13);11 try testSwitchWithNumbers(13);
13}12}
...@@ -23,7 +22,6 @@ fn testSwitchWithNumbers(x: u32) !void {...@@ -23,7 +22,6 @@ fn testSwitchWithNumbers(x: u32) !void {
2322
24test "switch with all ranges" {23test "switch with all ranges" {
25 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
26 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2725
28 try expect(testSwitchWithAllRanges(50, 3) == 1);26 try expect(testSwitchWithAllRanges(50, 3) == 1);
29 try expect(testSwitchWithAllRanges(101, 0) == 2);27 try expect(testSwitchWithAllRanges(101, 0) == 2);
...@@ -57,27 +55,25 @@ test "implicit comptime switch" {...@@ -57,27 +55,25 @@ test "implicit comptime switch" {
5755
58test "switch on enum" {56test "switch on enum" {
59 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO57 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
60 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
6158
62 const fruit = Fruit.Orange;59 const fruit = Fruit.Orange;
63 nonConstSwitchOnEnum(fruit);60 try expect(nonConstSwitchOnEnum(fruit));
64}61}
65const Fruit = enum {62const Fruit = enum {
66 Apple,63 Apple,
67 Orange,64 Orange,
68 Banana,65 Banana,
69};66};
70fn nonConstSwitchOnEnum(fruit: Fruit) void {67fn nonConstSwitchOnEnum(fruit: Fruit) bool {
71 switch (fruit) {68 return switch (fruit) {
72 Fruit.Apple => unreachable,69 Fruit.Apple => false,
73 Fruit.Orange => {},70 Fruit.Orange => true,
74 Fruit.Banana => unreachable,71 Fruit.Banana => false,
75 }72 };
76}73}
7774
78test "switch statement" {75test "switch statement" {
79 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO76 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
80 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8177
82 try nonConstSwitch(SwitchStatementFoo.C);78 try nonConstSwitch(SwitchStatementFoo.C);
83}79}
...@@ -94,7 +90,6 @@ const SwitchStatementFoo = enum { A, B, C, D };...@@ -94,7 +90,6 @@ const SwitchStatementFoo = enum { A, B, C, D };
9490
95test "switch with multiple expressions" {91test "switch with multiple expressions" {
96 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO92 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
97 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
9893
99 const x = switch (returnsFive()) {94 const x = switch (returnsFive()) {
100 1, 2, 3 => 1,95 1, 2, 3 => 1,
...@@ -123,7 +118,6 @@ fn trueIfBoolFalseOtherwise(comptime T: type) bool {...@@ -123,7 +118,6 @@ fn trueIfBoolFalseOtherwise(comptime T: type) bool {
123118
124test "switching on booleans" {119test "switching on booleans" {
125 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO120 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
126 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
127121
128 try testSwitchOnBools();122 try testSwitchOnBools();
129 try comptime testSwitchOnBools();123 try comptime testSwitchOnBools();
...@@ -179,7 +173,6 @@ test "undefined.u0" {...@@ -179,7 +173,6 @@ test "undefined.u0" {
179173
180test "switch with disjoint range" {174test "switch with disjoint range" {
181 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO175 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
182 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
183176
184 var q: u8 = 0;177 var q: u8 = 0;
185 _ = &q;178 _ = &q;
...@@ -191,8 +184,6 @@ test "switch with disjoint range" {...@@ -191,8 +184,6 @@ test "switch with disjoint range" {
191}184}
192185
193test "switch variable for range and multiple prongs" {186test "switch variable for range and multiple prongs" {
194 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
195
196 const S = struct {187 const S = struct {
197 fn doTheTest() !void {188 fn doTheTest() !void {
198 try doTheSwitch(16);189 try doTheSwitch(16);
...@@ -224,7 +215,6 @@ fn poll() void {...@@ -224,7 +215,6 @@ fn poll() void {
224215
225test "switch on global mutable var isn't constant-folded" {216test "switch on global mutable var isn't constant-folded" {
226 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO217 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
227 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
228218
229 while (state < 2) {219 while (state < 2) {
230 poll();220 poll();
...@@ -286,7 +276,6 @@ fn testSwitchEnumPtrCapture() !void {...@@ -286,7 +276,6 @@ fn testSwitchEnumPtrCapture() !void {
286276
287test "switch handles all cases of number" {277test "switch handles all cases of number" {
288 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO278 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
289 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
290279
291 try testSwitchHandleAllCases();280 try testSwitchHandleAllCases();
292 try comptime testSwitchHandleAllCases();281 try comptime testSwitchHandleAllCases();
...@@ -382,7 +371,6 @@ test "anon enum literal used in switch on union enum" {...@@ -382,7 +371,6 @@ test "anon enum literal used in switch on union enum" {
382371
383test "switch all prongs unreachable" {372test "switch all prongs unreachable" {
384 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO373 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
385 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
386374
387 try testAllProngsUnreachable();375 try testAllProngsUnreachable();
388 try comptime testAllProngsUnreachable();376 try comptime testAllProngsUnreachable();
...@@ -406,7 +394,6 @@ fn switchWithUnreachable(x: i32) i32 {...@@ -406,7 +394,6 @@ fn switchWithUnreachable(x: i32) i32 {
406394
407test "capture value of switch with all unreachable prongs" {395test "capture value of switch with all unreachable prongs" {
408 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
409 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
410397
411 const x = return_a_number() catch |err| switch (err) {398 const x = return_a_number() catch |err| switch (err) {
412 else => unreachable,399 else => unreachable,
...@@ -420,7 +407,6 @@ fn return_a_number() anyerror!i32 {...@@ -420,7 +407,6 @@ fn return_a_number() anyerror!i32 {
420407
421test "switch on integer with else capturing expr" {408test "switch on integer with else capturing expr" {
422 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO409 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
423 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
424410
425 const S = struct {411 const S = struct {
426 fn doTheTest() !void {412 fn doTheTest() !void {
...@@ -442,7 +428,6 @@ test "else prong of switch on error set excludes other cases" {...@@ -442,7 +428,6 @@ test "else prong of switch on error set excludes other cases" {
442 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO428 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
443 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO429 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
444 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;430 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
445 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
446431
447 const S = struct {432 const S = struct {
448 fn doTheTest() !void {433 fn doTheTest() !void {
...@@ -478,7 +463,6 @@ test "switch prongs with error set cases make a new error set type for capture v...@@ -478,7 +463,6 @@ test "switch prongs with error set cases make a new error set type for capture v
478 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO463 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
479 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO464 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
480 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;465 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
481 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
482466
483 const S = struct {467 const S = struct {
484 fn doTheTest() !void {468 fn doTheTest() !void {
...@@ -513,7 +497,6 @@ test "switch prongs with error set cases make a new error set type for capture v...@@ -513,7 +497,6 @@ test "switch prongs with error set cases make a new error set type for capture v
513497
514test "return result loc and then switch with range implicit casted to error union" {498test "return result loc and then switch with range implicit casted to error union" {
515 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO499 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
516 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
517500
518 const S = struct {501 const S = struct {
519 fn doTheTest() !void {502 fn doTheTest() !void {
...@@ -662,7 +645,6 @@ test "switch prong pointer capture alignment" {...@@ -662,7 +645,6 @@ test "switch prong pointer capture alignment" {
662test "switch on pointer type" {645test "switch on pointer type" {
663 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO646 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
664 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO647 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
665 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
666648
667 const S = struct {649 const S = struct {
668 const X = struct {650 const X = struct {
...@@ -735,7 +717,6 @@ test "switch capture copies its payload" {...@@ -735,7 +717,6 @@ test "switch capture copies its payload" {
735717
736test "capture of integer forwards the switch condition directly" {718test "capture of integer forwards the switch condition directly" {
737 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO719 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
738 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
739720
740 const S = struct {721 const S = struct {
741 fn foo(x: u8) !void {722 fn foo(x: u8) !void {
...@@ -757,7 +738,6 @@ test "capture of integer forwards the switch condition directly" {...@@ -757,7 +738,6 @@ test "capture of integer forwards the switch condition directly" {
757738
758test "enum value without tag name used as switch item" {739test "enum value without tag name used as switch item" {
759 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO740 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
760 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
761741
762 const E = enum(u32) {742 const E = enum(u32) {
763 a = 1,743 a = 1,
...@@ -775,8 +755,6 @@ test "enum value without tag name used as switch item" {...@@ -775,8 +755,6 @@ test "enum value without tag name used as switch item" {
775}755}
776756
777test "switch item sizeof" {757test "switch item sizeof" {
778 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
779
780 const S = struct {758 const S = struct {
781 fn doTheTest() !void {759 fn doTheTest() !void {
782 var a: usize = 0;760 var a: usize = 0;
...@@ -873,8 +851,6 @@ test "switch pointer capture peer type resolution" {...@@ -873,8 +851,6 @@ test "switch pointer capture peer type resolution" {
873}851}
874852
875test "inline switch range that includes the maximum value of the switched type" {853test "inline switch range that includes the maximum value of the switched type" {
876 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
877
878 const inputs: [3]u8 = .{ 0, 254, 255 };854 const inputs: [3]u8 = .{ 0, 254, 255 };
879 for (inputs) |input| {855 for (inputs) |input| {
880 switch (input) {856 switch (input) {
...@@ -933,7 +909,6 @@ test "peer type resolution on switch captures ignores unused payload bits" {...@@ -933,7 +909,6 @@ test "peer type resolution on switch captures ignores unused payload bits" {
933test "switch prong captures range" {909test "switch prong captures range" {
934 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO910 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
935 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO911 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
936 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
937912
938 const S = struct {913 const S = struct {
939 fn a(b: []u3, c: u3) void {914 fn a(b: []u3, c: u3) void {
...@@ -970,8 +945,6 @@ test "prong with inline call to unreachable" {...@@ -970,8 +945,6 @@ test "prong with inline call to unreachable" {
970}945}
971946
972test "block error return trace index is reset between prongs" {947test "block error return trace index is reset between prongs" {
973 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
974
975 const S = struct {948 const S = struct {
976 fn returnError() error{TestFailed} {949 fn returnError() error{TestFailed} {
977 return error.TestFailed;950 return error.TestFailed;
test/behavior/this.zig-1
...@@ -51,7 +51,6 @@ test "this used as optional function parameter" {...@@ -51,7 +51,6 @@ test "this used as optional function parameter" {
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO52 if (builtin.zig_backend == .stage2_sparc64) 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;
5554
56 var global: State = undefined;55 var global: State = undefined;
57 global.enter = prev;56 global.enter = prev;
test/behavior/try.zig-2
...@@ -4,7 +4,6 @@ const expect = std.testing.expect;...@@ -4,7 +4,6 @@ const expect = std.testing.expect;
44
5test "try on error union" {5test "try on error union" {
6 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
87
9 try tryOnErrorUnionImpl();8 try tryOnErrorUnionImpl();
10 try comptime tryOnErrorUnionImpl();9 try comptime tryOnErrorUnionImpl();
...@@ -52,7 +51,6 @@ test "`try`ing an if/else expression" {...@@ -52,7 +51,6 @@ test "`try`ing an if/else expression" {
52 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
54 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;53 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
55 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5654
57 const S = struct {55 const S = struct {
58 fn getError() !void {56 fn getError() !void {
test/behavior/tuple.zig-8
...@@ -10,7 +10,6 @@ test "tuple concatenation" {...@@ -10,7 +10,6 @@ test "tuple concatenation" {
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_aarch64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO12 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1413
15 const S = struct {14 const S = struct {
16 fn doTheTest() !void {15 fn doTheTest() !void {
...@@ -56,7 +55,6 @@ test "more tuple concatenation" {...@@ -56,7 +55,6 @@ test "more tuple concatenation" {
56 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO55 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO56 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;57 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
59 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
6058
61 const T = struct {59 const T = struct {
62 fn consume_tuple(tuple: anytype, len: usize) !void {60 fn consume_tuple(tuple: anytype, len: usize) !void {
...@@ -326,8 +324,6 @@ test "tuple type with void field" {...@@ -326,8 +324,6 @@ test "tuple type with void field" {
326}324}
327325
328test "zero sized struct in tuple handled correctly" {326test "zero sized struct in tuple handled correctly" {
329 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
330
331 const State = struct {327 const State = struct {
332 const Self = @This();328 const Self = @This();
333 data: @Type(.{329 data: @Type(.{
...@@ -369,7 +365,6 @@ test "branching inside tuple literal" {...@@ -369,7 +365,6 @@ test "branching inside tuple literal" {
369 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO365 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
370 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO366 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
371 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO367 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
372 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
373368
374 const S = struct {369 const S = struct {
375 fn foo(a: anytype) !void {370 fn foo(a: anytype) !void {
...@@ -474,7 +469,6 @@ test "coerce anon tuple to tuple" {...@@ -474,7 +469,6 @@ test "coerce anon tuple to tuple" {
474 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO469 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
475 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO470 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
476 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO471 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
477 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
478472
479 var x: u8 = 1;473 var x: u8 = 1;
480 var y: u16 = 2;474 var y: u16 = 2;
...@@ -579,8 +573,6 @@ test "comptime fields in tuple can be initialized" {...@@ -579,8 +573,6 @@ test "comptime fields in tuple can be initialized" {
579}573}
580574
581test "tuple default values" {575test "tuple default values" {
582 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
583
584 const T = struct {576 const T = struct {
585 usize,577 usize,
586 usize = 123,578 usize = 123,
test/behavior/type.zig-2
...@@ -203,7 +203,6 @@ test "Type.Opaque" {...@@ -203,7 +203,6 @@ test "Type.Opaque" {
203 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO203 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
204 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO204 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
206 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
207206
208 const Opaque = @Type(.{207 const Opaque = @Type(.{
209 .Opaque = .{208 .Opaque = .{
...@@ -261,7 +260,6 @@ test "Type.Struct" {...@@ -261,7 +260,6 @@ test "Type.Struct" {
261 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO260 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
262 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO261 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
263 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO262 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
264 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
265263
266 const A = @Type(@typeInfo(struct { x: u8, y: u32 }));264 const A = @Type(@typeInfo(struct { x: u8, y: u32 }));
267 const infoA = @typeInfo(A).Struct;265 const infoA = @typeInfo(A).Struct;
test/behavior/undefined.zig-1
...@@ -91,7 +91,6 @@ test "reslice of undefined global var slice" {...@@ -91,7 +91,6 @@ test "reslice of undefined global var slice" {
91 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO91 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
92 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO92 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
93 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO93 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
9594
96 var stack_buf: [100]u8 = [_]u8{0} ** 100;95 var stack_buf: [100]u8 = [_]u8{0} ** 100;
97 buf = &stack_buf;96 buf = &stack_buf;
test/behavior/underscore.zig-1
...@@ -8,7 +8,6 @@ test "ignore lval with underscore" {...@@ -8,7 +8,6 @@ test "ignore lval with underscore" {
88
9test "ignore lval with underscore (while loop)" {9test "ignore lval with underscore (while loop)" {
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1211
13 while (optionalReturnError()) |_| {12 while (optionalReturnError()) |_| {
14 while (optionalReturnError()) |_| {13 while (optionalReturnError()) |_| {
test/behavior/union.zig-8
...@@ -418,7 +418,6 @@ test "tagged union initialization with runtime void" {...@@ -418,7 +418,6 @@ test "tagged union initialization with runtime void" {
418 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;418 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
419 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;419 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
420 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO420 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
421 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
422421
423 try expect(testTaggedUnionInit({}));422 try expect(testTaggedUnionInit({}));
424}423}
...@@ -1744,7 +1743,6 @@ test "union with 128 bit integer" {...@@ -1744,7 +1743,6 @@ test "union with 128 bit integer" {
17441743
1745test "memset extern union" {1744test "memset extern union" {
1746 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1745 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1747 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
17481746
1749 const U = extern union {1747 const U = extern union {
1750 foo: u8,1748 foo: u8,
...@@ -1766,7 +1764,6 @@ test "memset extern union" {...@@ -1766,7 +1764,6 @@ test "memset extern union" {
17661764
1767test "memset packed union" {1765test "memset packed union" {
1768 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1766 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1769 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
17701767
1771 const U = packed union {1768 const U = packed union {
1772 a: u32,1769 a: u32,
...@@ -1977,8 +1974,6 @@ test "reinterpret packed union inside packed struct" {...@@ -1977,8 +1974,6 @@ test "reinterpret packed union inside packed struct" {
1977}1974}
19781975
1979test "inner struct initializer uses union layout" {1976test "inner struct initializer uses union layout" {
1980 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1981
1982 const namespace = struct {1977 const namespace = struct {
1983 const U = union {1978 const U = union {
1984 a: struct {1979 a: struct {
...@@ -2004,7 +1999,6 @@ test "inner struct initializer uses union layout" {...@@ -2004,7 +1999,6 @@ test "inner struct initializer uses union layout" {
20041999
2005test "inner struct initializer uses packed union layout" {2000test "inner struct initializer uses packed union layout" {
2006 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;2001 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2007 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
20082002
2009 const namespace = struct {2003 const namespace = struct {
2010 const U = packed union {2004 const U = packed union {
...@@ -2031,7 +2025,6 @@ test "inner struct initializer uses packed union layout" {...@@ -2031,7 +2025,6 @@ test "inner struct initializer uses packed union layout" {
20312025
2032test "extern union initialized via reintepreted struct field initializer" {2026test "extern union initialized via reintepreted struct field initializer" {
2033 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;2027 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2034 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
20352028
2036 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };2029 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
20372030
...@@ -2155,7 +2148,6 @@ test "pass register-sized field as non-register-sized union" {...@@ -2155,7 +2148,6 @@ test "pass register-sized field as non-register-sized union" {
21552148
2156test "circular dependency through pointer field of a union" {2149test "circular dependency through pointer field of a union" {
2157 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;2150 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2158 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
21592151
2160 const S = struct {2152 const S = struct {
2161 const UnionInner = extern struct {2153 const UnionInner = extern struct {
test/behavior/var_args.zig-10
...@@ -14,8 +14,6 @@ fn add(args: anytype) i32 {...@@ -14,8 +14,6 @@ fn add(args: anytype) i32 {
14}14}
1515
16test "add arbitrary args" {16test "add arbitrary args" {
17 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
18
19 try expect(add(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);17 try expect(add(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
20 try expect(add(.{@as(i32, 1234)}) == 1234);18 try expect(add(.{@as(i32, 1234)}) == 1234);
21 try expect(add(.{}) == 0);19 try expect(add(.{}) == 0);
...@@ -26,15 +24,12 @@ fn readFirstVarArg(args: anytype) void {...@@ -26,15 +24,12 @@ fn readFirstVarArg(args: anytype) void {
26}24}
2725
28test "send void arg to var args" {26test "send void arg to var args" {
29 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
30
31 readFirstVarArg(.{{}});27 readFirstVarArg(.{{}});
32}28}
3329
34test "pass args directly" {30test "pass args directly" {
35 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
36 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
37 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3833
39 try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);34 try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
40 try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234);35 try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234);
...@@ -48,7 +43,6 @@ fn addSomeStuff(args: anytype) i32 {...@@ -48,7 +43,6 @@ fn addSomeStuff(args: anytype) i32 {
48test "runtime parameter before var args" {43test "runtime parameter before var args" {
49 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO44 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO45 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
51 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5246
53 try expect((try extraFn(10, .{})) == 0);47 try expect((try extraFn(10, .{})) == 0);
54 try expect((try extraFn(10, .{false})) == 1);48 try expect((try extraFn(10, .{false})) == 1);
...@@ -87,15 +81,11 @@ fn foo2(args: anytype) bool {...@@ -87,15 +81,11 @@ fn foo2(args: anytype) bool {
87}81}
8882
89test "array of var args functions" {83test "array of var args functions" {
90 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
91
92 try expect(foos[0](.{}));84 try expect(foos[0](.{}));
93 try expect(!foos[1](.{}));85 try expect(!foos[1](.{}));
94}86}
9587
96test "pass zero length array to var args param" {88test "pass zero length array to var args param" {
97 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
98
99 doNothingWithFirstArg(.{""});89 doNothingWithFirstArg(.{""});
100}90}
10191
test/behavior/vector.zig+1-1
...@@ -166,7 +166,6 @@ test "array to vector" {...@@ -166,7 +166,6 @@ test "array to vector" {
166 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO166 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
168 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO168 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
169 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
170169
171 const S = struct {170 const S = struct {
172 fn doTheTest() !void {171 fn doTheTest() !void {
...@@ -434,6 +433,7 @@ test "load vector elements via runtime index" {...@@ -434,6 +433,7 @@ test "load vector elements via runtime index" {
434 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO433 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
435 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO434 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
436 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO435 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
436 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
437437
438 const S = struct {438 const S = struct {
439 fn doTheTest() !void {439 fn doTheTest() !void {
test/behavior/void.zig-1
...@@ -37,7 +37,6 @@ test "void optional" {...@@ -37,7 +37,6 @@ test "void optional" {
37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;38 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO39 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
40 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
4140
42 var x: ?void = {};41 var x: ?void = {};
43 _ = &x;42 _ = &x;
test/behavior/while.zig-4
...@@ -258,7 +258,6 @@ fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {...@@ -258,7 +258,6 @@ fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
258258
259test "while on error union with else result follow else prong" {259test "while on error union with else result follow else prong" {
260 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO260 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
261 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
262261
263 const result = while (returnError()) |value| {262 const result = while (returnError()) |value| {
264 break value;263 break value;
...@@ -268,7 +267,6 @@ test "while on error union with else result follow else prong" {...@@ -268,7 +267,6 @@ test "while on error union with else result follow else prong" {
268267
269test "while on error union with else result follow break prong" {268test "while on error union with else result follow break prong" {
270 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO269 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
271 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
272270
273 const result = while (returnSuccess(10)) |value| {271 const result = while (returnSuccess(10)) |value| {
274 break value;272 break value;
...@@ -315,7 +313,6 @@ test "while error 2 break statements and an else" {...@@ -315,7 +313,6 @@ test "while error 2 break statements and an else" {
315 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO313 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
316 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO314 if (builtin.zig_backend == .stage2_aarch64) 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 S = struct {317 const S = struct {
321 fn entry(opt_t: anyerror!bool, f: bool) !void {318 fn entry(opt_t: anyerror!bool, f: bool) !void {
...@@ -382,7 +379,6 @@ test "while loop with comptime true condition needs no else block to return valu...@@ -382,7 +379,6 @@ test "while loop with comptime true condition needs no else block to return valu
382test "int returned from switch in while" {379test "int returned from switch in while" {
383 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO380 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
384 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO381 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
385 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
386382
387 var x: u32 = 3;383 var x: u32 = 3;
388 const val: usize = while (true) switch (x) {384 const val: usize = while (true) switch (x) {
test/behavior/widening.zig-2
...@@ -32,7 +32,6 @@ test "implicit unsigned integer to signed integer" {...@@ -32,7 +32,6 @@ test "implicit unsigned integer to signed integer" {
32 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO32 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO33 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
34 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;34 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
35 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3635
37 var a: u8 = 250;36 var a: u8 = 250;
38 var b: i16 = a;37 var b: i16 = a;
...@@ -80,7 +79,6 @@ test "cast small unsigned to larger signed" {...@@ -80,7 +79,6 @@ test "cast small unsigned to larger signed" {
80 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO79 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
81 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO80 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
82 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;81 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
83 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8482
85 try expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200));83 try expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200));
86 try expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999));84 try expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999));