authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-05-27 01:43:37-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-06-13 02:24:39-07:00
log4fd8900337f363c87b916e3a96004f8f35845549
tree8366bb95ee83b325ba0f2e687d7cd16f39709743
parenta9ef0169432a6709ca59588050be703ab1a10357
signaturelock-open Commit is signed but in an unrecognized format.

riscv: rewrite "binOp"

Reorganize how the binOp and genBinOp functions work. I've spent quite a while here reading exactly through the spec and so many tests are enabled because of several critical issues the old design had. There are some regressions that will take a long time to figure out individually so I will ignore them for now, and pray they get fixed by themselves. When we're closer to 100% passing is when I will start diving into them one-by-one.

38 files changed, 1255 insertions(+), 1113 deletions(-)

src/arch/riscv64/CodeGen.zig+985-915
...@@ -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,6 +34,8 @@ const DebugInfoOutput = codegen.DebugInfoOutput;...@@ -32,6 +34,8 @@ 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;
...@@ -158,6 +162,14 @@ const MCValue = union(enum) {...@@ -158,6 +162,14 @@ const MCValue = union(enum) {
158 };162 };
159 }163 }
160164
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
161 fn isMutable(mcv: MCValue) bool {173 fn isMutable(mcv: MCValue) bool {
162 return switch (mcv) {174 return switch (mcv) {
163 .none => unreachable,175 .none => unreachable,
...@@ -289,6 +301,7 @@ const Branch = struct {...@@ -289,6 +301,7 @@ const Branch = struct {
289301
290const InstTrackingMap = std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InstTracking);302const InstTrackingMap = std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InstTracking);
291const ConstTrackingMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, InstTracking);303const ConstTrackingMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, InstTracking);
304
292const InstTracking = struct {305const InstTracking = struct {
293 long: MCValue,306 long: MCValue,
294 short: MCValue,307 short: MCValue,
...@@ -317,33 +330,37 @@ const InstTracking = struct {...@@ -317,33 +330,37 @@ const InstTracking = struct {
317 }, .short = result };330 }, .short = result };
318 }331 }
319332
320 fn getReg(func: InstTracking) ?Register {333 fn getReg(inst_tracking: InstTracking) ?Register {
321 return func.short.getReg();334 return inst_tracking.short.getReg();
322 }335 }
323336
324 fn getRegs(func: *const InstTracking) []const Register {337 fn getRegs(inst_tracking: *const InstTracking) []const Register {
325 return func.short.getRegs();338 return inst_tracking.short.getRegs();
326 }339 }
327340
328 fn spill(func: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {341 fn spill(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {
329 if (std.meta.eql(func.long, func.short)) return; // Already spilled342 if (std.meta.eql(inst_tracking.long, inst_tracking.short)) return; // Already spilled
330 // Allocate or reuse frame index343 // Allocate or reuse frame index
331 switch (func.long) {344 switch (inst_tracking.long) {
332 .none => func.long = try function.allocRegOrMem(inst, false),345 .none => inst_tracking.long = try function.allocRegOrMem(
346 function.typeOfIndex(inst),
347 inst,
348 false,
349 ),
333 .load_frame => {},350 .load_frame => {},
334 .reserved_frame => |index| func.long = .{ .load_frame = .{ .index = index } },351 .reserved_frame => |index| inst_tracking.long = .{ .load_frame = .{ .index = index } },
335 else => unreachable,352 else => unreachable,
336 }353 }
337 tracking_log.debug("spill %{d} from {} to {}", .{ inst, func.short, func.long });354 tracking_log.debug("spill %{d} from {} to {}", .{ inst, inst_tracking.short, inst_tracking.long });
338 try function.genCopy(function.typeOfIndex(inst), func.long, func.short);355 try function.genCopy(function.typeOfIndex(inst), inst_tracking.long, inst_tracking.short);
339 }356 }
340357
341 fn reuseFrame(func: *InstTracking) void {358 fn reuseFrame(inst_tracking: *InstTracking) void {
342 switch (func.long) {359 switch (inst_tracking.long) {
343 .reserved_frame => |index| func.long = .{ .load_frame = .{ .index = index } },360 .reserved_frame => |index| inst_tracking.long = .{ .load_frame = .{ .index = index } },
344 else => {},361 else => {},
345 }362 }
346 func.short = switch (func.long) {363 inst_tracking.short = switch (inst_tracking.long) {
347 .none,364 .none,
348 .unreach,365 .unreach,
349 .undef,366 .undef,
...@@ -353,7 +370,7 @@ const InstTracking = struct {...@@ -353,7 +370,7 @@ const InstTracking = struct {
353 .lea_frame,370 .lea_frame,
354 .load_symbol,371 .load_symbol,
355 .lea_symbol,372 .lea_symbol,
356 => func.long,373 => inst_tracking.long,
357 .dead,374 .dead,
358 .register,375 .register,
359 .register_pair,376 .register_pair,
...@@ -365,14 +382,14 @@ const InstTracking = struct {...@@ -365,14 +382,14 @@ const InstTracking = struct {
365 };382 };
366 }383 }
367384
368 fn trackSpill(func: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {385 fn trackSpill(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {
369 try function.freeValue(func.short);386 try function.freeValue(inst_tracking.short);
370 func.reuseFrame();387 inst_tracking.reuseFrame();
371 tracking_log.debug("%{d} => {} (spilled)", .{ inst, func.* });388 tracking_log.debug("%{d} => {} (spilled)", .{ inst, inst_tracking.* });
372 }389 }
373390
374 fn verifyMaterialize(func: InstTracking, target: InstTracking) void {391 fn verifyMaterialize(inst_tracking: InstTracking, target: InstTracking) void {
375 switch (func.long) {392 switch (inst_tracking.long) {
376 .none,393 .none,
377 .unreach,394 .unreach,
378 .undef,395 .undef,
...@@ -381,7 +398,7 @@ const InstTracking = struct {...@@ -381,7 +398,7 @@ const InstTracking = struct {
381 .lea_frame,398 .lea_frame,
382 .load_symbol,399 .load_symbol,
383 .lea_symbol,400 .lea_symbol,
384 => assert(std.meta.eql(func.long, target.long)),401 => assert(std.meta.eql(inst_tracking.long, target.long)),
385 .load_frame,402 .load_frame,
386 .reserved_frame,403 .reserved_frame,
387 => switch (target.long) {404 => switch (target.long) {
...@@ -402,73 +419,73 @@ const InstTracking = struct {...@@ -402,73 +419,73 @@ const InstTracking = struct {
402 }419 }
403420
404 fn materialize(421 fn materialize(
405 func: *InstTracking,422 inst_tracking: *InstTracking,
406 function: *Func,423 function: *Func,
407 inst: Air.Inst.Index,424 inst: Air.Inst.Index,
408 target: InstTracking,425 target: InstTracking,
409 ) !void {426 ) !void {
410 func.verifyMaterialize(target);427 inst_tracking.verifyMaterialize(target);
411 try func.materializeUnsafe(function, inst, target);428 try inst_tracking.materializeUnsafe(function, inst, target);
412 }429 }
413430
414 fn materializeUnsafe(431 fn materializeUnsafe(
415 func: InstTracking,432 inst_tracking: InstTracking,
416 function: *Func,433 function: *Func,
417 inst: Air.Inst.Index,434 inst: Air.Inst.Index,
418 target: InstTracking,435 target: InstTracking,
419 ) !void {436 ) !void {
420 const ty = function.typeOfIndex(inst);437 const ty = function.typeOfIndex(inst);
421 if ((func.long == .none or func.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)
422 try function.genCopy(ty, target.long, func.short);439 try function.genCopy(ty, target.long, inst_tracking.short);
423 try function.genCopy(ty, target.short, func.short);440 try function.genCopy(ty, target.short, inst_tracking.short);
424 }441 }
425442
426 fn trackMaterialize(func: *InstTracking, inst: Air.Inst.Index, target: InstTracking) void {443 fn trackMaterialize(inst_tracking: *InstTracking, inst: Air.Inst.Index, target: InstTracking) void {
427 func.verifyMaterialize(target);444 inst_tracking.verifyMaterialize(target);
428 // Don't clobber reserved frame indices445 // Don't clobber reserved frame indices
429 func.long = if (target.long == .none) switch (func.long) {446 inst_tracking.long = if (target.long == .none) switch (inst_tracking.long) {
430 .load_frame => |addr| .{ .reserved_frame = addr.index },447 .load_frame => |addr| .{ .reserved_frame = addr.index },
431 .reserved_frame => func.long,448 .reserved_frame => inst_tracking.long,
432 else => target.long,449 else => target.long,
433 } else target.long;450 } else target.long;
434 func.short = target.short;451 inst_tracking.short = target.short;
435 tracking_log.debug("%{d} => {} (materialize)", .{ inst, func.* });452 tracking_log.debug("%{d} => {} (materialize)", .{ inst, inst_tracking.* });
436 }453 }
437454
438 fn resurrect(func: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {455 fn resurrect(inst_tracking: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {
439 switch (func.short) {456 switch (inst_tracking.short) {
440 .dead => |die_generation| if (die_generation >= scope_generation) {457 .dead => |die_generation| if (die_generation >= scope_generation) {
441 func.reuseFrame();458 inst_tracking.reuseFrame();
442 tracking_log.debug("%{d} => {} (resurrect)", .{ inst, func.* });459 tracking_log.debug("%{d} => {} (resurrect)", .{ inst, inst_tracking.* });
443 },460 },
444 else => {},461 else => {},
445 }462 }
446 }463 }
447464
448 fn die(func: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {465 fn die(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {
449 if (func.short == .dead) return;466 if (inst_tracking.short == .dead) return;
450 try function.freeValue(func.short);467 try function.freeValue(inst_tracking.short);
451 func.short = .{ .dead = function.scope_generation };468 inst_tracking.short = .{ .dead = function.scope_generation };
452 tracking_log.debug("%{d} => {} (death)", .{ inst, func.* });469 tracking_log.debug("%{d} => {} (death)", .{ inst, inst_tracking.* });
453 }470 }
454471
455 fn reuse(472 fn reuse(
456 func: *InstTracking,473 inst_tracking: *InstTracking,
457 function: *Func,474 function: *Func,
458 new_inst: ?Air.Inst.Index,475 new_inst: ?Air.Inst.Index,
459 old_inst: Air.Inst.Index,476 old_inst: Air.Inst.Index,
460 ) void {477 ) void {
461 func.short = .{ .dead = function.scope_generation };478 inst_tracking.short = .{ .dead = function.scope_generation };
462 if (new_inst) |inst|479 if (new_inst) |inst|
463 tracking_log.debug("%{d} => {} (reuse %{d})", .{ inst, func.*, old_inst })480 tracking_log.debug("%{d} => {} (reuse %{d})", .{ inst, inst_tracking.*, old_inst })
464 else481 else
465 tracking_log.debug("tmp => {} (reuse %{d})", .{ func.*, old_inst });482 tracking_log.debug("tmp => {} (reuse %{d})", .{ inst_tracking.*, old_inst });
466 }483 }
467484
468 fn liveOut(func: *InstTracking, function: *Func, inst: Air.Inst.Index) void {485 fn liveOut(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) void {
469 for (func.getRegs()) |reg| {486 for (inst_tracking.getRegs()) |reg| {
470 if (function.register_manager.isRegFree(reg)) {487 if (function.register_manager.isRegFree(reg)) {
471 tracking_log.debug("%{d} => {} (live-out)", .{ inst, func.* });488 tracking_log.debug("%{d} => {} (live-out)", .{ inst, inst_tracking.* });
472 continue;489 continue;
473 }490 }
474491
...@@ -495,18 +512,18 @@ const InstTracking = struct {...@@ -495,18 +512,18 @@ const InstTracking = struct {
495 // Perform side-effects of freeValue manually.512 // Perform side-effects of freeValue manually.
496 function.register_manager.freeReg(reg);513 function.register_manager.freeReg(reg);
497514
498 tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, func.*, tracked_inst });515 tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, inst_tracking.*, tracked_inst });
499 }516 }
500 }517 }
501518
502 pub fn format(519 pub fn format(
503 func: InstTracking,520 inst_tracking: InstTracking,
504 comptime _: []const u8,521 comptime _: []const u8,
505 _: std.fmt.FormatOptions,522 _: std.fmt.FormatOptions,
506 writer: anytype,523 writer: anytype,
507 ) @TypeOf(writer).Error!void {524 ) @TypeOf(writer).Error!void {
508 if (!std.meta.eql(func.long, func.short)) try writer.print("|{}| ", .{func.long});525 if (!std.meta.eql(inst_tracking.long, inst_tracking.short)) try writer.print("|{}| ", .{inst_tracking.long});
509 try writer.print("{}", .{func.short});526 try writer.print("{}", .{inst_tracking.short});
510 }527 }
511};528};
512529
...@@ -741,6 +758,8 @@ pub fn generate(...@@ -741,6 +758,8 @@ pub fn generate(
741 function.mir_extra.deinit(gpa);758 function.mir_extra.deinit(gpa);
742 }759 }
743760
761 wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)});
762
744 try function.frame_allocs.resize(gpa, FrameIndex.named_count);763 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
745 function.frame_allocs.set(764 function.frame_allocs.set(
746 @intFromEnum(FrameIndex.stack_frame),765 @intFromEnum(FrameIndex.stack_frame),
...@@ -846,13 +865,133 @@ pub fn generate(...@@ -846,13 +865,133 @@ pub fn generate(
846 }865 }
847}866}
848867
868const FormatWipMirData = struct {
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}
921
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}
961
962const FormatTrackingData = struct {
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
849fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {978fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
850 const gpa = func.gpa;979 const gpa = func.gpa;
851
852 try func.mir_instructions.ensureUnusedCapacity(gpa, 1);980 try func.mir_instructions.ensureUnusedCapacity(gpa, 1);
853
854 const result_index: Mir.Inst.Index = @intCast(func.mir_instructions.len);981 const result_index: Mir.Inst.Index = @intCast(func.mir_instructions.len);
855 func.mir_instructions.appendAssumeCapacity(inst);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", .{});
856 return result_index;995 return result_index;
857}996}
858997
...@@ -979,7 +1118,7 @@ fn gen(func: *Func) !void {...@@ -979,7 +1118,7 @@ fn gen(func: *Func) !void {
979 .r = .ra,1118 .r = .ra,
980 .m = .{1119 .m = .{
981 .base = .{ .frame = .ret_addr },1120 .base = .{ .frame = .ret_addr },
982 .mod = .{ .rm = .{ .size = .dword } },1121 .mod = .{ .size = .dword, .unsigned = false },
983 },1122 },
984 } },1123 } },
985 });1124 });
...@@ -990,7 +1129,7 @@ fn gen(func: *Func) !void {...@@ -990,7 +1129,7 @@ fn gen(func: *Func) !void {
990 .r = .ra,1129 .r = .ra,
991 .m = .{1130 .m = .{
992 .base = .{ .frame = .ret_addr },1131 .base = .{ .frame = .ret_addr },
993 .mod = .{ .rm = .{ .size = .dword } },1132 .mod = .{ .size = .dword, .unsigned = false },
994 },1133 },
995 } },1134 } },
996 });1135 });
...@@ -1001,7 +1140,7 @@ fn gen(func: *Func) !void {...@@ -1001,7 +1140,7 @@ fn gen(func: *Func) !void {
1001 .r = .s0,1140 .r = .s0,
1002 .m = .{1141 .m = .{
1003 .base = .{ .frame = .base_ptr },1142 .base = .{ .frame = .base_ptr },
1004 .mod = .{ .rm = .{ .size = .dword } },1143 .mod = .{ .size = .dword, .unsigned = false },
1005 },1144 },
1006 } },1145 } },
1007 });1146 });
...@@ -1012,7 +1151,7 @@ fn gen(func: *Func) !void {...@@ -1012,7 +1151,7 @@ fn gen(func: *Func) !void {
1012 .r = .s0,1151 .r = .s0,
1013 .m = .{1152 .m = .{
1014 .base = .{ .frame = .base_ptr },1153 .base = .{ .frame = .base_ptr },
1015 .mod = .{ .rm = .{ .size = .dword } },1154 .mod = .{ .size = .dword, .unsigned = false },
1016 },1155 },
1017 } },1156 } },
1018 });1157 });
...@@ -1072,36 +1211,47 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1072,36 +1211,47 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
10721211
1073 for (body) |inst| {1212 for (body) |inst| {
1074 if (func.liveness.isUnused(inst) and !func.air.mustLower(inst, ip)) continue;1213 if (func.liveness.isUnused(inst) and !func.air.mustLower(inst, ip)) continue;
1214 wip_mir_log.debug("{}", .{func.fmtAir(inst)});
1215 verbose_tracking_log.debug("{}", .{func.fmtTracking()});
10751216
1076 const old_air_bookkeeping = func.air_bookkeeping;1217 const old_air_bookkeeping = func.air_bookkeeping;
1077 try func.inst_tracking.ensureUnusedCapacity(func.gpa, 1);1218 try func.inst_tracking.ensureUnusedCapacity(func.gpa, 1);
1078 switch (air_tags[@intFromEnum(inst)]) {1219 const tag: Air.Inst.Tag = air_tags[@intFromEnum(inst)];
1220 switch (tag) {
1079 // zig fmt: off1221 // zig fmt: off
1080 .ptr_add => try func.airPtrArithmetic(inst, .ptr_add),1222 .add,
1081 .ptr_sub => try func.airPtrArithmetic(inst, .ptr_sub),1223 .add_wrap,
1224 .sub,
1225 .sub_wrap,
10821226
1083 .add => try func.airBinOp(inst, .add),1227 .mul,
1084 .sub => try func.airBinOp(inst, .sub),1228 .mul_wrap,
1229 .div_trunc,
10851230
1086 .add_safe,1231 .shl, .shl_exact,
1087 .sub_safe,1232 .shr, .shr_exact,
1088 .mul_safe,
1089 => return func.fail("TODO implement safety_checked_instructions", .{}),
10901233
1091 .add_wrap => try func.airAddWrap(inst),1234 .bool_and,
1092 .add_sat => try func.airAddSat(inst),1235 .bool_or,
1093 .sub_wrap => try func.airSubWrap(inst),1236 .bit_and,
1094 .sub_sat => try func.airSubSat(inst),1237 .bit_or,
1095 .mul => try func.airMul(inst),1238
1096 .mul_wrap => try func.airMulWrap(inst),1239 .xor,
1097 .mul_sat => try func.airMulSat(inst),1240
1098 .rem => try func.airRem(inst),1241 .min,
1099 .mod => try func.airMod(inst),1242 .max,
1100 .shl, .shl_exact => try func.airShl(inst),1243 => try func.airBinOp(inst, tag),
1101 .shl_sat => try func.airShlSat(inst),1244
1102 .min => try func.airMinMax(inst, .min),1245
1103 .max => try func.airMinMax(inst, .max),1246 .ptr_add,
1104 .slice => try func.airSlice(inst),1247 .ptr_sub => try func.airPtrArithmetic(inst, tag),
1248
1249 .rem,
1250 .mod,
1251 .div_float,
1252 .div_floor,
1253 .div_exact,
1254 => return func.fail("TODO: {s}", .{@tagName(tag)}),
11051255
1106 .sqrt,1256 .sqrt,
1107 .sin,1257 .sin,
...@@ -1124,24 +1274,33 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1124,24 +1274,33 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1124 .mul_with_overflow => try func.airMulWithOverflow(inst),1274 .mul_with_overflow => try func.airMulWithOverflow(inst),
1125 .shl_with_overflow => try func.airShlWithOverflow(inst),1275 .shl_with_overflow => try func.airShlWithOverflow(inst),
11261276
1127 .div_float, .div_trunc, .div_floor, .div_exact => try func.airDiv(inst),
11281277
1129 .cmp_lt => try func.airCmp(inst),1278 .add_sat => try func.airAddSat(inst),
1130 .cmp_lte => try func.airCmp(inst),1279 .sub_sat => try func.airSubSat(inst),
1131 .cmp_eq => try func.airCmp(inst),1280 .mul_sat => try func.airMulSat(inst),
1132 .cmp_gte => try func.airCmp(inst),1281 .shl_sat => try func.airShlSat(inst),
1133 .cmp_gt => try func.airCmp(inst),1282
1134 .cmp_neq => try func.airCmp(inst),1283 .add_safe,
1284 .sub_safe,
1285 .mul_safe,
1286 => return func.fail("TODO implement safety_checked_instructions", .{}),
1287
1288 .cmp_lt,
1289 .cmp_lte,
1290 .cmp_eq,
1291 .cmp_gte,
1292 .cmp_gt,
1293 .cmp_neq,
1294 => try func.airCmp(inst, tag),
11351295
1136 .cmp_vector => try func.airCmpVector(inst),1296 .cmp_vector => try func.airCmpVector(inst),
1137 .cmp_lt_errors_len => try func.airCmpLtErrorsLen(inst),1297 .cmp_lt_errors_len => try func.airCmpLtErrorsLen(inst),
11381298
1139 .bool_and => try func.airBoolOp(inst),1299 .slice => try func.airSlice(inst),
1140 .bool_or => try func.airBoolOp(inst),1300 .array_to_slice => try func.airArrayToSlice(inst),
1141 .bit_and => try func.airBitAnd(inst),1301
1142 .bit_or => try func.airBitOr(inst),1302 .slice_ptr => try func.airSlicePtr(inst),
1143 .xor => try func.airXor(inst),1303 .slice_len => try func.airSliceLen(inst),
1144 .shr, .shr_exact => try func.airShr(inst),
11451304
1146 .alloc => try func.airAlloc(inst),1305 .alloc => try func.airAlloc(inst),
1147 .ret_ptr => try func.airRetPtr(inst),1306 .ret_ptr => try func.airRetPtr(inst),
...@@ -1181,7 +1340,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1181,7 +1340,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1181 .store_safe => try func.airStore(inst, true),1340 .store_safe => try func.airStore(inst, true),
1182 .struct_field_ptr=> try func.airStructFieldPtr(inst),1341 .struct_field_ptr=> try func.airStructFieldPtr(inst),
1183 .struct_field_val=> try func.airStructFieldVal(inst),1342 .struct_field_val=> try func.airStructFieldVal(inst),
1184 .array_to_slice => try func.airArrayToSlice(inst),
1185 .float_from_int => try func.airFloatFromInt(inst),1343 .float_from_int => try func.airFloatFromInt(inst),
1186 .int_from_float => try func.airIntFromFloat(inst),1344 .int_from_float => try func.airIntFromFloat(inst),
1187 .cmpxchg_strong => try func.airCmpxchg(inst),1345 .cmpxchg_strong => try func.airCmpxchg(inst),
...@@ -1229,7 +1387,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1229,7 +1387,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1229 .atomic_store_monotonic => try func.airAtomicStore(inst, .monotonic),1387 .atomic_store_monotonic => try func.airAtomicStore(inst, .monotonic),
1230 .atomic_store_release => try func.airAtomicStore(inst, .release),1388 .atomic_store_release => try func.airAtomicStore(inst, .release),
1231 .atomic_store_seq_cst => try func.airAtomicStore(inst, .seq_cst),1389 .atomic_store_seq_cst => try func.airAtomicStore(inst, .seq_cst),
1232
1233 .struct_field_ptr_index_0 => try func.airStructFieldPtrIndex(inst, 0),1390 .struct_field_ptr_index_0 => try func.airStructFieldPtrIndex(inst, 0),
1234 .struct_field_ptr_index_1 => try func.airStructFieldPtrIndex(inst, 1),1391 .struct_field_ptr_index_1 => try func.airStructFieldPtrIndex(inst, 1),
1235 .struct_field_ptr_index_2 => try func.airStructFieldPtrIndex(inst, 2),1392 .struct_field_ptr_index_2 => try func.airStructFieldPtrIndex(inst, 2),
...@@ -1238,15 +1395,15 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1238,15 +1395,15 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1238 .field_parent_ptr => try func.airFieldParentPtr(inst),1395 .field_parent_ptr => try func.airFieldParentPtr(inst),
12391396
1240 .switch_br => try func.airSwitchBr(inst),1397 .switch_br => try func.airSwitchBr(inst),
1241 .slice_ptr => try func.airSlicePtr(inst),
1242 .slice_len => try func.airSliceLen(inst),
12431398
1244 .ptr_slice_len_ptr => try func.airPtrSliceLenPtr(inst),1399 .ptr_slice_len_ptr => try func.airPtrSliceLenPtr(inst),
1245 .ptr_slice_ptr_ptr => try func.airPtrSlicePtrPtr(inst),1400 .ptr_slice_ptr_ptr => try func.airPtrSlicePtrPtr(inst),
12461401
1247 .array_elem_val => try func.airArrayElemVal(inst),1402 .array_elem_val => try func.airArrayElemVal(inst),
1403
1248 .slice_elem_val => try func.airSliceElemVal(inst),1404 .slice_elem_val => try func.airSliceElemVal(inst),
1249 .slice_elem_ptr => try func.airSliceElemPtr(inst),1405 .slice_elem_ptr => try func.airSliceElemPtr(inst),
1406
1250 .ptr_elem_val => try func.airPtrElemVal(inst),1407 .ptr_elem_val => try func.airPtrElemVal(inst),
1251 .ptr_elem_ptr => try func.airPtrElemPtr(inst),1408 .ptr_elem_ptr => try func.airPtrElemPtr(inst),
12521409
...@@ -1330,6 +1487,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1330,6 +1487,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1330 }1487 }
1331 }1488 }
1332 }1489 }
1490 verbose_tracking_log.debug("{}", .{func.fmtTracking()});
1333}1491}
13341492
1335fn getValue(func: *Func, value: MCValue, inst: ?Air.Inst.Index) !void {1493fn getValue(func: *Func, value: MCValue, inst: ?Air.Inst.Index) !void {
...@@ -1563,7 +1721,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {...@@ -1563,7 +1721,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {
1563 .i_type = .{1721 .i_type = .{
1564 .rd = reg,1722 .rd = reg,
1565 .rs1 = reg,1723 .rs1 = reg,
1566 .imm12 = Immediate.s(shift),1724 .imm12 = Immediate.u(shift),
1567 },1725 },
1568 },1726 },
1569 });1727 });
...@@ -1574,25 +1732,49 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {...@@ -1574,25 +1732,49 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {
1574 .i_type = .{1732 .i_type = .{
1575 .rd = reg,1733 .rd = reg,
1576 .rs1 = reg,1734 .rs1 = reg,
1577 .imm12 = Immediate.s(shift),1735 .imm12 = Immediate.u(shift),
1578 },1736 },
1579 },1737 },
1580 });1738 });
1581 },1739 },
1582 .unsigned => {1740 .unsigned => {
1583 const mask = ~@as(u64, 0) >> shift;1741 const mask = ~@as(u64, 0) >> shift;
1584 const tmp_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = mask });1742 if (mask < 256) {
1585 _ = try func.addInst(.{1743 _ = try func.addInst(.{
1586 .tag = .@"and",1744 .tag = .andi,
1587 .ops = .rrr,1745 .ops = .rri,
1588 .data = .{1746 .data = .{
1589 .r_type = .{1747 .i_type = .{
1590 .rd = reg,1748 .rd = reg,
1591 .rs1 = reg,1749 .rs1 = reg,
1592 .rs2 = tmp_reg,1750 .imm12 = Immediate.u(@intCast(mask)),
1751 },
1593 },1752 },
1594 },1753 });
1595 });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 }
1596 },1778 },
1597 }1779 }
1598}1780}
...@@ -1673,9 +1855,8 @@ fn regTempClassForType(func: *Func, ty: Type) RegisterManager.RegisterBitSet {...@@ -1673,9 +1855,8 @@ fn regTempClassForType(func: *Func, ty: Type) RegisterManager.RegisterBitSet {
1673 };1855 };
1674}1856}
16751857
1676fn allocRegOrMem(func: *Func, inst: Air.Inst.Index, reg_ok: bool) !MCValue {1858fn allocRegOrMem(func: *Func, elem_ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue {
1677 const zcu = func.bin_file.comp.module.?;1859 const zcu = func.bin_file.comp.module.?;
1678 const elem_ty = func.typeOfIndex(inst);
16791860
1680 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {1861 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {
1681 return func.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)});
...@@ -1714,66 +1895,15 @@ fn allocReg(func: *Func, reg_class: abi.RegisterClass) !struct { Register, Regis...@@ -1714,66 +1895,15 @@ fn allocReg(func: *Func, reg_class: abi.RegisterClass) !struct { Register, Regis
1714 return .{ reg, lock };1895 return .{ reg, lock };
1715}1896}
17161897
1717const PromoteOptions = struct {
1718 /// zeroes out the register before loading in the operand
1719 ///
1720 /// if the operand is already a register, it will truncate with 0
1721 zero: bool = false,
1722};
1723
1724/// Similar to `allocReg` but will copy the MCValue into the Register unless `operand` is already1898/// Similar to `allocReg` but will copy the MCValue into the Register unless `operand` is already
1725/// a register, in which case it will return a possible lock to that register.1899/// a register, in which case it will return a possible lock to that register.
1726fn promoteReg(func: *Func, ty: Type, operand: MCValue, options: PromoteOptions) !struct { Register, ?RegisterLock } {1900fn promoteReg(func: *Func, ty: Type, operand: MCValue) !struct { Register, ?RegisterLock } {
1727 const zcu = func.bin_file.comp.module.?;
1728 const bit_size = ty.bitSize(zcu);
1729
1730 if (operand == .register) {1901 if (operand == .register) {
1731 const op_reg = operand.register;1902 const op_reg = operand.register;
1732 if (options.zero and op_reg.class() == .int) {
1733 // we make sure to emit the truncate manually because binOp will call this function
1734 // and it could cause an infinite loop
1735
1736 _ = try func.addInst(.{
1737 .tag = .slli,
1738 .ops = .rri,
1739 .data = .{
1740 .i_type = .{
1741 .imm12 = Immediate.u(64 - bit_size),
1742 .rd = op_reg,
1743 .rs1 = op_reg,
1744 },
1745 },
1746 });
1747
1748 _ = try func.addInst(.{
1749 .tag = .srli,
1750 .ops = .rri,
1751 .data = .{
1752 .i_type = .{
1753 .imm12 = Immediate.u(64 - bit_size),
1754 .rd = op_reg,
1755 .rs1 = op_reg,
1756 },
1757 },
1758 });
1759 }
1760
1761 return .{ op_reg, func.register_manager.lockReg(operand.register) };1903 return .{ op_reg, func.register_manager.lockReg(operand.register) };
1762 }1904 }
17631905
1764 const reg, const lock = try func.allocReg(func.typeRegClass(ty));1906 const reg, const lock = try func.allocReg(func.typeRegClass(ty));
1765
1766 if (options.zero and reg.class() == .int) {
1767 _ = try func.addInst(.{
1768 .tag = .pseudo,
1769 .ops = .pseudo_mv,
1770 .data = .{ .rr = .{
1771 .rd = reg,
1772 .rs = .zero,
1773 } },
1774 });
1775 }
1776
1777 try func.genSetReg(ty, reg, operand);1907 try func.genSetReg(ty, reg, operand);
1778 return .{ reg, lock };1908 return .{ reg, lock };
1779}1909}
...@@ -1793,14 +1923,19 @@ fn elemOffset(func: *Func, index_ty: Type, index: MCValue, elem_size: u64) !Regi...@@ -1793,14 +1923,19 @@ fn elemOffset(func: *Func, index_ty: Type, index: MCValue, elem_size: u64) !Regi
1793 const lock = func.register_manager.lockRegAssumeUnused(reg);1923 const lock = func.register_manager.lockRegAssumeUnused(reg);
1794 defer func.register_manager.unlockReg(lock);1924 defer func.register_manager.unlockReg(lock);
17951925
1796 const result = try func.binOp(1926 const result_reg, const result_lock = try func.allocReg(.int);
1927 defer func.register_manager.unlockReg(result_lock);
1928
1929 try func.genBinOp(
1797 .mul,1930 .mul,
1798 .{ .register = reg },1931 .{ .register = reg },
1799 index_ty,1932 index_ty,
1800 .{ .immediate = elem_size },1933 .{ .immediate = elem_size },
1801 index_ty,1934 index_ty,
1935 result_reg,
1802 );1936 );
1803 break :blk result.register;1937
1938 break :blk result_reg;
1804 },1939 },
1805 }1940 }
1806 };1941 };
...@@ -1892,7 +2027,7 @@ fn airIntCast(func: *Func, inst: Air.Inst.Index) !void {...@@ -1892,7 +2027,7 @@ fn airIntCast(func: *Func, inst: Air.Inst.Index) !void {
1892 math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==2027 math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
1893 math.divCeil(u32, src_storage_bits, 64) catch unreachable and2028 math.divCeil(u32, src_storage_bits, 64) catch unreachable and
1894 func.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: {
1895 const dst_mcv = try func.allocRegOrMem(inst, true);2030 const dst_mcv = try func.allocRegOrMem(dst_ty, inst, true);
1896 try func.genCopy(min_ty, dst_mcv, src_mcv);2031 try func.genCopy(min_ty, dst_mcv, src_mcv);
1897 break :dst dst_mcv;2032 break :dst dst_mcv;
1898 };2033 };
...@@ -1904,7 +2039,7 @@ fn airIntCast(func: *Func, inst: Air.Inst.Index) !void {...@@ -1904,7 +2039,7 @@ fn airIntCast(func: *Func, inst: Air.Inst.Index) !void {
1904 break :result null; // TODO2039 break :result null; // TODO
19052040
1906 break :result dst_mcv;2041 break :result dst_mcv;
1907 } orelse return func.fail("TODO implement airIntCast from {} to {}", .{2042 } orelse return func.fail("TODO: implement airIntCast from {} to {}", .{
1908 src_ty.fmt(zcu), dst_ty.fmt(zcu),2043 src_ty.fmt(zcu), dst_ty.fmt(zcu),
1909 });2044 });
19102045
...@@ -1948,7 +2083,7 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void {...@@ -1948,7 +2083,7 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void {
1948 if (func.reuseOperand(inst, ty_op.operand, 0, operand) and operand == .register)2083 if (func.reuseOperand(inst, ty_op.operand, 0, operand) and operand == .register)
1949 operand.register2084 operand.register
1950 else2085 else
1951 (try func.allocRegOrMem(inst, true)).register;2086 (try func.allocRegOrMem(func.typeOfIndex(inst), inst, true)).register;
19522087
1953 _ = try func.addInst(.{2088 _ = try func.addInst(.{
1954 .tag = .pseudo,2089 .tag = .pseudo,
...@@ -1970,106 +2105,6 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void {...@@ -1970,106 +2105,6 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void {
1970 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });2105 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1971}2106}
19722107
1973fn airMinMax(
1974 func: *Func,
1975 inst: Air.Inst.Index,
1976 comptime tag: enum {
1977 max,
1978 min,
1979 },
1980) !void {
1981 const zcu = func.bin_file.comp.module.?;
1982 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
1983
1984 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
1985 const lhs = try func.resolveInst(bin_op.lhs);
1986 const rhs = try func.resolveInst(bin_op.rhs);
1987 const lhs_ty = func.typeOf(bin_op.lhs);
1988 const rhs_ty = func.typeOf(bin_op.rhs);
1989
1990 const int_info = lhs_ty.intInfo(zcu);
1991
1992 if (int_info.bits > 64) return func.fail("TODO: > 64 bit @min", .{});
1993
1994 const lhs_reg, const lhs_lock = blk: {
1995 if (lhs == .register) break :blk .{ lhs.register, func.register_manager.lockReg(lhs.register) };
1996
1997 const lhs_reg, const lhs_lock = try func.allocReg(.int);
1998 try func.genSetReg(lhs_ty, lhs_reg, lhs);
1999 break :blk .{ lhs_reg, lhs_lock };
2000 };
2001 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
2002
2003 const rhs_reg, const rhs_lock = blk: {
2004 if (rhs == .register) break :blk .{ rhs.register, func.register_manager.lockReg(rhs.register) };
2005
2006 const rhs_reg, const rhs_lock = try func.allocReg(.int);
2007 try func.genSetReg(rhs_ty, rhs_reg, rhs);
2008 break :blk .{ rhs_reg, rhs_lock };
2009 };
2010 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
2011
2012 const mask_reg, const mask_lock = try func.allocReg(.int);
2013 defer func.register_manager.unlockReg(mask_lock);
2014
2015 const result_reg, const result_lock = try func.allocReg(.int);
2016 defer func.register_manager.unlockReg(result_lock);
2017
2018 _ = try func.addInst(.{
2019 .tag = if (int_info.signedness == .unsigned) .sltu else .slt,
2020 .ops = .rrr,
2021 .data = .{ .r_type = .{
2022 .rd = mask_reg,
2023 .rs1 = lhs_reg,
2024 .rs2 = rhs_reg,
2025 } },
2026 });
2027
2028 _ = try func.addInst(.{
2029 .tag = .sub,
2030 .ops = .rrr,
2031 .data = .{ .r_type = .{
2032 .rd = mask_reg,
2033 .rs1 = .zero,
2034 .rs2 = mask_reg,
2035 } },
2036 });
2037
2038 _ = try func.addInst(.{
2039 .tag = .xor,
2040 .ops = .rrr,
2041 .data = .{ .r_type = .{
2042 .rd = result_reg,
2043 .rs1 = lhs_reg,
2044 .rs2 = rhs_reg,
2045 } },
2046 });
2047
2048 _ = try func.addInst(.{
2049 .tag = .@"and",
2050 .ops = .rrr,
2051 .data = .{ .r_type = .{
2052 .rd = mask_reg,
2053 .rs1 = result_reg,
2054 .rs2 = mask_reg,
2055 } },
2056 });
2057
2058 _ = try func.addInst(.{
2059 .tag = .xor,
2060 .ops = .rrr,
2061 .data = .{ .r_type = .{
2062 .rd = result_reg,
2063 .rs1 = if (tag == .min) rhs_reg else lhs_reg,
2064 .rs2 = mask_reg,
2065 } },
2066 });
2067
2068 break :result .{ .register = result_reg };
2069 };
2070 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2071}
2072
2073fn airSlice(func: *Func, inst: Air.Inst.Index) !void {2108fn airSlice(func: *Func, inst: Air.Inst.Index) !void {
2074 const zcu = func.bin_file.comp.module.?;2109 const zcu = func.bin_file.comp.module.?;
2075 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2110 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
...@@ -2094,417 +2129,487 @@ fn airSlice(func: *Func, inst: Air.Inst.Index) !void {...@@ -2094,417 +2129,487 @@ fn airSlice(func: *Func, inst: Air.Inst.Index) !void {
2094}2129}
20952130
2096fn airBinOp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {2131fn airBinOp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
2132 const zcu = func.bin_file.comp.module.?;
2097 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2133 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2098 const lhs = try func.resolveInst(bin_op.lhs);2134 const dst_mcv = try func.binOp(inst, tag, bin_op.lhs, bin_op.rhs);
2099 const rhs = try func.resolveInst(bin_op.rhs);
2100 const lhs_ty = func.typeOf(bin_op.lhs);
2101 const rhs_ty = func.typeOf(bin_op.rhs);
21022135
2103 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {2136 const dst_ty = func.typeOfIndex(inst);
2104 break :result try func.binOp(tag, lhs, lhs_ty, rhs, rhs_ty);2137 if (dst_ty.isAbiInt(zcu)) {
2105 };2138 const abi_size: u32 = @intCast(dst_ty.abiSize(zcu));
2106 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });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);
2146
2147 if (dst_mcv.isRegister()) {
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 }
2161
2162 return func.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
2107}2163}
21082164
2109fn binOp(2165fn binOp(
2166 func: *Func,
2167 maybe_inst: ?Air.Inst.Index,
2168 air_tag: Air.Inst.Tag,
2169 lhs_air: Air.Inst.Ref,
2170 rhs_air: Air.Inst.Ref,
2171) !MCValue {
2172 _ = maybe_inst;
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 }
2191
2192 if (lhs_ty.bitSize(zcu) > 64) return func.fail("TODO: binOp >= 64 bits", .{});
2193
2194 const lhs_mcv = try func.resolveInst(lhs_air);
2195 const rhs_mcv = try func.resolveInst(rhs_air);
2196
2197 const class_for_dst_ty: abi.RegisterClass = switch (air_tag) {
2198 // will always return int register no matter the input
2199 .cmp_eq,
2200 .cmp_neq,
2201 .cmp_lt,
2202 .cmp_lte,
2203 .cmp_gt,
2204 .cmp_gte,
2205 => .int,
2206
2207 else => func.typeRegClass(lhs_ty),
2208 };
2209
2210 const dst_reg, const dst_lock = try func.allocReg(class_for_dst_ty);
2211 defer func.register_manager.unlockReg(dst_lock);
2212
2213 try func.genBinOp(
2214 air_tag,
2215 lhs_mcv,
2216 lhs_ty,
2217 rhs_mcv,
2218 rhs_ty,
2219 dst_reg,
2220 );
2221
2222 return .{ .register = dst_reg };
2223}
2224
2225/// Does the same thing as binOp however is meant to be used internally to the backend.
2226///
2227/// The `dst_reg` argument is meant to be caller-locked. Asserts that the binOp result can be
2228/// fit into the register.
2229///
2230/// Assumes that the `dst_reg` class is correct.
2231fn genBinOp(
2110 func: *Func,2232 func: *Func,
2111 tag: Air.Inst.Tag,2233 tag: Air.Inst.Tag,
2112 lhs: MCValue,2234 lhs_mcv: MCValue,
2113 lhs_ty: Type,2235 lhs_ty: Type,
2114 rhs: MCValue,2236 rhs_mcv: MCValue,
2115 rhs_ty: Type,2237 rhs_ty: Type,
2116) InnerError!MCValue {2238 dst_reg: Register,
2239) !void {
2117 const zcu = func.bin_file.comp.module.?;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);
21182251
2119 switch (tag) {2252 switch (tag) {
2120 // Arithmetic operations on integers and floats
2121 .add,2253 .add,
2254 .add_wrap,
2122 .sub,2255 .sub,
2256 .sub_wrap,
2123 .mul,2257 .mul,
2124 .div_float,2258 .mul_wrap,
2125 .cmp_eq,
2126 .cmp_neq,
2127 .cmp_gt,
2128 .cmp_gte,
2129 .cmp_lt,
2130 .cmp_lte,
2131 => {2259 => {
2132 assert(lhs_ty.eql(rhs_ty, zcu));2260 if (!math.isPowerOfTwo(bit_size))
2133 switch (lhs_ty.zigTypeTag(zcu)) {2261 return func.fail(
2134 .Float => {2262 "TODO: genBinOp {s} non-pow 2, found {}",
2135 const float_bits = lhs_ty.floatBits(zcu.getTarget());2263 .{ @tagName(tag), bit_size },
2136 const float_reg_bits: u32 = if (func.hasFeature(.d)) 64 else 32;2264 );
2137 if (float_bits <= float_reg_bits) {
2138 return func.binOpFloat(tag, lhs, lhs_ty, rhs, rhs_ty);
2139 } else {
2140 return func.fail("TODO: binary operations for floats with bits > {d}", .{float_reg_bits});
2141 }
2142 },
2143 .Vector => return func.fail("TODO binary operations on vectors", .{}),
2144 .Int, .Enum, .ErrorSet => {
2145 const int_info = lhs_ty.intInfo(zcu);
2146 if (int_info.bits <= 64) {
2147 return func.binOpRegister(tag, lhs, lhs_ty, rhs, rhs_ty);
2148 } else {
2149 return func.fail("TODO binary operations on int with bits > 64", .{});
2150 }
2151 },
2152 else => |x| return func.fail("TOOD: binOp {s}", .{@tagName(x)}),
2153 }
2154 },
21552265
2156 .ptr_add,
2157 .ptr_sub,
2158 => {
2159 switch (lhs_ty.zigTypeTag(zcu)) {2266 switch (lhs_ty.zigTypeTag(zcu)) {
2160 .Pointer => {2267 .Int => {
2161 const ptr_ty = lhs_ty;2268 const mir_tag: Mir.Inst.Tag = switch (tag) {
2162 const elem_ty = switch (ptr_ty.ptrSize(zcu)) {2269 .add, .add_wrap => switch (bit_size) {
2163 .One => ptr_ty.childType(zcu).childType(zcu), // ptr to array, so get array element type2270 8, 16, 64 => .add,
2164 else => ptr_ty.childType(zcu),2271 32 => .addw,
2165 };
2166 const elem_size = elem_ty.abiSize(zcu);
2167
2168 if (elem_size == 1) {
2169 const base_tag: Air.Inst.Tag = switch (tag) {
2170 .ptr_add => .add,
2171 .ptr_sub => .sub,
2172 else => unreachable,2272 else => unreachable,
2173 };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 };
21742286
2175 return try func.binOpRegister(base_tag, lhs, lhs_ty, rhs, rhs_ty);2287 _ = try func.addInst(.{
2176 } else {2288 .tag = mir_tag,
2177 const offset = try func.binOp(2289 .ops = .rrr,
2178 .mul,2290 .data = .{
2179 rhs,2291 .r_type = .{
2180 Type.usize,2292 .rd = dst_reg,
2181 .{ .immediate = elem_size },2293 .rs1 = lhs_reg,
2182 Type.usize,2294 .rs2 = rhs_reg,
2183 );2295 },
2296 },
2297 });
21842298
2185 const addr = try func.binOp(2299 // truncate when the instruction is larger than the bit size.
2186 tag,2300 switch (bit_size) {
2187 lhs,2301 8, 16 => try func.truncateRegister(lhs_ty, dst_reg),
2188 Type.manyptr_u8,2302 32 => {}, // addw/subw affects the first 32-bits
2189 offset,2303 64 => {}, // add/sub affects the entire register
2190 Type.usize,2304 else => unreachable,
2191 );
2192 return addr;
2193 }2305 }
2194 },2306 },
2195 else => unreachable,2307 .Float => {
2196 }2308 const mir_tag: Mir.Inst.Tag = switch (tag) {
2197 },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 };
21982326
2199 // These instructions have unsymteric bit sizes on RHS and LHS.2327 _ = try func.addInst(.{
2200 .shr,2328 .tag = mir_tag,
2201 .shl,2329 .ops = .rrr,
2202 => {2330 .data = .{
2203 switch (lhs_ty.zigTypeTag(zcu)) {2331 .r_type = .{
2204 .Float => return func.fail("TODO binary operations on floats", .{}),2332 .rd = dst_reg,
2205 .Vector => return func.fail("TODO binary operations on vectors", .{}),2333 .rs1 = lhs_reg,
2206 .Int => {2334 .rs2 = rhs_reg,
2207 const int_info = lhs_ty.intInfo(zcu);2335 },
2208 if (int_info.bits <= 64) {2336 },
2209 return func.binOpRegister(tag, lhs, lhs_ty, rhs, rhs_ty);2337 });
2210 } else {
2211 return func.fail("TODO binary operations on int with bits > 64", .{});
2212 }
2213 },2338 },
2214 else => unreachable,2339 else => unreachable,
2215 }2340 }
2216 },2341 },
2217 else => return func.fail("TODO binOp {}", .{tag}),
2218 }
2219}
2220
2221fn binOpRegister(
2222 func: *Func,
2223 tag: Air.Inst.Tag,
2224 lhs: MCValue,
2225 lhs_ty: Type,
2226 rhs: MCValue,
2227 rhs_ty: Type,
2228) !MCValue {
2229 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{ .zero = true });
2230 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
2231
2232 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{ .zero = true });
2233 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
22342342
2235 const dest_reg, const dest_lock = try func.allocReg(.int);2343 .ptr_add,
2236 defer func.register_manager.unlockReg(dest_lock);2344 .ptr_sub,
22372345 => {
2238 const mir_tag: Mir.Inst.Tag = switch (tag) {2346 const tmp_reg = try func.copyToTmpRegister(rhs_ty, .{ .register = rhs_reg });
2239 .add => .add,2347 const tmp_mcv = MCValue{ .register = tmp_reg };
2240 .sub => .sub,2348 const tmp_lock = func.register_manager.lockRegAssumeUnused(tmp_reg);
2241 .mul => .mul,2349 defer func.register_manager.unlockReg(tmp_lock);
22422350
2243 .shl => .sllw,2351 // RISC-V has no immediate mul, so we copy the size to a temporary register
2244 .shr => .srlw,2352 const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu);
22452353 const elem_size_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = elem_size });
2246 .cmp_eq,2354
2247 .cmp_neq,2355 try func.genBinOp(
2248 .cmp_gt,2356 .mul,
2249 .cmp_gte,2357 tmp_mcv,
2250 .cmp_lt,2358 rhs_ty,
2251 .cmp_lte,2359 .{ .register = elem_size_reg },
2252 => .pseudo,2360 Type.usize,
2361 tmp_reg,
2362 );
22532363
2254 else => return func.fail("TODO: binOpRegister {s}", .{@tagName(tag)}),2364 try func.genBinOp(
2255 };2365 switch (tag) {
2366 .ptr_add => .add,
2367 .ptr_sub => .sub,
2368 else => unreachable,
2369 },
2370 lhs_mcv,
2371 Type.usize, // we know it's a pointer, so it'll be usize.
2372 tmp_mcv,
2373 Type.usize,
2374 dst_reg,
2375 );
2376 },
22562377
2257 switch (mir_tag) {2378 .bit_and,
2258 .add,2379 .bit_or,
2259 .sub,2380 .bool_and,
2260 .mul,2381 .bool_or,
2261 .sllw,
2262 .srlw,
2263 => {2382 => {
2264 _ = try func.addInst(.{2383 _ = try func.addInst(.{
2265 .tag = mir_tag,2384 .tag = switch (tag) {
2385 .bit_and, .bool_and => .@"and",
2386 .bit_or, .bool_or => .@"or",
2387 else => unreachable,
2388 },
2266 .ops = .rrr,2389 .ops = .rrr,
2267 .data = .{2390 .data = .{
2268 .r_type = .{2391 .r_type = .{
2269 .rd = dest_reg,2392 .rd = dst_reg,
2270 .rs1 = lhs_reg,2393 .rs1 = lhs_reg,
2271 .rs2 = rhs_reg,2394 .rs2 = rhs_reg,
2272 },2395 },
2273 },2396 },
2274 });2397 });
2398
2399 switch (tag) {
2400 .bool_and,
2401 .bool_or,
2402 => try func.truncateRegister(Type.bool, dst_reg),
2403 else => {},
2404 }
2275 },2405 },
22762406
2277 .pseudo => {2407 .div_trunc,
2278 const pseudo_op = switch (tag) {2408 => {
2279 .cmp_eq,2409 if (!math.isPowerOfTwo(bit_size))
2280 .cmp_neq,2410 return func.fail(
2281 .cmp_gt,2411 "TODO: genBinOp {s} non-pow 2, found {}",
2282 .cmp_gte,2412 .{ @tagName(tag), bit_size },
2283 .cmp_lt,2413 );
2284 .cmp_lte,2414
2285 => .pseudo_compare,2415 const mir_tag: Mir.Inst.Tag = switch (tag) {
2416 .div_trunc => switch (bit_size) {
2417 8, 16, 32 => if (is_unsigned) .divuw else .divw,
2418 64 => if (is_unsigned) .divu else .div,
2419 else => unreachable,
2420 },
2286 else => unreachable,2421 else => unreachable,
2287 };2422 };
22882423
2289 _ = try func.addInst(.{2424 _ = try func.addInst(.{
2290 .tag = .pseudo,2425 .tag = mir_tag,
2291 .ops = pseudo_op,2426 .ops = .rrr,
2292 .data = .{2427 .data = .{
2293 .compare = .{2428 .r_type = .{
2294 .rd = dest_reg,2429 .rd = dst_reg,
2295 .rs1 = lhs_reg,2430 .rs1 = lhs_reg,
2296 .rs2 = rhs_reg,2431 .rs2 = rhs_reg,
2297 .op = switch (tag) {
2298 .cmp_eq => .eq,
2299 .cmp_neq => .neq,
2300 .cmp_gt => .gt,
2301 .cmp_gte => .gte,
2302 .cmp_lt => .lt,
2303 .cmp_lte => .lte,
2304 else => unreachable,
2305 },
2306 .size = func.memSize(lhs_ty),
2307 },2432 },
2308 },2433 },
2309 });2434 });
2310 },
2311
2312 else => unreachable,
2313 }
2314
2315 return MCValue{ .register = dest_reg };
2316}
2317
2318fn binOpFloat(
2319 func: *Func,
2320 tag: Air.Inst.Tag,
2321 lhs: MCValue,
2322 lhs_ty: Type,
2323 rhs: MCValue,
2324 rhs_ty: Type,
2325) !MCValue {
2326 const zcu = func.bin_file.comp.module.?;
2327 const float_bits = lhs_ty.floatBits(zcu.getTarget());
2328
2329 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{});
2330 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
2331
2332 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{});
2333 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
2334
2335 const mir_tag: Mir.Inst.Tag = switch (tag) {
2336 .add => if (float_bits == 32) .fadds else .faddd,
2337 .sub => if (float_bits == 32) .fsubs else .fsubd,
2338 .mul => if (float_bits == 32) .fmuls else .fmuld,
2339 .div_float => if (float_bits == 32) .fdivs else .fdivd,
23402435
2341 .cmp_eq,2436 if (!is_unsigned) {
2342 .cmp_neq,2437 // truncate when the instruction is larger than the bit size.
2343 .cmp_gt,2438 switch (bit_size) {
2344 .cmp_gte,2439 8, 16 => try func.truncateRegister(lhs_ty, dst_reg),
2345 .cmp_lt,2440 32 => {}, // divw affects the first 32-bits
2346 .cmp_lte,2441 64 => {}, // div affects the entire register
2347 => .pseudo,2442 else => unreachable,
23482443 }
2349 else => return func.fail("TODO: binOpFloat mir_tag {s}", .{@tagName(tag)}),2444 }
2350 };2445 },
23512446
2352 const return_class: abi.RegisterClass = switch (tag) {2447 .shr,
2353 .add,2448 .shr_exact,
2354 .sub,2449 .shl,
2355 .mul,2450 .shl_exact,
2356 .div_float,2451 => {
2357 => .float,2452 if (!math.isPowerOfTwo(bit_size))
2453 return func.fail(
2454 "TODO: genBinOp {s} non-pow 2, found {}",
2455 .{ @tagName(tag), bit_size },
2456 );
23582457
2359 .cmp_eq,2458 // it's important that the shift amount is exact
2360 .cmp_neq,2459 try func.truncateRegister(rhs_ty, rhs_reg);
2361 .cmp_gt,
2362 .cmp_gte,
2363 .cmp_lt,
2364 .cmp_lte,
2365 => .int,
2366 else => unreachable,
2367 };
23682460
2369 const dest_reg, const dest_lock = try func.allocReg(return_class);2461 const mir_tag: Mir.Inst.Tag = switch (tag) {
2370 defer func.register_manager.unlockReg(dest_lock);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 },
2472 else => unreachable,
2473 };
23712474
2372 switch (tag) {
2373 .add,
2374 .sub,
2375 .mul,
2376 .div_float,
2377 => {
2378 _ = try func.addInst(.{2475 _ = try func.addInst(.{
2379 .tag = mir_tag,2476 .tag = mir_tag,
2380 .ops = .rrr,2477 .ops = .rrr,
2381 .data = .{ .r_type = .{2478 .data = .{ .r_type = .{
2382 .rd = dest_reg,2479 .rd = dst_reg,
2383 .rs1 = lhs_reg,2480 .rs1 = lhs_reg,
2384 .rs2 = rhs_reg,2481 .rs2 = rhs_reg,
2385 } },2482 } },
2386 });2483 });
2484
2485 switch (bit_size) {
2486 8, 16 => try func.truncateRegister(lhs_ty, dst_reg),
2487 32 => {},
2488 64 => {},
2489 else => unreachable,
2490 }
2387 },2491 },
23882492
2493 // TODO: move the isel logic out of lower and into here.
2389 .cmp_eq,2494 .cmp_eq,
2390 .cmp_neq,2495 .cmp_neq,
2391 .cmp_gt,
2392 .cmp_gte,
2393 .cmp_lt,2496 .cmp_lt,
2394 .cmp_lte,2497 .cmp_lte,
2498 .cmp_gt,
2499 .cmp_gte,
2395 => {2500 => {
2396 _ = try func.addInst(.{2501 _ = try func.addInst(.{
2397 .tag = .pseudo,2502 .tag = .pseudo,
2398 .ops = .pseudo_compare,2503 .ops = .pseudo_compare,
2399 .data = .{2504 .data = .{
2400 .compare = .{2505 .compare = .{
2401 .rd = dest_reg,
2402 .rs1 = lhs_reg,
2403 .rs2 = rhs_reg,
2404 .op = switch (tag) {2506 .op = switch (tag) {
2405 .cmp_eq => .eq,2507 .cmp_eq => .eq,
2406 .cmp_neq => .neq,2508 .cmp_neq => .neq,
2407 .cmp_gt => .gt,
2408 .cmp_gte => .gte,
2409 .cmp_lt => .lt,2509 .cmp_lt => .lt,
2410 .cmp_lte => .lte,2510 .cmp_lte => .lte,
2511 .cmp_gt => .gt,
2512 .cmp_gte => .gte,
2411 else => unreachable,2513 else => unreachable,
2412 },2514 },
2413 .size = func.memSize(lhs_ty),2515 .rd = dst_reg,
2516 .rs1 = lhs_reg,
2517 .rs2 = rhs_reg,
2518 .ty = lhs_ty,
2414 },2519 },
2415 },2520 },
2416 });2521 });
2417 },2522 },
24182523
2419 else => unreachable,2524 // A branchless @min/@max sequence.
2420 }2525 //
24212526 // Assume that a0 and a1 are the lhs and rhs respectively.
2422 return MCValue{ .register = dest_reg };2527 // Also assume that a2 is the destination register.
2423}2528 //
24242529 // Algorithm:
2425fn airPtrArithmetic(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {2530 // slt s0, a0, a1
2426 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2531 // sub s0, zero, s0
2427 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;2532 // xor a2, a0, a1
2428 const lhs = try func.resolveInst(bin_op.lhs);2533 // and s0, a2, s0
2429 const rhs = try func.resolveInst(bin_op.rhs);2534 // xor a2, a0, s0 # a0 is @min, a1 is @max
2430 const lhs_ty = func.typeOf(bin_op.lhs);2535 //
2431 const rhs_ty = func.typeOf(bin_op.rhs);2536 // "slt s0, a0, a1" will set s0 to 1 if a0 is less than a1, and 1 otherwise.
24322537 //
2433 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {2538 // "sub s0, zero, s0" will set all the bits of s0 to 1 if it was 1, otherwise it'll remain at 0.
2434 break :result try func.binOp(tag, lhs, lhs_ty, rhs, rhs_ty);2539 //
2435 };2540 // "xor a2, a0, a1" stores the bitwise XOR of a0 and a1 in a2. Effectively getting the difference between them.
2436 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2541 //
2437}2542 // "and a0, a2, s0" here we mask the result of the XOR with the negated s0. If a0 < a1, s0 is -1, which
24382543 // doesn't change the bits of a2. If a0 >= a1, s0 is 0, nullifying a2.
2439fn airAddWrap(func: *Func, inst: Air.Inst.Index) !void {2544 //
2440 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2545 // "xor a2, a0, s0" the final XOR operation adjusts a2 to be the minimum value of a0 and a1. If a0 was less than
2441 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement addwrap for {}", .{func.target.cpu.arch});2546 // a1, s0 was -1, flipping all the bits in a2 and effectively restoring a0. If a0 was greater than or equal to a1,
2442 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2547 // s0 was 0, leaving a2 unchanged as a0.
2443}2548 .min, .max => {
24442549 const int_info = lhs_ty.intInfo(zcu);
2445fn airAddSat(func: *Func, inst: Air.Inst.Index) !void {2550
2446 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2551 const mask_reg, const mask_lock = try func.allocReg(.int);
2447 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement add_sat for {}", .{func.target.cpu.arch});2552 defer func.register_manager.unlockReg(mask_lock);
2448 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2449}
2450
2451fn airSubWrap(func: *Func, inst: Air.Inst.Index) !void {
2452 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2453 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2454 // RISCV arthemtic instructions already wrap, so this is simply a sub binOp with
2455 // no overflow checks.
2456 const lhs = try func.resolveInst(bin_op.lhs);
2457 const rhs = try func.resolveInst(bin_op.rhs);
2458 const lhs_ty = func.typeOf(bin_op.lhs);
2459 const rhs_ty = func.typeOf(bin_op.rhs);
2460
2461 break :result try func.binOp(.sub, lhs, lhs_ty, rhs, rhs_ty);
2462 };
2463 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2464}
2465
2466fn airSubSat(func: *Func, inst: Air.Inst.Index) !void {
2467 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2468 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement sub_sat for {}", .{func.target.cpu.arch});
2469 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2470}
24712553
2472fn airMul(func: *Func, inst: Air.Inst.Index) !void {2554 _ = try func.addInst(.{
2473 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2555 .tag = if (int_info.signedness == .unsigned) .sltu else .slt,
2474 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {2556 .ops = .rrr,
2475 const lhs = try func.resolveInst(bin_op.lhs);2557 .data = .{ .r_type = .{
2476 const rhs = try func.resolveInst(bin_op.rhs);2558 .rd = mask_reg,
2477 const lhs_ty = func.typeOf(bin_op.lhs);2559 .rs1 = lhs_reg,
2478 const rhs_ty = func.typeOf(bin_op.rhs);2560 .rs2 = rhs_reg,
24792561 } },
2480 break :result try func.binOp(.mul, lhs, lhs_ty, rhs, rhs_ty);2562 });
2481 };
2482 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2483}
24842563
2485fn airDiv(func: *Func, inst: Air.Inst.Index) !void {2564 _ = try func.addInst(.{
2486 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2565 .tag = .sub,
2487 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {2566 .ops = .rrr,
2488 const lhs = try func.resolveInst(bin_op.lhs);2567 .data = .{ .r_type = .{
2489 const rhs = try func.resolveInst(bin_op.rhs);2568 .rd = mask_reg,
2490 const lhs_ty = func.typeOf(bin_op.lhs);2569 .rs1 = .zero,
2491 const rhs_ty = func.typeOf(bin_op.rhs);2570 .rs2 = mask_reg,
2571 } },
2572 });
24922573
2493 break :result try func.binOp(.div_float, lhs, lhs_ty, rhs, rhs_ty);2574 _ = try func.addInst(.{
2494 };2575 .tag = .xor,
2495 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2576 .ops = .rrr,
2496}2577 .data = .{ .r_type = .{
2578 .rd = dst_reg,
2579 .rs1 = lhs_reg,
2580 .rs2 = rhs_reg,
2581 } },
2582 });
24972583
2498fn airMulWrap(func: *Func, inst: Air.Inst.Index) !void {2584 _ = try func.addInst(.{
2499 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2585 .tag = .@"and",
2500 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement mulwrap for {}", .{func.target.cpu.arch});2586 .ops = .rrr,
2501 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2587 .data = .{ .r_type = .{
2588 .rd = mask_reg,
2589 .rs1 = dst_reg,
2590 .rs2 = mask_reg,
2591 } },
2592 });
2593
2594 _ = try func.addInst(.{
2595 .tag = .xor,
2596 .ops = .rrr,
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 }
2502}2606}
25032607
2504fn airMulSat(func: *Func, inst: Air.Inst.Index) !void {2608fn airPtrArithmetic(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
2505 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2609 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2506 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement mul_sat for {}", .{func.target.cpu.arch});2610 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;
2507 return func.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 });
2508}2613}
25092614
2510fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {2615fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
...@@ -2513,19 +2618,16 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2513,19 +2618,16 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2513 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;2618 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
25142619
2515 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {2620 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2516 const lhs = try func.resolveInst(extra.lhs);
2517 const rhs = try func.resolveInst(extra.rhs);
2518 const lhs_ty = func.typeOf(extra.lhs);2621 const lhs_ty = func.typeOf(extra.lhs);
2519 const rhs_ty = func.typeOf(extra.rhs);
25202622
2521 const int_info = lhs_ty.intInfo(zcu);2623 const int_info = lhs_ty.intInfo(zcu);
25222624
2523 const tuple_ty = func.typeOfIndex(inst);2625 const tuple_ty = func.typeOfIndex(inst);
2524 const result_mcv = try func.allocRegOrMem(inst, false);2626 const result_mcv = try func.allocRegOrMem(tuple_ty, inst, false);
2525 const offset = result_mcv.load_frame;2627 const offset = result_mcv.load_frame;
25262628
2527 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {2629 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
2528 const add_result = try func.binOp(.add, lhs, lhs_ty, rhs, rhs_ty);2630 const add_result = try func.binOp(null, .add, extra.lhs, extra.rhs);
2529 const add_result_reg = try func.copyToTmpRegister(lhs_ty, add_result);2631 const add_result_reg = try func.copyToTmpRegister(lhs_ty, add_result);
2530 const add_result_reg_lock = func.register_manager.lockRegAssumeUnused(add_result_reg);2632 const add_result_reg_lock = func.register_manager.lockRegAssumeUnused(add_result_reg);
2531 defer func.register_manager.unlockReg(add_result_reg_lock);2633 defer func.register_manager.unlockReg(add_result_reg_lock);
...@@ -2542,7 +2644,7 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2542,7 +2644,7 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2542 .i_type = .{2644 .i_type = .{
2543 .rd = shift_reg,2645 .rd = shift_reg,
2544 .rs1 = add_result_reg,2646 .rs1 = add_result_reg,
2545 .imm12 = Immediate.s(shift_amount),2647 .imm12 = Immediate.u(shift_amount),
2546 },2648 },
2547 },2649 },
2548 });2650 });
...@@ -2554,7 +2656,7 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2554,7 +2656,7 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2554 .i_type = .{2656 .i_type = .{
2555 .rd = shift_reg,2657 .rd = shift_reg,
2556 .rs1 = shift_reg,2658 .rs1 = shift_reg,
2557 .imm12 = Immediate.s(shift_amount),2659 .imm12 = Immediate.u(shift_amount),
2558 },2660 },
2559 },2661 },
2560 });2662 });
...@@ -2566,18 +2668,23 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2566,18 +2668,23 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2566 add_result,2668 add_result,
2567 );2669 );
25682670
2569 const overflow_mcv = try func.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(
2570 .cmp_neq,2675 .cmp_neq,
2571 .{ .register = shift_reg },2676 .{ .register = shift_reg },
2572 lhs_ty,2677 lhs_ty,
2573 .{ .register = add_result_reg },2678 .{ .register = add_result_reg },
2574 lhs_ty,2679 lhs_ty,
2680 overflow_reg,
2575 );2681 );
2682
2576 try func.genSetMem(2683 try func.genSetMem(
2577 .{ .frame = offset.index },2684 .{ .frame = offset.index },
2578 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),2685 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),
2579 Type.u1,2686 Type.u1,
2580 overflow_mcv,2687 .{ .register = overflow_reg },
2581 );2688 );
25822689
2583 break :result result_mcv;2690 break :result result_mcv;
...@@ -2602,49 +2709,64 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2602,49 +2709,64 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
26022709
2603 const int_info = lhs_ty.intInfo(zcu);2710 const int_info = lhs_ty.intInfo(zcu);
26042711
2605 if (!math.isPowerOfTwo(int_info.bits) or !(int_info.bits >= 8)) {2712 if (!math.isPowerOfTwo(int_info.bits) or int_info.bits < 8) {
2606 return func.fail("TODO: airSubWithOverflow non-power of 2 and less than 8 bits", .{});2713 return func.fail("TODO: airSubWithOverflow non-power of 2 and less than 8 bits", .{});
2607 }2714 }
26082715
2716 if (int_info.bits > 64) {
2717 return func.fail("TODO: airSubWithOverflow > 64 bits", .{});
2718 }
2719
2609 const tuple_ty = func.typeOfIndex(inst);2720 const tuple_ty = func.typeOfIndex(inst);
2610 const result_mcv = try func.allocRegOrMem(inst, false);2721 const result_mcv = try func.allocRegOrMem(tuple_ty, inst, false);
2611 const offset = result_mcv.load_frame;2722 const offset = result_mcv.load_frame;
26122723
2613 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{});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);
2614 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);2736 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
26152737
2616 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{});2738 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs);
2617 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);2739 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
26182740
2619 const dest_reg, const dest_lock = try func.allocReg(.int);2741 const overflow_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = 0 });
2620 defer func.register_manager.unlockReg(dest_lock);2742
2743 const overflow_lock = func.register_manager.lockRegAssumeUnused(overflow_reg);
2744 defer func.register_manager.unlockReg(overflow_lock);
26212745
2622 switch (int_info.signedness) {2746 switch (int_info.signedness) {
2623 .unsigned => return func.fail("TODO: airSubWithOverflow unsigned", .{}),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 },
2624 .signed => {2767 .signed => {
2625 switch (int_info.bits) {2768 switch (int_info.bits) {
2626 64 => {2769 64 => {
2627 // result
2628 _ = try func.addInst(.{
2629 .tag = .sub,
2630 .ops = .rrr,
2631 .data = .{ .r_type = .{
2632 .rd = dest_reg,
2633 .rs1 = lhs_reg,
2634 .rs2 = rhs_reg,
2635 } },
2636 });
2637
2638 try func.genSetMem(
2639 .{ .frame = offset.index },
2640 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))),
2641 lhs_ty,
2642 .{ .register = dest_reg },
2643 );
2644
2645 // overflow check
2646 const overflow_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = 0 });
2647
2648 _ = try func.addInst(.{2770 _ = try func.addInst(.{
2649 .tag = .slt,2771 .tag = .slt,
2650 .ops = .rrr,2772 .ops = .rrr,
...@@ -2675,19 +2797,20 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2675,19 +2797,20 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2675 } },2797 } },
2676 });2798 });
26772799
2678 const overflow_mcv = try func.binOp(2800 try func.genBinOp(
2679 .cmp_neq,2801 .cmp_neq,
2680 .{ .register = overflow_reg },2802 .{ .register = overflow_reg },
2681 Type.usize,2803 Type.usize,
2682 .{ .register = rhs_reg },2804 .{ .register = rhs_reg },
2683 Type.usize,2805 Type.usize,
2806 overflow_reg,
2684 );2807 );
26852808
2686 try func.genSetMem(2809 try func.genSetMem(
2687 .{ .frame = offset.index },2810 .{ .frame = offset.index },
2688 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),2811 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),
2689 Type.u1,2812 Type.u1,
2690 overflow_mcv,2813 .{ .register = overflow_reg },
2691 );2814 );
26922815
2693 break :result result_mcv;2816 break :result result_mcv;
...@@ -2702,16 +2825,42 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2702,16 +2825,42 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2702}2825}
27032826
2704fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {2827fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2705 //const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];2828 const zcu = func.bin_file.comp.module.?;
2706 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2829 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2707 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;2830 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
2708 const zcu = func.bin_file.comp.module.?;2831
2709 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {2832 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2710 const lhs = try func.resolveInst(extra.lhs);2833 const lhs = try func.resolveInst(extra.lhs);
2711 const rhs = try func.resolveInst(extra.rhs);2834 const rhs = try func.resolveInst(extra.rhs);
2712 const lhs_ty = func.typeOf(extra.lhs);2835 const lhs_ty = func.typeOf(extra.lhs);
2713 const rhs_ty = func.typeOf(extra.rhs);2836 const rhs_ty = func.typeOf(extra.rhs);
27142837
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 );
2863
2715 switch (lhs_ty.zigTypeTag(zcu)) {2864 switch (lhs_ty.zigTypeTag(zcu)) {
2716 else => |x| return func.fail("TODO: airMulWithOverflow {s}", .{@tagName(x)}),2865 else => |x| return func.fail("TODO: airMulWithOverflow {s}", .{@tagName(x)}),
2717 .Int => {2866 .Int => {
...@@ -2719,74 +2868,53 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2719,74 +2868,53 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2719 const int_info = lhs_ty.intInfo(zcu);2868 const int_info = lhs_ty.intInfo(zcu);
2720 switch (int_info.bits) {2869 switch (int_info.bits) {
2721 1...32 => {2870 1...32 => {
2722 if (func.hasFeature(.m)) {2871 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
2723 const dest = try func.binOp(.mul, lhs, lhs_ty, rhs, rhs_ty);2872 if (int_info.signedness == .unsigned) {
27242873 switch (int_info.bits) {
2725 const add_result_lock = func.register_manager.lockRegAssumeUnused(dest.register);2874 1...8 => {
2726 defer func.register_manager.unlockReg(add_result_lock);2875 const max_val = std.math.pow(u16, 2, int_info.bits) - 1;
27272876
2728 const tuple_ty = func.typeOfIndex(inst);2877 const add_reg, const add_lock = try func.promoteReg(lhs_ty, lhs);
27292878 defer if (add_lock) |lock| func.register_manager.unlockReg(lock);
2730 const result_mcv = try func.allocRegOrMem(inst, true);2879
27312880 const overflow_reg, const overflow_lock = try func.allocReg(.int);
2732 const result_off: i32 = @intCast(tuple_ty.structFieldOffset(0, zcu));2881 defer func.register_manager.unlockReg(overflow_lock);
2733 const overflow_off: i32 = @intCast(tuple_ty.structFieldOffset(1, zcu));2882
27342883 _ = try func.addInst(.{
2735 try func.genCopy(2884 .tag = .andi,
2736 lhs_ty,2885 .ops = .rri,
2737 result_mcv.offset(result_off),2886 .data = .{ .i_type = .{
2738 dest,2887 .rd = overflow_reg,
2739 );2888 .rs1 = add_reg,
27402889 .imm12 = Immediate.s(max_val),
2741 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {2890 } },
2742 if (int_info.signedness == .unsigned) {2891 });
2743 switch (int_info.bits) {2892
2744 1...8 => {2893 try func.genBinOp(
2745 const max_val = std.math.pow(u16, 2, int_info.bits) - 1;2894 .cmp_neq,
27462895 .{ .register = overflow_reg },
2747 const add_reg, const add_lock = try func.promoteReg(lhs_ty, lhs, .{});2896 lhs_ty,
2748 defer if (add_lock) |lock| func.register_manager.unlockReg(lock);2897 .{ .register = add_reg },
27492898 lhs_ty,
2750 const overflow_reg, const overflow_lock = try func.allocReg(.int);2899 overflow_reg,
2751 defer func.register_manager.unlockReg(overflow_lock);2900 );
27522901
2753 _ = try func.addInst(.{2902 try func.genCopy(
2754 .tag = .andi,2903 lhs_ty,
2755 .ops = .rri,2904 result_mcv.offset(overflow_off),
2756 .data = .{ .i_type = .{2905 .{ .register = overflow_reg },
2757 .rd = overflow_reg,2906 );
2758 .rs1 = add_reg,2907
2759 .imm12 = Immediate.s(max_val),2908 break :result result_mcv;
2760 } },2909 },
2761 });2910
27622911 else => return func.fail("TODO: airMulWithOverflow check for size {d}", .{int_info.bits}),
2763 const overflow_mcv = try func.binOp(
2764 .cmp_neq,
2765 .{ .register = overflow_reg },
2766 lhs_ty,
2767 .{ .register = add_reg },
2768 lhs_ty,
2769 );
2770
2771 try func.genCopy(
2772 lhs_ty,
2773 result_mcv.offset(overflow_off),
2774 overflow_mcv,
2775 );
2776
2777 break :result result_mcv;
2778 },
2779
2780 else => return func.fail("TODO: airMulWithOverflow check for size {d}", .{int_info.bits}),
2781 }
2782 } else {
2783 return func.fail("TODO: airMulWithOverflow calculate carry for signed addition", .{});
2784 }2912 }
2785 } else {2913 } else {
2786 return func.fail("TODO: airMulWithOverflow with < 8 bits or non-pow of 2", .{});2914 return func.fail("TODO: airMulWithOverflow calculate carry for signed addition", .{});
2787 }2915 }
2788 } else {2916 } else {
2789 return func.fail("TODO: emulate mul for targets without M feature", .{});2917 return func.fail("TODO: airMulWithOverflow with < 8 bits or non-pow of 2", .{});
2790 }2918 }
2791 },2919 },
2792 else => return func.fail("TODO: airMulWithOverflow larger than 32-bit mul", .{}),2920 else => return func.fail("TODO: airMulWithOverflow larger than 32-bit mul", .{}),
...@@ -2799,123 +2927,32 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2799,123 +2927,32 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2799}2927}
28002928
2801fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void {2929fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2802 _ = inst;
2803 return func.fail("TODO implement airShlWithOverflow for {}", .{func.target.cpu.arch});
2804}
2805
2806fn airRem(func: *Func, inst: Air.Inst.Index) !void {
2807 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2808 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement rem for {}", .{func.target.cpu.arch});
2809 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2810}
2811
2812fn airMod(func: *Func, inst: Air.Inst.Index) !void {
2813 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2814 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement zcu for {}", .{func.target.cpu.arch});
2815 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2816}
2817
2818fn airBitAnd(func: *Func, inst: Air.Inst.Index) !void {
2819 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2930 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2820 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {2931 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShlWithOverflow", .{});
2821 const lhs = try func.resolveInst(bin_op.lhs);
2822 const rhs = try func.resolveInst(bin_op.rhs);
2823
2824 const lhs_ty = func.typeOf(bin_op.lhs);
2825 const rhs_ty = func.typeOf(bin_op.rhs);
2826
2827 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{});
2828 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
2829
2830 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{});
2831 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
2832
2833 const dest_reg, const dest_lock = try func.allocReg(.int);
2834 defer func.register_manager.unlockReg(dest_lock);
2835
2836 _ = try func.addInst(.{
2837 .tag = .@"and",
2838 .ops = .rrr,
2839 .data = .{ .r_type = .{
2840 .rd = dest_reg,
2841 .rs1 = lhs_reg,
2842 .rs2 = rhs_reg,
2843 } },
2844 });
2845
2846 break :result .{ .register = dest_reg };
2847 };
2848 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2932 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2849}2933}
28502934
2851fn airBitOr(func: *Func, inst: Air.Inst.Index) !void {2935fn airAddSat(func: *Func, inst: Air.Inst.Index) !void {
2852 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2936 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2853 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {2937 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airAddSat", .{});
2854 const lhs = try func.resolveInst(bin_op.lhs);
2855 const rhs = try func.resolveInst(bin_op.rhs);
2856
2857 const lhs_ty = func.typeOf(bin_op.lhs);
2858 const rhs_ty = func.typeOf(bin_op.rhs);
2859
2860 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{});
2861 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
2862
2863 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{});
2864 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
2865
2866 const dest_reg, const dest_lock = try func.allocReg(.int);
2867 defer func.register_manager.unlockReg(dest_lock);
2868
2869 _ = try func.addInst(.{
2870 .tag = .@"or",
2871 .ops = .rrr,
2872 .data = .{ .r_type = .{
2873 .rd = dest_reg,
2874 .rs1 = lhs_reg,
2875 .rs2 = rhs_reg,
2876 } },
2877 });
2878
2879 break :result .{ .register = dest_reg };
2880 };
2881 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2938 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2882}2939}
28832940
2884fn airXor(func: *Func, inst: Air.Inst.Index) !void {2941fn airSubSat(func: *Func, inst: Air.Inst.Index) !void {
2885 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2942 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2886 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement xor for {}", .{func.target.cpu.arch});2943 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airSubSat", .{});
2887 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2944 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2888}2945}
28892946
2890fn airShl(func: *Func, inst: Air.Inst.Index) !void {2947fn airMulSat(func: *Func, inst: Air.Inst.Index) !void {
2891 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2948 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2892 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {2949 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airMulSat", .{});
2893 const lhs = try func.resolveInst(bin_op.lhs);
2894 const rhs = try func.resolveInst(bin_op.rhs);
2895 const lhs_ty = func.typeOf(bin_op.lhs);
2896 const rhs_ty = func.typeOf(bin_op.rhs);
2897
2898 break :result try func.binOp(.shl, lhs, lhs_ty, rhs, rhs_ty);
2899 };
2900 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2950 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2901}2951}
29022952
2903fn airShlSat(func: *Func, inst: Air.Inst.Index) !void {2953fn airShlSat(func: *Func, inst: Air.Inst.Index) !void {
2904 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2954 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2905 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement shl_sat for {}", .{func.target.cpu.arch});2955 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShlSat", .{});
2906 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2907}
2908
2909fn airShr(func: *Func, inst: Air.Inst.Index) !void {
2910 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2911 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2912 const lhs = try func.resolveInst(bin_op.lhs);
2913 const rhs = try func.resolveInst(bin_op.rhs);
2914 const lhs_ty = func.typeOf(bin_op.lhs);
2915 const rhs_ty = func.typeOf(bin_op.rhs);
2916
2917 break :result try func.binOp(.shr, lhs, lhs_ty, rhs, rhs_ty);
2918 };
2919 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2956 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2920}2957}
29212958
...@@ -2935,7 +2972,7 @@ fn airOptionalPayload(func: *Func, inst: Air.Inst.Index) !void {...@@ -2935,7 +2972,7 @@ fn airOptionalPayload(func: *Func, inst: Air.Inst.Index) !void {
2935 break :result opt_mcv;2972 break :result opt_mcv;
2936 }2973 }
29372974
2938 const pl_mcv = try func.allocRegOrMem(inst, true);2975 const pl_mcv = try func.allocRegOrMem(pl_ty, inst, true);
2939 try func.genCopy(pl_ty, pl_mcv, opt_mcv);2976 try func.genCopy(pl_ty, pl_mcv, opt_mcv);
2940 break :result pl_mcv;2977 break :result pl_mcv;
2941 };2978 };
...@@ -2978,15 +3015,15 @@ fn airUnwrapErrErr(func: *Func, inst: Air.Inst.Index) !void {...@@ -2978,15 +3015,15 @@ fn airUnwrapErrErr(func: *Func, inst: Air.Inst.Index) !void {
2978 const eu_lock = func.register_manager.lockReg(reg);3015 const eu_lock = func.register_manager.lockReg(reg);
2979 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);3016 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);
29803017
2981 var result = try func.copyToNewRegister(inst, operand);3018 const result = try func.copyToNewRegister(inst, operand);
2982
2983 if (err_off > 0) {3019 if (err_off > 0) {
2984 result = try func.binOp(3020 try func.genBinOp(
2985 .shr,3021 .shr,
2986 result,3022 result,
2987 err_union_ty,3023 err_union_ty,
2988 .{ .immediate = @as(u6, @intCast(err_off * 8)) },3024 .{ .immediate = @as(u6, @intCast(err_off * 8)) },
2989 Type.u8,3025 Type.u8,
3026 result.register,
2990 );3027 );
2991 }3028 }
2992 break :result result;3029 break :result result;
...@@ -3031,19 +3068,18 @@ fn genUnwrapErrUnionPayloadMir(...@@ -3031,19 +3068,18 @@ fn genUnwrapErrUnionPayloadMir(
3031 const eu_lock = func.register_manager.lockReg(reg);3068 const eu_lock = func.register_manager.lockReg(reg);
3032 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);3069 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);
30333070
3034 var result: MCValue = .{ .register = try func.copyToTmpRegister(err_union_ty, err_union) };3071 const result_reg = try func.copyToTmpRegister(err_union_ty, err_union);
3035
3036 if (payload_off > 0) {3072 if (payload_off > 0) {
3037 result = try func.binOp(3073 try func.genBinOp(
3038 .shr,3074 .shr,
3039 result,3075 .{ .register = result_reg },
3040 err_union_ty,3076 err_union_ty,
3041 .{ .immediate = @as(u6, @intCast(payload_off * 8)) },3077 .{ .immediate = @as(u6, @intCast(payload_off * 8)) },
3042 Type.u8,3078 Type.u8,
3079 result_reg,
3043 );3080 );
3044 }3081 }
30453082 break :result .{ .register = result_reg };
3046 break :result result;
3047 },3083 },
3048 else => return func.fail("TODO implement genUnwrapErrUnionPayloadMir for {}", .{err_union}),3084 else => return func.fail("TODO implement genUnwrapErrUnionPayloadMir for {}", .{err_union}),
3049 }3085 }
...@@ -3108,7 +3144,7 @@ fn airWrapOptional(func: *Func, inst: Air.Inst.Index) !void {...@@ -3108,7 +3144,7 @@ fn airWrapOptional(func: *Func, inst: Air.Inst.Index) !void {
3108 };3144 };
3109 defer if (pl_lock) |lock| func.register_manager.unlockReg(lock);3145 defer if (pl_lock) |lock| func.register_manager.unlockReg(lock);
31103146
3111 const opt_mcv = try func.allocRegOrMem(inst, true);3147 const opt_mcv = try func.allocRegOrMem(opt_ty, inst, true);
3112 try func.genCopy(pl_ty, opt_mcv, pl_mcv);3148 try func.genCopy(pl_ty, opt_mcv, pl_mcv);
31133149
3114 if (!same_repr) {3150 if (!same_repr) {
...@@ -3237,7 +3273,7 @@ fn airSlicePtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -3237,7 +3273,7 @@ fn airSlicePtr(func: *Func, inst: Air.Inst.Index) !void {
3237 const src_mcv = try func.resolveInst(ty_op.operand);3273 const src_mcv = try func.resolveInst(ty_op.operand);
3238 if (func.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;
32393275
3240 const dst_mcv = try func.allocRegOrMem(inst, true);3276 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
3241 const dst_ty = func.typeOfIndex(inst);3277 const dst_ty = func.typeOfIndex(inst);
3242 try func.genCopy(dst_ty, dst_mcv, src_mcv);3278 try func.genCopy(dst_ty, dst_mcv, src_mcv);
3243 break :result dst_mcv;3279 break :result dst_mcv;
...@@ -3249,6 +3285,8 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {...@@ -3249,6 +3285,8 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
3249 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3285 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3250 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {3286 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3251 const src_mcv = try func.resolveInst(ty_op.operand);3287 const src_mcv = try func.resolveInst(ty_op.operand);
3288 const ty = func.typeOfIndex(inst);
3289
3252 switch (src_mcv) {3290 switch (src_mcv) {
3253 .load_frame => |frame_addr| {3291 .load_frame => |frame_addr| {
3254 const len_mcv: MCValue = .{ .load_frame = .{3292 const len_mcv: MCValue = .{ .load_frame = .{
...@@ -3257,7 +3295,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {...@@ -3257,7 +3295,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
3257 } };3295 } };
3258 if (func.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;
32593297
3260 const dst_mcv = try func.allocRegOrMem(inst, true);3298 const dst_mcv = try func.allocRegOrMem(ty, inst, true);
3261 try func.genCopy(Type.usize, dst_mcv, len_mcv);3299 try func.genCopy(Type.usize, dst_mcv, len_mcv);
3262 break :result dst_mcv;3300 break :result dst_mcv;
3263 },3301 },
...@@ -3266,7 +3304,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {...@@ -3266,7 +3304,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
32663304
3267 if (func.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;
32683306
3269 const dst_mcv = try func.allocRegOrMem(inst, true);3307 const dst_mcv = try func.allocRegOrMem(ty, inst, true);
3270 try func.genCopy(Type.usize, dst_mcv, len_mcv);3308 try func.genCopy(Type.usize, dst_mcv, len_mcv);
3271 break :result dst_mcv;3309 break :result dst_mcv;
3272 },3310 },
...@@ -3289,41 +3327,19 @@ fn airPtrSlicePtrPtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -3289,41 +3327,19 @@ fn airPtrSlicePtrPtr(func: *Func, inst: Air.Inst.Index) !void {
3289}3327}
32903328
3291fn airSliceElemVal(func: *Func, inst: Air.Inst.Index) !void {3329fn airSliceElemVal(func: *Func, inst: Air.Inst.Index) !void {
3292 const zcu = func.bin_file.comp.module.?;3330 const mod = func.bin_file.comp.module.?;
3293 const is_volatile = false; // TODO
3294 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3331 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
32953332
3296 if (!is_volatile and func.liveness.isUnused(inst)) return func.finishAir(
3297 inst,
3298 .unreach,
3299 .{ bin_op.lhs, bin_op.rhs, .none },
3300 );
3301 const result: MCValue = result: {3333 const result: MCValue = result: {
3302 const slice_mcv = try func.resolveInst(bin_op.lhs);3334 const elem_ty = func.typeOfIndex(inst);
3303 const index_mcv = try func.resolveInst(bin_op.rhs);3335 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
33043336
3305 const slice_ty = func.typeOf(bin_op.lhs);3337 const slice_ty = func.typeOf(bin_op.lhs);
33063338 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
3307 const slice_ptr_field_type = slice_ty.slicePtrFieldType(zcu);3339 const elem_ptr = try func.genSliceElemPtr(bin_op.lhs, bin_op.rhs);
33083340 const dst_mcv = try func.allocRegOrMem(elem_ty, inst, false);
3309 const index_lock: ?RegisterLock = if (index_mcv == .register)3341 try func.load(dst_mcv, elem_ptr, slice_ptr_field_type);
3310 func.register_manager.lockRegAssumeUnused(index_mcv.register)3342 break :result dst_mcv;
3311 else
3312 null;
3313 defer if (index_lock) |reg| func.register_manager.unlockReg(reg);
3314
3315 const base_mcv: MCValue = switch (slice_mcv) {
3316 .load_frame,
3317 .load_symbol,
3318 => .{ .register = try func.copyToTmpRegister(slice_ptr_field_type, slice_mcv) },
3319 else => return func.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}),
3320 };
3321
3322 const dest = try func.allocRegOrMem(inst, true);
3323 const addr = try func.binOp(.ptr_add, base_mcv, slice_ptr_field_type, index_mcv, Type.usize);
3324 try func.load(dest, addr, slice_ptr_field_type);
3325
3326 break :result dest;
3327 };3343 };
3328 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3344 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3329}3345}
...@@ -3331,14 +3347,58 @@ fn airSliceElemVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -3331,14 +3347,58 @@ fn airSliceElemVal(func: *Func, inst: Air.Inst.Index) !void {
3331fn airSliceElemPtr(func: *Func, inst: Air.Inst.Index) !void {3347fn airSliceElemPtr(func: *Func, inst: Air.Inst.Index) !void {
3332 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3348 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
3333 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;3349 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
3334 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement slice_elem_ptr for {}", .{func.target.cpu.arch});3350 const dst_mcv = try func.genSliceElemPtr(extra.lhs, extra.rhs);
3335 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });3351 return func.finishAir(inst, dst_mcv, .{ extra.lhs, extra.rhs, .none });
3352}
3353
3354fn genSliceElemPtr(func: *Func, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
3355 const zcu = func.bin_file.comp.module.?;
3356 const slice_ty = func.typeOf(lhs);
3357 const slice_mcv = try func.resolveInst(lhs);
3358 const slice_mcv_lock: ?RegisterLock = switch (slice_mcv) {
3359 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
3360 else => null,
3361 };
3362 defer if (slice_mcv_lock) |lock| func.register_manager.unlockReg(lock);
3363
3364 const elem_ty = slice_ty.childType(zcu);
3365 const elem_size = elem_ty.abiSize(zcu);
3366
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,
3372 };
3373 defer if (index_mcv_lock) |lock| func.register_manager.unlockReg(lock);
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 });
3392
3393 return .{ .register = addr_reg };
3336}3394}
33373395
3338fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {3396fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
3339 const zcu = func.bin_file.comp.module.?;3397 const zcu = func.bin_file.comp.module.?;
3340 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3398 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3341 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {3399 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3400 const result_ty = func.typeOfIndex(inst);
3401
3342 const array_ty = func.typeOf(bin_op.lhs);3402 const array_ty = func.typeOf(bin_op.lhs);
3343 const array_mcv = try func.resolveInst(bin_op.lhs);3403 const array_mcv = try func.resolveInst(bin_op.lhs);
33443404
...@@ -3367,7 +3427,7 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -3367,7 +3427,7 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
3367 const offset_lock = func.register_manager.lockRegAssumeUnused(offset_reg);3427 const offset_lock = func.register_manager.lockRegAssumeUnused(offset_reg);
3368 defer func.register_manager.unlockReg(offset_lock);3428 defer func.register_manager.unlockReg(offset_lock);
33693429
3370 const dst_mcv = try func.allocRegOrMem(inst, false);3430 const dst_mcv = try func.allocRegOrMem(result_ty, inst, false);
3371 _ = try func.addInst(.{3431 _ = try func.addInst(.{
3372 .tag = .add,3432 .tag = .add,
3373 .ops = .rrr,3433 .ops = .rrr,
...@@ -3427,7 +3487,19 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -3427,7 +3487,19 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {
3427 const offset_reg_lock = func.register_manager.lockRegAssumeUnused(offset_reg);3487 const offset_reg_lock = func.register_manager.lockRegAssumeUnused(offset_reg);
3428 defer func.register_manager.unlockReg(offset_reg_lock);3488 defer func.register_manager.unlockReg(offset_reg_lock);
34293489
3430 break :result try func.binOp(.ptr_add, base_ptr_mcv, base_ptr_ty, .{ .register = offset_reg }, base_ptr_ty);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 );
3501
3502 break :result MCValue{ .register = result_reg };
3431 };3503 };
3432 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });3504 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
3433}3505}
...@@ -3487,7 +3559,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {...@@ -3487,7 +3559,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
3487 .data = .{ .i_type = .{3559 .data = .{ .i_type = .{
3488 .rd = temp_reg,3560 .rd = temp_reg,
3489 .rs1 = operand_reg,3561 .rs1 = operand_reg,
3490 .imm12 = Immediate.s(63),3562 .imm12 = Immediate.u(63),
3491 } },3563 } },
3492 });3564 });
34933565
...@@ -3695,7 +3767,7 @@ fn airLoad(func: *Func, inst: Air.Inst.Index) !void {...@@ -3695,7 +3767,7 @@ fn airLoad(func: *Func, inst: Air.Inst.Index) !void {
3695 // 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.
3696 break :blk ptr;3768 break :blk ptr;
3697 } else {3769 } else {
3698 break :blk try func.allocRegOrMem(inst, true);3770 break :blk try func.allocRegOrMem(elem_ty, inst, true);
3699 }3771 }
3700 };3772 };
37013773
...@@ -3876,7 +3948,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -3876,7 +3948,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
3876 .tag = .srli,3948 .tag = .srli,
3877 .ops = .rri,3949 .ops = .rri,
3878 .data = .{ .i_type = .{3950 .data = .{ .i_type = .{
3879 .imm12 = Immediate.s(@intCast(field_off)),3951 .imm12 = Immediate.u(@intCast(field_off)),
3880 .rd = dst_reg,3952 .rd = dst_reg,
3881 .rs1 = dst_reg,3953 .rs1 = dst_reg,
3882 } },3954 } },
...@@ -3911,7 +3983,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -3911,7 +3983,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
3911 func.reuseOperand(inst, operand, 0, src_mcv))3983 func.reuseOperand(inst, operand, 0, src_mcv))
3912 off_mcv3984 off_mcv
3913 else dst: {3985 else dst: {
3914 const dst_mcv = try func.allocRegOrMem(inst, true);3986 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
3915 try func.genCopy(field_ty, dst_mcv, off_mcv);3987 try func.genCopy(field_ty, dst_mcv, off_mcv);
3916 break :dst dst_mcv;3988 break :dst dst_mcv;
3917 };3989 };
...@@ -3972,7 +4044,7 @@ fn airArg(func: *Func, inst: Air.Inst.Index) !void {...@@ -3972,7 +4044,7 @@ fn airArg(func: *Func, inst: Air.Inst.Index) !void {
3972 const src_mcv = func.args[arg_index];4044 const src_mcv = func.args[arg_index];
3973 const arg_ty = func.typeOfIndex(inst);4045 const arg_ty = func.typeOfIndex(inst);
39744046
3975 const dst_mcv = try func.allocRegOrMem(inst, false);4047 const dst_mcv = try func.allocRegOrMem(arg_ty, inst, false);
39764048
3977 log.debug("airArg {} -> {}", .{ src_mcv, dst_mcv });4049 log.debug("airArg {} -> {}", .{ src_mcv, dst_mcv });
39784050
...@@ -4004,13 +4076,13 @@ fn airBreakpoint(func: *Func) !void {...@@ -4004,13 +4076,13 @@ fn airBreakpoint(func: *Func) !void {
4004}4076}
40054077
4006fn airRetAddr(func: *Func, inst: Air.Inst.Index) !void {4078fn airRetAddr(func: *Func, inst: Air.Inst.Index) !void {
4007 const dst_mcv = try func.allocRegOrMem(inst, true);4079 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
4008 try func.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } });4080 try func.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } });
4009 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });4081 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
4010}4082}
40114083
4012fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void {4084fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void {
4013 const dst_mcv = try func.allocRegOrMem(inst, true);4085 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
4014 try func.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } });4086 try func.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } });
4015 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });4087 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
4016}4088}
...@@ -4196,10 +4268,7 @@ fn genCall(...@@ -4196,10 +4268,7 @@ fn genCall(
4196 if (func.mod.pic) {4268 if (func.mod.pic) {
4197 return func.fail("TODO: genCall pic", .{});4269 return func.fail("TODO: genCall pic", .{});
4198 } else {4270 } else {
4199 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);4271 try func.genSetReg(Type.usize, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } });
4200 const got_addr = sym.zigGotAddress(elf_file);
4201 try func.genSetReg(Type.usize, .ra, .{ .memory = @intCast(got_addr) });
4202
4203 _ = try func.addInst(.{4272 _ = try func.addInst(.{
4204 .tag = .jalr,4273 .tag = .jalr,
4205 .ops = .rri,4274 .ops = .rri,
...@@ -4323,14 +4392,11 @@ fn airRetLoad(func: *Func, inst: Air.Inst.Index) !void {...@@ -4323,14 +4392,11 @@ fn airRetLoad(func: *Func, inst: Air.Inst.Index) !void {
4323 try func.exitlude_jump_relocs.append(func.gpa, index);4392 try func.exitlude_jump_relocs.append(func.gpa, index);
4324}4393}
43254394
4326fn airCmp(func: *Func, inst: Air.Inst.Index) !void {4395fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
4327 const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];
4328 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;4396 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
4329 const zcu = func.bin_file.comp.module.?;4397 const zcu = func.bin_file.comp.module.?;
43304398
4331 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {4399 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4332 const lhs = try func.resolveInst(bin_op.lhs);
4333 const rhs = try func.resolveInst(bin_op.rhs);
4334 const lhs_ty = func.typeOf(bin_op.lhs);4400 const lhs_ty = func.typeOf(bin_op.lhs);
43354401
4336 switch (lhs_ty.zigTypeTag(zcu)) {4402 switch (lhs_ty.zigTypeTag(zcu)) {
...@@ -4346,7 +4412,7 @@ fn airCmp(func: *Func, inst: Air.Inst.Index) !void {...@@ -4346,7 +4412,7 @@ fn airCmp(func: *Func, inst: Air.Inst.Index) !void {
4346 .Int => lhs_ty,4412 .Int => lhs_ty,
4347 .Bool => Type.u1,4413 .Bool => Type.u1,
4348 .Pointer => Type.usize,4414 .Pointer => Type.usize,
4349 .ErrorSet => Type.u16,4415 .ErrorSet => Type.anyerror,
4350 .Optional => blk: {4416 .Optional => blk: {
4351 const payload_ty = lhs_ty.optionalChild(zcu);4417 const payload_ty = lhs_ty.optionalChild(zcu);
4352 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {4418 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
...@@ -4362,7 +4428,7 @@ fn airCmp(func: *Func, inst: Air.Inst.Index) !void {...@@ -4362,7 +4428,7 @@ fn airCmp(func: *Func, inst: Air.Inst.Index) !void {
43624428
4363 const int_info = int_ty.intInfo(zcu);4429 const int_info = int_ty.intInfo(zcu);
4364 if (int_info.bits <= 64) {4430 if (int_info.bits <= 64) {
4365 break :result try func.binOp(tag, lhs, int_ty, rhs, int_ty);4431 break :result try func.binOp(inst, tag, bin_op.lhs, bin_op.rhs);
4366 } else {4432 } else {
4367 return func.fail("TODO riscv cmp for ints > 64 bits", .{});4433 return func.fail("TODO riscv cmp for ints > 64 bits", .{});
4368 }4434 }
...@@ -4373,7 +4439,7 @@ fn airCmp(func: *Func, inst: Air.Inst.Index) !void {...@@ -4373,7 +4439,7 @@ fn airCmp(func: *Func, inst: Air.Inst.Index) !void {
4373 if (float_bits > float_reg_size) {4439 if (float_bits > float_reg_size) {
4374 return func.fail("TODO: airCmp float > 64/32 bits", .{});4440 return func.fail("TODO: airCmp float > 64/32 bits", .{});
4375 }4441 }
4376 break :result try func.binOpFloat(tag, lhs, lhs_ty, rhs, lhs_ty);4442 break :result try func.binOp(inst, tag, bin_op.lhs, bin_op.rhs);
4377 },4443 },
4378 else => unreachable,4444 else => unreachable,
4379 }4445 }
...@@ -4537,7 +4603,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -4537,7 +4603,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
4537 else4603 else
4538 .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = Type.bool };4604 .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = Type.bool };
45394605
4540 const return_mcv = try func.allocRegOrMem(inst, true);4606 const return_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
4541 assert(return_mcv == .register); // should not be larger 8 bytes4607 assert(return_mcv == .register); // should not be larger 8 bytes
4542 const return_reg = return_mcv.register;4608 const return_reg = return_mcv.register;
45434609
...@@ -4569,7 +4635,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -4569,7 +4635,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
4569 some_info.ty,4635 some_info.ty,
4570 .{ .immediate = 0 },4636 .{ .immediate = 0 },
4571 ),4637 ),
4572 .size = .byte,4638 .ty = Type.bool,
4573 },4639 },
4574 },4640 },
4575 });4641 });
...@@ -4601,7 +4667,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -4601,7 +4667,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
4601 some_info.ty,4667 some_info.ty,
4602 .{ .immediate = 0 },4668 .{ .immediate = 0 },
4603 ),4669 ),
4604 .size = .byte,4670 .ty = Type.bool,
4605 },4671 },
4606 },4672 },
4607 });4673 });
...@@ -4623,9 +4689,9 @@ fn airIsNull(func: *Func, inst: Air.Inst.Index) !void {...@@ -4623,9 +4689,9 @@ fn airIsNull(func: *Func, inst: Air.Inst.Index) !void {
4623fn airIsNullPtr(func: *Func, inst: Air.Inst.Index) !void {4689fn airIsNullPtr(func: *Func, inst: Air.Inst.Index) !void {
4624 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4690 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4625 const operand = try func.resolveInst(un_op);4691 const operand = try func.resolveInst(un_op);
4626 _ = operand; // autofix4692 _ = operand;
4627 const ty = func.typeOf(un_op);4693 const ty = func.typeOf(un_op);
4628 _ = ty; // autofix4694 _ = ty;
46294695
4630 if (true) return func.fail("TODO: airIsNullPtr", .{});4696 if (true) return func.fail("TODO: airIsNullPtr", .{});
46314697
...@@ -4656,9 +4722,9 @@ fn airIsNonNull(func: *Func, inst: Air.Inst.Index) !void {...@@ -4656,9 +4722,9 @@ fn airIsNonNull(func: *Func, inst: Air.Inst.Index) !void {
4656fn airIsNonNullPtr(func: *Func, inst: Air.Inst.Index) !void {4722fn airIsNonNullPtr(func: *Func, inst: Air.Inst.Index) !void {
4657 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4723 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4658 const operand = try func.resolveInst(un_op);4724 const operand = try func.resolveInst(un_op);
4659 _ = operand; // autofix4725 _ = operand;
4660 const ty = func.typeOf(un_op);4726 const ty = func.typeOf(un_op);
4661 _ = ty; // autofix4727 _ = ty;
46624728
4663 if (true) return func.fail("TODO: airIsNonNullPtr", .{});4729 if (true) return func.fail("TODO: airIsNonNullPtr", .{});
46644730
...@@ -4685,7 +4751,7 @@ fn airIsErrPtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -4685,7 +4751,7 @@ fn airIsErrPtr(func: *Func, inst: Air.Inst.Index) !void {
4685 // 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.
4686 break :blk operand_ptr;4752 break :blk operand_ptr;
4687 } else {4753 } else {
4688 break :blk try func.allocRegOrMem(inst, true);4754 break :blk try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
4689 }4755 }
4690 };4756 };
4691 try func.load(operand, operand_ptr, func.typeOf(un_op));4757 try func.load(operand, operand_ptr, func.typeOf(un_op));
...@@ -4701,45 +4767,44 @@ fn airIsErrPtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -4701,45 +4767,44 @@ fn airIsErrPtr(func: *Func, inst: Air.Inst.Index) !void {
4701///4767///
4702/// Result is in the return register.4768/// Result is in the return register.
4703fn isErr(func: *Func, 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 {
4770 _ = maybe_inst;
4704 const zcu = func.bin_file.comp.module.?;4771 const zcu = func.bin_file.comp.module.?;
4705 const err_ty = eu_ty.errorUnionSet(zcu);4772 const err_ty = eu_ty.errorUnionSet(zcu);
4706 if (err_ty.errorSetIsEmpty(zcu)) return MCValue{ .immediate = 0 }; // always false4773 if (err_ty.errorSetIsEmpty(zcu)) return MCValue{ .immediate = 0 }; // always false
4707
4708 _ = maybe_inst;
4709
4710 const err_off: u31 = @intCast(errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));4774 const err_off: u31 = @intCast(errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
47114775
4776 const return_reg, const return_lock = try func.allocReg(.int);
4777 defer func.register_manager.unlockReg(return_lock);
4778
4712 switch (eu_mcv) {4779 switch (eu_mcv) {
4713 .register => |reg| {4780 .register => |reg| {
4714 const eu_lock = func.register_manager.lockReg(reg);4781 const eu_lock = func.register_manager.lockReg(reg);
4715 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);4782 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);
47164783
4717 const return_reg = try func.copyToTmpRegister(eu_ty, eu_mcv);4784 try func.genCopy(eu_ty, .{ .register = return_reg }, eu_mcv);
4718 const return_lock = func.register_manager.lockRegAssumeUnused(return_reg);
4719 defer func.register_manager.unlockReg(return_lock);
4720
4721 var return_mcv: MCValue = .{ .register = return_reg };
47224785
4723 if (err_off > 0) {4786 if (err_off > 0) {
4724 return_mcv = try func.binOp(4787 try func.genBinOp(
4725 .shr,4788 .shr,
4726 return_mcv,4789 .{ .register = return_reg },
4727 eu_ty,4790 eu_ty,
4728 .{ .immediate = @as(u6, @intCast(err_off * 8)) },4791 .{ .immediate = @as(u6, @intCast(err_off * 8)) },
4729 Type.u8,4792 Type.u8,
4793 return_reg,
4730 );4794 );
4731 }4795 }
47324796
4733 return try func.binOp(4797 try func.genBinOp(
4734 .cmp_neq,4798 .cmp_neq,
4735 return_mcv,4799 .{ .register = return_reg },
4736 Type.u16,4800 Type.anyerror,
4737 .{ .immediate = 0 },4801 .{ .immediate = 0 },
4738 Type.u16,4802 Type.u8,
4803 return_reg,
4739 );4804 );
4740 },4805 },
4741 .load_frame => |frame_addr| {4806 .load_frame => |frame_addr| {
4742 return func.binOp(4807 try func.genBinOp(
4743 .cmp_neq,4808 .cmp_neq,
4744 .{ .load_frame = .{4809 .{ .load_frame = .{
4745 .index = frame_addr.index,4810 .index = frame_addr.index,
...@@ -4748,10 +4813,13 @@ fn isErr(func: *Func, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)...@@ -4748,10 +4813,13 @@ fn isErr(func: *Func, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)
4748 Type.anyerror,4813 Type.anyerror,
4749 .{ .immediate = 0 },4814 .{ .immediate = 0 },
4750 Type.anyerror,4815 Type.anyerror,
4816 return_reg,
4751 );4817 );
4752 },4818 },
4753 else => return func.fail("TODO implement isErr for {}", .{eu_mcv}),4819 else => return func.fail("TODO implement isErr for {}", .{eu_mcv}),
4754 }4820 }
4821
4822 return .{ .register = return_reg };
4755}4823}
47564824
4757fn airIsNonErr(func: *Func, inst: Air.Inst.Index) !void {4825fn airIsNonErr(func: *Func, inst: Air.Inst.Index) !void {
...@@ -4799,7 +4867,7 @@ fn airIsNonErrPtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -4799,7 +4867,7 @@ fn airIsNonErrPtr(func: *Func, inst: Air.Inst.Index) !void {
4799 // 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.
4800 break :blk operand_ptr;4868 break :blk operand_ptr;
4801 } else {4869 } else {
4802 break :blk try func.allocRegOrMem(inst, true);4870 break :blk try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
4803 }4871 }
4804 };4872 };
4805 const operand_ptr_ty = func.typeOf(un_op);4873 const operand_ptr_ty = func.typeOf(un_op);
...@@ -4916,16 +4984,18 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {...@@ -4916,16 +4984,18 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {
4916 // switch branches must be comptime-known, so this is stored in an immediate4984 // switch branches must be comptime-known, so this is stored in an immediate
4917 const item_mcv = try func.resolveInst(item);4985 const item_mcv = try func.resolveInst(item);
49184986
4919 const cmp_mcv: MCValue = try func.binOp(4987 const cmp_reg, const cmp_lock = try func.allocReg(.int);
4988 defer func.register_manager.unlockReg(cmp_lock);
4989
4990 try func.genBinOp(
4920 .cmp_neq,4991 .cmp_neq,
4921 condition,4992 condition,
4922 condition_ty,4993 condition_ty,
4923 item_mcv,4994 item_mcv,
4924 condition_ty,4995 condition_ty,
4996 cmp_reg,
4925 );4997 );
49264998
4927 const cmp_reg = try func.copyToTmpRegister(Type.bool, cmp_mcv);
4928
4929 if (!(i < relocs.len - 1)) {4999 if (!(i < relocs.len - 1)) {
4930 _ = try func.addInst(.{5000 _ = try func.addInst(.{
4931 .tag = .pseudo,5001 .tag = .pseudo,
...@@ -5019,7 +5089,7 @@ fn airBr(func: *Func, inst: Air.Inst.Index) !void {...@@ -5019,7 +5089,7 @@ fn airBr(func: *Func, inst: Air.Inst.Index) !void {
5019 break :result block_tracking.short;5089 break :result block_tracking.short;
5020 }5090 }
50215091
5022 const dst_mcv = if (first_br) try func.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: {
5023 try func.getValue(block_tracking.short, br.block_inst);5093 try func.getValue(block_tracking.short, br.block_inst);
5024 break :dst block_tracking.short;5094 break :dst block_tracking.short;
5025 };5095 };
...@@ -5063,10 +5133,10 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void {...@@ -5063,10 +5133,10 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void {
5063 const lhs_ty = Type.bool;5133 const lhs_ty = Type.bool;
5064 const rhs_ty = Type.bool;5134 const rhs_ty = Type.bool;
50655135
5066 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{});5136 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs);
5067 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);5137 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
50685138
5069 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{});5139 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs);
5070 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);5140 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
50715141
5072 const result_reg, const result_lock = try func.allocReg(.int);5142 const result_reg, const result_lock = try func.allocReg(.int);
...@@ -5262,7 +5332,7 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {...@@ -5262,7 +5332,7 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
5262 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) {
5263 .register_pair, .memory, .indirect, .load_frame => null,5333 .register_pair, .memory, .indirect, .load_frame => null,
5264 .load_symbol => src: {5334 .load_symbol => src: {
5265 const src_addr_reg, const src_addr_lock = try func.promoteReg(Type.usize, src_mcv.address(), .{});5335 const src_addr_reg, const src_addr_lock = try func.promoteReg(Type.usize, src_mcv.address());
5266 errdefer func.register_manager.unlockReg(src_addr_lock);5336 errdefer func.register_manager.unlockReg(src_addr_lock);
52675337
5268 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 };
...@@ -5557,7 +5627,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5557,7 +5627,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5557 .data = .{ .i_type = .{5627 .data = .{ .i_type = .{
5558 .rd = reg,5628 .rd = reg,
5559 .rs1 = reg,5629 .rs1 = reg,
5560 .imm12 = Immediate.s(32),5630 .imm12 = Immediate.u(32),
5561 } },5631 } },
5562 });5632 });
55635633
...@@ -5604,10 +5674,9 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5604,10 +5674,9 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5604 .m = .{5674 .m = .{
5605 .base = .{ .frame = frame.index },5675 .base = .{ .frame = frame.index },
5606 .mod = .{5676 .mod = .{
5607 .rm = .{5677 .size = func.memSize(ty),
5608 .size = func.memSize(ty),5678 .unsigned = ty.isUnsignedInt(zcu),
5609 .disp = frame.off,5679 .disp = frame.off,
5610 },
5611 },5680 },
5612 },5681 },
5613 } },5682 } },
...@@ -5622,7 +5691,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5622,7 +5691,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5622 .data = .{ .i_type = .{5691 .data = .{ .i_type = .{
5623 .rd = reg,5692 .rd = reg,
5624 .rs1 = reg,5693 .rs1 = reg,
5625 .imm12 = Immediate.s(0),5694 .imm12 = Immediate.u(0),
5626 } },5695 } },
5627 });5696 });
5628 },5697 },
...@@ -5636,19 +5705,17 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5636,19 +5705,17 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5636 .register_offset => |reg_off| .{5705 .register_offset => |reg_off| .{
5637 .base = .{ .reg = reg_off.reg },5706 .base = .{ .reg = reg_off.reg },
5638 .mod = .{5707 .mod = .{
5639 .rm = .{5708 .size = func.memSize(ty),
5640 .size = func.memSize(ty),5709 .disp = reg_off.off,
5641 .disp = reg_off.off,5710 .unsigned = false,
5642 },
5643 },5711 },
5644 },5712 },
5645 .lea_frame => |frame| .{5713 .lea_frame => |frame| .{
5646 .base = .{ .frame = frame.index },5714 .base = .{ .frame = frame.index },
5647 .mod = .{5715 .mod = .{
5648 .rm = .{5716 .size = func.memSize(ty),
5649 .size = func.memSize(ty),5717 .disp = frame.off,
5650 .disp = frame.off,5718 .unsigned = false,
5651 },
5652 },5719 },
5653 },5720 },
5654 else => unreachable,5721 else => unreachable,
...@@ -5787,9 +5854,10 @@ fn genSetMem(...@@ -5787,9 +5854,10 @@ fn genSetMem(
5787 .r = reg,5854 .r = reg,
5788 .m = .{5855 .m = .{
5789 .base = .{ .frame = frame_index },5856 .base = .{ .frame = frame_index },
5790 .mod = .{ .rm = .{5857 .mod = .{
5791 .size = Memory.Size.fromByteSize(src_size),5858 .size = Memory.Size.fromByteSize(src_size),
5792 } },5859 .unsigned = false,
5860 },
5793 },5861 },
5794 } },5862 } },
5795 });5863 });
...@@ -5802,10 +5870,11 @@ fn genSetMem(...@@ -5802,10 +5870,11 @@ fn genSetMem(
5802 .r = reg,5870 .r = reg,
5803 .m = .{5871 .m = .{
5804 .base = base,5872 .base = base,
5805 .mod = .{ .rm = .{5873 .mod = .{
5806 .size = func.memSize(ty),5874 .size = func.memSize(ty),
5807 .disp = disp,5875 .disp = disp,
5808 } },5876 .unsigned = false,
5877 },
5809 },5878 },
5810 } },5879 } },
5811 });5880 });
...@@ -5820,7 +5889,7 @@ fn genSetMem(...@@ -5820,7 +5889,7 @@ fn genSetMem(
5820 .immediate => {5889 .immediate => {
5821 // TODO: remove this lock in favor of a copyToTmpRegister when we load 64 bit immediates with5890 // TODO: remove this lock in favor of a copyToTmpRegister when we load 64 bit immediates with
5822 // a register allocation.5891 // a register allocation.
5823 const reg, const reg_lock = try func.promoteReg(ty, src_mcv, .{});5892 const reg, const reg_lock = try func.promoteReg(ty, src_mcv);
5824 defer if (reg_lock) |lock| func.register_manager.unlockReg(lock);5893 defer if (reg_lock) |lock| func.register_manager.unlockReg(lock);
58255894
5826 return func.genSetMem(base, disp, ty, .{ .register = reg });5895 return func.genSetMem(base, disp, ty, .{ .register = reg });
...@@ -5833,9 +5902,10 @@ fn airIntFromPtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -5833,9 +5902,10 @@ fn airIntFromPtr(func: *Func, inst: Air.Inst.Index) !void {
5833 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;5902 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
5834 const result = result: {5903 const result = result: {
5835 const src_mcv = try func.resolveInst(un_op);5904 const src_mcv = try func.resolveInst(un_op);
5905 const src_ty = func.typeOfIndex(inst);
5836 if (func.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;5906 if (func.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;
58375907
5838 const dst_mcv = try func.allocRegOrMem(inst, true);5908 const dst_mcv = try func.allocRegOrMem(src_ty, inst, true);
5839 const dst_ty = func.typeOfIndex(inst);5909 const dst_ty = func.typeOfIndex(inst);
5840 try func.genCopy(dst_ty, dst_mcv, src_mcv);5910 try func.genCopy(dst_ty, dst_mcv, src_mcv);
5841 break :result dst_mcv;5911 break :result dst_mcv;
...@@ -5858,7 +5928,7 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {...@@ -5858,7 +5928,7 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {
58585928
5859 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
5860 func.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: {
5861 const dst_mcv = try func.allocRegOrMem(inst, true);5931 const dst_mcv = try func.allocRegOrMem(dst_ty, inst, true);
5862 try func.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))) {
5863 .lt => dst_ty,5933 .lt => dst_ty,
5864 .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,
...@@ -6080,7 +6150,7 @@ fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {...@@ -6080,7 +6150,7 @@ fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {
6080 .tag = .slli,6150 .tag = .slli,
6081 .ops = .rri,6151 .ops = .rri,
6082 .data = .{ .i_type = .{6152 .data = .{ .i_type = .{
6083 .imm12 = Immediate.s(4),6153 .imm12 = Immediate.u(4),
6084 .rd = err_reg,6154 .rd = err_reg,
6085 .rs1 = err_reg,6155 .rs1 = err_reg,
6086 } },6156 } },
...@@ -6104,7 +6174,7 @@ fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {...@@ -6104,7 +6174,7 @@ fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {
6104 .r = start_reg,6174 .r = start_reg,
6105 .m = .{6175 .m = .{
6106 .base = .{ .reg = addr_reg },6176 .base = .{ .reg = addr_reg },
6107 .mod = .{ .off = 0 },6177 .mod = .{ .size = .dword, .unsigned = true },
6108 },6178 },
6109 },6179 },
6110 },6180 },
...@@ -6118,13 +6188,13 @@ fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {...@@ -6118,13 +6188,13 @@ fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {
6118 .r = end_reg,6188 .r = end_reg,
6119 .m = .{6189 .m = .{
6120 .base = .{ .reg = addr_reg },6190 .base = .{ .reg = addr_reg },
6121 .mod = .{ .off = 8 },6191 .mod = .{ .size = .dword, .unsigned = true },
6122 },6192 },
6123 },6193 },
6124 },6194 },
6125 });6195 });
61266196
6127 const dst_mcv = try func.allocRegOrMem(inst, false);6197 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, false);
6128 const frame = dst_mcv.load_frame;6198 const frame = dst_mcv.load_frame;
6129 try func.genSetMem(6199 try func.genSetMem(
6130 .{ .frame = frame.index },6200 .{ .frame = frame.index },
src/arch/riscv64/Encoding.zig+168-53
...@@ -4,6 +4,7 @@ data: Data,...@@ -4,6 +4,7 @@ data: Data,
4const OpCode = enum(u7) {4const OpCode = enum(u7) {
5 OP = 0b0110011,5 OP = 0b0110011,
6 OP_IMM = 0b0010011,6 OP_IMM = 0b0010011,
7 OP_IMM_32 = 0b0011011,
7 OP_32 = 0b0111011,8 OP_32 = 0b0111011,
89
9 BRANCH = 0b1100011,10 BRANCH = 0b1100011,
...@@ -41,17 +42,22 @@ const Enc = struct {...@@ -41,17 +42,22 @@ const Enc = struct {
41 funct3: u3,42 funct3: u3,
42 funct7: u7,43 funct7: u7,
43 },44 },
44 /// funct3 + offset
45 fo: struct {
46 funct3: u3,
47 offset: u12 = 0,
48 },
49 /// funct5 + rm + fmt45 /// funct5 + rm + fmt
50 fmt: struct {46 fmt: struct {
51 funct5: u5,47 funct5: u5,
52 rm: u3,48 rm: u3,
53 fmt: Fmt,49 fmt: Fmt,
54 },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 },
55 /// U-type61 /// U-type
56 none,62 none,
57 },63 },
...@@ -72,10 +78,14 @@ pub const Mnemonic = enum {...@@ -72,10 +78,14 @@ pub const Mnemonic = enum {
72 sltiu,78 sltiu,
73 xori,79 xori,
74 andi,80 andi,
81
75 slli,82 slli,
76 srli,83 srli,
77 srai,84 srai,
78 sllw,85
86 slliw,
87 srliw,
88 sraiw,
7989
80 addi,90 addi,
81 jalr,91 jalr,
...@@ -98,19 +108,48 @@ pub const Mnemonic = enum {...@@ -98,19 +108,48 @@ pub const Mnemonic = enum {
98108
99 // R Type109 // R Type
100 add,110 add,
111 addw,
112 sub,
113 subw,
101 @"and",114 @"and",
102 @"or",115 @"or",
103 sub,
104 slt,116 slt,
105 mul,
106 sltu,117 sltu,
107 xor,118 xor,
108119
120 sll,
121 srl,
122 sra,
123
124 sllw,
125 srlw,
126 sraw,
127
109 // System128 // System
110 ecall,129 ecall,
111 ebreak,130 ebreak,
112 unimp,131 unimp,
113132
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
114 // F extension (32-bit float)153 // F extension (32-bit float)
115 fadds,154 fadds,
116 fsubs,155 fsubs,
...@@ -170,19 +209,56 @@ pub const Mnemonic = enum {...@@ -170,19 +209,56 @@ pub const Mnemonic = enum {
170 .slt => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000000 } } },209 .slt => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000000 } } },
171210
172 .mul => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } },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 } } },
173225
174226
175 // OP_IMM227 // OP_IMM
176228
177 .addi => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b000 } } },229 .addi => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b000 } } },
178 .andi => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b111 } } },230 .andi => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b111 } } },
179 .xori => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b100 } } },231 .xori => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b100 } } },
180 232
181 .sltiu => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b011 } } },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
182241
183 .slli => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b001 } } },242 .slliw => .{ .opcode = .OP_IMM_32, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b001, .has_5 = false } } },
184 .srli => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b101 } } },243 .srliw => .{ .opcode = .OP_IMM_32, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b101, .has_5 = false } } },
185 .srai => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b101, .offset = 1 << 10 } } },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 } } },
186262
187263
188 // OP_FP264 // OP_FP
...@@ -226,43 +302,38 @@ pub const Mnemonic = enum {...@@ -226,43 +302,38 @@ pub const Mnemonic = enum {
226302
227 // LOAD303 // LOAD
228304
229 .lb => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b000 } } },305 .lb => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b000 } } },
230 .lh => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b001 } } },306 .lh => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b001 } } },
231 .lw => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b010 } } },307 .lw => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b010 } } },
232 .ld => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b011 } } },308 .ld => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b011 } } },
233 .lbu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b100 } } },309 .lbu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b100 } } },
234 .lhu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b101 } } },310 .lhu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b101 } } },
235 .lwu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b110 } } },311 .lwu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b110 } } },
236312
237313
238 // STORE314 // STORE
239 315
240 .sb => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b000 } } },316 .sb => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b000 } } },
241 .sh => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b001 } } },317 .sh => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b001 } } },
242 .sw => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b010 } } },318 .sw => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b010 } } },
243 .sd => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b011 } } },319 .sd => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b011 } } },
244320
245321
246 // LOAD_FP322 // LOAD_FP
247323
248 .flw => .{ .opcode = .LOAD_FP, .data = .{ .fo = .{ .funct3 = 0b010 } } },324 .flw => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },
249 .fld => .{ .opcode = .LOAD_FP, .data = .{ .fo = .{ .funct3 = 0b011 } } },325 .fld => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },
250 326
251327
252 // STORE_FP328 // STORE_FP
253329
254 .fsw => .{ .opcode = .STORE_FP, .data = .{ .fo = .{ .funct3 = 0b010 } } },330 .fsw => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },
255 .fsd => .{ .opcode = .STORE_FP, .data = .{ .fo = .{ .funct3 = 0b011 } } },331 .fsd => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },
256332
257333
258 // JALR334 // JALR
259335
260 .jalr => .{ .opcode = .JALR, .data = .{ .fo = .{ .funct3 = 0b000 } } },336 .jalr => .{ .opcode = .JALR, .data = .{ .f = .{ .funct3 = 0b000 } } },
261
262
263 // OP_32
264
265 .sllw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } },
266337
267338
268 // LUI339 // LUI
...@@ -282,18 +353,18 @@ pub const Mnemonic = enum {...@@ -282,18 +353,18 @@ pub const Mnemonic = enum {
282353
283 // BRANCH354 // BRANCH
284355
285 .beq => .{ .opcode = .BRANCH, .data = .{ .fo = .{ .funct3 = 0b000 } } },356 .beq => .{ .opcode = .BRANCH, .data = .{ .f = .{ .funct3 = 0b000 } } },
286357
287358
288 // SYSTEM359 // SYSTEM
289360
290 .ecall => .{ .opcode = .SYSTEM, .data = .{ .fo = .{ .funct3 = 0b000 } } },361 .ecall => .{ .opcode = .SYSTEM, .data = .{ .f = .{ .funct3 = 0b000 } } },
291 .ebreak => .{ .opcode = .SYSTEM, .data = .{ .fo = .{ .funct3 = 0b000 } } },362 .ebreak => .{ .opcode = .SYSTEM, .data = .{ .f = .{ .funct3 = 0b000 } } },
292 363
293364
294 // NONE365 // NONE
295 366
296 .unimp => .{ .opcode = .NONE, .data = .{ .fo = .{ .funct3 = 0b000 } } },367 .unimp => .{ .opcode = .NONE, .data = .{ .f = .{ .funct3 = 0b000 } } },
297368
298369
299 // zig fmt: on370 // zig fmt: on
...@@ -320,10 +391,15 @@ pub const InstEnc = enum {...@@ -320,10 +391,15 @@ pub const InstEnc = enum {
320 .sltiu,391 .sltiu,
321 .xori,392 .xori,
322 .andi,393 .andi,
394
323 .slli,395 .slli,
324 .srli,396 .srli,
325 .srai,397 .srai,
326398
399 .slliw,
400 .srliw,
401 .sraiw,
402
327 .ld,403 .ld,
328 .lw,404 .lw,
329 .lwu,405 .lwu,
...@@ -357,14 +433,41 @@ pub const InstEnc = enum {...@@ -357,14 +433,41 @@ pub const InstEnc = enum {
357433
358 .slt,434 .slt,
359 .sltu,435 .sltu,
436
437 .sll,
438 .srl,
439 .sra,
440
360 .sllw,441 .sllw,
361 .mul,442 .srlw,
443 .sraw,
444
445 .div,
446 .divu,
447 .divw,
448 .divuw,
449
450 .rem,
451 .remu,
452 .remw,
453 .remuw,
454
362 .xor,455 .xor,
363 .add,
364 .sub,
365 .@"and",456 .@"and",
366 .@"or",457 .@"or",
367458
459 .add,
460 .addw,
461
462 .sub,
463 .subw,
464
465 .mul,
466 .mulw,
467 .mulh,
468 .mulhu,
469 .mulhsu,
470
368 .fadds,471 .fadds,
369 .faddd,472 .faddd,
370473
...@@ -516,12 +619,12 @@ pub const Data = union(InstEnc) {...@@ -516,12 +619,12 @@ pub const Data = union(InstEnc) {
516 .imm0_11 = switch (mnem) {619 .imm0_11 = switch (mnem) {
517 .ecall => 0x000,620 .ecall => 0x000,
518 .ebreak => 0x001,621 .ebreak => 0x001,
519 .unimp => 0,622 .unimp => 0x000,
520 else => unreachable,623 else => unreachable,
521 },624 },
522625
523 .opcode = @intFromEnum(enc.opcode),626 .opcode = @intFromEnum(enc.opcode),
524 .funct3 = enc.data.fo.funct3,627 .funct3 = enc.data.f.funct3,
525 },628 },
526 };629 };
527 },630 },
...@@ -567,20 +670,32 @@ pub const Data = union(InstEnc) {...@@ -567,20 +670,32 @@ pub const Data = union(InstEnc) {
567 .imm5_11 = @truncate(umm >> 5),670 .imm5_11 = @truncate(umm >> 5),
568671
569 .opcode = @intFromEnum(enc.opcode),672 .opcode = @intFromEnum(enc.opcode),
570 .funct3 = enc.data.fo.funct3,673 .funct3 = enc.data.f.funct3,
571 },674 },
572 };675 };
573 },676 },
574 .I => {677 .I => {
575 assert(ops.len == 3);678 assert(ops.len == 3);
576 return .{679 return .{
577 .I = .{680 .I = switch (enc.data) {
578 .rd = ops[0].reg.encodeId(),681 .f => |f| .{
579 .rs1 = ops[1].reg.encodeId(),682 .rd = ops[0].reg.encodeId(),
580 .imm0_11 = ops[2].imm.asBits(u12) + enc.data.fo.offset,683 .rs1 = ops[1].reg.encodeId(),
684 .imm0_11 = ops[2].imm.asBits(u12),
581685
582 .opcode = @intFromEnum(enc.opcode),686 .opcode = @intFromEnum(enc.opcode),
583 .funct3 = enc.data.fo.funct3,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,
584 },699 },
585 };700 };
586 },701 },
...@@ -629,7 +744,7 @@ pub const Data = union(InstEnc) {...@@ -629,7 +744,7 @@ pub const Data = union(InstEnc) {
629 .imm12 = @truncate(umm >> 12),744 .imm12 = @truncate(umm >> 12),
630745
631 .opcode = @intFromEnum(enc.opcode),746 .opcode = @intFromEnum(enc.opcode),
632 .funct3 = enc.data.fo.funct3,747 .funct3 = enc.data.f.funct3,
633 },748 },
634 };749 };
635 },750 },
src/arch/riscv64/Lower.zig+26-14
...@@ -44,6 +44,8 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -44,6 +44,8 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
44 insts: []const Instruction,44 insts: []const Instruction,
45 relocs: []const Reloc,45 relocs: []const Reloc,
46} {46} {
47 const zcu = lower.bin_file.comp.module.?;
48
47 lower.result_insts = undefined;49 lower.result_insts = undefined;
48 lower.result_relocs = undefined;50 lower.result_relocs = undefined;
49 errdefer lower.result_insts = undefined;51 errdefer lower.result_insts = undefined;
...@@ -75,13 +77,14 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -75,13 +77,14 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
75 const dest_reg_class = dest_reg.class();77 const dest_reg_class = dest_reg.class();
76 const float = dest_reg_class == .float;78 const float = dest_reg_class == .float;
7779
78 const src_size = rm.m.mod.size();80 const src_size = rm.m.mod.size;
81 const unsigned = rm.m.mod.unsigned;
7982
80 const tag: Encoding.Mnemonic = if (!float)83 const tag: Encoding.Mnemonic = if (!float)
81 switch (src_size) {84 switch (src_size) {
82 .byte => .lb,85 .byte => if (unsigned) .lbu else .lb,
83 .hword => .lh,86 .hword => if (unsigned) .lhu else .lh,
84 .word => .lw,87 .word => if (unsigned) .lwu else .lw,
85 .dword => .ld,88 .dword => .ld,
86 }89 }
87 else switch (src_size) {90 else switch (src_size) {
...@@ -103,7 +106,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -103,7 +106,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
103 const float = src_reg_class == .float;106 const float = src_reg_class == .float;
104107
105 // TODO: do we actually need this? are all stores not usize?108 // TODO: do we actually need this? are all stores not usize?
106 const dest_size = rm.m.mod.size();109 const dest_size = rm.m.mod.size;
107110
108 const tag: Encoding.Mnemonic = if (!float)111 const tag: Encoding.Mnemonic = if (!float)
109 switch (dest_size) {112 switch (dest_size) {
...@@ -181,10 +184,12 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -181,10 +184,12 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
181184
182 try lower.emit(.lui, &.{185 try lower.emit(.lui, &.{
183 .{ .reg = dst_reg },186 .{ .reg = dst_reg },
184 .{ .imm = lower.reloc(.{ .load_symbol_reloc = .{187 .{ .imm = lower.reloc(.{
185 .atom_index = data.atom_index,188 .load_symbol_reloc = .{
186 .sym_index = data.sym_index,189 .atom_index = data.atom_index,
187 } }) },190 .sym_index = data.sym_index,
191 },
192 }) },
188 });193 });
189194
190 // the above reloc implies this one195 // the above reloc implies this one
...@@ -237,7 +242,14 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -237,7 +242,14 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
237 const rs2 = compare.rs2;242 const rs2 = compare.rs2;
238243
239 const class = rs1.class();244 const class = rs1.class();
240 const size = compare.size.bitSize();245 const ty = compare.ty;
246 const size = std.math.ceilPowerOfTwo(u64, ty.bitSize(zcu)) catch {
247 return lower.fail("pseudo_compare size {}", .{ty.bitSize(zcu)});
248 };
249
250 const is_unsigned = ty.isUnsignedInt(zcu);
251
252 const less_than: Encoding.Mnemonic = if (is_unsigned) .sltu else .slt;
241253
242 switch (class) {254 switch (class) {
243 .int => switch (op) {255 .int => switch (op) {
...@@ -268,14 +280,14 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -268,14 +280,14 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
268 });280 });
269 },281 },
270 .gt => {282 .gt => {
271 try lower.emit(.sltu, &.{283 try lower.emit(less_than, &.{
272 .{ .reg = rd },284 .{ .reg = rd },
273 .{ .reg = rs1 },285 .{ .reg = rs1 },
274 .{ .reg = rs2 },286 .{ .reg = rs2 },
275 });287 });
276 },288 },
277 .gte => {289 .gte => {
278 try lower.emit(.sltu, &.{290 try lower.emit(less_than, &.{
279 .{ .reg = rd },291 .{ .reg = rd },
280 .{ .reg = rs1 },292 .{ .reg = rs1 },
281 .{ .reg = rs2 },293 .{ .reg = rs2 },
...@@ -288,14 +300,14 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -288,14 +300,14 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
288 });300 });
289 },301 },
290 .lt => {302 .lt => {
291 try lower.emit(.slt, &.{303 try lower.emit(less_than, &.{
292 .{ .reg = rd },304 .{ .reg = rd },
293 .{ .reg = rs1 },305 .{ .reg = rs1 },
294 .{ .reg = rs2 },306 .{ .reg = rs2 },
295 });307 });
296 },308 },
297 .lte => {309 .lte => {
298 try lower.emit(.slt, &.{310 try lower.emit(less_than, &.{
299 .{ .reg = rd },311 .{ .reg = rd },
300 .{ .reg = rs2 },312 .{ .reg = rs2 },
301 .{ .reg = rs1 },313 .{ .reg = rs1 },
src/arch/riscv64/Mir.zig+27-2
...@@ -39,16 +39,28 @@ pub const Inst = struct {...@@ -39,16 +39,28 @@ pub const Inst = struct {
39 unimp,39 unimp,
4040
41 add,41 add,
42 addw,
42 sub,43 sub,
44 subw,
4345
44 sltu,46 sltu,
45 slt,47 slt,
4648
47 srli,
48 slli,49 slli,
50 srli,
49 srai,51 srai,
52
53 slliw,
54 srliw,
55 sraiw,
56
57 sll,
58 srl,
59 sra,
60
50 sllw,61 sllw,
51 srlw,62 srlw,
63 sraw,
5264
53 jal,65 jal,
5466
...@@ -69,6 +81,17 @@ pub const Inst = struct {...@@ -69,6 +81,17 @@ pub const Inst = struct {
6981
70 // M extension82 // M extension
71 mul,83 mul,
84 mulw,
85
86 div,
87 divu,
88 divw,
89 divuw,
90
91 rem,
92 remu,
93 remw,
94 remuw,
7295
73 // F extension (32-bit float)96 // F extension (32-bit float)
74 fadds,97 fadds,
...@@ -216,7 +239,7 @@ pub const Inst = struct {...@@ -216,7 +239,7 @@ pub const Inst = struct {
216 lt,239 lt,
217 lte,240 lte,
218 },241 },
219 size: Memory.Size,242 ty: Type,
220 },243 },
221244
222 reloc: struct {245 reloc: struct {
...@@ -408,6 +431,8 @@ pub const RegisterList = struct {...@@ -408,6 +431,8 @@ pub const RegisterList = struct {
408const Mir = @This();431const Mir = @This();
409const std = @import("std");432const std = @import("std");
410const builtin = @import("builtin");433const builtin = @import("builtin");
434const Type = @import("../../type.zig").Type;
435
411const assert = std.debug.assert;436const assert = std.debug.assert;
412437
413const bits = @import("bits.zig");438const bits = @import("bits.zig");
src/arch/riscv64/bits.zig+5-35
...@@ -19,19 +19,10 @@ pub const Memory = struct {...@@ -19,19 +19,10 @@ pub const Memory = struct {
19 reloc: Symbol,19 reloc: Symbol,
20 };20 };
2121
22 pub const Mod = union(enum(u1)) {22 pub const Mod = struct {
23 rm: struct {23 size: Size,
24 size: Size,24 unsigned: bool,
25 disp: i32 = 0,25 disp: i32 = 0,
26 },
27 off: i32,
28
29 pub fn size(mod: Mod) Size {
30 return switch (mod) {
31 .rm => |rm| rm.size,
32 .off => Size.dword, // assumed to be a register size
33 };
34 }
35 };26 };
3627
37 pub const Size = enum(u4) {28 pub const Size = enum(u4) {
...@@ -76,10 +67,7 @@ pub const Memory = struct {...@@ -76,10 +67,7 @@ pub const Memory = struct {
7667
77 /// Asserts `mem` can be represented as a `FrameLoc`.68 /// Asserts `mem` can be represented as a `FrameLoc`.
78 pub fn toFrameLoc(mem: Memory, mir: Mir) Mir.FrameLoc {69 pub fn toFrameLoc(mem: Memory, mir: Mir) Mir.FrameLoc {
79 const offset: i32 = switch (mem.mod) {70 const offset: i32 = mem.mod.disp;
80 .off => |off| off,
81 .rm => |rm| rm.disp,
82 };
8371
84 switch (mem.base) {72 switch (mem.base) {
85 .reg => |reg| {73 .reg => |reg| {
...@@ -130,24 +118,6 @@ pub const Immediate = union(enum) {...@@ -130,24 +118,6 @@ pub const Immediate = union(enum) {
130 };118 };
131 }119 }
132120
133 pub fn asUnsigned(imm: Immediate, bit_size: u64) u64 {
134 return switch (imm) {
135 .signed => |x| switch (bit_size) {
136 1, 8 => @as(u8, @bitCast(@as(i8, @intCast(x)))),
137 16 => @as(u16, @bitCast(@as(i16, @intCast(x)))),
138 32, 64 => @as(u32, @bitCast(x)),
139 else => unreachable,
140 },
141 .unsigned => |x| switch (bit_size) {
142 1, 8 => @as(u8, @intCast(x)),
143 16 => @as(u16, @intCast(x)),
144 32 => @as(u32, @intCast(x)),
145 64 => x,
146 else => unreachable,
147 },
148 };
149 }
150
151 pub fn asBits(imm: Immediate, comptime T: type) T {121 pub fn asBits(imm: Immediate, comptime T: type) T {
152 const int_info = @typeInfo(T).Int;122 const int_info = @typeInfo(T).Int;
153 if (int_info.signedness != .unsigned) @compileError("Immediate.asBits needs unsigned T");123 if (int_info.signedness != .unsigned) @compileError("Immediate.asBits needs unsigned T");
src/arch/riscv64/encoder.zig+25
...@@ -32,6 +32,31 @@ pub const Instruction = struct {...@@ -32,6 +32,31 @@ pub const Instruction = struct {
32 pub fn encode(inst: Instruction, writer: anytype) !void {32 pub fn encode(inst: Instruction, writer: anytype) !void {
33 try writer.writeInt(u32, inst.encoding.data.toU32(), .little);33 try writer.writeInt(u32, inst.encoding.data.toU32(), .little);
34 }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 }
35};60};
3661
37const std = @import("std");62const std = @import("std");
test/behavior/align.zig-1
...@@ -249,7 +249,6 @@ fn testBytesAlign(b: u8) !void {...@@ -249,7 +249,6 @@ fn testBytesAlign(b: u8) !void {
249}249}
250250
251test "@alignCast slices" {251test "@alignCast slices" {
252 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
253 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;252 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
254 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;253 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
255 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO254 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/array.zig+1-11
...@@ -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;
...@@ -244,7 +241,6 @@ fn plusOne(x: u32) u32 {...@@ -244,7 +241,6 @@ fn plusOne(x: u32) u32 {
244test "single-item pointer to array indexing and slicing" {241test "single-item pointer to array indexing and slicing" {
245 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;242 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
246 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO243 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
247 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
248244
249 try testSingleItemPtrArrayIndexSlice();245 try testSingleItemPtrArrayIndexSlice();
250 try comptime testSingleItemPtrArrayIndexSlice();246 try comptime testSingleItemPtrArrayIndexSlice();
...@@ -270,7 +266,6 @@ fn doSomeMangling(array: *[4]u8) void {...@@ -270,7 +266,6 @@ fn doSomeMangling(array: *[4]u8) void {
270266
271test "implicit cast zero sized array ptr to slice" {267test "implicit cast zero sized array ptr to slice" {
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 {270 {
276 var b = "".*;271 var b = "".*;
...@@ -309,7 +304,6 @@ const Str = struct { a: []Sub };...@@ -309,7 +304,6 @@ const Str = struct { a: []Sub };
309test "set global var array via slice embedded in struct" {304test "set global var array via slice embedded in struct" {
310 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;305 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
311 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO306 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
312 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
313307
314 var s = Str{ .a = s_array[0..] };308 var s = Str{ .a = s_array[0..] };
315309
...@@ -376,7 +370,6 @@ test "comptime evaluating function that takes array by value" {...@@ -376,7 +370,6 @@ test "comptime evaluating function that takes array by value" {
376test "runtime initialize array elem and then implicit cast to slice" {370test "runtime initialize array elem and then implicit cast to slice" {
377 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;371 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
378 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO372 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
379 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
380373
381 var two: i32 = 2;374 var two: i32 = 2;
382 _ = &two;375 _ = &two;
...@@ -387,7 +380,6 @@ test "runtime initialize array elem and then implicit cast to slice" {...@@ -387,7 +380,6 @@ test "runtime initialize array elem and then implicit cast to slice" {
387test "array literal as argument to function" {380test "array literal as argument to function" {
388 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
389 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO382 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
390 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
391383
392 const S = struct {384 const S = struct {
393 fn entry(two: i32) !void {385 fn entry(two: i32) !void {
...@@ -416,7 +408,6 @@ test "double nested array to const slice cast in array literal" {...@@ -416,7 +408,6 @@ test "double nested array to const slice cast in array literal" {
416 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;408 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
417 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO409 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
418 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO410 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
419 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
420411
421 const S = struct {412 const S = struct {
422 fn entry(two: i32) !void {413 fn entry(two: i32) !void {
...@@ -522,7 +513,6 @@ test "type deduction for array subscript expression" {...@@ -522,7 +513,6 @@ test "type deduction for array subscript expression" {
522 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;513 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
523 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO514 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
524 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO515 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
525 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
526516
527 const S = struct {517 const S = struct {
528 fn doTheTest() !void {518 fn doTheTest() !void {
...@@ -542,6 +532,7 @@ test "sentinel element count towards the ABI size calculation" {...@@ -542,6 +532,7 @@ test "sentinel element count towards the ABI size calculation" {
542 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO532 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
543 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
544 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO534 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
535 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
545536
546 const S = struct {537 const S = struct {
547 fn doTheTest() !void {538 fn doTheTest() !void {
...@@ -956,7 +947,6 @@ test "array initialized with string literal" {...@@ -956,7 +947,6 @@ test "array initialized with string literal" {
956947
957test "array initialized with array with sentinel" {948test "array initialized with array with sentinel" {
958 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO949 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
959 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
960950
961 const S = struct {951 const S = struct {
962 a: u32,952 a: u32,
test/behavior/basic.zig-3
...@@ -709,7 +709,6 @@ test "result location is optional inside error union" {...@@ -709,7 +709,6 @@ test "result location is optional inside error union" {
709 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO709 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
710 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO710 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
711 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO711 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
712 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
713712
714 const x = maybe(true) catch unreachable;713 const x = maybe(true) catch unreachable;
715 try expect(x.? == 42);714 try expect(x.? == 42);
...@@ -1091,8 +1090,6 @@ test "orelse coercion as function argument" {...@@ -1091,8 +1090,6 @@ test "orelse coercion as function argument" {
1091}1090}
10921091
1093test "runtime-known globals initialized with undefined" {1092test "runtime-known globals initialized with undefined" {
1094 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1095
1096 const S = struct {1093 const S = struct {
1097 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 };
1098 var vp: [*]u32 = undefined;1095 var vp: [*]u32 = undefined;
test/behavior/bitcast.zig+3
...@@ -165,6 +165,7 @@ test "@bitCast packed structs at runtime and comptime" {...@@ -165,6 +165,7 @@ test "@bitCast packed structs at runtime and comptime" {
165 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;165 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
166 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO166 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
167 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;167 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
168 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
168169
169 const Full = packed struct {170 const Full = packed struct {
170 number: u16,171 number: u16,
...@@ -191,6 +192,7 @@ test "@bitCast packed structs at runtime and comptime" {...@@ -191,6 +192,7 @@ test "@bitCast packed structs at runtime and comptime" {
191test "@bitCast extern structs at runtime and comptime" {192test "@bitCast extern structs at runtime and comptime" {
192 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;193 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
193 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO194 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
195 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
194196
195 const Full = extern struct {197 const Full = extern struct {
196 number: u16,198 number: u16,
...@@ -225,6 +227,7 @@ test "bitcast packed struct to integer and back" {...@@ -225,6 +227,7 @@ test "bitcast packed struct to integer and back" {
225 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;227 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
226 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO228 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
227 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;229 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
230 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
228231
229 const LevelUpMove = packed struct {232 const LevelUpMove = packed struct {
230 move_id: u9,233 move_id: u9,
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/cast.zig+1-24
...@@ -266,7 +266,6 @@ fn MakeType(comptime T: type) type {...@@ -266,7 +266,6 @@ fn MakeType(comptime T: type) type {
266test "implicit cast from *[N]T to [*c]T" {266test "implicit cast from *[N]T to [*c]T" {
267 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;267 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
268 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO268 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
269 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
270269
271 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };270 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
272 var y: [*c]u16 = &x;271 var y: [*c]u16 = &x;
...@@ -343,7 +342,6 @@ test "array coercion to undefined at runtime" {...@@ -343,7 +342,6 @@ test "array coercion to undefined at runtime" {
343 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;342 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
344 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO343 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
345 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;344 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
346 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
347345
348 @setRuntimeSafety(true);346 @setRuntimeSafety(true);
349347
...@@ -409,7 +407,6 @@ test "peer type unsigned int to signed" {...@@ -409,7 +407,6 @@ test "peer type unsigned int to signed" {
409test "expected [*c]const u8, found [*:0]const u8" {407test "expected [*c]const u8, found [*:0]const u8" {
410 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;408 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
411 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO409 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
412 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
413410
414 var a: [*:0]const u8 = "hello";411 var a: [*:0]const u8 = "hello";
415 _ = &a;412 _ = &a;
...@@ -496,7 +493,6 @@ test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {...@@ -496,7 +493,6 @@ test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
496 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;493 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
497 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO494 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
498 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO495 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
499 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
500496
501 const S = struct {497 const S = struct {
502 fn doTheTest() anyerror!void {498 fn doTheTest() anyerror!void {
...@@ -577,7 +573,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {...@@ -577,7 +573,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
577test "single-item pointer of array to slice to unknown length pointer" {573test "single-item pointer of array to slice to unknown length pointer" {
578 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;574 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
579 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO575 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
580 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
581576
582 try testCastPtrOfArrayToSliceAndPtr();577 try testCastPtrOfArrayToSliceAndPtr();
583 try comptime testCastPtrOfArrayToSliceAndPtr();578 try comptime testCastPtrOfArrayToSliceAndPtr();
...@@ -673,6 +668,7 @@ test "@floatCast cast down" {...@@ -673,6 +668,7 @@ test "@floatCast cast down" {
673test "peer type resolution: unreachable, error set, unreachable" {668test "peer type resolution: unreachable, error set, unreachable" {
674 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO669 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
675 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO670 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
671 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
676672
677 const Error = error{673 const Error = error{
678 FileDescriptorAlreadyPresentInSet,674 FileDescriptorAlreadyPresentInSet,
...@@ -834,7 +830,6 @@ test "peer cast *[0]T to E![]const T" {...@@ -834,7 +830,6 @@ test "peer cast *[0]T to E![]const T" {
834 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;830 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
835 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;831 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
836 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO832 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
837 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
838833
839 var buffer: [5]u8 = "abcde".*;834 var buffer: [5]u8 = "abcde".*;
840 const buf: anyerror![]const u8 = buffer[0..];835 const buf: anyerror![]const u8 = buffer[0..];
...@@ -850,7 +845,6 @@ test "peer cast *[0]T to []const T" {...@@ -850,7 +845,6 @@ test "peer cast *[0]T to []const T" {
850 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;845 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
851 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;846 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
852 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO847 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
853 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
854848
855 var buffer: [5]u8 = "abcde".*;849 var buffer: [5]u8 = "abcde".*;
856 const buf: []const u8 = buffer[0..];850 const buf: []const u8 = buffer[0..];
...@@ -895,7 +889,6 @@ test "peer resolution of string literals" {...@@ -895,7 +889,6 @@ test "peer resolution of string literals" {
895test "peer cast [:x]T to []T" {889test "peer cast [:x]T to []T" {
896 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;890 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
897 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO891 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
898 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
899892
900 const S = struct {893 const S = struct {
901 fn doTheTest() !void {894 fn doTheTest() !void {
...@@ -912,7 +905,6 @@ test "peer cast [:x]T to []T" {...@@ -912,7 +905,6 @@ test "peer cast [:x]T to []T" {
912test "peer cast [N:x]T to [N]T" {905test "peer cast [N:x]T to [N]T" {
913 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;906 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
914 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO907 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
915 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
916908
917 const S = struct {909 const S = struct {
918 fn doTheTest() !void {910 fn doTheTest() !void {
...@@ -929,7 +921,6 @@ test "peer cast [N:x]T to [N]T" {...@@ -929,7 +921,6 @@ test "peer cast [N:x]T to [N]T" {
929test "peer cast *[N:x]T to *[N]T" {921test "peer cast *[N:x]T to *[N]T" {
930 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO922 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
931 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO923 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
932 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
933924
934 const S = struct {925 const S = struct {
935 fn doTheTest() !void {926 fn doTheTest() !void {
...@@ -987,7 +978,6 @@ test "peer cast [:x]T to [*:x]T" {...@@ -987,7 +978,6 @@ test "peer cast [:x]T to [*:x]T" {
987test "peer type resolution implicit cast to return type" {978test "peer type resolution implicit cast to return type" {
988 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;979 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
989 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO980 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
990 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
991981
992 const S = struct {982 const S = struct {
993 fn doTheTest() !void {983 fn doTheTest() !void {
...@@ -1008,7 +998,6 @@ test "peer type resolution implicit cast to return type" {...@@ -1008,7 +998,6 @@ test "peer type resolution implicit cast to return type" {
1008test "peer type resolution implicit cast to variable type" {998test "peer type resolution implicit cast to variable type" {
1009 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;999 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1010 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1000 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1011 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10121001
1013 const S = struct {1002 const S = struct {
1014 fn doTheTest() !void {1003 fn doTheTest() !void {
...@@ -1052,7 +1041,6 @@ test "cast between C pointer with different but compatible types" {...@@ -1052,7 +1041,6 @@ test "cast between C pointer with different but compatible types" {
1052test "peer type resolve string lit with sentinel-terminated mutable slice" {1041test "peer type resolve string lit with sentinel-terminated mutable slice" {
1053 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1042 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1054 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1043 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1055 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10561044
1057 var array: [4:0]u8 = undefined;1045 var array: [4:0]u8 = undefined;
1058 array[4] = 0; // TODO remove this when #4372 is solved1046 array[4] = 0; // TODO remove this when #4372 is solved
...@@ -1119,7 +1107,6 @@ test "implicit cast from [*]T to ?*anyopaque" {...@@ -1119,7 +1107,6 @@ test "implicit cast from [*]T to ?*anyopaque" {
1119 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1107 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1108 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1121 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1109 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1122 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11231110
1124 var a = [_]u8{ 3, 2, 1 };1111 var a = [_]u8{ 3, 2, 1 };
1125 var runtime_zero: usize = 0;1112 var runtime_zero: usize = 0;
...@@ -1319,7 +1306,6 @@ test "*const [N]null u8 to ?[]const u8" {...@@ -1319,7 +1306,6 @@ test "*const [N]null u8 to ?[]const u8" {
1319 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1306 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1307 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1308 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1322 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13231309
1324 const S = struct {1310 const S = struct {
1325 fn doTheTest() !void {1311 fn doTheTest() !void {
...@@ -1363,7 +1349,6 @@ test "assignment to optional pointer result loc" {...@@ -1363,7 +1349,6 @@ test "assignment to optional pointer result loc" {
1363}1349}
13641350
1365test "cast between *[N]void and []void" {1351test "cast between *[N]void and []void" {
1366 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1367 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1352 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13681353
1369 var a: [4]void = undefined;1354 var a: [4]void = undefined;
...@@ -1618,8 +1603,6 @@ test "optional slice passed as parameter coerced to allowzero many pointer" {...@@ -1618,8 +1603,6 @@ test "optional slice passed as parameter coerced to allowzero many pointer" {
1618}1603}
16191604
1620test "single item pointer to pointer to array to slice" {1605test "single item pointer to pointer to array to slice" {
1621 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1622
1623 var x: i32 = 1234;1606 var x: i32 = 1234;
1624 try expect(@as([]const i32, @as(*[1]i32, &x))[0] == 1234);1607 try expect(@as([]const i32, @as(*[1]i32, &x))[0] == 1234);
1625 const z1 = @as([]const i32, @as(*[1]i32, &x));1608 const z1 = @as([]const i32, @as(*[1]i32, &x));
...@@ -1662,8 +1645,6 @@ test "@volatileCast without a result location" {...@@ -1662,8 +1645,6 @@ test "@volatileCast without a result location" {
1662}1645}
16631646
1664test "coercion from single-item pointer to @as to slice" {1647test "coercion from single-item pointer to @as to slice" {
1665 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1666
1667 var x: u32 = 1;1648 var x: u32 = 1;
16681649
1669 // Why the following line gets a compile error?1650 // Why the following line gets a compile error?
...@@ -1728,7 +1709,6 @@ test "peer type resolution: same array type with sentinel" {...@@ -1728,7 +1709,6 @@ test "peer type resolution: same array type with sentinel" {
1728 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1709 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1729 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1710 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1730 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1711 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1731 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
17321712
1733 var a: [2:0]u32 = .{ 0, 1 };1713 var a: [2:0]u32 = .{ 0, 1 };
1734 var b: [2:0]u32 = .{ 2, 3 };1714 var b: [2:0]u32 = .{ 2, 3 };
...@@ -1751,7 +1731,6 @@ test "peer type resolution: array with sentinel and array without sentinel" {...@@ -1751,7 +1731,6 @@ test "peer type resolution: array with sentinel and array without sentinel" {
1751 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1731 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1752 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1732 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1753 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1733 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1754 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
17551734
1756 var a: [2:0]u32 = .{ 0, 1 };1735 var a: [2:0]u32 = .{ 0, 1 };
1757 var b: [2]u32 = .{ 2, 3 };1736 var b: [2]u32 = .{ 2, 3 };
...@@ -1956,7 +1935,6 @@ test "peer type resolution: array and tuple" {...@@ -1956,7 +1935,6 @@ test "peer type resolution: array and tuple" {
1956 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1935 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1957 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1936 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1958 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1937 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1959 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19601938
1961 var arr: [3]i32 = .{ 1, 2, 3 };1939 var arr: [3]i32 = .{ 1, 2, 3 };
1962 _ = &arr;1940 _ = &arr;
...@@ -2281,7 +2259,6 @@ test "peer type resolution: arrays of compatible types" {...@@ -2281,7 +2259,6 @@ test "peer type resolution: arrays of compatible types" {
2281 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2259 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2282 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2260 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2283 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2261 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2284 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
22852262
2286 var e0: u8 = 3;2263 var e0: u8 = 3;
2287 var e1: u8 = 2;2264 var e1: u8 = 2;
test/behavior/enum.zig+1
...@@ -618,6 +618,7 @@ test "enum with specified tag values" {...@@ -618,6 +618,7 @@ test "enum with specified tag values" {
618test "non-exhaustive enum" {618test "non-exhaustive enum" {
619 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;619 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
620 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO620 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
621 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
621622
622 const S = struct {623 const S = struct {
623 const E = enum(u8) { a, b, _ };624 const E = enum(u8) { a, b, _ };
test/behavior/error.zig-1
...@@ -856,7 +856,6 @@ test "alignment of wrapping an error union payload" {...@@ -856,7 +856,6 @@ test "alignment of wrapping an error union payload" {
856856
857test "compare error union and error set" {857test "compare error union and error set" {
858 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO858 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
859 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
860859
861 var a: anyerror = error.Foo;860 var a: anyerror = error.Foo;
862 var b: anyerror!u32 = error.Bar;861 var b: anyerror!u32 = error.Bar;
test/behavior/eval.zig+2-3
...@@ -395,6 +395,7 @@ test "return 0 from function that has u0 return type" {...@@ -395,6 +395,7 @@ test "return 0 from function that has u0 return type" {
395test "statically initialized struct" {395test "statically initialized struct" {
396 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO396 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
397 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO397 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
398 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
398399
399 st_init_str_foo.x += 1;400 st_init_str_foo.x += 1;
400 try expect(st_init_str_foo.x == 14);401 try expect(st_init_str_foo.x == 14);
...@@ -740,7 +741,6 @@ test "array concatenation of function calls" {...@@ -740,7 +741,6 @@ test "array concatenation of function calls" {
740 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;741 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
741 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;742 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
742 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO743 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
743 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
744744
745 var a = oneItem(3) ++ oneItem(4);745 var a = oneItem(3) ++ oneItem(4);
746 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));746 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
...@@ -750,7 +750,6 @@ test "array multiplication of function calls" {...@@ -750,7 +750,6 @@ test "array multiplication of function calls" {
750 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;750 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
751 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;751 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
752 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO752 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
753 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
754753
755 var a = oneItem(3) ** scalar(2);754 var a = oneItem(3) ** scalar(2);
756 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));755 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
...@@ -768,7 +767,6 @@ test "array concatenation peer resolves element types - value" {...@@ -768,7 +767,6 @@ test "array concatenation peer resolves element types - value" {
768 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;767 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
769 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;768 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
770 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO769 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
771 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
772770
773 var a = [2]u3{ 1, 7 };771 var a = [2]u3{ 1, 7 };
774 var b = [3]u8{ 200, 225, 255 };772 var b = [3]u8{ 200, 225, 255 };
...@@ -786,6 +784,7 @@ test "array concatenation peer resolves element types - pointer" {...@@ -786,6 +784,7 @@ test "array concatenation peer resolves element types - pointer" {
786 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;784 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
787 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
788 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO786 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
787 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
789788
790 var a = [2]u3{ 1, 7 };789 var a = [2]u3{ 1, 7 };
791 var b = [3]u8{ 200, 225, 255 };790 var b = [3]u8{ 200, 225, 255 };
test/behavior/for.zig-5
...@@ -200,7 +200,6 @@ test "for on slice with allowzero ptr" {...@@ -200,7 +200,6 @@ test "for on slice with allowzero ptr" {
200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
202 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO202 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
203 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
204203
205 const S = struct {204 const S = struct {
206 fn doTheTest(slice: []const u8) !void {205 fn doTheTest(slice: []const u8) !void {
...@@ -216,7 +215,6 @@ test "for on slice with allowzero ptr" {...@@ -216,7 +215,6 @@ test "for on slice with allowzero ptr" {
216test "else continue outer for" {215test "else continue outer for" {
217 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
218 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO217 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
219 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
220218
221 var i: usize = 6;219 var i: usize = 6;
222 var buf: [5]u8 = undefined;220 var buf: [5]u8 = undefined;
...@@ -313,7 +311,6 @@ test "slice and two counters, one is offset and one is runtime" {...@@ -313,7 +311,6 @@ test "slice and two counters, one is offset and one is runtime" {
313 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO311 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
314 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO312 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
315 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
316 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
317314
318 const slice: []const u8 = "blah";315 const slice: []const u8 = "blah";
319 var start: usize = 0;316 var start: usize = 0;
...@@ -343,7 +340,6 @@ test "two slices, one captured by-ref" {...@@ -343,7 +340,6 @@ test "two slices, one captured by-ref" {
343 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO340 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
344 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
345 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO342 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
346 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
347343
348 var buf: [10]u8 = undefined;344 var buf: [10]u8 = undefined;
349 const slice1: []const u8 = "blah";345 const slice1: []const u8 = "blah";
...@@ -400,7 +396,6 @@ test "inline for with slice as the comptime-known" {...@@ -400,7 +396,6 @@ test "inline for with slice as the comptime-known" {
400 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
401 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
402 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO398 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
403 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
404399
405 const comptime_slice = "hello";400 const comptime_slice = "hello";
406 var runtime_i: usize = 3;401 var runtime_i: usize = 3;
test/behavior/generics.zig-2
...@@ -158,7 +158,6 @@ test "generic fn with implicit cast" {...@@ -158,7 +158,6 @@ test "generic fn with implicit cast" {
158 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;158 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
160 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO160 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
161 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
162161
163 try expect(getFirstByte(u8, &[_]u8{13}) == 13);162 try expect(getFirstByte(u8, &[_]u8{13}) == 13);
164 try expect(getFirstByte(u16, &[_]u16{163 try expect(getFirstByte(u16, &[_]u16{
...@@ -320,7 +319,6 @@ test "generic function instantiation non-duplicates" {...@@ -320,7 +319,6 @@ test "generic function instantiation non-duplicates" {
320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO319 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
321 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO320 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
322 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
323 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
324 if (builtin.os.tag == .wasi) return error.SkipZigTest;322 if (builtin.os.tag == .wasi) return error.SkipZigTest;
325323
326 const S = struct {324 const S = struct {
test/behavior/globals.zig-1
...@@ -29,7 +29,6 @@ test "slices pointing at the same address as global array." {...@@ -29,7 +29,6 @@ test "slices pointing at the same address as global array." {
29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
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 const S = struct {33 const S = struct {
35 const a = [_]u8{ 1, 2, 3 };34 const a = [_]u8{ 1, 2, 3 };
test/behavior/if.zig-1
...@@ -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);
test/behavior/inline_switch.zig-1
...@@ -76,7 +76,6 @@ test "inline switch unions" {...@@ -76,7 +76,6 @@ test "inline switch unions" {
76test "inline else bool" {76test "inline else bool" {
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
79 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8079
81 var a = true;80 var a = true;
82 _ = &a;81 _ = &a;
test/behavior/math.zig-6
...@@ -592,8 +592,6 @@ fn testSignedWrappingEval(x: i32) !void {...@@ -592,8 +592,6 @@ fn testSignedWrappingEval(x: i32) !void {
592}592}
593593
594test "signed negation wrapping" {594test "signed negation wrapping" {
595 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
596
597 try testSignedNegationWrappingEval(minInt(i16));595 try testSignedNegationWrappingEval(minInt(i16));
598 try comptime testSignedNegationWrappingEval(minInt(i16));596 try comptime testSignedNegationWrappingEval(minInt(i16));
599}597}
...@@ -664,8 +662,6 @@ test "bit shift a u1" {...@@ -664,8 +662,6 @@ test "bit shift a u1" {
664}662}
665663
666test "truncating shift right" {664test "truncating shift right" {
667 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
668
669 try testShrTrunc(maxInt(u16));665 try testShrTrunc(maxInt(u16));
670 try comptime testShrTrunc(maxInt(u16));666 try comptime testShrTrunc(maxInt(u16));
671}667}
...@@ -1455,8 +1451,6 @@ fn testShlExact(x: u8) !void {...@@ -1455,8 +1451,6 @@ fn testShlExact(x: u8) !void {
1455}1451}
14561452
1457test "exact shift right" {1453test "exact shift right" {
1458 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1459
1460 try testShrExact(0b10110100);1454 try testShrExact(0b10110100);
1461 try comptime testShrExact(0b10110100);1455 try comptime testShrExact(0b10110100);
1462}1456}
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/optional.zig-2
...@@ -488,7 +488,6 @@ const NoReturn = struct {...@@ -488,7 +488,6 @@ const NoReturn = struct {
488488
489test "optional of noreturn used with if" {489test "optional of noreturn used with if" {
490 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO490 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
491 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
492491
493 NoReturn.a = 64;492 NoReturn.a = 64;
494 if (NoReturn.loop()) |_| {493 if (NoReturn.loop()) |_| {
...@@ -500,7 +499,6 @@ test "optional of noreturn used with if" {...@@ -500,7 +499,6 @@ test "optional of noreturn used with if" {
500499
501test "optional of noreturn used with orelse" {500test "optional of noreturn used with orelse" {
502 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO501 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
503 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
504502
505 NoReturn.a = 64;503 NoReturn.a = 64;
506 const val = NoReturn.testOrelse();504 const val = NoReturn.testOrelse();
test/behavior/packed-struct.zig+2-2
...@@ -258,6 +258,7 @@ test "nested packed struct unaligned" {...@@ -258,6 +258,7 @@ test "nested packed struct unaligned" {
258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;260 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
261 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
261 if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet262 if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet
262263
263 const S1 = packed struct {264 const S1 = packed struct {
...@@ -330,6 +331,7 @@ test "byte-aligned field pointer offsets" {...@@ -330,6 +331,7 @@ test "byte-aligned field pointer offsets" {
330 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;331 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
331 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO332 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
332 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;333 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
334 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
333335
334 const S = struct {336 const S = struct {
335 const A = packed struct {337 const A = packed struct {
...@@ -491,7 +493,6 @@ test "@intFromPtr on a packed struct field" {...@@ -491,7 +493,6 @@ test "@intFromPtr on a packed struct field" {
491 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;493 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
492 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO494 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
493 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;495 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
494 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
495 if (native_endian != .little) return error.SkipZigTest;496 if (native_endian != .little) return error.SkipZigTest;
496497
497 const S = struct {498 const S = struct {
...@@ -515,7 +516,6 @@ test "@intFromPtr on a packed struct field unaligned and nested" {...@@ -515,7 +516,6 @@ test "@intFromPtr on a packed struct field unaligned and nested" {
515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;516 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
516 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO517 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
517 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;518 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
518 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
519 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
520520
521 const S1 = packed struct {521 const S1 = packed struct {
test/behavior/pointers.zig-3
...@@ -201,7 +201,6 @@ test "allowzero pointer and slice" {...@@ -201,7 +201,6 @@ test "allowzero pointer and slice" {
201 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO201 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
202 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;202 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
203 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO203 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
204 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
205204
206 var ptr: [*]allowzero i32 = @ptrFromInt(0);205 var ptr: [*]allowzero i32 = @ptrFromInt(0);
207 const opt_ptr: ?[*]allowzero i32 = ptr;206 const opt_ptr: ?[*]allowzero i32 = ptr;
...@@ -440,7 +439,6 @@ test "indexing array with sentinel returns correct type" {...@@ -440,7 +439,6 @@ test "indexing array with sentinel returns correct type" {
440test "element pointer to slice" {439test "element pointer to slice" {
441 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO440 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
442 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO441 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
443 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
444442
445 const S = struct {443 const S = struct {
446 fn doTheTest() !void {444 fn doTheTest() !void {
...@@ -488,7 +486,6 @@ test "element pointer arithmetic to slice" {...@@ -488,7 +486,6 @@ test "element pointer arithmetic to slice" {
488486
489test "array slicing to slice" {487test "array slicing to slice" {
490 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO488 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
491 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
492489
493 const S = struct {490 const S = struct {
494 fn doTheTest() !void {491 fn doTheTest() !void {
test/behavior/ptrcast.zig-2
...@@ -232,7 +232,6 @@ test "implicit optional pointer to optional anyopaque pointer" {...@@ -232,7 +232,6 @@ test "implicit optional pointer to optional anyopaque pointer" {
232 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO232 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
234 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO234 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
235 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
236235
237 var buf: [4]u8 = "aoeu".*;236 var buf: [4]u8 = "aoeu".*;
238 const x: ?[*]u8 = &buf;237 const x: ?[*]u8 = &buf;
...@@ -245,7 +244,6 @@ test "@ptrCast slice to slice" {...@@ -245,7 +244,6 @@ test "@ptrCast slice to slice" {
245 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO244 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
246 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO245 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO246 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
248 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
249247
250 const S = struct {248 const S = struct {
251 fn foo(slice: []u32) []i32 {249 fn foo(slice: []u32) []i32 {
test/behavior/reflection.zig+1
...@@ -28,6 +28,7 @@ fn dummy(a: bool, b: i32, c: f32) i32 {...@@ -28,6 +28,7 @@ fn dummy(a: bool, b: i32, c: f32) i32 {
28test "reflection: @field" {28test "reflection: @field" {
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO30 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3132
32 var f = Foo{33 var f = Foo{
33 .one = 42,34 .one = 42,
test/behavior/sizeof_and_typeof.zig-1
...@@ -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);
test/behavior/slice.zig-12
...@@ -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);
...@@ -233,7 +232,6 @@ test "runtime safety lets us slice from len..len" {...@@ -233,7 +232,6 @@ test "runtime safety lets us slice from len..len" {
233 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;232 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
234 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;233 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
235 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO234 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
236 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
237235
238 var an_array = [_]u8{ 1, 2, 3 };236 var an_array = [_]u8{ 1, 2, 3 };
239 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));237 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
...@@ -289,7 +287,6 @@ fn sliceSum(comptime q: []const u8) i32 {...@@ -289,7 +287,6 @@ fn sliceSum(comptime q: []const u8) i32 {
289test "slice type with custom alignment" {287test "slice type with custom alignment" {
290 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;288 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
291 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO289 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
292 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
293290
294 const LazilyResolvedType = struct {291 const LazilyResolvedType = struct {
295 anything: i32,292 anything: i32,
...@@ -347,7 +344,6 @@ test "empty array to slice" {...@@ -347,7 +344,6 @@ test "empty array to slice" {
347test "@ptrCast slice to pointer" {344test "@ptrCast slice to pointer" {
348 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;345 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
349 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO346 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
350 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
351347
352 const S = struct {348 const S = struct {
353 fn doTheTest() !void {349 fn doTheTest() !void {
...@@ -402,7 +398,6 @@ test "slice syntax resulting in pointer-to-array" {...@@ -402,7 +398,6 @@ test "slice syntax resulting in pointer-to-array" {
402 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO398 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
403 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO399 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
404 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO400 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
405 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
406 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;401 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
407402
408 const S = struct {403 const S = struct {
...@@ -622,7 +617,6 @@ test "slice syntax resulting in pointer-to-array" {...@@ -622,7 +617,6 @@ test "slice syntax resulting in pointer-to-array" {
622test "slice pointer-to-array null terminated" {617test "slice pointer-to-array null terminated" {
623 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO618 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
624 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO619 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
625 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
626620
627 comptime {621 comptime {
628 var array = [5:0]u8{ 1, 2, 3, 4, 5 };622 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
...@@ -641,7 +635,6 @@ test "slice pointer-to-array null terminated" {...@@ -641,7 +635,6 @@ test "slice pointer-to-array null terminated" {
641635
642test "slice pointer-to-array zero length" {636test "slice pointer-to-array zero length" {
643 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO637 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
644 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
645638
646 comptime {639 comptime {
647 {640 {
...@@ -676,7 +669,6 @@ test "type coercion of pointer to anon struct literal to pointer to slice" {...@@ -676,7 +669,6 @@ test "type coercion of pointer to anon struct literal to pointer to slice" {
676 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO669 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
677 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO670 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
678 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO671 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
679 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
680672
681 const S = struct {673 const S = struct {
682 const U = union {674 const U = union {
...@@ -786,7 +778,6 @@ test "slicing array with sentinel as end index" {...@@ -786,7 +778,6 @@ test "slicing array with sentinel as end index" {
786test "slicing slice with sentinel as end index" {778test "slicing slice with sentinel as end index" {
787 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;779 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
788 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO780 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
789 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
790781
791 const S = struct {782 const S = struct {
792 fn do() !void {783 fn do() !void {
...@@ -857,7 +848,6 @@ test "global slice field access" {...@@ -857,7 +848,6 @@ test "global slice field access" {
857}848}
858849
859test "slice of void" {850test "slice of void" {
860 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
861 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;851 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
862852
863 var n: usize = 10;853 var n: usize = 10;
...@@ -981,7 +971,6 @@ test "get address of element of zero-sized slice" {...@@ -981,7 +971,6 @@ test "get address of element of zero-sized slice" {
981 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO971 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
982 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO972 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
983 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO973 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
984 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
985 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;974 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
986975
987 const S = struct {976 const S = struct {
...@@ -996,7 +985,6 @@ test "sentinel-terminated 0-length slices" {...@@ -996,7 +985,6 @@ test "sentinel-terminated 0-length slices" {
996 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO985 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
997 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO986 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
998 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO987 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
999 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1000988
1001 const u32s: [4]u32 = [_]u32{ 0, 1, 2, 3 };989 const u32s: [4]u32 = [_]u32{ 0, 1, 2, 3 };
1002990
test/behavior/struct.zig+4
...@@ -68,6 +68,7 @@ const SmallStruct = struct {...@@ -68,6 +68,7 @@ const SmallStruct = struct {
6868
69test "lower unnamed constants" {69test "lower unnamed constants" {
70 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO70 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
71 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7172
72 var foo = SmallStruct{ .a = 1, .b = 255 };73 var foo = SmallStruct{ .a = 1, .b = 255 };
73 try expect(foo.first() == 1);74 try expect(foo.first() == 1);
...@@ -874,6 +875,7 @@ test "packed struct field passed to generic function" {...@@ -874,6 +875,7 @@ test "packed struct field passed to generic function" {
874test "anonymous struct literal syntax" {875test "anonymous struct literal syntax" {
875 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;876 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
876 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO877 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
878 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
877879
878 const S = struct {880 const S = struct {
879 const Point = struct {881 const Point = struct {
...@@ -1103,6 +1105,7 @@ test "packed struct with undefined initializers" {...@@ -1103,6 +1105,7 @@ test "packed struct with undefined initializers" {
1103 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1104 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1106 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1105 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1107 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1108 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11061109
1107 const S = struct {1110 const S = struct {
1108 const P = packed struct {1111 const P = packed struct {
...@@ -1365,6 +1368,7 @@ test "store to comptime field" {...@@ -1365,6 +1368,7 @@ test "store to comptime field" {
1365test "struct field init value is size of the struct" {1368test "struct field init value is size of the struct" {
1366 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1369 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1367 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1370 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1371 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13681372
1369 const namespace = struct {1373 const namespace = struct {
1370 const S = extern struct {1374 const S = extern struct {
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-4
...@@ -118,7 +118,6 @@ fn trueIfBoolFalseOtherwise(comptime T: type) bool {...@@ -118,7 +118,6 @@ fn trueIfBoolFalseOtherwise(comptime T: type) bool {
118118
119test "switching on booleans" {119test "switching on booleans" {
120 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO120 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
121 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
122121
123 try testSwitchOnBools();122 try testSwitchOnBools();
124 try comptime testSwitchOnBools();123 try comptime testSwitchOnBools();
...@@ -277,7 +276,6 @@ fn testSwitchEnumPtrCapture() !void {...@@ -277,7 +276,6 @@ fn testSwitchEnumPtrCapture() !void {
277276
278test "switch handles all cases of number" {277test "switch handles all cases of number" {
279 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO278 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
280 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
281279
282 try testSwitchHandleAllCases();280 try testSwitchHandleAllCases();
283 try comptime testSwitchHandleAllCases();281 try comptime testSwitchHandleAllCases();
...@@ -647,7 +645,6 @@ test "switch prong pointer capture alignment" {...@@ -647,7 +645,6 @@ test "switch prong pointer capture alignment" {
647test "switch on pointer type" {645test "switch on pointer type" {
648 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO646 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
649 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO647 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
650 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
651648
652 const S = struct {649 const S = struct {
653 const X = struct {650 const X = struct {
...@@ -912,7 +909,6 @@ test "peer type resolution on switch captures ignores unused payload bits" {...@@ -912,7 +909,6 @@ test "peer type resolution on switch captures ignores unused payload bits" {
912test "switch prong captures range" {909test "switch prong captures range" {
913 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO910 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
914 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO911 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
915 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
916912
917 const S = struct {913 const S = struct {
918 fn a(b: []u3, c: u3) void {914 fn a(b: []u3, c: u3) void {
test/behavior/this.zig+1
...@@ -27,6 +27,7 @@ test "this refer to module call private fn" {...@@ -27,6 +27,7 @@ test "this refer to module call private fn" {
27test "this refer to container" {27test "this refer to container" {
28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3031
31 var pt: Point(i32) = undefined;32 var pt: Point(i32) = undefined;
32 pt.x = 12;33 pt.x = 12;
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/union.zig+3
...@@ -2044,6 +2044,7 @@ test "extern union initialized via reintepreted struct field initializer" {...@@ -2044,6 +2044,7 @@ test "extern union initialized via reintepreted struct field initializer" {
20442044
2045test "packed union initialized via reintepreted struct field initializer" {2045test "packed union initialized via reintepreted struct field initializer" {
2046 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;2046 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2047 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
20472048
2048 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };2049 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
20492050
...@@ -2064,6 +2065,7 @@ test "packed union initialized via reintepreted struct field initializer" {...@@ -2064,6 +2065,7 @@ test "packed union initialized via reintepreted struct field initializer" {
20642065
2065test "store of comptime reinterpreted memory to extern union" {2066test "store of comptime reinterpreted memory to extern union" {
2066 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;2067 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2068 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
20672069
2068 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };2070 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
20692071
...@@ -2086,6 +2088,7 @@ test "store of comptime reinterpreted memory to extern union" {...@@ -2086,6 +2088,7 @@ test "store of comptime reinterpreted memory to extern union" {
20862088
2087test "store of comptime reinterpreted memory to packed union" {2089test "store of comptime reinterpreted memory to packed union" {
2088 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;2090 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2091 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
20892092
2090 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };2093 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
20912094
test/behavior/vector.zig-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 {
test/behavior/while.zig-1
...@@ -379,7 +379,6 @@ test "while loop with comptime true condition needs no else block to return valu...@@ -379,7 +379,6 @@ test "while loop with comptime true condition needs no else block to return valu
379test "int returned from switch in while" {379test "int returned from switch in while" {
380 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO380 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
381 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO381 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
382 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
383382
384 var x: u32 = 3;383 var x: u32 = 3;
385 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));