authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-15 07:05:24+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-15 07:05:24+01:00
logbe98f30a2d647075564e02791813ddfb599f6cd7
tree7cb73181d19a46ef8c1fbf671ce85a17fe0c9644
parentdc6553d93eb856a1593d43f0d1ea387c74fa7b44
parent6c195db03a502074952181261807cf9a8e140d8d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10893 from joachimschmidt557/stage2-aarch64

stage2 AArch64: get zig test working; enable behavior tests

33 files changed, 1477 insertions(+), 359 deletions(-)

ci/zinc/linux_test.sh+3-2
...@@ -7,8 +7,9 @@ ZIG=$DEBUG_STAGING/bin/zig...@@ -7,8 +7,9 @@ ZIG=$DEBUG_STAGING/bin/zig
7$ZIG test test/behavior.zig -fno-stage1 -I test -fLLVM7$ZIG test test/behavior.zig -fno-stage1 -I test -fLLVM
8$ZIG test test/behavior.zig -fno-stage1 -I test -fLLVM -target aarch64-linux --test-cmd qemu-aarch64 --test-cmd-bin8$ZIG test test/behavior.zig -fno-stage1 -I test -fLLVM -target aarch64-linux --test-cmd qemu-aarch64 --test-cmd-bin
9$ZIG test test/behavior.zig -fno-stage1 -I test -ofmt=c9$ZIG test test/behavior.zig -fno-stage1 -I test -ofmt=c
10$ZIG test test/behavior.zig -fno-stage1 -I test -target wasm32-wasi --test-cmd wasmtime --test-cmd-bin10$ZIG test test/behavior.zig -fno-stage1 -I test -target wasm32-wasi --test-cmd wasmtime --test-cmd-bin
11$ZIG test test/behavior.zig -fno-stage1 -I test -target arm-linux --test-cmd qemu-arm --test-cmd-bin11$ZIG test test/behavior.zig -fno-stage1 -I test -target arm-linux --test-cmd qemu-arm --test-cmd-bin
12$ZIG test test/behavior.zig -fno-stage1 -I test -target aarch64-linux --test-cmd qemu-aarch64 --test-cmd-bin
12$ZIG test test/behavior.zig -fno-stage1 -I test13$ZIG test test/behavior.zig -fno-stage1 -I test
1314
14$ZIG build test-behavior -fqemu -fwasmtime15$ZIG build test-behavior -fqemu -fwasmtime
src/arch/aarch64/CodeGen.zig+881-233
...@@ -511,10 +511,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -511,10 +511,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
511511
512 switch (air_tags[inst]) {512 switch (air_tags[inst]) {
513 // zig fmt: off513 // zig fmt: off
514 .add, .ptr_add => try self.airAdd(inst),514 .add, .ptr_add => try self.airBinOp(inst),
515 .addwrap => try self.airAddWrap(inst),515 .addwrap => try self.airAddWrap(inst),
516 .add_sat => try self.airAddSat(inst),516 .add_sat => try self.airAddSat(inst),
517 .sub, .ptr_sub => try self.airSub(inst),517 .sub, .ptr_sub => try self.airBinOp(inst),
518 .subwrap => try self.airSubWrap(inst),518 .subwrap => try self.airSubWrap(inst),
519 .sub_sat => try self.airSubSat(inst),519 .sub_sat => try self.airSubSat(inst),
520 .mul => try self.airMul(inst),520 .mul => try self.airMul(inst),
...@@ -894,6 +894,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -894,6 +894,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
894 const ty_op = self.air.instructions.items(.data)[inst].ty_op;894 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
895 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {895 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
896 const operand = try self.resolveInst(ty_op.operand);896 const operand = try self.resolveInst(ty_op.operand);
897 const operand_ty = self.air.typeOf(ty_op.operand);
897 switch (operand) {898 switch (operand) {
898 .dead => unreachable,899 .dead => unreachable,
899 .unreach => unreachable,900 .unreach => unreachable,
...@@ -923,12 +924,19 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -923,12 +924,19 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
923 };924 };
924 break :result r;925 break :result r;
925 },926 },
926 else => {},927 else => {
928 switch (operand_ty.zigTypeTag()) {
929 .Bool => {
930 // TODO convert this to mvn + and
931 const dest = try self.binOp(.xor, null, operand, .{ .immediate = 1 }, operand_ty, Type.bool);
932 break :result dest;
933 },
934 else => return self.fail("TODO bitwise not", .{}),
935 }
936 },
927 }937 }
928
929 return self.fail("TODO implement NOT for {}", .{self.target.cpu.arch});
930 };938 };
931 _ = result;939 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
932}940}
933941
934fn airMin(self: *Self, inst: Air.Inst.Index) !void {942fn airMin(self: *Self, inst: Air.Inst.Index) !void {
...@@ -950,9 +958,306 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -950,9 +958,306 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
950 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });958 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
951}959}
952960
953fn airAdd(self: *Self, inst: Air.Inst.Index) !void {961/// Don't call this function directly. Use binOp instead.
962///
963/// Calling this function signals an intention to generate a Mir
964/// instruction of the form
965///
966/// op dest, lhs, rhs
967///
968/// Asserts that generating an instruction of that form is possible.
969fn binOpRegister(
970 self: *Self,
971 tag: Air.Inst.Tag,
972 maybe_inst: ?Air.Inst.Index,
973 lhs: MCValue,
974 rhs: MCValue,
975 lhs_ty: Type,
976 rhs_ty: Type,
977) !MCValue {
978 const lhs_is_register = lhs == .register;
979 const rhs_is_register = rhs == .register;
980
981 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});
982 if (rhs_is_register) self.register_manager.freezeRegs(&.{rhs.register});
983
984 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
985
986 const lhs_reg = if (lhs_is_register) lhs.register else blk: {
987 const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: {
988 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
989 break :inst Air.refToIndex(bin_op.lhs).?;
990 } else null;
991
992 const reg = try self.register_manager.allocReg(track_inst);
993 self.register_manager.freezeRegs(&.{reg});
994
995 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
996
997 break :blk reg;
998 };
999 defer self.register_manager.unfreezeRegs(&.{lhs_reg});
1000
1001 const rhs_reg = if (rhs_is_register) rhs.register else blk: {
1002 const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: {
1003 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1004 break :inst Air.refToIndex(bin_op.rhs).?;
1005 } else null;
1006
1007 const reg = try self.register_manager.allocReg(track_inst);
1008 self.register_manager.freezeRegs(&.{reg});
1009
1010 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
1011
1012 break :blk reg;
1013 };
1014 defer self.register_manager.unfreezeRegs(&.{rhs_reg});
1015
1016 const dest_reg = if (maybe_inst) |inst| blk: {
1017 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1018
1019 if (lhs_is_register and self.reuseOperand(inst, bin_op.lhs, 0, lhs)) {
1020 break :blk lhs_reg;
1021 } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) {
1022 break :blk rhs_reg;
1023 } else {
1024 break :blk try self.register_manager.allocReg(inst);
1025 }
1026 } else try self.register_manager.allocReg(null);
1027
1028 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
1029 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
1030
1031 const mir_tag: Mir.Inst.Tag = switch (tag) {
1032 .add, .ptr_add => .add_shifted_register,
1033 .sub, .ptr_sub => .sub_shifted_register,
1034 .xor => .eor_shifted_register,
1035 else => unreachable,
1036 };
1037 const mir_data: Mir.Inst.Data = switch (tag) {
1038 .add,
1039 .sub,
1040 .ptr_add,
1041 .ptr_sub,
1042 => .{ .rrr_imm6_shift = .{
1043 .rd = dest_reg,
1044 .rn = lhs_reg,
1045 .rm = rhs_reg,
1046 .imm6 = 0,
1047 .shift = .lsl,
1048 } },
1049 .xor => .{ .rrr_imm6_logical_shift = .{
1050 .rd = dest_reg,
1051 .rn = lhs_reg,
1052 .rm = rhs_reg,
1053 .imm6 = 0,
1054 .shift = .lsl,
1055 } },
1056 else => unreachable,
1057 };
1058
1059 _ = try self.addInst(.{
1060 .tag = mir_tag,
1061 .data = mir_data,
1062 });
1063
1064 return MCValue{ .register = dest_reg };
1065}
1066
1067/// Don't call this function directly. Use binOp instead.
1068///
1069/// Calling this function signals an intention to generate a Mir
1070/// instruction of the form
1071///
1072/// op dest, lhs, #rhs_imm
1073///
1074/// Set lhs_and_rhs_swapped to true iff inst.bin_op.lhs corresponds to
1075/// rhs and vice versa. This parameter is only used when maybe_inst !=
1076/// null.
1077///
1078/// Asserts that generating an instruction of that form is possible.
1079fn binOpImmediate(
1080 self: *Self,
1081 tag: Air.Inst.Tag,
1082 maybe_inst: ?Air.Inst.Index,
1083 lhs: MCValue,
1084 rhs: MCValue,
1085 lhs_ty: Type,
1086 lhs_and_rhs_swapped: bool,
1087) !MCValue {
1088 const lhs_is_register = lhs == .register;
1089
1090 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});
1091
1092 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
1093
1094 const lhs_reg = if (lhs_is_register) lhs.register else blk: {
1095 const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: {
1096 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1097 break :inst Air.refToIndex(
1098 if (lhs_and_rhs_swapped) bin_op.rhs else bin_op.lhs,
1099 ).?;
1100 } else null;
1101
1102 const reg = try self.register_manager.allocReg(track_inst);
1103 self.register_manager.freezeRegs(&.{reg});
1104
1105 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
1106
1107 break :blk reg;
1108 };
1109 defer self.register_manager.unfreezeRegs(&.{lhs_reg});
1110
1111 const dest_reg = if (maybe_inst) |inst| blk: {
1112 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1113
1114 if (lhs_is_register and self.reuseOperand(
1115 inst,
1116 if (lhs_and_rhs_swapped) bin_op.rhs else bin_op.lhs,
1117 if (lhs_and_rhs_swapped) 1 else 0,
1118 lhs,
1119 )) {
1120 break :blk lhs_reg;
1121 } else {
1122 break :blk try self.register_manager.allocReg(inst);
1123 }
1124 } else try self.register_manager.allocReg(null);
1125
1126 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
1127
1128 const mir_tag: Mir.Inst.Tag = switch (tag) {
1129 .add => .add_immediate,
1130 .sub => .sub_immediate,
1131 else => unreachable,
1132 };
1133 const mir_data: Mir.Inst.Data = switch (tag) {
1134 .add,
1135 .sub,
1136 => .{ .rr_imm12_sh = .{
1137 .rd = dest_reg,
1138 .rn = lhs_reg,
1139 .imm12 = @intCast(u12, rhs.immediate),
1140 } },
1141 else => unreachable,
1142 };
1143
1144 _ = try self.addInst(.{
1145 .tag = mir_tag,
1146 .data = mir_data,
1147 });
1148
1149 return MCValue{ .register = dest_reg };
1150}
1151
1152/// For all your binary operation needs, this function will generate
1153/// the corresponding Mir instruction(s). Returns the location of the
1154/// result.
1155///
1156/// If the binary operation itself happens to be an Air instruction,
1157/// pass the corresponding index in the inst parameter. That helps
1158/// this function do stuff like reusing operands.
1159///
1160/// This function does not do any lowering to Mir itself, but instead
1161/// looks at the lhs and rhs and determines which kind of lowering
1162/// would be best suitable and then delegates the lowering to other
1163/// functions.
1164fn binOp(
1165 self: *Self,
1166 tag: Air.Inst.Tag,
1167 maybe_inst: ?Air.Inst.Index,
1168 lhs: MCValue,
1169 rhs: MCValue,
1170 lhs_ty: Type,
1171 rhs_ty: Type,
1172) !MCValue {
1173 switch (tag) {
1174 // Arithmetic operations on integers and floats
1175 .add,
1176 .sub,
1177 => {
1178 switch (lhs_ty.zigTypeTag()) {
1179 .Float => return self.fail("TODO binary operations on floats", .{}),
1180 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1181 .Int => {
1182 assert(lhs_ty.eql(rhs_ty));
1183 const int_info = lhs_ty.intInfo(self.target.*);
1184 if (int_info.bits <= 64) {
1185 // Only say yes if the operation is
1186 // commutative, i.e. we can swap both of the
1187 // operands
1188 const lhs_immediate_ok = switch (tag) {
1189 .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
1190 .sub => false,
1191 else => unreachable,
1192 };
1193 const rhs_immediate_ok = switch (tag) {
1194 .add,
1195 .sub,
1196 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
1197 else => unreachable,
1198 };
1199
1200 if (rhs_immediate_ok) {
1201 return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false);
1202 } else if (lhs_immediate_ok) {
1203 // swap lhs and rhs
1204 return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true);
1205 } else {
1206 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1207 }
1208 } else {
1209 return self.fail("TODO binary operations on int with bits > 64", .{});
1210 }
1211 },
1212 else => unreachable,
1213 }
1214 },
1215 // Bitwise operations on integers
1216 .xor => {
1217 switch (lhs_ty.zigTypeTag()) {
1218 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1219 .Int => return self.fail("TODO binary operations on vectors", .{}),
1220 .Bool => {
1221 assert(lhs_ty.eql(rhs_ty));
1222 // TODO boolean operations with immediates
1223 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1224 },
1225 else => unreachable,
1226 }
1227 },
1228 .ptr_add,
1229 .ptr_sub,
1230 => {
1231 switch (lhs_ty.zigTypeTag()) {
1232 .Pointer => {
1233 const ptr_ty = lhs_ty;
1234 const pointee_ty = switch (ptr_ty.ptrSize()) {
1235 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type
1236 else => ptr_ty.childType(),
1237 };
1238
1239 if (pointee_ty.abiSize(self.target.*) > 1) {
1240 return self.fail("TODO ptr_add, ptr_sub with more element sizes", .{});
1241 }
1242
1243 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1244 },
1245 else => unreachable,
1246 }
1247 },
1248 else => unreachable,
1249 }
1250}
1251
1252fn airBinOp(self: *Self, inst: Air.Inst.Index) !void {
1253 const tag = self.air.instructions.items(.tag)[inst];
954 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1254 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
955 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement add for {}", .{self.target.cpu.arch});1255 const lhs = try self.resolveInst(bin_op.lhs);
1256 const rhs = try self.resolveInst(bin_op.rhs);
1257 const lhs_ty = self.air.typeOf(bin_op.lhs);
1258 const rhs_ty = self.air.typeOf(bin_op.rhs);
1259
1260 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
956 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1261 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
957}1262}
9581263
...@@ -968,12 +1273,6 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -968,12 +1273,6 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
968 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1273 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
969}1274}
9701275
971fn airSub(self: *Self, inst: Air.Inst.Index) !void {
972 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
973 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement sub for {}", .{self.target.cpu.arch});
974 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
975}
976
977fn airSubWrap(self: *Self, inst: Air.Inst.Index) !void {1276fn airSubWrap(self: *Self, inst: Air.Inst.Index) !void {
978 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1277 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
979 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement subwrap for {}", .{self.target.cpu.arch});1278 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement subwrap for {}", .{self.target.cpu.arch});
...@@ -1098,13 +1397,26 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -1098,13 +1397,26 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
10981397
1099fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {1398fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
1100 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1399 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1101 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement unwrap error union error for {}", .{self.target.cpu.arch});1400 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1401 const error_union_ty = self.air.typeOf(ty_op.operand);
1402 const payload_ty = error_union_ty.errorUnionPayload();
1403 const mcv = try self.resolveInst(ty_op.operand);
1404 if (!payload_ty.hasRuntimeBits()) break :result mcv;
1405
1406 return self.fail("TODO implement unwrap error union error for non-empty payloads", .{});
1407 };
1102 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1408 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1103}1409}
11041410
1105fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {1411fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
1106 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1412 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1107 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement unwrap error union payload for {}", .{self.target.cpu.arch});1413 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1414 const error_union_ty = self.air.typeOf(ty_op.operand);
1415 const payload_ty = error_union_ty.errorUnionPayload();
1416 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;
1417
1418 return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{});
1419 };
1108 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1420 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1109}1421}
11101422
...@@ -1146,7 +1458,14 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -1146,7 +1458,14 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
1146/// E to E!T1458/// E to E!T
1147fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {1459fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
1148 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1460 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1149 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement wrap errunion error for {}", .{self.target.cpu.arch});1461 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1462 const error_union_ty = self.air.getRefType(ty_op.ty);
1463 const payload_ty = error_union_ty.errorUnionPayload();
1464 const mcv = try self.resolveInst(ty_op.operand);
1465 if (!payload_ty.hasRuntimeBits()) break :result mcv;
1466
1467 return self.fail("TODO implement wrap errunion error for non-empty payloads", .{});
1468 };
1150 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1469 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1151}1470}
11521471
...@@ -1158,7 +1477,20 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1158,7 +1477,20 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
11581477
1159fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {1478fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
1160 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1479 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1161 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_len for {}", .{self.target.cpu.arch});1480 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1481 const mcv = try self.resolveInst(ty_op.operand);
1482 switch (mcv) {
1483 .dead, .unreach => unreachable,
1484 .register => unreachable, // a slice doesn't fit in one register
1485 .stack_offset => |off| {
1486 break :result MCValue{ .stack_offset = off };
1487 },
1488 .memory => |addr| {
1489 break :result MCValue{ .memory = addr + 8 };
1490 },
1491 else => return self.fail("TODO implement slice_len for {}", .{mcv}),
1492 }
1493 };
1162 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1494 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1163}1495}
11641496
...@@ -1177,10 +1509,114 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1177,10 +1509,114 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
1177fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {1509fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1178 const is_volatile = false; // TODO1510 const is_volatile = false; // TODO
1179 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1511 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1180 const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_elem_val for {}", .{self.target.cpu.arch});1512
1513 if (!is_volatile and self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1514 const result: MCValue = result: {
1515 const slice_mcv = try self.resolveInst(bin_op.lhs);
1516
1517 // TODO optimize for the case where the index is a constant,
1518 // i.e. index_mcv == .immediate
1519 const index_mcv = try self.resolveInst(bin_op.rhs);
1520 const index_is_register = index_mcv == .register;
1521
1522 const slice_ty = self.air.typeOf(bin_op.lhs);
1523 const elem_ty = slice_ty.childType();
1524 const elem_size = elem_ty.abiSize(self.target.*);
1525
1526 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1527 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
1528
1529 if (index_is_register) self.register_manager.freezeRegs(&.{index_mcv.register});
1530 defer if (index_is_register) self.register_manager.unfreezeRegs(&.{index_mcv.register});
1531
1532 const base_mcv: MCValue = switch (slice_mcv) {
1533 .stack_offset => |off| .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, .{ .stack_offset = off + 8 }) },
1534 else => return self.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}),
1535 };
1536 self.register_manager.freezeRegs(&.{base_mcv.register});
1537
1538 // TODO implement optimized ldr for airSliceElemVal
1539 const dst_mcv = try self.allocRegOrMem(inst, true);
1540
1541 const offset_mcv = try self.genMulConstant(bin_op.rhs, @intCast(u32, elem_size));
1542 assert(offset_mcv == .register); // result of multiplication should always be register
1543 self.register_manager.freezeRegs(&.{offset_mcv.register});
1544
1545 const addr_reg = try self.register_manager.allocReg(null);
1546 self.register_manager.freezeRegs(&.{addr_reg});
1547 defer self.register_manager.unfreezeRegs(&.{addr_reg});
1548
1549 _ = try self.addInst(.{
1550 .tag = .add_shifted_register,
1551 .data = .{ .rrr_imm6_shift = .{
1552 .rd = addr_reg,
1553 .rn = base_mcv.register,
1554 .rm = offset_mcv.register,
1555 .imm6 = 0,
1556 .shift = .lsl,
1557 } },
1558 });
1559
1560 // At this point in time, neither the base register
1561 // nor the offset register contains any valuable data
1562 // anymore.
1563 self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register });
1564
1565 try self.load(dst_mcv, .{ .register = addr_reg }, slice_ptr_field_type);
1566
1567 break :result dst_mcv;
1568 };
1181 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1569 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1182}1570}
11831571
1572fn genMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {
1573 const lhs = try self.resolveInst(op);
1574 const rhs = MCValue{ .immediate = imm };
1575
1576 const lhs_is_register = lhs == .register;
1577
1578 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});
1579 defer if (lhs_is_register) self.register_manager.unfreezeRegs(&.{lhs.register});
1580
1581 // Destination must be a register
1582 // LHS must be a register
1583 // RHS must be a register
1584 var dst_mcv: MCValue = undefined;
1585 var lhs_mcv: MCValue = lhs;
1586 var rhs_mcv: MCValue = rhs;
1587
1588 // Allocate registers for operands and/or destination
1589 // Allocate 1 or 2 registers
1590 if (lhs_is_register) {
1591 // Move RHS to register
1592 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(null) };
1593 rhs_mcv = dst_mcv;
1594 } else {
1595 // Move LHS and RHS to register
1596 const regs = try self.register_manager.allocRegs(2, .{ null, null });
1597 lhs_mcv = MCValue{ .register = regs[0] };
1598 rhs_mcv = MCValue{ .register = regs[1] };
1599 dst_mcv = lhs_mcv;
1600 }
1601
1602 // Move the operands to the newly allocated registers
1603 if (!lhs_is_register) {
1604 try self.genSetReg(self.air.typeOf(op), lhs_mcv.register, lhs);
1605 }
1606 try self.genSetReg(Type.initTag(.usize), rhs_mcv.register, rhs);
1607
1608 _ = try self.addInst(.{
1609 .tag = .mul,
1610 .data = .{ .rrr = .{
1611 .rd = dst_mcv.register,
1612 .rn = lhs_mcv.register,
1613 .rm = rhs_mcv.register,
1614 } },
1615 });
1616
1617 return dst_mcv;
1618}
1619
1184fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {1620fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
1185 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1621 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1186 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;1622 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
...@@ -1295,8 +1731,74 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1295,8 +1731,74 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1295 .embedded_in_code => {1731 .embedded_in_code => {
1296 return self.fail("TODO implement loading from MCValue.embedded_in_code", .{});1732 return self.fail("TODO implement loading from MCValue.embedded_in_code", .{});
1297 },1733 },
1298 .register => {1734 .register => |addr_reg| {
1299 return self.fail("TODO implement loading from MCValue.register for {}", .{self.target.cpu.arch});1735 self.register_manager.freezeRegs(&.{addr_reg});
1736 defer self.register_manager.unfreezeRegs(&.{addr_reg});
1737
1738 switch (dst_mcv) {
1739 .dead => unreachable,
1740 .undef => unreachable,
1741 .compare_flags_signed, .compare_flags_unsigned => unreachable,
1742 .embedded_in_code => unreachable,
1743 .register => |dst_reg| {
1744 _ = try self.addInst(.{
1745 .tag = .ldr_immediate,
1746 .data = .{ .load_store_register_immediate = .{
1747 .rt = dst_reg,
1748 .rn = addr_reg,
1749 .offset = Instruction.LoadStoreOffset.none.immediate,
1750 } },
1751 });
1752 },
1753 .stack_offset => |off| {
1754 if (elem_ty.abiSize(self.target.*) <= 8) {
1755 const tmp_reg = try self.register_manager.allocReg(null);
1756 self.register_manager.freezeRegs(&.{tmp_reg});
1757 defer self.register_manager.unfreezeRegs(&.{tmp_reg});
1758
1759 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
1760 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
1761 } else {
1762 // TODO optimize the register allocation
1763 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
1764 self.register_manager.freezeRegs(&regs);
1765 defer self.register_manager.unfreezeRegs(&regs);
1766
1767 const src_reg = addr_reg;
1768 const dst_reg = regs[0];
1769 const len_reg = regs[1];
1770 const count_reg = regs[2];
1771 const tmp_reg = regs[3];
1772
1773 // sub dst_reg, fp, #off
1774 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
1775 const adj_off = off + elem_size;
1776 const offset = math.cast(u12, adj_off) catch return self.fail("TODO load: larger stack offsets", .{});
1777 _ = try self.addInst(.{
1778 .tag = .sub_immediate,
1779 .data = .{ .rr_imm12_sh = .{
1780 .rd = dst_reg,
1781 .rn = .x29,
1782 .imm12 = offset,
1783 } },
1784 });
1785
1786 // mov len, #elem_size
1787 const len_imm = math.cast(u16, elem_size) catch return self.fail("TODO load: larger stack offsets", .{});
1788 _ = try self.addInst(.{
1789 .tag = .movk,
1790 .data = .{ .r_imm16_sh = .{
1791 .rd = len_reg,
1792 .imm16 = len_imm,
1793 } },
1794 });
1795
1796 // memcpy(src, dst, len)
1797 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
1798 }
1799 },
1800 else => return self.fail("TODO load from register into {}", .{dst_mcv}),
1801 }
1300 },1802 },
1301 .memory,1803 .memory,
1302 .stack_offset,1804 .stack_offset,
...@@ -1311,6 +1813,84 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1311,6 +1813,84 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1311 }1813 }
1312}1814}
13131815
1816fn genInlineMemcpy(
1817 self: *Self,
1818 src: Register,
1819 dst: Register,
1820 len: Register,
1821 count: Register,
1822 tmp: Register,
1823) !void {
1824 // movk count, #0
1825 _ = try self.addInst(.{
1826 .tag = .movk,
1827 .data = .{ .r_imm16_sh = .{
1828 .rd = count,
1829 .imm16 = 0,
1830 } },
1831 });
1832
1833 // loop:
1834 // cmp count, len
1835 _ = try self.addInst(.{
1836 .tag = .cmp_shifted_register,
1837 .data = .{ .rrr_imm6_shift = .{
1838 .rd = .xzr,
1839 .rn = count,
1840 .rm = len,
1841 .imm6 = 0,
1842 .shift = .lsl,
1843 } },
1844 });
1845
1846 // bge end
1847 _ = try self.addInst(.{
1848 .tag = .b_cond,
1849 .data = .{ .inst_cond = .{
1850 .inst = @intCast(u32, self.mir_instructions.len + 5),
1851 .cond = .ge,
1852 } },
1853 });
1854
1855 // ldrb tmp, [src, count]
1856 _ = try self.addInst(.{
1857 .tag = .ldrb_register,
1858 .data = .{ .load_store_register_register = .{
1859 .rt = tmp,
1860 .rn = src,
1861 .offset = Instruction.LoadStoreOffset.reg(count).register,
1862 } },
1863 });
1864
1865 // strb tmp, [dest, count]
1866 _ = try self.addInst(.{
1867 .tag = .strb_register,
1868 .data = .{ .load_store_register_register = .{
1869 .rt = tmp,
1870 .rn = dst,
1871 .offset = Instruction.LoadStoreOffset.reg(count).register,
1872 } },
1873 });
1874
1875 // add count, count, #1
1876 _ = try self.addInst(.{
1877 .tag = .add_immediate,
1878 .data = .{ .rr_imm12_sh = .{
1879 .rd = count,
1880 .rn = count,
1881 .imm12 = 1,
1882 } },
1883 });
1884
1885 // b loop
1886 _ = try self.addInst(.{
1887 .tag = .b,
1888 .data = .{ .inst = @intCast(u32, self.mir_instructions.len - 5) },
1889 });
1890
1891 // end:
1892}
1893
1314fn airLoad(self: *Self, inst: Air.Inst.Index) !void {1894fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1315 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1895 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1316 const elem_ty = self.air.typeOfIndex(inst);1896 const elem_ty = self.air.typeOfIndex(inst);
...@@ -1337,11 +1917,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -1337,11 +1917,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1337 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1917 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1338}1918}
13391919
1340fn airStore(self: *Self, inst: Air.Inst.Index) !void {1920fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
1341 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1342 const ptr = try self.resolveInst(bin_op.lhs);
1343 const value = try self.resolveInst(bin_op.rhs);
1344 const elem_ty = self.air.typeOf(bin_op.rhs);
1345 switch (ptr) {1921 switch (ptr) {
1346 .none => unreachable,1922 .none => unreachable,
1347 .undef => unreachable,1923 .undef => unreachable,
...@@ -1350,13 +1926,13 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void {...@@ -1350,13 +1926,13 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void {
1350 .compare_flags_unsigned => unreachable,1926 .compare_flags_unsigned => unreachable,
1351 .compare_flags_signed => unreachable,1927 .compare_flags_signed => unreachable,
1352 .immediate => |imm| {1928 .immediate => |imm| {
1353 try self.setRegOrMem(elem_ty, .{ .memory = imm }, value);1929 try self.setRegOrMem(value_ty, .{ .memory = imm }, value);
1354 },1930 },
1355 .ptr_stack_offset => |off| {1931 .ptr_stack_offset => |off| {
1356 try self.genSetStack(elem_ty, off, value);1932 try self.genSetStack(value_ty, off, value);
1357 },1933 },
1358 .ptr_embedded_in_code => |off| {1934 .ptr_embedded_in_code => |off| {
1359 try self.setRegOrMem(elem_ty, .{ .embedded_in_code = off }, value);1935 try self.setRegOrMem(value_ty, .{ .embedded_in_code = off }, value);
1360 },1936 },
1361 .embedded_in_code => {1937 .embedded_in_code => {
1362 return self.fail("TODO implement storing to MCValue.embedded_in_code", .{});1938 return self.fail("TODO implement storing to MCValue.embedded_in_code", .{});
...@@ -1364,33 +1940,55 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void {...@@ -1364,33 +1940,55 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void {
1364 .register => {1940 .register => {
1365 return self.fail("TODO implement storing to MCValue.register", .{});1941 return self.fail("TODO implement storing to MCValue.register", .{});
1366 },1942 },
1367 .memory => {1943 .memory,
1368 return self.fail("TODO implement storing to MCValue.memory", .{});1944 .stack_offset,
1369 },1945 => {
1370 .stack_offset => {1946 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);
1371 return self.fail("TODO implement storing to MCValue.stack_offset", .{});1947 try self.store(.{ .register = addr_reg }, value, ptr_ty, value_ty);
1372 },1948 },
1373 }1949 }
1950}
1951
1952fn airStore(self: *Self, inst: Air.Inst.Index) !void {
1953 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1954 const ptr = try self.resolveInst(bin_op.lhs);
1955 const value = try self.resolveInst(bin_op.rhs);
1956 const ptr_ty = self.air.typeOf(bin_op.lhs);
1957 const value_ty = self.air.typeOf(bin_op.rhs);
1958
1959 try self.store(ptr, value, ptr_ty, value_ty);
1960
1374 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });1961 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1375}1962}
13761963
1377fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {1964fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {
1378 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1965 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1379 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;1966 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
1380 return self.structFieldPtr(extra.struct_operand, ty_pl.ty, extra.field_index);1967 const result = try self.structFieldPtr(inst, extra.struct_operand, extra.field_index);
1968 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
1381}1969}
13821970
1383fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {1971fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
1384 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1972 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1385 return self.structFieldPtr(ty_op.operand, ty_op.ty, index);1973 const result = try self.structFieldPtr(inst, ty_op.operand, index);
1974 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1386}1975}
1387fn structFieldPtr(self: *Self, operand: Air.Inst.Ref, ty: Air.Inst.Ref, index: u32) !void {1976
1388 _ = self;1977fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
1389 _ = operand;1978 return if (self.liveness.isUnused(inst)) .dead else result: {
1390 _ = ty;1979 const mcv = try self.resolveInst(operand);
1391 _ = index;1980 const struct_ty = self.air.typeOf(operand).childType();
1392 return self.fail("TODO implement codegen struct_field_ptr", .{});1981 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));
1393 //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });1982 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
1983 const struct_field_ty = struct_ty.structFieldType(index);
1984 const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*));
1985 switch (mcv) {
1986 .ptr_stack_offset => |off| {
1987 break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size };
1988 },
1989 else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}),
1990 }
1991 };
1394}1992}
13951993
1396fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {1994fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
...@@ -1487,49 +2085,55 @@ fn airFence(self: *Self) !void {...@@ -1487,49 +2085,55 @@ fn airFence(self: *Self) !void {
14872085
1488fn airCall(self: *Self, inst: Air.Inst.Index) !void {2086fn airCall(self: *Self, inst: Air.Inst.Index) !void {
1489 const pl_op = self.air.instructions.items(.data)[inst].pl_op;2087 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
1490 const fn_ty = self.air.typeOf(pl_op.operand);
1491 const callee = pl_op.operand;2088 const callee = pl_op.operand;
1492 const extra = self.air.extraData(Air.Call, pl_op.payload);2089 const extra = self.air.extraData(Air.Call, pl_op.payload);
1493 const args = @bitCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);2090 const args = @bitCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);
2091 const ty = self.air.typeOf(callee);
2092
2093 const fn_ty = switch (ty.zigTypeTag()) {
2094 .Fn => ty,
2095 .Pointer => ty.childType(),
2096 else => unreachable,
2097 };
14942098
1495 var info = try self.resolveCallingConventionValues(fn_ty);2099 var info = try self.resolveCallingConventionValues(fn_ty);
1496 defer info.deinit(self);2100 defer info.deinit(self);
14972101
1498 // Due to incremental compilation, how function calls are generated depends2102 for (info.args) |mc_arg, arg_i| {
1499 // on linking.2103 const arg = args[arg_i];
1500 if (self.bin_file.tag == link.File.Elf.base_tag or self.bin_file.tag == link.File.Coff.base_tag) {2104 const arg_ty = self.air.typeOf(arg);
1501 for (info.args) |mc_arg, arg_i| {2105 const arg_mcv = try self.resolveInst(args[arg_i]);
1502 const arg = args[arg_i];2106
1503 const arg_ty = self.air.typeOf(arg);2107 switch (mc_arg) {
1504 const arg_mcv = try self.resolveInst(args[arg_i]);2108 .none => continue,
15052109 .undef => unreachable,
1506 switch (mc_arg) {2110 .immediate => unreachable,
1507 .none => continue,2111 .unreach => unreachable,
1508 .undef => unreachable,2112 .dead => unreachable,
1509 .immediate => unreachable,2113 .embedded_in_code => unreachable,
1510 .unreach => unreachable,2114 .memory => unreachable,
1511 .dead => unreachable,2115 .compare_flags_signed => unreachable,
1512 .embedded_in_code => unreachable,2116 .compare_flags_unsigned => unreachable,
1513 .memory => unreachable,2117 .register => |reg| {
1514 .compare_flags_signed => unreachable,2118 try self.register_manager.getReg(reg, null);
1515 .compare_flags_unsigned => unreachable,2119 try self.genSetReg(arg_ty, reg, arg_mcv);
1516 .register => |reg| {2120 },
1517 try self.register_manager.getReg(reg, null);2121 .stack_offset => {
1518 try self.genSetReg(arg_ty, reg, arg_mcv);2122 return self.fail("TODO implement calling with parameters in memory", .{});
1519 },2123 },
1520 .stack_offset => {2124 .ptr_stack_offset => {
1521 return self.fail("TODO implement calling with parameters in memory", .{});2125 return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});
1522 },2126 },
1523 .ptr_stack_offset => {2127 .ptr_embedded_in_code => {
1524 return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});2128 return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
1525 },2129 },
1526 .ptr_embedded_in_code => {
1527 return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
1528 },
1529 }
1530 }2130 }
2131 }
15312132
1532 if (self.air.value(callee)) |func_value| {2133 // Due to incremental compilation, how function calls are generated depends
2134 // on linking.
2135 if (self.air.value(callee)) |func_value| {
2136 if (self.bin_file.tag == link.File.Elf.base_tag or self.bin_file.tag == link.File.Coff.base_tag) {
1533 if (func_value.castTag(.function)) |func_payload| {2137 if (func_value.castTag(.function)) |func_payload| {
1534 const func = func_payload.data;2138 const func = func_payload.data;
1535 const ptr_bits = self.target.cpu.arch.ptrBitWidth();2139 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
...@@ -1553,45 +2157,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -1553,45 +2157,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
1553 } else {2157 } else {
1554 return self.fail("TODO implement calling bitcasted functions", .{});2158 return self.fail("TODO implement calling bitcasted functions", .{});
1555 }2159 }
1556 } else {2160 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
1557 return self.fail("TODO implement calling runtime known function pointer", .{});
1558 }
1559 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
1560 for (info.args) |mc_arg, arg_i| {
1561 const arg = args[arg_i];
1562 const arg_ty = self.air.typeOf(arg);
1563 const arg_mcv = try self.resolveInst(args[arg_i]);
1564 // Here we do not use setRegOrMem even though the logic is similar, because
1565 // the function call will move the stack pointer, so the offsets are different.
1566 switch (mc_arg) {
1567 .none => continue,
1568 .register => |reg| {
1569 try self.register_manager.getReg(reg, null);
1570 try self.genSetReg(arg_ty, reg, arg_mcv);
1571 },
1572 .stack_offset => {
1573 // Here we need to emit instructions like this:
1574 // mov qword ptr [rsp + stack_offset], x
1575 return self.fail("TODO implement calling with parameters in memory", .{});
1576 },
1577 .ptr_stack_offset => {
1578 return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});
1579 },
1580 .ptr_embedded_in_code => {
1581 return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
1582 },
1583 .undef => unreachable,
1584 .immediate => unreachable,
1585 .unreach => unreachable,
1586 .dead => unreachable,
1587 .embedded_in_code => unreachable,
1588 .memory => unreachable,
1589 .compare_flags_signed => unreachable,
1590 .compare_flags_unsigned => unreachable,
1591 }
1592 }
1593
1594 if (self.air.value(callee)) |func_value| {
1595 if (func_value.castTag(.function)) |func_payload| {2161 if (func_value.castTag(.function)) |func_payload| {
1596 const func = func_payload.data;2162 const func = func_payload.data;
1597 // TODO I'm hacking my way through here by repurposing .memory for storing2163 // TODO I'm hacking my way through here by repurposing .memory for storing
...@@ -1627,41 +2193,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -1627,41 +2193,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
1627 } else {2193 } else {
1628 return self.fail("TODO implement calling bitcasted functions", .{});2194 return self.fail("TODO implement calling bitcasted functions", .{});
1629 }2195 }
1630 } else {2196 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
1631 return self.fail("TODO implement calling runtime known function pointer", .{});
1632 }
1633 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
1634 for (info.args) |mc_arg, arg_i| {
1635 const arg = args[arg_i];
1636 const arg_ty = self.air.typeOf(arg);
1637 const arg_mcv = try self.resolveInst(args[arg_i]);
1638
1639 switch (mc_arg) {
1640 .none => continue,
1641 .undef => unreachable,
1642 .immediate => unreachable,
1643 .unreach => unreachable,
1644 .dead => unreachable,
1645 .embedded_in_code => unreachable,
1646 .memory => unreachable,
1647 .compare_flags_signed => unreachable,
1648 .compare_flags_unsigned => unreachable,
1649 .register => |reg| {
1650 try self.register_manager.getReg(reg, null);
1651 try self.genSetReg(arg_ty, reg, arg_mcv);
1652 },
1653 .stack_offset => {
1654 return self.fail("TODO implement calling with parameters in memory", .{});
1655 },
1656 .ptr_stack_offset => {
1657 return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});
1658 },
1659 .ptr_embedded_in_code => {
1660 return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
1661 },
1662 }
1663 }
1664 if (self.air.value(callee)) |func_value| {
1665 if (func_value.castTag(.function)) |func_payload| {2197 if (func_value.castTag(.function)) |func_payload| {
1666 try p9.seeDecl(func_payload.data.owner_decl);2198 try p9.seeDecl(func_payload.data.owner_decl);
1667 const ptr_bits = self.target.cpu.arch.ptrBitWidth();2199 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
...@@ -1681,10 +2213,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -1681,10 +2213,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
1681 } else {2213 } else {
1682 return self.fail("TODO implement calling bitcasted functions", .{});2214 return self.fail("TODO implement calling bitcasted functions", .{});
1683 }2215 }
1684 } else {2216 } else unreachable;
1685 return self.fail("TODO implement calling runtime known function pointer", .{});2217 } else {
1686 }2218 assert(ty.zigTypeTag() == .Pointer);
1687 } else unreachable;2219 const mcv = try self.resolveInst(callee);
2220 try self.genSetReg(ty, .x30, mcv);
2221
2222 _ = try self.addInst(.{
2223 .tag = .blr,
2224 .data = .{ .reg = .x30 },
2225 });
2226 }
16882227
1689 const result: MCValue = result: {2228 const result: MCValue = result: {
1690 switch (info.return_value) {2229 switch (info.return_value) {
...@@ -1741,12 +2280,23 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -1741,12 +2280,23 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
17412280
1742fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {2281fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1743 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2282 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2283
1744 if (self.liveness.isUnused(inst))2284 if (self.liveness.isUnused(inst))
1745 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });2285 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
2286
1746 const ty = self.air.typeOf(bin_op.lhs);2287 const ty = self.air.typeOf(bin_op.lhs);
1747 assert(ty.eql(self.air.typeOf(bin_op.rhs)));2288
1748 if (ty.zigTypeTag() == .ErrorSet)2289 if (ty.abiSize(self.target.*) > 8) {
1749 return self.fail("TODO implement cmp for errors", .{});2290 return self.fail("TODO cmp for types with size > 8", .{});
2291 }
2292
2293 const signedness: std.builtin.Signedness = blk: {
2294 // by default we tell the operand type is unsigned (i.e. bools and enum values)
2295 if (ty.zigTypeTag() != .Int) break :blk .unsigned;
2296
2297 // incase of an actual integer, we emit the correct signedness
2298 break :blk ty.intInfo(self.target.*).signedness;
2299 };
17502300
1751 const lhs = try self.resolveInst(bin_op.lhs);2301 const lhs = try self.resolveInst(bin_op.lhs);
1752 const rhs = try self.resolveInst(bin_op.rhs);2302 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -1812,8 +2362,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -1812,8 +2362,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1812 .immediate => |imm| {2362 .immediate => |imm| {
1813 _ = try self.addInst(.{2363 _ = try self.addInst(.{
1814 .tag = .cmp_immediate,2364 .tag = .cmp_immediate,
1815 .data = .{ .rr_imm12_sh = .{2365 .data = .{ .r_imm12_sh = .{
1816 .rd = .xzr,
1817 .rn = lhs_mcv.register,2366 .rn = lhs_mcv.register,
1818 .imm12 = @intCast(u12, imm),2367 .imm12 = @intCast(u12, imm),
1819 } },2368 } },
...@@ -1822,9 +2371,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -1822,9 +2371,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1822 else => unreachable,2371 else => unreachable,
1823 }2372 }
18242373
1825 break :result switch (ty.isSignedInt()) {2374 break :result switch (signedness) {
1826 true => MCValue{ .compare_flags_signed = op },2375 .signed => MCValue{ .compare_flags_signed = op },
1827 false => MCValue{ .compare_flags_unsigned = op },2376 .unsigned => MCValue{ .compare_flags_unsigned = op },
1828 };2377 };
1829 };2378 };
1830 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2379 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
...@@ -1876,7 +2425,22 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1876,7 +2425,22 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1876 },2425 },
1877 },2426 },
1878 }),2427 }),
1879 else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(cond)}),2428 else => blk: {
2429 const reg = switch (cond) {
2430 .register => |r| r,
2431 else => try self.copyToTmpRegister(Type.bool, cond),
2432 };
2433
2434 break :blk try self.addInst(.{
2435 .tag = .cbz,
2436 .data = .{
2437 .r_inst = .{
2438 .rt = reg,
2439 .inst = undefined, // populated later through performReloc
2440 },
2441 },
2442 });
2443 },
1880 };2444 };
18812445
1882 // Capture the state of register and stack allocation state so that we can revert to it.2446 // Capture the state of register and stack allocation state so that we can revert to it.
...@@ -2008,18 +2572,51 @@ fn isNonNull(self: *Self, operand: MCValue) !MCValue {...@@ -2008,18 +2572,51 @@ fn isNonNull(self: *Self, operand: MCValue) !MCValue {
2008 return self.fail("TODO call isNull and invert the result", .{});2572 return self.fail("TODO call isNull and invert the result", .{});
2009}2573}
20102574
2011fn isErr(self: *Self, operand: MCValue) !MCValue {2575fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
2012 _ = operand;2576 _ = operand;
2013 // Here you can specialize this instruction if it makes sense to, otherwise the default2577
2014 // will call isNonNull and invert the result.2578 const error_type = ty.errorUnionSet();
2015 return self.fail("TODO call isNonErr and invert the result", .{});2579 const payload_type = ty.errorUnionPayload();
2580
2581 if (!error_type.hasRuntimeBits()) {
2582 return MCValue{ .immediate = 0 }; // always false
2583 } else if (!payload_type.hasRuntimeBits()) {
2584 if (error_type.abiSize(self.target.*) <= 8) {
2585 const reg_mcv: MCValue = switch (operand) {
2586 .register => operand,
2587 else => .{ .register = try self.copyToTmpRegister(error_type, operand) },
2588 };
2589
2590 _ = try self.addInst(.{
2591 .tag = .cmp_immediate,
2592 .data = .{ .r_imm12_sh = .{
2593 .rn = reg_mcv.register,
2594 .imm12 = 0,
2595 } },
2596 });
2597
2598 return MCValue{ .compare_flags_unsigned = .gt };
2599 } else {
2600 return self.fail("TODO isErr for errors with size > 8", .{});
2601 }
2602 } else {
2603 return self.fail("TODO isErr for non-empty payloads", .{});
2604 }
2016}2605}
20172606
2018fn isNonErr(self: *Self, operand: MCValue) !MCValue {2607fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
2019 _ = operand;2608 const is_err_result = try self.isErr(ty, operand);
2020 // Here you can specialize this instruction if it makes sense to, otherwise the default2609 switch (is_err_result) {
2021 // will call isNull and invert the result.2610 .compare_flags_unsigned => |op| {
2022 return self.fail("TODO call isErr and invert the result", .{});2611 assert(op == .gt);
2612 return MCValue{ .compare_flags_unsigned = .lte };
2613 },
2614 .immediate => |imm| {
2615 assert(imm == 0);
2616 return MCValue{ .immediate = 1 };
2617 },
2618 else => unreachable,
2619 }
2023}2620}
20242621
2025fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {2622fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
...@@ -2080,7 +2677,8 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2080,7 +2677,8 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
2080 const un_op = self.air.instructions.items(.data)[inst].un_op;2677 const un_op = self.air.instructions.items(.data)[inst].un_op;
2081 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2678 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2082 const operand = try self.resolveInst(un_op);2679 const operand = try self.resolveInst(un_op);
2083 break :result try self.isErr(operand);2680 const ty = self.air.typeOf(un_op);
2681 break :result try self.isErr(ty, operand);
2084 };2682 };
2085 return self.finishAir(inst, result, .{ un_op, .none, .none });2683 return self.finishAir(inst, result, .{ un_op, .none, .none });
2086}2684}
...@@ -2089,6 +2687,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2089,6 +2687,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2089 const un_op = self.air.instructions.items(.data)[inst].un_op;2687 const un_op = self.air.instructions.items(.data)[inst].un_op;
2090 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2688 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2091 const operand_ptr = try self.resolveInst(un_op);2689 const operand_ptr = try self.resolveInst(un_op);
2690 const ptr_ty = self.air.typeOf(un_op);
2092 const operand: MCValue = blk: {2691 const operand: MCValue = blk: {
2093 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {2692 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
2094 // The MCValue that holds the pointer can be re-used as the value.2693 // The MCValue that holds the pointer can be re-used as the value.
...@@ -2098,7 +2697,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2098,7 +2697,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2098 }2697 }
2099 };2698 };
2100 try self.load(operand, operand_ptr, self.air.typeOf(un_op));2699 try self.load(operand, operand_ptr, self.air.typeOf(un_op));
2101 break :result try self.isErr(operand);2700 break :result try self.isErr(ptr_ty.elemType(), operand);
2102 };2701 };
2103 return self.finishAir(inst, result, .{ un_op, .none, .none });2702 return self.finishAir(inst, result, .{ un_op, .none, .none });
2104}2703}
...@@ -2107,7 +2706,8 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2107,7 +2706,8 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
2107 const un_op = self.air.instructions.items(.data)[inst].un_op;2706 const un_op = self.air.instructions.items(.data)[inst].un_op;
2108 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2707 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2109 const operand = try self.resolveInst(un_op);2708 const operand = try self.resolveInst(un_op);
2110 break :result try self.isNonErr(operand);2709 const ty = self.air.typeOf(un_op);
2710 break :result try self.isNonErr(ty, operand);
2111 };2711 };
2112 return self.finishAir(inst, result, .{ un_op, .none, .none });2712 return self.finishAir(inst, result, .{ un_op, .none, .none });
2113}2713}
...@@ -2116,6 +2716,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2116,6 +2716,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2116 const un_op = self.air.instructions.items(.data)[inst].un_op;2716 const un_op = self.air.instructions.items(.data)[inst].un_op;
2117 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2717 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2118 const operand_ptr = try self.resolveInst(un_op);2718 const operand_ptr = try self.resolveInst(un_op);
2719 const ptr_ty = self.air.typeOf(un_op);
2119 const operand: MCValue = blk: {2720 const operand: MCValue = blk: {
2120 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {2721 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
2121 // The MCValue that holds the pointer can be re-used as the value.2722 // The MCValue that holds the pointer can be re-used as the value.
...@@ -2125,7 +2726,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2125,7 +2726,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2125 }2726 }
2126 };2727 };
2127 try self.load(operand, operand_ptr, self.air.typeOf(un_op));2728 try self.load(operand, operand_ptr, self.air.typeOf(un_op));
2128 break :result try self.isNonErr(operand);2729 break :result try self.isNonErr(ptr_ty.elemType(), operand);
2129 };2730 };
2130 return self.finishAir(inst, result, .{ un_op, .none, .none });2731 return self.finishAir(inst, result, .{ un_op, .none, .none });
2131}2732}
...@@ -2184,8 +2785,9 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {...@@ -2184,8 +2785,9 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
2184fn performReloc(self: *Self, inst: Mir.Inst.Index) !void {2785fn performReloc(self: *Self, inst: Mir.Inst.Index) !void {
2185 const tag = self.mir_instructions.items(.tag)[inst];2786 const tag = self.mir_instructions.items(.tag)[inst];
2186 switch (tag) {2787 switch (tag) {
2187 .b_cond => self.mir_instructions.items(.data)[inst].inst_cond.inst = @intCast(Air.Inst.Index, self.mir_instructions.len),2788 .cbz => self.mir_instructions.items(.data)[inst].r_inst.inst = @intCast(Mir.Inst.Index, self.mir_instructions.len),
2188 .b => self.mir_instructions.items(.data)[inst].inst = @intCast(Air.Inst.Index, self.mir_instructions.len),2789 .b_cond => self.mir_instructions.items(.data)[inst].inst_cond.inst = @intCast(Mir.Inst.Index, self.mir_instructions.len),
2790 .b => self.mir_instructions.items(.data)[inst].inst = @intCast(Mir.Inst.Index, self.mir_instructions.len),
2189 else => unreachable,2791 else => unreachable,
2190 }2792 }
2191}2793}
...@@ -2212,7 +2814,16 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {...@@ -2212,7 +2814,16 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
2212 const operand_mcv = try self.resolveInst(operand);2814 const operand_mcv = try self.resolveInst(operand);
2213 const block_mcv = block_data.mcv;2815 const block_mcv = block_data.mcv;
2214 if (block_mcv == .none) {2816 if (block_mcv == .none) {
2215 block_data.mcv = operand_mcv;2817 block_data.mcv = switch (operand_mcv) {
2818 .none, .dead, .unreach => unreachable,
2819 .register, .stack_offset, .memory => operand_mcv,
2820 .immediate => blk: {
2821 const new_mcv = try self.allocRegOrMem(block, true);
2822 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
2823 break :blk new_mcv;
2824 },
2825 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),
2826 };
2216 } else {2827 } else {
2217 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);2828 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);
2218 }2829 }
...@@ -2412,8 +3023,61 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -2412,8 +3023,61 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
2412 if (stack_offset == off)3023 if (stack_offset == off)
2413 return; // Copy stack variable to itself; nothing to do.3024 return; // Copy stack variable to itself; nothing to do.
24143025
2415 const reg = try self.copyToTmpRegister(ty, mcv);3026 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
2416 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });3027 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
3028 if (ty.abiSize(self.target.*) <= ptr_bytes) {
3029 const reg = try self.copyToTmpRegister(ty, mcv);
3030 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
3031 } else {
3032 // TODO optimize the register allocation
3033 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });
3034 self.register_manager.freezeRegs(&regs);
3035 defer self.register_manager.unfreezeRegs(&regs);
3036
3037 const src_reg = regs[0];
3038 const dst_reg = regs[1];
3039 const len_reg = regs[2];
3040 const count_reg = regs[3];
3041 const tmp_reg = regs[4];
3042
3043 // sub src_reg, fp, #off
3044 const adj_src_offset = off + @intCast(u32, ty.abiSize(self.target.*));
3045 const src_offset = math.cast(u12, adj_src_offset) catch return self.fail("TODO load: larger stack offsets", .{});
3046 _ = try self.addInst(.{
3047 .tag = .sub_immediate,
3048 .data = .{ .rr_imm12_sh = .{
3049 .rd = src_reg,
3050 .rn = .x29,
3051 .imm12 = src_offset,
3052 } },
3053 });
3054
3055 // sub dst_reg, fp, #stack_offset
3056 const adj_dst_off = stack_offset + @intCast(u32, ty.abiSize(self.target.*));
3057 const dst_offset = math.cast(u12, adj_dst_off) catch return self.fail("TODO load: larger stack offsets", .{});
3058 _ = try self.addInst(.{
3059 .tag = .sub_immediate,
3060 .data = .{ .rr_imm12_sh = .{
3061 .rd = dst_reg,
3062 .rn = .x29,
3063 .imm12 = dst_offset,
3064 } },
3065 });
3066
3067 // mov len, #elem_size
3068 const elem_size = @intCast(u32, ty.abiSize(self.target.*));
3069 const len_imm = math.cast(u16, elem_size) catch return self.fail("TODO load: larger stack offsets", .{});
3070 _ = try self.addInst(.{
3071 .tag = .movk,
3072 .data = .{ .r_imm16_sh = .{
3073 .rd = len_reg,
3074 .imm16 = len_imm,
3075 } },
3076 });
3077
3078 // memcpy(src, dst, len)
3079 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
3080 }
2417 },3081 },
2418 }3082 }
2419}3083}
...@@ -2445,11 +3109,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -2445,11 +3109,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
24453109
2446 _ = try self.addInst(.{3110 _ = try self.addInst(.{
2447 .tag = .cset,3111 .tag = .cset,
2448 .data = .{ .rrr_cond = .{3112 .data = .{ .r_cond = .{
2449 .rd = reg,3113 .rd = reg,
2450 .rn = .xzr,3114 .cond = condition.negate(),
2451 .rm = .xzr,
2452 .cond = condition,
2453 } },3115 } },
2454 });3116 });
2455 },3117 },
...@@ -2533,7 +3195,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -2533,7 +3195,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
2533 } },3195 } },
2534 });3196 });
2535 },3197 },
2536 else => return self.fail("TODO implement genSetReg other types abi_size={}", .{abi_size}),3198 3, 5, 6, 7 => return self.fail("TODO implement genSetReg types size {}", .{abi_size}),
3199 else => unreachable,
2537 }3200 }
2538 },3201 },
2539 else => return self.fail("TODO implement genSetReg for aarch64 {}", .{mcv}),3202 else => return self.fail("TODO implement genSetReg for aarch64 {}", .{mcv}),
...@@ -2713,27 +3376,6 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -2713,27 +3376,6 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
2713 }3376 }
2714}3377}
27153378
2716/// If the MCValue is an immediate, and it does not fit within this type,
2717/// we put it in a register.
2718/// A potential opportunity for future optimization here would be keeping track
2719/// of the fact that the instruction is available both as an immediate
2720/// and as a register.
2721fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCValue {
2722 const mcv = try self.resolveInst(operand);
2723 const ti = @typeInfo(T).Int;
2724 switch (mcv) {
2725 .immediate => |imm| {
2726 // This immediate is unsigned.
2727 const U = std.meta.Int(.unsigned, ti.bits - @boolToInt(ti.signedness == .signed));
2728 if (imm >= math.maxInt(U)) {
2729 return MCValue{ .register = try self.copyToTmpRegister(Type.initTag(.usize), mcv) };
2730 }
2731 },
2732 else => {},
2733 }
2734 return mcv;
2735}
2736
2737fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {3379fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {
2738 const ptr_bits = self.target.cpu.arch.ptrBitWidth();3380 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
2739 const ptr_bytes: u64 = @divExact(ptr_bits, 8);3381 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
...@@ -2847,31 +3489,32 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -2847,31 +3489,32 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
2847 }3489 }
2848 },3490 },
2849 .ErrorSet => {3491 .ErrorSet => {
2850 switch (typed_value.val.tag()) {3492 const err_name = typed_value.val.castTag(.@"error").?.data.name;
2851 .@"error" => {3493 const module = self.bin_file.options.module.?;
2852 const err_name = typed_value.val.castTag(.@"error").?.data.name;3494 const global_error_set = module.global_error_set;
2853 const module = self.bin_file.options.module.?;3495 const error_index = global_error_set.get(err_name).?;
2854 const global_error_set = module.global_error_set;3496 return MCValue{ .immediate = error_index };
2855 const error_index = global_error_set.get(err_name).?;
2856 return MCValue{ .immediate = error_index };
2857 },
2858 else => {
2859 // In this case we are rendering an error union which has a 0 bits payload.
2860 return MCValue{ .immediate = 0 };
2861 },
2862 }
2863 },3497 },
2864 .ErrorUnion => {3498 .ErrorUnion => {
2865 const error_type = typed_value.ty.errorUnionSet();3499 const error_type = typed_value.ty.errorUnionSet();
2866 const payload_type = typed_value.ty.errorUnionPayload();3500 const payload_type = typed_value.ty.errorUnionPayload();
2867 const sub_val = typed_value.val.castTag(.eu_payload).?.data;
28683501
2869 if (!payload_type.hasRuntimeBits()) {3502 if (typed_value.val.castTag(.eu_payload)) |pl| {
2870 // We use the error type directly as the type.3503 if (!payload_type.hasRuntimeBits()) {
2871 return self.genTypedValue(.{ .ty = error_type, .val = sub_val });3504 // We use the error type directly as the type.
2872 }3505 return MCValue{ .immediate = 0 };
3506 }
28733507
2874 return self.fail("TODO implement error union const of type '{}'", .{typed_value.ty});3508 _ = pl;
3509 return self.fail("TODO implement error union const of type '{}' (non-error)", .{typed_value.ty});
3510 } else {
3511 if (!payload_type.hasRuntimeBits()) {
3512 // We use the error type directly as the type.
3513 return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val });
3514 }
3515
3516 return self.fail("TODO implement error union const of type '{}' (error)", .{typed_value.ty});
3517 }
2875 },3518 },
2876 else => return self.fail("TODO implement const of type '{}'", .{typed_value.ty}),3519 else => return self.fail("TODO implement const of type '{}'", .{typed_value.ty}),
2877 }3520 }
...@@ -3015,13 +3658,18 @@ fn parseRegName(name: []const u8) ?Register {...@@ -3015,13 +3658,18 @@ fn parseRegName(name: []const u8) ?Register {
3015}3658}
30163659
3017fn registerAlias(reg: Register, size_bytes: u32) Register {3660fn registerAlias(reg: Register, size_bytes: u32) Register {
3018 _ = size_bytes;3661 if (size_bytes == 0) {
30193662 unreachable; // should be comptime known
3020 return reg;3663 } else if (size_bytes <= 4) {
3664 return reg.to32();
3665 } else if (size_bytes <= 8) {
3666 return reg.to64();
3667 } else {
3668 unreachable; // TODO handle floating-point registers
3669 }
3021}3670}
30223671
3023/// For most architectures this does nothing. For x86_64 it resolves any aliased registers3672/// Resolves any aliased registers to the 64-bit wide ones.
3024/// to the 64-bit wide ones.
3025fn toCanonicalReg(reg: Register) Register {3673fn toCanonicalReg(reg: Register) Register {
3026 return reg;3674 return reg.to64();
3027}3675}
src/arch/aarch64/Emit.zig+131-56
...@@ -50,11 +50,13 @@ const InnerError = error{...@@ -50,11 +50,13 @@ const InnerError = error{
50};50};
5151
52const BranchType = enum {52const BranchType = enum {
53 cbz,
53 b_cond,54 b_cond,
54 unconditional_branch_immediate,55 unconditional_branch_immediate,
5556
56 fn default(tag: Mir.Inst.Tag) BranchType {57 fn default(tag: Mir.Inst.Tag) BranchType {
57 return switch (tag) {58 return switch (tag) {
59 .cbz => .cbz,
58 .b, .bl => .unconditional_branch_immediate,60 .b, .bl => .unconditional_branch_immediate,
59 .b_cond => .b_cond,61 .b_cond => .b_cond,
60 else => unreachable,62 else => unreachable,
...@@ -83,6 +85,8 @@ pub fn emitMir(...@@ -83,6 +85,8 @@ pub fn emitMir(
83 .b => try emit.mirBranch(inst),85 .b => try emit.mirBranch(inst),
84 .bl => try emit.mirBranch(inst),86 .bl => try emit.mirBranch(inst),
8587
88 .cbz => try emit.mirCompareAndBranch(inst),
89
86 .blr => try emit.mirUnconditionalBranchRegister(inst),90 .blr => try emit.mirUnconditionalBranchRegister(inst),
87 .ret => try emit.mirUnconditionalBranchRegister(inst),91 .ret => try emit.mirUnconditionalBranchRegister(inst),
8892
...@@ -91,7 +95,9 @@ pub fn emitMir(...@@ -91,7 +95,9 @@ pub fn emitMir(
9195
92 .call_extern => try emit.mirCallExtern(inst),96 .call_extern => try emit.mirCallExtern(inst),
9397
98 .add_shifted_register => try emit.mirAddSubtractShiftedRegister(inst),
94 .cmp_shifted_register => try emit.mirAddSubtractShiftedRegister(inst),99 .cmp_shifted_register => try emit.mirAddSubtractShiftedRegister(inst),
100 .sub_shifted_register => try emit.mirAddSubtractShiftedRegister(inst),
95101
96 .cset => try emit.mirConditionalSelect(inst),102 .cset => try emit.mirConditionalSelect(inst),
97103
...@@ -100,6 +106,8 @@ pub fn emitMir(...@@ -100,6 +106,8 @@ pub fn emitMir(
100 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),106 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),
101 .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),107 .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),
102108
109 .eor_shifted_register => try emit.mirLogicalShiftedRegister(inst),
110
103 .load_memory => try emit.mirLoadMemory(inst),111 .load_memory => try emit.mirLoadMemory(inst),
104112
105 .ldp => try emit.mirLoadStoreRegisterPair(inst),113 .ldp => try emit.mirLoadStoreRegisterPair(inst),
...@@ -128,10 +136,13 @@ pub fn emitMir(...@@ -128,10 +136,13 @@ pub fn emitMir(
128136
129 .mov_register => try emit.mirMoveRegister(inst),137 .mov_register => try emit.mirMoveRegister(inst),
130 .mov_to_from_sp => try emit.mirMoveRegister(inst),138 .mov_to_from_sp => try emit.mirMoveRegister(inst),
139 .mvn => try emit.mirMoveRegister(inst),
131140
132 .movk => try emit.mirMoveWideImmediate(inst),141 .movk => try emit.mirMoveWideImmediate(inst),
133 .movz => try emit.mirMoveWideImmediate(inst),142 .movz => try emit.mirMoveWideImmediate(inst),
134143
144 .mul => try emit.mirDataProcessing3Source(inst),
145
135 .nop => try emit.mirNop(),146 .nop => try emit.mirNop(),
136147
137 .push_regs => try emit.mirPushPopRegs(inst),148 .push_regs => try emit.mirPushPopRegs(inst),
...@@ -156,15 +167,22 @@ fn optimalBranchType(emit: *Emit, tag: Mir.Inst.Tag, offset: i64) !BranchType {...@@ -156,15 +167,22 @@ fn optimalBranchType(emit: *Emit, tag: Mir.Inst.Tag, offset: i64) !BranchType {
156 assert(offset & 0b11 == 0);167 assert(offset & 0b11 == 0);
157168
158 switch (tag) {169 switch (tag) {
170 .cbz => {
171 if (std.math.cast(i19, @shrExact(offset, 2))) |_| {
172 return BranchType.cbz;
173 } else |_| {
174 return emit.fail("TODO support cbz branches larger than +-1 MiB", .{});
175 }
176 },
159 .b, .bl => {177 .b, .bl => {
160 if (std.math.cast(i26, offset >> 2)) |_| {178 if (std.math.cast(i26, @shrExact(offset, 2))) |_| {
161 return BranchType.unconditional_branch_immediate;179 return BranchType.unconditional_branch_immediate;
162 } else |_| {180 } else |_| {
163 return emit.fail("TODO support branches larger than +-128 MiB", .{});181 return emit.fail("TODO support unconditional branches larger than +-128 MiB", .{});
164 }182 }
165 },183 },
166 .b_cond => {184 .b_cond => {
167 if (std.math.cast(i19, offset >> 2)) |_| {185 if (std.math.cast(i19, @shrExact(offset, 2))) |_| {
168 return BranchType.b_cond;186 return BranchType.b_cond;
169 } else |_| {187 } else |_| {
170 return emit.fail("TODO support conditional branches larger than +-1 MiB", .{});188 return emit.fail("TODO support conditional branches larger than +-1 MiB", .{});
...@@ -179,8 +197,10 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {...@@ -179,8 +197,10 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
179197
180 if (isBranch(tag)) {198 if (isBranch(tag)) {
181 switch (emit.branch_types.get(inst).?) {199 switch (emit.branch_types.get(inst).?) {
182 .unconditional_branch_immediate => return 4,200 .cbz,
183 .b_cond => return 4,201 .unconditional_branch_immediate,
202 .b_cond,
203 => return 4,
184 }204 }
185 }205 }
186206
...@@ -201,6 +221,12 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {...@@ -201,6 +221,12 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
201 return 5 * 4;221 return 5 * 4;
202 }222 }
203 },223 },
224 .pop_regs, .push_regs => {
225 const reg_list = emit.mir.instructions.items(.data)[inst].reg_list;
226 const number_of_regs = @popCount(u32, reg_list);
227 const number_of_insts = std.math.divCeil(u6, number_of_regs, 2) catch unreachable;
228 return number_of_insts * 4;
229 },
204 .call_extern => return 4,230 .call_extern => return 4,
205 .dbg_line,231 .dbg_line,
206 .dbg_epilogue_begin,232 .dbg_epilogue_begin,
...@@ -212,7 +238,11 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {...@@ -212,7 +238,11 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
212238
213fn isBranch(tag: Mir.Inst.Tag) bool {239fn isBranch(tag: Mir.Inst.Tag) bool {
214 return switch (tag) {240 return switch (tag) {
215 .b, .bl, .b_cond => true,241 .cbz,
242 .b,
243 .bl,
244 .b_cond,
245 => true,
216 else => false,246 else => false,
217 };247 };
218}248}
...@@ -221,6 +251,7 @@ fn branchTarget(emit: *Emit, inst: Mir.Inst.Index) Mir.Inst.Index {...@@ -221,6 +251,7 @@ fn branchTarget(emit: *Emit, inst: Mir.Inst.Index) Mir.Inst.Index {
221 const tag = emit.mir.instructions.items(.tag)[inst];251 const tag = emit.mir.instructions.items(.tag)[inst];
222252
223 switch (tag) {253 switch (tag) {
254 .cbz => return emit.mir.instructions.items(.data)[inst].r_inst.inst,
224 .b, .bl => return emit.mir.instructions.items(.data)[inst].inst,255 .b, .bl => return emit.mir.instructions.items(.data)[inst].inst,
225 .b_cond => return emit.mir.instructions.items(.data)[inst].inst_cond.inst,256 .b_cond => return emit.mir.instructions.items(.data)[inst].inst_cond.inst,
226 else => unreachable,257 else => unreachable,
...@@ -414,27 +445,30 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {...@@ -414,27 +445,30 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
414445
415fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {446fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
416 const tag = emit.mir.instructions.items(.tag)[inst];447 const tag = emit.mir.instructions.items(.tag)[inst];
417 const rr_imm12_sh = emit.mir.instructions.items(.data)[inst].rr_imm12_sh;
418
419 switch (tag) {448 switch (tag) {
420 .add_immediate => try emit.writeInstruction(Instruction.add(449 .add_immediate,
421 rr_imm12_sh.rd,450 .sub_immediate,
422 rr_imm12_sh.rn,451 => {
423 rr_imm12_sh.imm12,452 const rr_imm12_sh = emit.mir.instructions.items(.data)[inst].rr_imm12_sh;
424 rr_imm12_sh.sh == 1,453 const rd = rr_imm12_sh.rd;
425 )),454 const rn = rr_imm12_sh.rn;
426 .cmp_immediate => try emit.writeInstruction(Instruction.subs(455 const imm12 = rr_imm12_sh.imm12;
427 rr_imm12_sh.rd,456 const sh = rr_imm12_sh.sh == 1;
428 rr_imm12_sh.rn,457
429 rr_imm12_sh.imm12,458 switch (tag) {
430 rr_imm12_sh.sh == 1,459 .add_immediate => try emit.writeInstruction(Instruction.add(rd, rn, imm12, sh)),
431 )),460 .sub_immediate => try emit.writeInstruction(Instruction.sub(rd, rn, imm12, sh)),
432 .sub_immediate => try emit.writeInstruction(Instruction.sub(461 else => unreachable,
433 rr_imm12_sh.rd,462 }
434 rr_imm12_sh.rn,463 },
435 rr_imm12_sh.imm12,464 .cmp_immediate => {
436 rr_imm12_sh.sh == 1,465 const r_imm12_sh = emit.mir.instructions.items(.data)[inst].r_imm12_sh;
437 )),466 const rn = r_imm12_sh.rn;
467 const imm12 = r_imm12_sh.imm12;
468 const sh = r_imm12_sh.sh == 1;
469
470 try emit.writeInstruction(Instruction.subs(.xzr, rn, imm12, sh));
471 },
438 else => unreachable,472 else => unreachable,
439 }473 }
440}474}
...@@ -481,6 +515,23 @@ fn mirBranch(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -481,6 +515,23 @@ fn mirBranch(emit: *Emit, inst: Mir.Inst.Index) !void {
481 }515 }
482}516}
483517
518fn mirCompareAndBranch(emit: *Emit, inst: Mir.Inst.Index) !void {
519 const tag = emit.mir.instructions.items(.tag)[inst];
520 const r_inst = emit.mir.instructions.items(.data)[inst].r_inst;
521
522 const offset = @intCast(i64, emit.code_offset_mapping.get(r_inst.inst).?) - @intCast(i64, emit.code.items.len);
523 const branch_type = emit.branch_types.get(inst).?;
524 log.debug("mirCompareAndBranch: {} offset={}", .{ inst, offset });
525
526 switch (branch_type) {
527 .cbz => switch (tag) {
528 .cbz => try emit.writeInstruction(Instruction.cbz(r_inst.rt, @intCast(i21, offset))),
529 else => unreachable,
530 },
531 else => unreachable,
532 }
533}
534
484fn mirUnconditionalBranchRegister(emit: *Emit, inst: Mir.Inst.Index) !void {535fn mirUnconditionalBranchRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
485 const tag = emit.mir.instructions.items(.tag)[inst];536 const tag = emit.mir.instructions.items(.tag)[inst];
486 const reg = emit.mir.instructions.items(.data)[inst].reg;537 const reg = emit.mir.instructions.items(.data)[inst].reg;
...@@ -565,30 +616,42 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -565,30 +616,42 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
565fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {616fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
566 const tag = emit.mir.instructions.items(.tag)[inst];617 const tag = emit.mir.instructions.items(.tag)[inst];
567 const rrr_imm6_shift = emit.mir.instructions.items(.data)[inst].rrr_imm6_shift;618 const rrr_imm6_shift = emit.mir.instructions.items(.data)[inst].rrr_imm6_shift;
619 const rd = rrr_imm6_shift.rd;
620 const rn = rrr_imm6_shift.rn;
621 const rm = rrr_imm6_shift.rm;
622 const shift = rrr_imm6_shift.shift;
623 const imm6 = rrr_imm6_shift.imm6;
568624
569 switch (tag) {625 switch (tag) {
570 .cmp_shifted_register => try emit.writeInstruction(Instruction.subsShiftedRegister(626 .add_shifted_register => try emit.writeInstruction(Instruction.addShiftedRegister(rd, rn, rm, shift, imm6)),
571 rrr_imm6_shift.rd,627 .cmp_shifted_register => try emit.writeInstruction(Instruction.subsShiftedRegister(rd, rn, rm, shift, imm6)),
572 rrr_imm6_shift.rn,628 .sub_shifted_register => try emit.writeInstruction(Instruction.subShiftedRegister(rd, rn, rm, shift, imm6)),
573 rrr_imm6_shift.rm,
574 rrr_imm6_shift.shift,
575 rrr_imm6_shift.imm6,
576 )),
577 else => unreachable,629 else => unreachable,
578 }630 }
579}631}
580632
581fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void {633fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void {
582 const tag = emit.mir.instructions.items(.tag)[inst];634 const tag = emit.mir.instructions.items(.tag)[inst];
583 const rrr_cond = emit.mir.instructions.items(.data)[inst].rrr_cond;635 switch (tag) {
636 .cset => {
637 const r_cond = emit.mir.instructions.items(.data)[inst].r_cond;
638 try emit.writeInstruction(Instruction.csinc(r_cond.rd, .xzr, .xzr, r_cond.cond));
639 },
640 else => unreachable,
641 }
642}
643
644fn mirLogicalShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
645 const tag = emit.mir.instructions.items(.tag)[inst];
646 const rrr_imm6_logical_shift = emit.mir.instructions.items(.data)[inst].rrr_imm6_logical_shift;
647 const rd = rrr_imm6_logical_shift.rd;
648 const rn = rrr_imm6_logical_shift.rn;
649 const rm = rrr_imm6_logical_shift.rm;
650 const shift = rrr_imm6_logical_shift.shift;
651 const imm6 = rrr_imm6_logical_shift.imm6;
584652
585 switch (tag) {653 switch (tag) {
586 .cset => try emit.writeInstruction(Instruction.csinc(654 .eor_shifted_register => try emit.writeInstruction(Instruction.eor(rd, rn, rm, shift, imm6)),
587 rrr_cond.rd,
588 rrr_cond.rn,
589 rrr_cond.rm,
590 rrr_cond.cond,
591 )),
592 else => unreachable,655 else => unreachable,
593 }656 }
594}657}
...@@ -653,20 +716,14 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -653,20 +716,14 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
653fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {716fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {
654 const tag = emit.mir.instructions.items(.tag)[inst];717 const tag = emit.mir.instructions.items(.tag)[inst];
655 const load_store_register_pair = emit.mir.instructions.items(.data)[inst].load_store_register_pair;718 const load_store_register_pair = emit.mir.instructions.items(.data)[inst].load_store_register_pair;
719 const rt = load_store_register_pair.rt;
720 const rt2 = load_store_register_pair.rt2;
721 const rn = load_store_register_pair.rn;
722 const offset = load_store_register_pair.offset;
656723
657 switch (tag) {724 switch (tag) {
658 .stp => try emit.writeInstruction(Instruction.stp(725 .stp => try emit.writeInstruction(Instruction.stp(rt, rt2, rn, offset)),
659 load_store_register_pair.rt,726 .ldp => try emit.writeInstruction(Instruction.ldp(rt, rt2, rn, offset)),
660 load_store_register_pair.rt2,
661 load_store_register_pair.rn,
662 load_store_register_pair.offset,
663 )),
664 .ldp => try emit.writeInstruction(Instruction.ldp(
665 load_store_register_pair.rt,
666 load_store_register_pair.rt2,
667 load_store_register_pair.rn,
668 load_store_register_pair.offset,
669 )),
670 else => unreachable,727 else => unreachable,
671 }728 }
672}729}
...@@ -782,11 +839,19 @@ fn mirLoadStoreRegisterRegister(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -782,11 +839,19 @@ fn mirLoadStoreRegisterRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
782839
783fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {840fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
784 const tag = emit.mir.instructions.items(.tag)[inst];841 const tag = emit.mir.instructions.items(.tag)[inst];
785 const rr = emit.mir.instructions.items(.data)[inst].rr;
786
787 switch (tag) {842 switch (tag) {
788 .mov_register => try emit.writeInstruction(Instruction.orr(rr.rd, .xzr, rr.rn, Instruction.Shift.none)),843 .mov_register => {
789 .mov_to_from_sp => try emit.writeInstruction(Instruction.add(rr.rd, rr.rn, 0, false)),844 const rr = emit.mir.instructions.items(.data)[inst].rr;
845 try emit.writeInstruction(Instruction.orr(rr.rd, .xzr, rr.rn, .lsl, 0));
846 },
847 .mov_to_from_sp => {
848 const rr = emit.mir.instructions.items(.data)[inst].rr;
849 try emit.writeInstruction(Instruction.add(rr.rd, rr.rn, 0, false));
850 },
851 .mvn => {
852 const rr_imm6_shift = emit.mir.instructions.items(.data)[inst].rr_imm6_shift;
853 try emit.writeInstruction(Instruction.orn(rr_imm6_shift.rd, .xzr, rr_imm6_shift.rm, .lsl, 0));
854 },
790 else => unreachable,855 else => unreachable,
791 }856 }
792}857}
...@@ -802,6 +867,16 @@ fn mirMoveWideImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -802,6 +867,16 @@ fn mirMoveWideImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
802 }867 }
803}868}
804869
870fn mirDataProcessing3Source(emit: *Emit, inst: Mir.Inst.Index) !void {
871 const tag = emit.mir.instructions.items(.tag)[inst];
872 const rrr = emit.mir.instructions.items(.data)[inst].rrr;
873
874 switch (tag) {
875 .mul => try emit.writeInstruction(Instruction.mul(rrr.rd, rrr.rn, rrr.rm)),
876 else => unreachable,
877 }
878}
879
805fn mirNop(emit: *Emit) !void {880fn mirNop(emit: *Emit) !void {
806 try emit.writeInstruction(Instruction.nop());881 try emit.writeInstruction(Instruction.nop());
807}882}
src/arch/aarch64/Mir.zig+59-6
...@@ -26,6 +26,8 @@ pub const Inst = struct {...@@ -26,6 +26,8 @@ pub const Inst = struct {
26 pub const Tag = enum(u16) {26 pub const Tag = enum(u16) {
27 /// Add (immediate)27 /// Add (immediate)
28 add_immediate,28 add_immediate,
29 /// Add (shifted register)
30 add_shifted_register,
29 /// Branch conditionally31 /// Branch conditionally
30 b_cond,32 b_cond,
31 /// Branch33 /// Branch
...@@ -38,6 +40,8 @@ pub const Inst = struct {...@@ -38,6 +40,8 @@ pub const Inst = struct {
38 brk,40 brk,
39 /// Pseudo-instruction: Call extern41 /// Pseudo-instruction: Call extern
40 call_extern,42 call_extern,
43 /// Compare and Branch on Zero
44 cbz,
41 /// Compare (immediate)45 /// Compare (immediate)
42 cmp_immediate,46 cmp_immediate,
43 /// Compare (shifted register)47 /// Compare (shifted register)
...@@ -50,6 +54,8 @@ pub const Inst = struct {...@@ -50,6 +54,8 @@ pub const Inst = struct {
50 dbg_epilogue_begin,54 dbg_epilogue_begin,
51 /// Pseudo-instruction: Update debug line55 /// Pseudo-instruction: Update debug line
52 dbg_line,56 dbg_line,
57 /// Bitwise Exclusive OR (shifted register)
58 eor_shifted_register,
53 /// Pseudo-instruction: Load memory59 /// Pseudo-instruction: Load memory
54 ///60 ///
55 /// Payload is `LoadMemory`61 /// Payload is `LoadMemory`
...@@ -82,6 +88,10 @@ pub const Inst = struct {...@@ -82,6 +88,10 @@ pub const Inst = struct {
82 movk,88 movk,
83 /// Move wide with zero89 /// Move wide with zero
84 movz,90 movz,
91 /// Multiply
92 mul,
93 /// Bitwise NOT
94 mvn,
85 /// No Operation95 /// No Operation
86 nop,96 nop,
87 /// Pseudo-instruction: Pop multiple registers97 /// Pseudo-instruction: Pop multiple registers
...@@ -112,6 +122,8 @@ pub const Inst = struct {...@@ -112,6 +122,8 @@ pub const Inst = struct {
112 strh_register,122 strh_register,
113 /// Subtract (immediate)123 /// Subtract (immediate)
114 sub_immediate,124 sub_immediate,
125 /// Subtract (shifted register)
126 sub_shifted_register,
115 /// Supervisor Call127 /// Supervisor Call
116 svc,128 svc,
117 };129 };
...@@ -171,6 +183,20 @@ pub const Inst = struct {...@@ -171,6 +183,20 @@ pub const Inst = struct {
171 imm16: u16,183 imm16: u16,
172 hw: u2 = 0,184 hw: u2 = 0,
173 },185 },
186 /// A register and a condition
187 ///
188 /// Used by e.g. cset
189 r_cond: struct {
190 rd: Register,
191 cond: bits.Instruction.Condition,
192 },
193 /// A register and another instruction
194 ///
195 /// Used by e.g. cbz
196 r_inst: struct {
197 rt: Register,
198 inst: Index,
199 },
174 /// Two registers200 /// Two registers
175 ///201 ///
176 /// Used by e.g. mov_register202 /// Used by e.g. mov_register
...@@ -178,6 +204,14 @@ pub const Inst = struct {...@@ -178,6 +204,14 @@ pub const Inst = struct {
178 rd: Register,204 rd: Register,
179 rn: Register,205 rn: Register,
180 },206 },
207 /// A register, an unsigned 12-bit immediate, and an optional shift
208 ///
209 /// Used by e.g. cmp_immediate
210 r_imm12_sh: struct {
211 rn: Register,
212 imm12: u12,
213 sh: u1 = 0,
214 },
181 /// Two registers, an unsigned 12-bit immediate, and an optional shift215 /// Two registers, an unsigned 12-bit immediate, and an optional shift
182 ///216 ///
183 /// Used by e.g. sub_immediate217 /// Used by e.g. sub_immediate
...@@ -187,6 +221,23 @@ pub const Inst = struct {...@@ -187,6 +221,23 @@ pub const Inst = struct {
187 imm12: u12,221 imm12: u12,
188 sh: u1 = 0,222 sh: u1 = 0,
189 },223 },
224 /// Two registers and a shift (shift type and 6-bit amount)
225 ///
226 /// Used by e.g. mvn
227 rr_imm6_shift: struct {
228 rd: Register,
229 rm: Register,
230 imm6: u6,
231 shift: bits.Instruction.AddSubtractShiftedRegisterShift,
232 },
233 /// Two registers
234 ///
235 /// Used by e.g. mul
236 rrr: struct {
237 rd: Register,
238 rn: Register,
239 rm: Register,
240 },
190 /// Three registers and a shift (shift type and 6-bit amount)241 /// Three registers and a shift (shift type and 6-bit amount)
191 ///242 ///
192 /// Used by e.g. cmp_shifted_register243 /// Used by e.g. cmp_shifted_register
...@@ -197,18 +248,20 @@ pub const Inst = struct {...@@ -197,18 +248,20 @@ pub const Inst = struct {
197 imm6: u6,248 imm6: u6,
198 shift: bits.Instruction.AddSubtractShiftedRegisterShift,249 shift: bits.Instruction.AddSubtractShiftedRegisterShift,
199 },250 },
200 /// Three registers and a condition251 /// Three registers and a shift (logical instruction version)
252 /// (shift type and 6-bit amount)
201 ///253 ///
202 /// Used by e.g. cset254 /// Used by e.g. eor_shifted_register
203 rrr_cond: struct {255 rrr_imm6_logical_shift: struct {
204 rd: Register,256 rd: Register,
205 rn: Register,257 rn: Register,
206 rm: Register,258 rm: Register,
207 cond: bits.Instruction.Condition,259 imm6: u6,
260 shift: bits.Instruction.LogicalShiftedRegisterShift,
208 },261 },
209 /// Two registers and a LoadStoreOffsetImmediate262 /// Two registers and a LoadStoreOffsetImmediate
210 ///263 ///
211 /// Used by e.g. str_register264 /// Used by e.g. str_immediate
212 load_store_register_immediate: struct {265 load_store_register_immediate: struct {
213 rt: Register,266 rt: Register,
214 rn: Register,267 rn: Register,
...@@ -224,7 +277,7 @@ pub const Inst = struct {...@@ -224,7 +277,7 @@ pub const Inst = struct {
224 },277 },
225 /// A registers and a stack offset278 /// A registers and a stack offset
226 ///279 ///
227 /// Used by e.g. str_register280 /// Used by e.g. str_stack
228 load_store_stack: struct {281 load_store_stack: struct {
229 rt: Register,282 rt: Register,
230 offset: u32,283 offset: u32,
src/arch/aarch64/bits.zig+138-43
...@@ -332,23 +332,17 @@ pub const Instruction = union(enum) {...@@ -332,23 +332,17 @@ pub const Instruction = union(enum) {
332 op: u1,332 op: u1,
333 sf: u1,333 sf: u1,
334 },334 },
335335 data_processing_3_source: packed struct {
336 pub const Shift = struct {336 rd: u5,
337 shift: Type = .lsl,337 rn: u5,
338 amount: u6 = 0,338 ra: u5,
339339 o0: u1,
340 pub const Type = enum(u2) {340 rm: u5,
341 lsl,341 op31: u3,
342 lsr,342 fixed: u5 = 0b11011,
343 asr,343 op54: u2,
344 ror,344 sf: u1,
345 };345 },
346
347 pub const none = Shift{
348 .shift = .lsl,
349 .amount = 0,
350 };
351 };
352346
353 pub const Condition = enum(u4) {347 pub const Condition = enum(u4) {
354 /// Integer: Equal348 /// Integer: Equal
...@@ -470,6 +464,7 @@ pub const Instruction = union(enum) {...@@ -470,6 +464,7 @@ pub const Instruction = union(enum) {
470 .conditional_branch => |v| @as(u32, v.cond) | (@as(u32, v.o0) << 4) | (@as(u32, v.imm19) << 5) | (@as(u32, v.o1) << 24) | (@as(u32, v.fixed) << 25),464 .conditional_branch => |v| @as(u32, v.cond) | (@as(u32, v.o0) << 4) | (@as(u32, v.imm19) << 5) | (@as(u32, v.o1) << 24) | (@as(u32, v.fixed) << 25),
471 .compare_and_branch => |v| @as(u32, v.rt) | (@as(u32, v.imm19) << 5) | (@as(u32, v.op) << 24) | (@as(u32, v.fixed) << 25) | (@as(u32, v.sf) << 31),465 .compare_and_branch => |v| @as(u32, v.rt) | (@as(u32, v.imm19) << 5) | (@as(u32, v.op) << 24) | (@as(u32, v.fixed) << 25) | (@as(u32, v.sf) << 31),
472 .conditional_select => |v| @as(u32, v.rd) | @as(u32, v.rn) << 5 | @as(u32, v.op2) << 10 | @as(u32, v.cond) << 12 | @as(u32, v.rm) << 16 | @as(u32, v.fixed) << 21 | @as(u32, v.s) << 29 | @as(u32, v.op) << 30 | @as(u32, v.sf) << 31,466 .conditional_select => |v| @as(u32, v.rd) | @as(u32, v.rn) << 5 | @as(u32, v.op2) << 10 | @as(u32, v.cond) << 12 | @as(u32, v.rm) << 16 | @as(u32, v.fixed) << 21 | @as(u32, v.s) << 29 | @as(u32, v.op) << 30 | @as(u32, v.sf) << 31,
467 .data_processing_3_source => |v| @bitCast(u32, v),
473 };468 };
474 }469 }
475470
...@@ -807,25 +802,28 @@ pub const Instruction = union(enum) {...@@ -807,25 +802,28 @@ pub const Instruction = union(enum) {
807 };802 };
808 }803 }
809804
805 pub const LogicalShiftedRegisterShift = enum(u2) { lsl, lsr, asr, ror };
806
810 fn logicalShiftedRegister(807 fn logicalShiftedRegister(
811 opc: u2,808 opc: u2,
812 n: u1,809 n: u1,
813 shift: Shift,
814 rd: Register,810 rd: Register,
815 rn: Register,811 rn: Register,
816 rm: Register,812 rm: Register,
813 shift: LogicalShiftedRegisterShift,
814 amount: u6,
817 ) Instruction {815 ) Instruction {
818 switch (rd.size()) {816 switch (rd.size()) {
819 32 => {817 32 => {
820 assert(shift.amount < 32);818 assert(amount < 32);
821 return Instruction{819 return Instruction{
822 .logical_shifted_register = .{820 .logical_shifted_register = .{
823 .rd = rd.id(),821 .rd = rd.id(),
824 .rn = rn.id(),822 .rn = rn.id(),
825 .imm6 = shift.amount,823 .imm6 = amount,
826 .rm = rm.id(),824 .rm = rm.id(),
827 .n = n,825 .n = n,
828 .shift = @enumToInt(shift.shift),826 .shift = @enumToInt(shift),
829 .opc = opc,827 .opc = opc,
830 .sf = 0b0,828 .sf = 0b0,
831 },829 },
...@@ -836,10 +834,10 @@ pub const Instruction = union(enum) {...@@ -836,10 +834,10 @@ pub const Instruction = union(enum) {
836 .logical_shifted_register = .{834 .logical_shifted_register = .{
837 .rd = rd.id(),835 .rd = rd.id(),
838 .rn = rn.id(),836 .rn = rn.id(),
839 .imm6 = shift.amount,837 .imm6 = amount,
840 .rm = rm.id(),838 .rm = rm.id(),
841 .n = n,839 .n = n,
842 .shift = @enumToInt(shift.shift),840 .shift = @enumToInt(shift),
843 .opc = opc,841 .opc = opc,
844 .sf = 0b1,842 .sf = 0b1,
845 },843 },
...@@ -967,6 +965,33 @@ pub const Instruction = union(enum) {...@@ -967,6 +965,33 @@ pub const Instruction = union(enum) {
967 };965 };
968 }966 }
969967
968 fn dataProcessing3Source(
969 op54: u2,
970 op31: u3,
971 o0: u1,
972 rd: Register,
973 rn: Register,
974 rm: Register,
975 ra: Register,
976 ) Instruction {
977 return Instruction{
978 .data_processing_3_source = .{
979 .rd = rd.id(),
980 .rn = rn.id(),
981 .ra = ra.id(),
982 .o0 = o0,
983 .rm = rm.id(),
984 .op31 = op31,
985 .op54 = op54,
986 .sf = switch (rd.size()) {
987 32 => 0b0,
988 64 => 0b1,
989 else => unreachable, // unexpected register size
990 },
991 },
992 };
993 }
994
970 // Helper functions for assembly syntax functions995 // Helper functions for assembly syntax functions
971996
972 // Move wide (immediate)997 // Move wide (immediate)
...@@ -1120,36 +1145,84 @@ pub const Instruction = union(enum) {...@@ -1120,36 +1145,84 @@ pub const Instruction = union(enum) {
11201145
1121 // Logical (shifted register)1146 // Logical (shifted register)
11221147
1123 pub fn @"and"(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1148 pub fn @"and"(
1124 return logicalShiftedRegister(0b00, 0b0, shift, rd, rn, rm);1149 rd: Register,
1150 rn: Register,
1151 rm: Register,
1152 shift: LogicalShiftedRegisterShift,
1153 amount: u6,
1154 ) Instruction {
1155 return logicalShiftedRegister(0b00, 0b0, rd, rn, rm, shift, amount);
1125 }1156 }
11261157
1127 pub fn bic(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1158 pub fn bic(
1128 return logicalShiftedRegister(0b00, 0b1, shift, rd, rn, rm);1159 rd: Register,
1160 rn: Register,
1161 rm: Register,
1162 shift: LogicalShiftedRegisterShift,
1163 amount: u6,
1164 ) Instruction {
1165 return logicalShiftedRegister(0b00, 0b1, rd, rn, rm, shift, amount);
1129 }1166 }
11301167
1131 pub fn orr(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1168 pub fn orr(
1132 return logicalShiftedRegister(0b01, 0b0, shift, rd, rn, rm);1169 rd: Register,
1170 rn: Register,
1171 rm: Register,
1172 shift: LogicalShiftedRegisterShift,
1173 amount: u6,
1174 ) Instruction {
1175 return logicalShiftedRegister(0b01, 0b0, rd, rn, rm, shift, amount);
1133 }1176 }
11341177
1135 pub fn orn(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1178 pub fn orn(
1136 return logicalShiftedRegister(0b01, 0b1, shift, rd, rn, rm);1179 rd: Register,
1180 rn: Register,
1181 rm: Register,
1182 shift: LogicalShiftedRegisterShift,
1183 amount: u6,
1184 ) Instruction {
1185 return logicalShiftedRegister(0b01, 0b1, rd, rn, rm, shift, amount);
1137 }1186 }
11381187
1139 pub fn eor(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1188 pub fn eor(
1140 return logicalShiftedRegister(0b10, 0b0, shift, rd, rn, rm);1189 rd: Register,
1190 rn: Register,
1191 rm: Register,
1192 shift: LogicalShiftedRegisterShift,
1193 amount: u6,
1194 ) Instruction {
1195 return logicalShiftedRegister(0b10, 0b0, rd, rn, rm, shift, amount);
1141 }1196 }
11421197
1143 pub fn eon(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1198 pub fn eon(
1144 return logicalShiftedRegister(0b10, 0b1, shift, rd, rn, rm);1199 rd: Register,
1200 rn: Register,
1201 rm: Register,
1202 shift: LogicalShiftedRegisterShift,
1203 amount: u6,
1204 ) Instruction {
1205 return logicalShiftedRegister(0b10, 0b1, rd, rn, rm, shift, amount);
1145 }1206 }
11461207
1147 pub fn ands(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1208 pub fn ands(
1148 return logicalShiftedRegister(0b11, 0b0, shift, rd, rn, rm);1209 rd: Register,
1210 rn: Register,
1211 rm: Register,
1212 shift: LogicalShiftedRegisterShift,
1213 amount: u6,
1214 ) Instruction {
1215 return logicalShiftedRegister(0b11, 0b0, rd, rn, rm, shift, amount);
1149 }1216 }
11501217
1151 pub fn bics(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1218 pub fn bics(
1152 return logicalShiftedRegister(0b11, 0b1, shift, rd, rn, rm);1219 rd: Register,
1220 rn: Register,
1221 rm: Register,
1222 shift: LogicalShiftedRegisterShift,
1223 amount: u6,
1224 ) Instruction {
1225 return logicalShiftedRegister(0b11, 0b1, rd, rn, rm, shift, amount);
1153 }1226 }
11541227
1155 // Add/subtract (immediate)1228 // Add/subtract (immediate)
...@@ -1245,6 +1318,24 @@ pub const Instruction = union(enum) {...@@ -1245,6 +1318,24 @@ pub const Instruction = union(enum) {
1245 pub fn csneg(rd: Register, rn: Register, rm: Register, cond: Condition) Instruction {1318 pub fn csneg(rd: Register, rn: Register, rm: Register, cond: Condition) Instruction {
1246 return conditionalSelect(0b01, 0b1, 0b0, rd, rn, rm, cond);1319 return conditionalSelect(0b01, 0b1, 0b0, rd, rn, rm, cond);
1247 }1320 }
1321
1322 // Data processing (3 source)
1323
1324 pub fn madd(rd: Register, rn: Register, rm: Register, ra: Register) Instruction {
1325 return dataProcessing3Source(0b00, 0b000, 0b0, rd, rn, rm, ra);
1326 }
1327
1328 pub fn msub(rd: Register, rn: Register, rm: Register, ra: Register) Instruction {
1329 return dataProcessing3Source(0b00, 0b000, 0b1, rd, rn, rm, ra);
1330 }
1331
1332 pub fn mul(rd: Register, rn: Register, rm: Register) Instruction {
1333 return madd(rd, rn, rm, .xzr);
1334 }
1335
1336 pub fn mneg(rd: Register, rn: Register, rm: Register) Instruction {
1337 return msub(rd, rn, rm, .xzr);
1338 }
1248};1339};
12491340
1250test {1341test {
...@@ -1259,11 +1350,11 @@ test "serialize instructions" {...@@ -1259,11 +1350,11 @@ test "serialize instructions" {
12591350
1260 const testcases = [_]Testcase{1351 const testcases = [_]Testcase{
1261 .{ // orr x0, xzr, x11352 .{ // orr x0, xzr, x1
1262 .inst = Instruction.orr(.x0, .xzr, .x1, Instruction.Shift.none),1353 .inst = Instruction.orr(.x0, .xzr, .x1, .lsl, 0),
1263 .expected = 0b1_01_01010_00_0_00001_000000_11111_00000,1354 .expected = 0b1_01_01010_00_0_00001_000000_11111_00000,
1264 },1355 },
1265 .{ // orn x0, xzr, x11356 .{ // orn x0, xzr, x1
1266 .inst = Instruction.orn(.x0, .xzr, .x1, Instruction.Shift.none),1357 .inst = Instruction.orn(.x0, .xzr, .x1, .lsl, 0),
1267 .expected = 0b1_01_01010_00_1_00001_000000_11111_00000,1358 .expected = 0b1_01_01010_00_1_00001_000000_11111_00000,
1268 },1359 },
1269 .{ // movz x1, #41360 .{ // movz x1, #4
...@@ -1383,11 +1474,11 @@ test "serialize instructions" {...@@ -1383,11 +1474,11 @@ test "serialize instructions" {
1383 .expected = 0b10_101_0_001_1_0000010_00010_11111_00001,1474 .expected = 0b10_101_0_001_1_0000010_00010_11111_00001,
1384 },1475 },
1385 .{ // and x0, x4, x21476 .{ // and x0, x4, x2
1386 .inst = Instruction.@"and"(.x0, .x4, .x2, .{}),1477 .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0),
1387 .expected = 0b1_00_01010_00_0_00010_000000_00100_00000,1478 .expected = 0b1_00_01010_00_0_00010_000000_00100_00000,
1388 },1479 },
1389 .{ // and x0, x4, x2, lsl #0x81480 .{ // and x0, x4, x2, lsl #0x8
1390 .inst = Instruction.@"and"(.x0, .x4, .x2, .{ .shift = .lsl, .amount = 0x8 }),1481 .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0x8),
1391 .expected = 0b1_00_01010_00_0_00010_001000_00100_00000,1482 .expected = 0b1_00_01010_00_0_00010_001000_00100_00000,
1392 },1483 },
1393 .{ // add x0, x10, #101484 .{ // add x0, x10, #10
...@@ -1414,6 +1505,10 @@ test "serialize instructions" {...@@ -1414,6 +1505,10 @@ test "serialize instructions" {
1414 .inst = Instruction.csinc(.x1, .x2, .x4, .eq),1505 .inst = Instruction.csinc(.x1, .x2, .x4, .eq),
1415 .expected = 0b1_0_0_11010100_00100_0000_0_1_00010_00001,1506 .expected = 0b1_0_0_11010100_00100_0000_0_1_00010_00001,
1416 },1507 },
1508 .{ // mul x1, x4, x9
1509 .inst = Instruction.mul(.x1, .x4, .x9),
1510 .expected = 0b1_00_11011_000_01001_0_11111_00100_00001,
1511 },
1417 };1512 };
14181513
1419 for (testcases) |case| {1514 for (testcases) |case| {
test/behavior.zig+1-1
...@@ -54,7 +54,7 @@ test {...@@ -54,7 +54,7 @@ test {
54 _ = @import("behavior/decltest.zig");54 _ = @import("behavior/decltest.zig");
55 }55 }
5656
57 if (builtin.zig_backend != .stage2_arm and builtin.zig_backend != .stage2_x86_64) {57 if (builtin.zig_backend != .stage2_arm and builtin.zig_backend != .stage2_x86_64 and builtin.zig_backend != .stage2_aarch64) {
58 // Tests that pass (partly) for stage1, llvm backend, C backend, wasm backend.58 // Tests that pass (partly) for stage1, llvm backend, C backend, wasm backend.
59 _ = @import("behavior/bitcast.zig");59 _ = @import("behavior/bitcast.zig");
60 _ = @import("behavior/bugs/624.zig");60 _ = @import("behavior/bugs/624.zig");
test/behavior/align.zig+18
...@@ -27,6 +27,7 @@ test "default alignment allows unspecified in type syntax" {...@@ -27,6 +27,7 @@ test "default alignment allows unspecified in type syntax" {
27}27}
2828
29test "implicitly decreasing pointer alignment" {29test "implicitly decreasing pointer alignment" {
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
30 const a: u32 align(4) = 3;31 const a: u32 align(4) = 3;
31 const b: u32 align(8) = 4;32 const b: u32 align(8) = 4;
32 try expect(addUnaligned(&a, &b) == 7);33 try expect(addUnaligned(&a, &b) == 7);
...@@ -37,6 +38,7 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {...@@ -37,6 +38,7 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
37}38}
3839
39test "@alignCast pointers" {40test "@alignCast pointers" {
41 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
40 var x: u32 align(4) = 1;42 var x: u32 align(4) = 1;
41 expectsOnly1(&x);43 expectsOnly1(&x);
42 try expect(x == 2);44 try expect(x == 2);
...@@ -102,6 +104,7 @@ fn fnWithAlignedStack() i32 {...@@ -102,6 +104,7 @@ fn fnWithAlignedStack() i32 {
102}104}
103105
104test "implicitly decreasing slice alignment" {106test "implicitly decreasing slice alignment" {
107 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;108 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
106109
107 const a: u32 align(4) = 3;110 const a: u32 align(4) = 3;
...@@ -113,6 +116,7 @@ fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {...@@ -113,6 +116,7 @@ fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
113}116}
114117
115test "specifying alignment allows pointer cast" {118test "specifying alignment allows pointer cast" {
119 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
116 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
117121
118 try testBytesAlign(0x33);122 try testBytesAlign(0x33);
...@@ -124,6 +128,7 @@ fn testBytesAlign(b: u8) !void {...@@ -124,6 +128,7 @@ fn testBytesAlign(b: u8) !void {
124}128}
125129
126test "@alignCast slices" {130test "@alignCast slices" {
131 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
127 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;132 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
128133
129 var array align(4) = [_]u32{ 1, 1 };134 var array align(4) = [_]u32{ 1, 1 };
...@@ -139,6 +144,7 @@ fn sliceExpects4(slice: []align(4) u32) void {...@@ -139,6 +144,7 @@ fn sliceExpects4(slice: []align(4) u32) void {
139}144}
140145
141test "return error union with 128-bit integer" {146test "return error union with 128-bit integer" {
147 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
142 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;148 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
143149
144 try expect(3 == try give());150 try expect(3 == try give());
...@@ -148,6 +154,7 @@ fn give() anyerror!u128 {...@@ -148,6 +154,7 @@ fn give() anyerror!u128 {
148}154}
149155
150test "page aligned array on stack" {156test "page aligned array on stack" {
157 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
151 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;158 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
152 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;159 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
153 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;160 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
...@@ -173,6 +180,7 @@ fn noop1() align(1) void {}...@@ -173,6 +180,7 @@ fn noop1() align(1) void {}
173fn noop4() align(4) void {}180fn noop4() align(4) void {}
174181
175test "function alignment" {182test "function alignment" {
183 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
176 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;184 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
177 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;185 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
178 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;186 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
...@@ -189,6 +197,7 @@ test "function alignment" {...@@ -189,6 +197,7 @@ test "function alignment" {
189}197}
190198
191test "implicitly decreasing fn alignment" {199test "implicitly decreasing fn alignment" {
200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
192 if (builtin.zig_backend == .stage1) return error.SkipZigTest;201 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
193 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;202 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
194 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;203 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
...@@ -216,6 +225,7 @@ fn alignedBig() align(16) i32 {...@@ -216,6 +225,7 @@ fn alignedBig() align(16) i32 {
216}225}
217226
218test "@alignCast functions" {227test "@alignCast functions" {
228 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
219 if (builtin.zig_backend == .stage1) return error.SkipZigTest;229 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
220 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;230 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
221 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;231 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
...@@ -239,6 +249,7 @@ fn simple4() align(4) i32 {...@@ -239,6 +249,7 @@ fn simple4() align(4) i32 {
239}249}
240250
241test "generic function with align param" {251test "generic function with align param" {
252 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
242 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;253 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
243 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;254 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
244 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;255 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
...@@ -260,6 +271,7 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {...@@ -260,6 +271,7 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
260}271}
261272
262test "runtime known array index has best alignment possible" {273test "runtime known array index has best alignment possible" {
274 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
263 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;275 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
264 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;276 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
...@@ -302,6 +314,7 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {...@@ -302,6 +314,7 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {
302}314}
303315
304test "alignment of function with c calling convention" {316test "alignment of function with c calling convention" {
317 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
305 if (builtin.zig_backend == .stage1) return error.SkipZigTest;318 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
306319
307 var runtime_nothing = &nothing;320 var runtime_nothing = &nothing;
...@@ -318,6 +331,7 @@ const DefaultAligned = struct {...@@ -318,6 +331,7 @@ const DefaultAligned = struct {
318};331};
319332
320test "read 128-bit field from default aligned struct in stack memory" {333test "read 128-bit field from default aligned struct in stack memory" {
334 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
321 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;335 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
322 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;336 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
323 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;337 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
...@@ -337,6 +351,7 @@ var default_aligned_global = DefaultAligned{...@@ -337,6 +351,7 @@ var default_aligned_global = DefaultAligned{
337};351};
338352
339test "read 128-bit field from default aligned struct in global memory" {353test "read 128-bit field from default aligned struct in global memory" {
354 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
340 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;355 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
341 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;356 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
342 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;357 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
...@@ -348,6 +363,7 @@ test "read 128-bit field from default aligned struct in global memory" {...@@ -348,6 +363,7 @@ test "read 128-bit field from default aligned struct in global memory" {
348}363}
349364
350test "struct field explicit alignment" {365test "struct field explicit alignment" {
366 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
351 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;367 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
352 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;368 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
353 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;369 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
...@@ -369,6 +385,7 @@ test "struct field explicit alignment" {...@@ -369,6 +385,7 @@ test "struct field explicit alignment" {
369}385}
370386
371test "align(@alignOf(T)) T does not force resolution of T" {387test "align(@alignOf(T)) T does not force resolution of T" {
388 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
372 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;389 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
373 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;390 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
374 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;391 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
...@@ -397,6 +414,7 @@ test "align(@alignOf(T)) T does not force resolution of T" {...@@ -397,6 +414,7 @@ test "align(@alignOf(T)) T does not force resolution of T" {
397}414}
398415
399test "align(N) on functions" {416test "align(N) on functions" {
417 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
400 if (builtin.zig_backend == .stage1) return error.SkipZigTest;418 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
401 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;419 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
402 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;420 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
test/behavior/alignof.zig+1
...@@ -11,6 +11,7 @@ const Foo = struct {...@@ -11,6 +11,7 @@ const Foo = struct {
11};11};
1212
13test "@alignOf(T) before referencing T" {13test "@alignOf(T) before referencing T" {
14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
14 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
16 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
test/behavior/array.zig+27
...@@ -6,6 +6,7 @@ const expect = testing.expect;...@@ -6,6 +6,7 @@ const expect = testing.expect;
6const expectEqual = testing.expectEqual;6const expectEqual = testing.expectEqual;
77
8test "array to slice" {8test "array to slice" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1011
11 const a: u32 align(4) = 3;12 const a: u32 align(4) = 3;
...@@ -20,6 +21,7 @@ test "array to slice" {...@@ -20,6 +21,7 @@ test "array to slice" {
20}21}
2122
22test "arrays" {23test "arrays" {
24 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2426
25 var array: [5]u32 = undefined;27 var array: [5]u32 = undefined;
...@@ -46,6 +48,7 @@ fn getArrayLen(a: []const u32) usize {...@@ -46,6 +48,7 @@ fn getArrayLen(a: []const u32) usize {
46}48}
4749
48test "array init with mult" {50test "array init with mult" {
51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
49 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;52 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
5053
51 const a = 'a';54 const a = 'a';
...@@ -57,6 +60,7 @@ test "array init with mult" {...@@ -57,6 +60,7 @@ test "array init with mult" {
57}60}
5861
59test "array literal with explicit type" {62test "array literal with explicit type" {
63 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
60 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;64 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6165
62 const hex_mult: [4]u16 = .{ 4096, 256, 16, 1 };66 const hex_mult: [4]u16 = .{ 4096, 256, 16, 1 };
...@@ -86,6 +90,7 @@ const ArrayDotLenConstExpr = struct {...@@ -86,6 +90,7 @@ const ArrayDotLenConstExpr = struct {
86const some_array = [_]u8{ 0, 1, 2, 3 };90const some_array = [_]u8{ 0, 1, 2, 3 };
8791
88test "array literal with specified size" {92test "array literal with specified size" {
93 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
89 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;94 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9095
91 var array = [2]u8{ 1, 2 };96 var array = [2]u8{ 1, 2 };
...@@ -94,6 +99,7 @@ test "array literal with specified size" {...@@ -94,6 +99,7 @@ test "array literal with specified size" {
94}99}
95100
96test "array len field" {101test "array len field" {
102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
97 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;103 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
98104
99 var arr = [4]u8{ 0, 0, 0, 0 };105 var arr = [4]u8{ 0, 0, 0, 0 };
...@@ -105,6 +111,7 @@ test "array len field" {...@@ -105,6 +111,7 @@ test "array len field" {
105}111}
106112
107test "array with sentinels" {113test "array with sentinels" {
114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
108 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;115 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
109116
110 const S = struct {117 const S = struct {
...@@ -134,6 +141,7 @@ test "array with sentinels" {...@@ -134,6 +141,7 @@ test "array with sentinels" {
134}141}
135142
136test "void arrays" {143test "void arrays" {
144 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
137 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;145 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
138146
139 var array: [4]void = undefined;147 var array: [4]void = undefined;
...@@ -144,6 +152,7 @@ test "void arrays" {...@@ -144,6 +152,7 @@ test "void arrays" {
144}152}
145153
146test "nested arrays" {154test "nested arrays" {
155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
147 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;156 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
148157
149 const array_of_strings = [_][]const u8{ "hello", "this", "is", "my", "thing" };158 const array_of_strings = [_][]const u8{ "hello", "this", "is", "my", "thing" };
...@@ -157,6 +166,7 @@ test "nested arrays" {...@@ -157,6 +166,7 @@ test "nested arrays" {
157}166}
158167
159test "implicit comptime in array type size" {168test "implicit comptime in array type size" {
169 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
160 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;170 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
161171
162 var arr: [plusOne(10)]bool = undefined;172 var arr: [plusOne(10)]bool = undefined;
...@@ -168,6 +178,7 @@ fn plusOne(x: u32) u32 {...@@ -168,6 +178,7 @@ fn plusOne(x: u32) u32 {
168}178}
169179
170test "single-item pointer to array indexing and slicing" {180test "single-item pointer to array indexing and slicing" {
181 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
171 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;182 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
172183
173 try testSingleItemPtrArrayIndexSlice();184 try testSingleItemPtrArrayIndexSlice();
...@@ -193,6 +204,7 @@ fn doSomeMangling(array: *[4]u8) void {...@@ -193,6 +204,7 @@ fn doSomeMangling(array: *[4]u8) void {
193}204}
194205
195test "implicit cast zero sized array ptr to slice" {206test "implicit cast zero sized array ptr to slice" {
207 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
196 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;208 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
197209
198 {210 {
...@@ -208,6 +220,7 @@ test "implicit cast zero sized array ptr to slice" {...@@ -208,6 +220,7 @@ test "implicit cast zero sized array ptr to slice" {
208}220}
209221
210test "anonymous list literal syntax" {222test "anonymous list literal syntax" {
223 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
211 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;224 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
212225
213 const S = struct {226 const S = struct {
...@@ -227,6 +240,7 @@ var s_array: [8]Sub = undefined;...@@ -227,6 +240,7 @@ var s_array: [8]Sub = undefined;
227const Sub = struct { b: u8 };240const Sub = struct { b: u8 };
228const Str = struct { a: []Sub };241const Str = struct { a: []Sub };
229test "set global var array via slice embedded in struct" {242test "set global var array via slice embedded in struct" {
243 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
230 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO244 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
231 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO245 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
232 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO246 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -243,6 +257,7 @@ test "set global var array via slice embedded in struct" {...@@ -243,6 +257,7 @@ test "set global var array via slice embedded in struct" {
243}257}
244258
245test "read/write through global variable array of struct fields initialized via array mult" {259test "read/write through global variable array of struct fields initialized via array mult" {
260 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
246 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO261 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
247 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO262 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
248 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO263 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -264,6 +279,7 @@ test "read/write through global variable array of struct fields initialized via...@@ -264,6 +279,7 @@ test "read/write through global variable array of struct fields initialized via
264}279}
265280
266test "implicit cast single-item pointer" {281test "implicit cast single-item pointer" {
282 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
267 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO283 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
268 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO284 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
269 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO285 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -284,6 +300,7 @@ fn testArrayByValAtComptime(b: [2]u8) u8 {...@@ -284,6 +300,7 @@ fn testArrayByValAtComptime(b: [2]u8) u8 {
284}300}
285301
286test "comptime evaluating function that takes array by value" {302test "comptime evaluating function that takes array by value" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
287 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO304 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
288 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO305 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
289 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO306 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -296,6 +313,7 @@ test "comptime evaluating function that takes array by value" {...@@ -296,6 +313,7 @@ test "comptime evaluating function that takes array by value" {
296}313}
297314
298test "runtime initialize array elem and then implicit cast to slice" {315test "runtime initialize array elem and then implicit cast to slice" {
316 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
299 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO317 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
300 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO318 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
301 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO319 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -306,6 +324,7 @@ test "runtime initialize array elem and then implicit cast to slice" {...@@ -306,6 +324,7 @@ test "runtime initialize array elem and then implicit cast to slice" {
306}324}
307325
308test "array literal as argument to function" {326test "array literal as argument to function" {
327 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
309 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO328 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
310 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO329 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
311 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO330 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -334,6 +353,7 @@ test "array literal as argument to function" {...@@ -334,6 +353,7 @@ test "array literal as argument to function" {
334}353}
335354
336test "double nested array to const slice cast in array literal" {355test "double nested array to const slice cast in array literal" {
356 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
337 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO357 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
338 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO358 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
339 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -395,6 +415,7 @@ test "double nested array to const slice cast in array literal" {...@@ -395,6 +415,7 @@ test "double nested array to const slice cast in array literal" {
395}415}
396416
397test "anonymous literal in array" {417test "anonymous literal in array" {
418 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
398 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO419 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
399 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO420 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
400 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO421 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -420,6 +441,7 @@ test "anonymous literal in array" {...@@ -420,6 +441,7 @@ test "anonymous literal in array" {
420}441}
421442
422test "access the null element of a null terminated array" {443test "access the null element of a null terminated array" {
444 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
423 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO445 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
424 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO446 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
425 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO447 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -437,6 +459,7 @@ test "access the null element of a null terminated array" {...@@ -437,6 +459,7 @@ test "access the null element of a null terminated array" {
437}459}
438460
439test "type deduction for array subscript expression" {461test "type deduction for array subscript expression" {
462 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
440 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO463 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
441 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO464 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
442 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO465 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -455,6 +478,7 @@ test "type deduction for array subscript expression" {...@@ -455,6 +478,7 @@ test "type deduction for array subscript expression" {
455}478}
456479
457test "sentinel element count towards the ABI size calculation" {480test "sentinel element count towards the ABI size calculation" {
481 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
458 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO482 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
459 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO483 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
460 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO484 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
...@@ -481,6 +505,7 @@ test "sentinel element count towards the ABI size calculation" {...@@ -481,6 +505,7 @@ test "sentinel element count towards the ABI size calculation" {
481}505}
482506
483test "zero-sized array with recursive type definition" {507test "zero-sized array with recursive type definition" {
508 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
484 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO509 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
485 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO510 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
486 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO511 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
...@@ -505,6 +530,7 @@ test "zero-sized array with recursive type definition" {...@@ -505,6 +530,7 @@ test "zero-sized array with recursive type definition" {
505}530}
506531
507test "type coercion of anon struct literal to array" {532test "type coercion of anon struct literal to array" {
533 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
508 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO534 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
509 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO535 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
510 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO536 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -540,6 +566,7 @@ test "type coercion of anon struct literal to array" {...@@ -540,6 +566,7 @@ test "type coercion of anon struct literal to array" {
540}566}
541567
542test "type coercion of pointer to anon struct literal to pointer to array" {568test "type coercion of pointer to anon struct literal to pointer to array" {
569 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
543 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO570 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
544 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO571 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
545 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO572 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
test/behavior/basic.zig+32
...@@ -15,6 +15,7 @@ test "empty function with comments" {...@@ -15,6 +15,7 @@ test "empty function with comments" {
15}15}
1616
17test "truncate" {17test "truncate" {
18 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1920
20 try expect(testTruncate(0x10fd) == 0xfd);21 try expect(testTruncate(0x10fd) == 0xfd);
...@@ -25,6 +26,7 @@ fn testTruncate(x: u32) u8 {...@@ -25,6 +26,7 @@ fn testTruncate(x: u32) u8 {
25}26}
2627
27test "truncate to non-power-of-two integers" {28test "truncate to non-power-of-two integers" {
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
28 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2931
30 try testTrunc(u32, u1, 0b10101, 0b1);32 try testTrunc(u32, u1, 0b10101, 0b1);
...@@ -46,6 +48,7 @@ const g1: i32 = 1233 + 1;...@@ -46,6 +48,7 @@ const g1: i32 = 1233 + 1;
46var g2: i32 = 0;48var g2: i32 = 0;
4749
48test "global variables" {50test "global variables" {
51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
49 try expect(g2 == 0);52 try expect(g2 == 0);
50 g2 = g1;53 g2 = g1;
51 try expect(g2 == 1234);54 try expect(g2 == 1234);
...@@ -112,6 +115,7 @@ fn first4KeysOfHomeRow() []const u8 {...@@ -112,6 +115,7 @@ fn first4KeysOfHomeRow() []const u8 {
112}115}
113116
114test "return string from function" {117test "return string from function" {
118 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;119 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
116 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;120 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
117121
...@@ -119,12 +123,14 @@ test "return string from function" {...@@ -119,12 +123,14 @@ test "return string from function" {
119}123}
120124
121test "hex escape" {125test "hex escape" {
126 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
122 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;127 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
123128
124 try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));129 try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
125}130}
126131
127test "multiline string" {132test "multiline string" {
133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
128 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
129135
130 const s1 =136 const s1 =
...@@ -137,6 +143,7 @@ test "multiline string" {...@@ -137,6 +143,7 @@ test "multiline string" {
137}143}
138144
139test "multiline string comments at start" {145test "multiline string comments at start" {
146 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;147 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
141148
142 const s1 =149 const s1 =
...@@ -149,6 +156,7 @@ test "multiline string comments at start" {...@@ -149,6 +156,7 @@ test "multiline string comments at start" {
149}156}
150157
151test "multiline string comments at end" {158test "multiline string comments at end" {
159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
152 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;160 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
153161
154 const s1 =162 const s1 =
...@@ -161,6 +169,7 @@ test "multiline string comments at end" {...@@ -161,6 +169,7 @@ test "multiline string comments at end" {
161}169}
162170
163test "multiline string comments in middle" {171test "multiline string comments in middle" {
172 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;173 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
165174
166 const s1 =175 const s1 =
...@@ -173,6 +182,7 @@ test "multiline string comments in middle" {...@@ -173,6 +182,7 @@ test "multiline string comments in middle" {
173}182}
174183
175test "multiline string comments at multiple places" {184test "multiline string comments at multiple places" {
185 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
176 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;186 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
177187
178 const s1 =188 const s1 =
...@@ -191,6 +201,7 @@ test "string concatenation" {...@@ -191,6 +201,7 @@ test "string concatenation" {
191}201}
192202
193test "array mult operator" {203test "array mult operator" {
204 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
194 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;205 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
195206
196 try expect(mem.eql(u8, "ab" ** 5, "ababababab"));207 try expect(mem.eql(u8, "ab" ** 5, "ababababab"));
...@@ -216,6 +227,7 @@ test "compile time global reinterpret" {...@@ -216,6 +227,7 @@ test "compile time global reinterpret" {
216}227}
217228
218test "cast undefined" {229test "cast undefined" {
230 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
219 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;231 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
220232
221 const array: [100]u8 = undefined;233 const array: [100]u8 = undefined;
...@@ -227,6 +239,7 @@ fn testCastUndefined(x: []const u8) void {...@@ -227,6 +239,7 @@ fn testCastUndefined(x: []const u8) void {
227}239}
228240
229test "implicit cast after unreachable" {241test "implicit cast after unreachable" {
242 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
230 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;243 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
231244
232 try expect(outer() == 1234);245 try expect(outer() == 1234);
...@@ -284,6 +297,7 @@ fn fB() []const u8 {...@@ -284,6 +297,7 @@ fn fB() []const u8 {
284}297}
285298
286test "call function pointer in struct" {299test "call function pointer in struct" {
300 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
287 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;301 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
288 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;302 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
289303
...@@ -310,6 +324,7 @@ const FnPtrWrapper = struct {...@@ -310,6 +324,7 @@ const FnPtrWrapper = struct {
310};324};
311325
312test "const ptr from var variable" {326test "const ptr from var variable" {
327 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
313 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;328 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
314329
315 var x: u64 = undefined;330 var x: u64 = undefined;
...@@ -326,6 +341,7 @@ fn copy(src: *const u64, dst: *u64) void {...@@ -326,6 +341,7 @@ fn copy(src: *const u64, dst: *u64) void {
326}341}
327342
328test "call result of if else expression" {343test "call result of if else expression" {
344 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
329 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;345 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
330 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;346 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
331 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO347 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
...@@ -339,6 +355,7 @@ fn f2(x: bool) []const u8 {...@@ -339,6 +355,7 @@ fn f2(x: bool) []const u8 {
339}355}
340356
341test "memcpy and memset intrinsics" {357test "memcpy and memset intrinsics" {
358 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
342 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
343 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;360 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
344 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO361 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
...@@ -361,6 +378,7 @@ fn testMemcpyMemset() !void {...@@ -361,6 +378,7 @@ fn testMemcpyMemset() !void {
361}378}
362379
363test "variable is allowed to be a pointer to an opaque type" {380test "variable is allowed to be a pointer to an opaque type" {
381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
364 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;382 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
365 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;383 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
366 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO384 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
...@@ -374,6 +392,7 @@ fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {...@@ -374,6 +392,7 @@ fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
374}392}
375393
376test "take address of parameter" {394test "take address of parameter" {
395 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
377 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;396 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
378 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;397 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
379398
...@@ -400,6 +419,7 @@ fn testPointerToVoidReturnType2() *const void {...@@ -400,6 +419,7 @@ fn testPointerToVoidReturnType2() *const void {
400}419}
401420
402test "array 2D const double ptr" {421test "array 2D const double ptr" {
422 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
403 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;423 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
404 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;424 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
405425
...@@ -419,6 +439,7 @@ fn testArray2DConstDoublePtr(ptr: *const f32) !void {...@@ -419,6 +439,7 @@ fn testArray2DConstDoublePtr(ptr: *const f32) !void {
419}439}
420440
421test "double implicit cast in same expression" {441test "double implicit cast in same expression" {
442 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
422 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;443 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
423 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;444 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
424445
...@@ -430,6 +451,7 @@ fn nine() u8 {...@@ -430,6 +451,7 @@ fn nine() u8 {
430}451}
431452
432test "struct inside function" {453test "struct inside function" {
454 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
433 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;455 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
434456
435 try testStructInFn();457 try testStructInFn();
...@@ -451,6 +473,7 @@ fn testStructInFn() !void {...@@ -451,6 +473,7 @@ fn testStructInFn() !void {
451}473}
452474
453test "fn call returning scalar optional in equality expression" {475test "fn call returning scalar optional in equality expression" {
476 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
454 try expect(getNull() == null);477 try expect(getNull() == null);
455}478}
456479
...@@ -459,6 +482,7 @@ fn getNull() ?*i32 {...@@ -459,6 +482,7 @@ fn getNull() ?*i32 {
459}482}
460483
461test "global variable assignment with optional unwrapping with var initialized to undefined" {484test "global variable assignment with optional unwrapping with var initialized to undefined" {
485 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
462 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;486 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
463487
464 const S = struct {488 const S = struct {
...@@ -476,6 +500,7 @@ test "global variable assignment with optional unwrapping with var initialized t...@@ -476,6 +500,7 @@ test "global variable assignment with optional unwrapping with var initialized t
476var global_foo: *i32 = undefined;500var global_foo: *i32 = undefined;
477501
478test "peer result location with typed parent, runtime condition, comptime prongs" {502test "peer result location with typed parent, runtime condition, comptime prongs" {
503 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
479 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;504 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
480 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;505 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
481506
...@@ -550,6 +575,7 @@ test "comptime cast fn to ptr" {...@@ -550,6 +575,7 @@ test "comptime cast fn to ptr" {
550}575}
551576
552test "equality compare fn ptrs" {577test "equality compare fn ptrs" {
578 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
553 if (builtin.zig_backend == .stage1) return error.SkipZigTest;579 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
554580
555 var a = &emptyFn;581 var a = &emptyFn;
...@@ -557,6 +583,7 @@ test "equality compare fn ptrs" {...@@ -557,6 +583,7 @@ test "equality compare fn ptrs" {
557}583}
558584
559test "self reference through fn ptr field" {585test "self reference through fn ptr field" {
586 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
560 if (builtin.zig_backend == .stage1) return error.SkipZigTest;587 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
561 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;588 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
562589
...@@ -576,6 +603,7 @@ test "self reference through fn ptr field" {...@@ -576,6 +603,7 @@ test "self reference through fn ptr field" {
576}603}
577604
578test "global variable initialized to global variable array element" {605test "global variable initialized to global variable array element" {
606 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
579 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;607 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
580 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;608 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
581609
...@@ -593,6 +621,7 @@ var gdt = [_]GDTEntry{...@@ -593,6 +621,7 @@ var gdt = [_]GDTEntry{
593var global_ptr = &gdt[0];621var global_ptr = &gdt[0];
594622
595test "global constant is loaded with a runtime-known index" {623test "global constant is loaded with a runtime-known index" {
624 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
596 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;625 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
597626
598 const S = struct {627 const S = struct {
...@@ -610,6 +639,7 @@ test "global constant is loaded with a runtime-known index" {...@@ -610,6 +639,7 @@ test "global constant is loaded with a runtime-known index" {
610}639}
611640
612test "multiline string literal is null terminated" {641test "multiline string literal is null terminated" {
642 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
613 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;643 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
614 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;644 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
615645
...@@ -643,6 +673,7 @@ test "explicit cast optional pointers" {...@@ -643,6 +673,7 @@ test "explicit cast optional pointers" {
643}673}
644674
645test "pointer comparison" {675test "pointer comparison" {
676 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
646 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;677 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
647 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;678 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
648679
...@@ -655,6 +686,7 @@ fn ptrEql(a: *const []const u8, b: *const []const u8) bool {...@@ -655,6 +686,7 @@ fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
655}686}
656687
657test "string concatenation" {688test "string concatenation" {
689 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
658 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;690 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
659 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;691 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
660692
test/behavior/bit_shifting.zig+1
...@@ -61,6 +61,7 @@ fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, compt...@@ -61,6 +61,7 @@ fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, compt
61}61}
6262
63test "sharded table" {63test "sharded table" {
64 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
64 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;65 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;67 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
test/behavior/bugs/1381.zig+1
...@@ -12,6 +12,7 @@ const A = union(enum) {...@@ -12,6 +12,7 @@ const A = union(enum) {
12};12};
1313
14test "union that needs padding bytes inside an array" {14test "union that needs padding bytes inside an array" {
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
16 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
17 var as = [_]A{18 var as = [_]A{
test/behavior/bugs/1486.zig+2
...@@ -1,10 +1,12 @@...@@ -1,10 +1,12 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const builtin = @import("builtin");
34
4const ptr = &global;5const ptr = &global;
5var global: usize = 123;6var global: usize = 123;
67
7test "constant pointer to global variable causes runtime load" {8test "constant pointer to global variable causes runtime load" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8 global = 1234;10 global = 1234;
9 try expect(&global == ptr);11 try expect(&global == ptr);
10 try expect(ptr.* == 1234);12 try expect(ptr.* == 1234);
test/behavior/bugs/1735.zig+1
...@@ -42,6 +42,7 @@ const a = struct {...@@ -42,6 +42,7 @@ const a = struct {
42};42};
4343
44test "initialization" {44test "initialization" {
45 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
45 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;46 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
46 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
47 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;48 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
test/behavior/bugs/1741.zig+1
...@@ -2,6 +2,7 @@ const std = @import("std");...@@ -2,6 +2,7 @@ const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4test "fixed" {4test "fixed" {
5 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
5 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;6 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
7 const x: f32 align(128) = 12.34;8 const x: f32 align(128) = 12.34;
test/behavior/bugs/2006.zig+1
...@@ -6,6 +6,7 @@ const S = struct {...@@ -6,6 +6,7 @@ const S = struct {
6 p: *S,6 p: *S,
7};7};
8test "bug 2006" {8test "bug 2006" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
10 var a: S = undefined;11 var a: S = undefined;
11 a = S{ .p = undefined };12 a = S{ .p = undefined };
test/behavior/bugs/2578.zig+1
...@@ -12,6 +12,7 @@ fn bar(pointer: ?*anyopaque) void {...@@ -12,6 +12,7 @@ fn bar(pointer: ?*anyopaque) void {
12}12}
1313
14test "fixed" {14test "fixed" {
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO18 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
test/behavior/bugs/3007.zig+1
...@@ -19,6 +19,7 @@ fn get_foo() Foo.FooError!*Foo {...@@ -19,6 +19,7 @@ fn get_foo() Foo.FooError!*Foo {
19}19}
2020
21test "fixed" {21test "fixed" {
22 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO24 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO25 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
test/behavior/bugs/3112.zig+1
...@@ -12,6 +12,7 @@ fn prev(p: ?State) void {...@@ -12,6 +12,7 @@ fn prev(p: ?State) void {
12}12}
1313
14test "zig test crash" {14test "zig test crash" {
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage1) return error.SkipZigTest;16 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
16 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
17 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
test/behavior/bugs/3367.zig+1
...@@ -10,6 +10,7 @@ const Mixin = struct {...@@ -10,6 +10,7 @@ const Mixin = struct {
10};10};
1111
12test "container member access usingnamespace decls" {12test "container member access usingnamespace decls" {
13 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;14 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
15 var foo = Foo{};16 var foo = Foo{};
test/behavior/bugs/394.zig+1
...@@ -11,6 +11,7 @@ const expect = @import("std").testing.expect;...@@ -11,6 +11,7 @@ const expect = @import("std").testing.expect;
11const builtin = @import("builtin");11const builtin = @import("builtin");
1212
13test "bug 394 fixed" {13test "bug 394 fixed" {
14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;16 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
16 const x = S{17 const x = S{
test/behavior/bugs/656.zig+1
...@@ -11,6 +11,7 @@ const Value = struct {...@@ -11,6 +11,7 @@ const Value = struct {
11};11};
1212
13test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {13test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {
14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;16 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
16 try foo(false, true);17 try foo(false, true);
test/behavior/bugs/7250.zig+1
...@@ -14,6 +14,7 @@ threadlocal var g_uart0 = nrfx_uart_t{...@@ -14,6 +14,7 @@ threadlocal var g_uart0 = nrfx_uart_t{
14};14};
1515
16test "reference a global threadlocal variable" {16test "reference a global threadlocal variable" {
17 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;20 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
test/behavior/cast.zig+36
...@@ -18,6 +18,7 @@ test "integer literal to pointer cast" {...@@ -18,6 +18,7 @@ test "integer literal to pointer cast" {
18}18}
1919
20test "peer type resolution: ?T and T" {20test "peer type resolution: ?T and T" {
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;22 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2223
23 try expect(peerTypeTAndOptionalT(true, false).? == 0);24 try expect(peerTypeTAndOptionalT(true, false).? == 0);
...@@ -94,6 +95,7 @@ test "comptime_int @intToFloat" {...@@ -94,6 +95,7 @@ test "comptime_int @intToFloat" {
94}95}
9596
96test "@floatToInt" {97test "@floatToInt" {
98 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
97 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO99 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
98 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
99101
...@@ -116,6 +118,7 @@ fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {...@@ -116,6 +118,7 @@ fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
116}118}
117119
118test "implicitly cast indirect pointer to maybe-indirect pointer" {120test "implicitly cast indirect pointer to maybe-indirect pointer" {
121 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
119 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;122 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
120123
121 const S = struct {124 const S = struct {
...@@ -174,6 +177,7 @@ test "@floatCast comptime_int and comptime_float" {...@@ -174,6 +177,7 @@ test "@floatCast comptime_int and comptime_float" {
174}177}
175178
176test "coerce undefined to optional" {179test "coerce undefined to optional" {
180 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
177 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;181 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
178182
179 try expect(MakeType(void).getNull() == null);183 try expect(MakeType(void).getNull() == null);
...@@ -193,6 +197,7 @@ fn MakeType(comptime T: type) type {...@@ -193,6 +197,7 @@ fn MakeType(comptime T: type) type {
193}197}
194198
195test "implicit cast from *[N]T to [*c]T" {199test "implicit cast from *[N]T to [*c]T" {
200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
196 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;201 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
197202
198 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };203 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
...@@ -205,6 +210,7 @@ test "implicit cast from *[N]T to [*c]T" {...@@ -205,6 +210,7 @@ test "implicit cast from *[N]T to [*c]T" {
205}210}
206211
207test "*usize to *void" {212test "*usize to *void" {
213 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
208 var i = @as(usize, 0);214 var i = @as(usize, 0);
209 var v = @ptrCast(*void, &i);215 var v = @ptrCast(*void, &i);
210 v.* = {};216 v.* = {};
...@@ -230,6 +236,7 @@ test "@intCast to u0 and use the result" {...@@ -230,6 +236,7 @@ test "@intCast to u0 and use the result" {
230}236}
231237
232test "peer result null and comptime_int" {238test "peer result null and comptime_int" {
239 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
233 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;240 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
234241
235 const S = struct {242 const S = struct {
...@@ -253,6 +260,7 @@ test "peer result null and comptime_int" {...@@ -253,6 +260,7 @@ test "peer result null and comptime_int" {
253}260}
254261
255test "*const ?[*]const T to [*c]const [*c]const T" {262test "*const ?[*]const T to [*c]const [*c]const T" {
263 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
256 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;264 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
257265
258 var array = [_]u8{ 'o', 'k' };266 var array = [_]u8{ 'o', 'k' };
...@@ -264,6 +272,7 @@ test "*const ?[*]const T to [*c]const [*c]const T" {...@@ -264,6 +272,7 @@ test "*const ?[*]const T to [*c]const [*c]const T" {
264}272}
265273
266test "array coersion to undefined at runtime" {274test "array coersion to undefined at runtime" {
275 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
267 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;276 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
268277
269 @setRuntimeSafety(true);278 @setRuntimeSafety(true);
...@@ -293,6 +302,7 @@ fn implicitIntLitToOptional() void {...@@ -293,6 +302,7 @@ fn implicitIntLitToOptional() void {
293}302}
294303
295test "return u8 coercing into ?u32 return type" {304test "return u8 coercing into ?u32 return type" {
305 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
296 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;306 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
297307
298 const S = struct {308 const S = struct {
...@@ -313,6 +323,7 @@ test "cast from ?[*]T to ??[*]T" {...@@ -313,6 +323,7 @@ test "cast from ?[*]T to ??[*]T" {
313}323}
314324
315test "peer type unsigned int to signed" {325test "peer type unsigned int to signed" {
326 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;327 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
317 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;328 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
318329
...@@ -325,6 +336,7 @@ test "peer type unsigned int to signed" {...@@ -325,6 +336,7 @@ test "peer type unsigned int to signed" {
325}336}
326337
327test "expected [*c]const u8, found [*:0]const u8" {338test "expected [*c]const u8, found [*:0]const u8" {
339 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
328 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;340 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
329 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;341 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
330342
...@@ -384,6 +396,7 @@ fn castToOptionalTypeError(z: i32) !void {...@@ -384,6 +396,7 @@ fn castToOptionalTypeError(z: i32) !void {
384}396}
385397
386test "implicitly cast from [0]T to anyerror![]T" {398test "implicitly cast from [0]T to anyerror![]T" {
399 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
387 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO400 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
388 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO401 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
389 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO402 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -455,6 +468,7 @@ fn testCastConstArrayRefToConstSlice() !void {...@@ -455,6 +468,7 @@ fn testCastConstArrayRefToConstSlice() !void {
455}468}
456469
457test "peer type resolution: error and [N]T" {470test "peer type resolution: error and [N]T" {
471 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
458 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
459 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO473 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
460474
...@@ -689,6 +703,7 @@ test "type coercion related to sentinel-termination" {...@@ -689,6 +703,7 @@ test "type coercion related to sentinel-termination" {
689}703}
690704
691test "peer type resolution implicit cast to return type" {705test "peer type resolution implicit cast to return type" {
706 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
692 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO707 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
693 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO708 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
694 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO709 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -710,6 +725,7 @@ test "peer type resolution implicit cast to return type" {...@@ -710,6 +725,7 @@ test "peer type resolution implicit cast to return type" {
710}725}
711726
712test "peer type resolution implicit cast to variable type" {727test "peer type resolution implicit cast to variable type" {
728 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
713 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO729 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
714 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO730 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
715 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO731 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -806,6 +822,7 @@ test "comptime float casts" {...@@ -806,6 +822,7 @@ test "comptime float casts" {
806}822}
807823
808test "pointer reinterpret const float to int" {824test "pointer reinterpret const float to int" {
825 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
809 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO826 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
810 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO827 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
811 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO828 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -822,6 +839,7 @@ test "pointer reinterpret const float to int" {...@@ -822,6 +839,7 @@ test "pointer reinterpret const float to int" {
822}839}
823840
824test "implicit cast from [*]T to ?*anyopaque" {841test "implicit cast from [*]T to ?*anyopaque" {
842 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
825 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO843 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
826 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO844 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
827 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO845 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -840,6 +858,7 @@ fn incrementVoidPtrArray(array: ?*anyopaque, len: usize) void {...@@ -840,6 +858,7 @@ fn incrementVoidPtrArray(array: ?*anyopaque, len: usize) void {
840}858}
841859
842test "compile time int to ptr of function" {860test "compile time int to ptr of function" {
861 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
843 if (builtin.zig_backend == .stage1) return error.SkipZigTest;862 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
844 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) return error.SkipZigTest; // TODO863 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) return error.SkipZigTest; // TODO
845 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO864 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
...@@ -857,6 +876,7 @@ fn foobar(func: PFN_void) !void {...@@ -857,6 +876,7 @@ fn foobar(func: PFN_void) !void {
857}876}
858877
859test "implicit ptr to *anyopaque" {878test "implicit ptr to *anyopaque" {
879 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
860 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO880 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
861 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO881 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
862 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO882 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -871,6 +891,7 @@ test "implicit ptr to *anyopaque" {...@@ -871,6 +891,7 @@ test "implicit ptr to *anyopaque" {
871}891}
872892
873test "return null from fn() anyerror!?&T" {893test "return null from fn() anyerror!?&T" {
894 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
874 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO895 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
875 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO896 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
876897
...@@ -887,6 +908,7 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {...@@ -887,6 +908,7 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
887}908}
888909
889test "peer type resolution: [0]u8 and []const u8" {910test "peer type resolution: [0]u8 and []const u8" {
911 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
890 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO912 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
891 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO913 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
892 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO914 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -907,6 +929,7 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {...@@ -907,6 +929,7 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
907}929}
908930
909test "implicitly cast from [N]T to ?[]const T" {931test "implicitly cast from [N]T to ?[]const T" {
932 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
910 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO933 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
911 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO934 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
912 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO935 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -920,6 +943,7 @@ fn castToOptionalSlice() ?[]const u8 {...@@ -920,6 +943,7 @@ fn castToOptionalSlice() ?[]const u8 {
920}943}
921944
922test "cast u128 to f128 and back" {945test "cast u128 to f128 and back" {
946 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
923 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO947 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
924 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO948 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
925 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO949 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -941,6 +965,7 @@ fn cast128Float(x: u128) f128 {...@@ -941,6 +965,7 @@ fn cast128Float(x: u128) f128 {
941}965}
942966
943test "implicit cast from *[N]T to ?[*]T" {967test "implicit cast from *[N]T to ?[*]T" {
968 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
944 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO969 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
945 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO970 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
946 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO971 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -956,6 +981,7 @@ test "implicit cast from *[N]T to ?[*]T" {...@@ -956,6 +981,7 @@ test "implicit cast from *[N]T to ?[*]T" {
956}981}
957982
958test "implicit cast from *T to ?*anyopaque" {983test "implicit cast from *T to ?*anyopaque" {
984 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
959 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO985 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
960 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO986 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
961 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO987 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -970,6 +996,7 @@ fn incrementVoidPtrValue(value: ?*anyopaque) void {...@@ -970,6 +996,7 @@ fn incrementVoidPtrValue(value: ?*anyopaque) void {
970}996}
971997
972test "implicit cast *[0]T to E![]const u8" {998test "implicit cast *[0]T to E![]const u8" {
999 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
973 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1000 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
974 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1001 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
975 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1002 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -987,6 +1014,7 @@ test "cast from array reference to fn: comptime fn ptr" {...@@ -987,6 +1014,7 @@ test "cast from array reference to fn: comptime fn ptr" {
987 try expect(@ptrToInt(f) == @ptrToInt(&global_array));1014 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
988}1015}
989test "cast from array reference to fn: runtime fn ptr" {1016test "cast from array reference to fn: runtime fn ptr" {
1017 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
990 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1018 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
991 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1019 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
992 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1020 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -996,6 +1024,7 @@ test "cast from array reference to fn: runtime fn ptr" {...@@ -996,6 +1024,7 @@ test "cast from array reference to fn: runtime fn ptr" {
996}1024}
9971025
998test "*const [N]null u8 to ?[]const u8" {1026test "*const [N]null u8 to ?[]const u8" {
1027 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
999 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1028 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1000 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1001 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1030 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -1034,6 +1063,7 @@ test "cast between [*c]T and ?[*:0]T on fn parameter" {...@@ -1034,6 +1063,7 @@ test "cast between [*c]T and ?[*:0]T on fn parameter" {
10341063
1035var global_struct: struct { f0: usize } = undefined;1064var global_struct: struct { f0: usize } = undefined;
1036test "assignment to optional pointer result loc" {1065test "assignment to optional pointer result loc" {
1066 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1037 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1067 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1038 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1068 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1039 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1069 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -1043,6 +1073,7 @@ test "assignment to optional pointer result loc" {...@@ -1043,6 +1073,7 @@ test "assignment to optional pointer result loc" {
1043}1073}
10441074
1045test "cast between *[N]void and []void" {1075test "cast between *[N]void and []void" {
1076 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1046 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1077 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1047 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1078 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10481079
...@@ -1052,6 +1083,7 @@ test "cast between *[N]void and []void" {...@@ -1052,6 +1083,7 @@ test "cast between *[N]void and []void" {
1052}1083}
10531084
1054test "peer resolve arrays of different size to const slice" {1085test "peer resolve arrays of different size to const slice" {
1086 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1055 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1087 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1056 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1088 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10571089
...@@ -1065,6 +1097,7 @@ fn boolToStr(b: bool) []const u8 {...@@ -1065,6 +1097,7 @@ fn boolToStr(b: bool) []const u8 {
1065}1097}
10661098
1067test "cast f16 to wider types" {1099test "cast f16 to wider types" {
1100 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1068 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1101 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1069 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1070 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1103 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -1083,6 +1116,7 @@ test "cast f16 to wider types" {...@@ -1083,6 +1116,7 @@ test "cast f16 to wider types" {
1083}1116}
10841117
1085test "cast f128 to narrower types" {1118test "cast f128 to narrower types" {
1119 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1086 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1120 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1087 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1121 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1088 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1122 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -1101,6 +1135,7 @@ test "cast f128 to narrower types" {...@@ -1101,6 +1135,7 @@ test "cast f128 to narrower types" {
1101}1135}
11021136
1103test "peer type resolution: unreachable, null, slice" {1137test "peer type resolution: unreachable, null, slice" {
1138 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1104 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1139 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1106 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1141 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -1119,6 +1154,7 @@ test "peer type resolution: unreachable, null, slice" {...@@ -1119,6 +1154,7 @@ test "peer type resolution: unreachable, null, slice" {
1119}1154}
11201155
1121test "cast i8 fn call peers to i32 result" {1156test "cast i8 fn call peers to i32 result" {
1157 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1122 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1158 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1123 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1159 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11241160
test/behavior/fn_delegation.zig+1
...@@ -32,6 +32,7 @@ fn custom(comptime T: type, comptime num: u64) fn (T) u64 {...@@ -32,6 +32,7 @@ fn custom(comptime T: type, comptime num: u64) fn (T) u64 {
32}32}
3333
34test "fn delegation" {34test "fn delegation" {
35 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
35 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO36 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
3637
37 const foo = Foo{};38 const foo = Foo{};
test/behavior/ir_block_deps.zig+1
...@@ -18,6 +18,7 @@ fn getErrInt() anyerror!i32 {...@@ -18,6 +18,7 @@ fn getErrInt() anyerror!i32 {
18}18}
1919
20test "ir block deps" {20test "ir block deps" {
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO23 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2324
test/behavior/optional.zig+10
...@@ -5,6 +5,7 @@ const expect = testing.expect;...@@ -5,6 +5,7 @@ const expect = testing.expect;
5const expectEqual = testing.expectEqual;5const expectEqual = testing.expectEqual;
66
7test "passing an optional integer as a parameter" {7test "passing an optional integer as a parameter" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1011
...@@ -25,6 +26,7 @@ test "passing an optional integer as a parameter" {...@@ -25,6 +26,7 @@ test "passing an optional integer as a parameter" {
25pub const EmptyStruct = struct {};26pub const EmptyStruct = struct {};
2627
27test "optional pointer to size zero struct" {28test "optional pointer to size zero struct" {
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
28 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
29 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3032
...@@ -34,6 +36,7 @@ test "optional pointer to size zero struct" {...@@ -34,6 +36,7 @@ test "optional pointer to size zero struct" {
34}36}
3537
36test "equality compare optional pointers" {38test "equality compare optional pointers" {
39 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO40 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
38 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO41 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3942
...@@ -58,6 +61,7 @@ fn testNullPtrsEql() !void {...@@ -58,6 +61,7 @@ fn testNullPtrsEql() !void {
58}61}
5962
60test "optional with void type" {63test "optional with void type" {
64 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
61 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
62 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO66 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
6367
...@@ -69,6 +73,7 @@ test "optional with void type" {...@@ -69,6 +73,7 @@ test "optional with void type" {
69}73}
7074
71test "address of unwrap optional" {75test "address of unwrap optional" {
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
72 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
73 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7479
...@@ -89,6 +94,7 @@ test "address of unwrap optional" {...@@ -89,6 +94,7 @@ test "address of unwrap optional" {
89}94}
9095
91test "nested optional field in struct" {96test "nested optional field in struct" {
97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
92 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO98 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
93 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO99 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
94100
...@@ -105,6 +111,7 @@ test "nested optional field in struct" {...@@ -105,6 +111,7 @@ test "nested optional field in struct" {
105}111}
106112
107test "equality compare optional with non-optional" {113test "equality compare optional with non-optional" {
114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
108 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO116 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
110117
...@@ -142,6 +149,7 @@ fn test_cmp_optional_non_optional() !void {...@@ -142,6 +149,7 @@ fn test_cmp_optional_non_optional() !void {
142}149}
143150
144test "unwrap function call with optional pointer return value" {151test "unwrap function call with optional pointer return value" {
152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
145 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO153 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
146 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO154 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
147155
...@@ -163,6 +171,7 @@ test "unwrap function call with optional pointer return value" {...@@ -163,6 +171,7 @@ test "unwrap function call with optional pointer return value" {
163}171}
164172
165test "nested orelse" {173test "nested orelse" {
174 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
166 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO175 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
167 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO176 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
168177
...@@ -189,6 +198,7 @@ test "nested orelse" {...@@ -189,6 +198,7 @@ test "nested orelse" {
189}198}
190199
191test "self-referential struct through a slice of optional" {200test "self-referential struct through a slice of optional" {
201 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
192 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO202 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
193 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO203 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
194 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO204 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
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 {
28}28}
2929
30test "reflection: @field" {30test "reflection: @field" {
31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO32 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO33 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3334
test/behavior/slice.zig+14
...@@ -27,6 +27,7 @@ comptime {...@@ -27,6 +27,7 @@ comptime {
27}27}
2828
29test "slicing" {29test "slicing" {
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;32 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO33 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
...@@ -68,6 +69,7 @@ test "comptime slice of undefined pointer of length 0" {...@@ -68,6 +69,7 @@ test "comptime slice of undefined pointer of length 0" {
68}69}
6970
70test "implicitly cast array of size 0 to slice" {71test "implicitly cast array of size 0 to slice" {
72 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO73 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;74 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
7375
...@@ -80,6 +82,7 @@ fn assertLenIsZero(msg: []const u8) !void {...@@ -80,6 +82,7 @@ fn assertLenIsZero(msg: []const u8) !void {
80}82}
8183
82test "access len index of sentinel-terminated slice" {84test "access len index of sentinel-terminated slice" {
85 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
83 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO86 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
8487
85 const S = struct {88 const S = struct {
...@@ -129,6 +132,7 @@ test "slice of type" {...@@ -129,6 +132,7 @@ test "slice of type" {
129}132}
130133
131test "generic malloc free" {134test "generic malloc free" {
135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
132 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO136 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
133 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
134 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;138 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
...@@ -187,6 +191,7 @@ test "comptime pointer cast array and then slice" {...@@ -187,6 +191,7 @@ test "comptime pointer cast array and then slice" {
187}191}
188192
189test "slicing zero length array" {193test "slicing zero length array" {
194 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
190 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO195 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
191 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;196 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
192 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;197 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
...@@ -202,6 +207,7 @@ test "slicing zero length array" {...@@ -202,6 +207,7 @@ test "slicing zero length array" {
202const x = @intToPtr([*]i32, 0x1000)[0..0x500];207const x = @intToPtr([*]i32, 0x1000)[0..0x500];
203const y = x[0x100..];208const y = x[0x100..];
204test "compile time slice of pointer to hard coded address" {209test "compile time slice of pointer to hard coded address" {
210 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
205 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO211 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
206 if (builtin.zig_backend == .stage1) return error.SkipZigTest;212 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
207 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;213 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
...@@ -215,6 +221,7 @@ test "compile time slice of pointer to hard coded address" {...@@ -215,6 +221,7 @@ test "compile time slice of pointer to hard coded address" {
215}221}
216222
217test "slice string literal has correct type" {223test "slice string literal has correct type" {
224 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
218 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;225 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
219 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;226 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
220227
...@@ -230,6 +237,7 @@ test "slice string literal has correct type" {...@@ -230,6 +237,7 @@ test "slice string literal has correct type" {
230}237}
231238
232test "result location zero sized array inside struct field implicit cast to slice" {239test "result location zero sized array inside struct field implicit cast to slice" {
240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
233 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO241 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
234242
235 const E = struct {243 const E = struct {
...@@ -240,6 +248,7 @@ test "result location zero sized array inside struct field implicit cast to slic...@@ -240,6 +248,7 @@ test "result location zero sized array inside struct field implicit cast to slic
240}248}
241249
242test "runtime safety lets us slice from len..len" {250test "runtime safety lets us slice from len..len" {
251 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
243 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;252 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
244 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;253 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
245254
...@@ -252,6 +261,7 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {...@@ -252,6 +261,7 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
252}261}
253262
254test "C pointer" {263test "C pointer" {
264 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
255 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
256 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;266 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
257267
...@@ -262,6 +272,7 @@ test "C pointer" {...@@ -262,6 +272,7 @@ test "C pointer" {
262}272}
263273
264test "C pointer slice access" {274test "C pointer slice access" {
275 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;276 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
266 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;277 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
267278
...@@ -291,6 +302,7 @@ fn sliceSum(comptime q: []const u8) i32 {...@@ -291,6 +302,7 @@ fn sliceSum(comptime q: []const u8) i32 {
291}302}
292303
293test "slice type with custom alignment" {304test "slice type with custom alignment" {
305 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
294 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;306 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
295 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;307 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
296308
...@@ -305,6 +317,7 @@ test "slice type with custom alignment" {...@@ -305,6 +317,7 @@ test "slice type with custom alignment" {
305}317}
306318
307test "obtaining a null terminated slice" {319test "obtaining a null terminated slice" {
320 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
308 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;321 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
309 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;322 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
310 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO323 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
...@@ -350,6 +363,7 @@ test "empty array to slice" {...@@ -350,6 +363,7 @@ test "empty array to slice" {
350}363}
351364
352test "@ptrCast slice to pointer" {365test "@ptrCast slice to pointer" {
366 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
353 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;367 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
354 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;368 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
355369
test/behavior/struct.zig+28
...@@ -9,6 +9,7 @@ const maxInt = std.math.maxInt;...@@ -9,6 +9,7 @@ const maxInt = std.math.maxInt;
9top_level_field: i32,9top_level_field: i32,
1010
11test "top level fields" {11test "top level fields" {
12 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;13 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1314
14 var instance = @This(){15 var instance = @This(){
...@@ -42,6 +43,7 @@ const StructWithFields = struct {...@@ -42,6 +43,7 @@ const StructWithFields = struct {
42};43};
4344
44test "non-packed struct has fields padded out to the required alignment" {45test "non-packed struct has fields padded out to the required alignment" {
46 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
45 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
4648
47 const foo = StructWithFields{ .a = 5, .b = 1, .c = 10, .d = 2 };49 const foo = StructWithFields{ .a = 5, .b = 1, .c = 10, .d = 2 };
...@@ -65,6 +67,7 @@ const SmallStruct = struct {...@@ -65,6 +67,7 @@ const SmallStruct = struct {
65};67};
6668
67test "lower unnamed constants" {69test "lower unnamed constants" {
70 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
68 var foo = SmallStruct{ .a = 1, .b = 255 };71 var foo = SmallStruct{ .a = 1, .b = 255 };
69 try expect(foo.first() == 1);72 try expect(foo.first() == 1);
70 try expect(foo.second() == 255);73 try expect(foo.second() == 255);
...@@ -83,6 +86,7 @@ const StructFoo = struct {...@@ -83,6 +86,7 @@ const StructFoo = struct {
83};86};
8487
85test "structs" {88test "structs" {
89 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
86 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;90 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8791
88 var foo: StructFoo = undefined;92 var foo: StructFoo = undefined;
...@@ -101,6 +105,7 @@ fn testMutation(foo: *StructFoo) void {...@@ -101,6 +105,7 @@ fn testMutation(foo: *StructFoo) void {
101}105}
102106
103test "struct byval assign" {107test "struct byval assign" {
108 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
104 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
105110
106 var foo1: StructFoo = undefined;111 var foo1: StructFoo = undefined;
...@@ -134,6 +139,7 @@ fn returnEmptyStructInstance() StructWithNoFields {...@@ -134,6 +139,7 @@ fn returnEmptyStructInstance() StructWithNoFields {
134}139}
135140
136test "fn call of struct field" {141test "fn call of struct field" {
142 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;143 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
138144
139 const Foo = struct {145 const Foo = struct {
...@@ -165,12 +171,14 @@ const MemberFnTestFoo = struct {...@@ -165,12 +171,14 @@ const MemberFnTestFoo = struct {
165};171};
166172
167test "call member function directly" {173test "call member function directly" {
174 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
168 const instance = MemberFnTestFoo{ .x = 1234 };175 const instance = MemberFnTestFoo{ .x = 1234 };
169 const result = MemberFnTestFoo.member(instance);176 const result = MemberFnTestFoo.member(instance);
170 try expect(result == 1234);177 try expect(result == 1234);
171}178}
172179
173test "store member function in variable" {180test "store member function in variable" {
181 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
174 const instance = MemberFnTestFoo{ .x = 1234 };182 const instance = MemberFnTestFoo{ .x = 1234 };
175 const memberFn = MemberFnTestFoo.member;183 const memberFn = MemberFnTestFoo.member;
176 const result = memberFn(instance);184 const result = memberFn(instance);
...@@ -178,6 +186,7 @@ test "store member function in variable" {...@@ -178,6 +186,7 @@ test "store member function in variable" {
178}186}
179187
180test "member functions" {188test "member functions" {
189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
181 const r = MemberFnRand{ .seed = 1234 };190 const r = MemberFnRand{ .seed = 1234 };
182 try expect(r.getSeed() == 1234);191 try expect(r.getSeed() == 1234);
183}192}
...@@ -189,6 +198,7 @@ const MemberFnRand = struct {...@@ -189,6 +198,7 @@ const MemberFnRand = struct {
189};198};
190199
191test "return struct byval from function" {200test "return struct byval from function" {
201 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
192 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;202 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
193203
194 const bar = makeBar2(1234, 5678);204 const bar = makeBar2(1234, 5678);
...@@ -206,6 +216,7 @@ fn makeBar2(x: i32, y: i32) Bar {...@@ -206,6 +216,7 @@ fn makeBar2(x: i32, y: i32) Bar {
206}216}
207217
208test "call method with mutable reference to struct with no fields" {218test "call method with mutable reference to struct with no fields" {
219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
210221
211 const S = struct {222 const S = struct {
...@@ -238,6 +249,7 @@ test "usingnamespace within struct scope" {...@@ -238,6 +249,7 @@ test "usingnamespace within struct scope" {
238}249}
239250
240test "struct field init with catch" {251test "struct field init with catch" {
252 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
241 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;253 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
242254
243 const S = struct {255 const S = struct {
...@@ -296,6 +308,7 @@ const Val = struct {...@@ -296,6 +308,7 @@ const Val = struct {
296};308};
297309
298test "struct point to self" {310test "struct point to self" {
311 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
299 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO312 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
300 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO313 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
301 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO314 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -314,6 +327,7 @@ test "struct point to self" {...@@ -314,6 +327,7 @@ test "struct point to self" {
314}327}
315328
316test "void struct fields" {329test "void struct fields" {
330 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
317 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO331 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
318 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO332 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
319 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO333 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -334,6 +348,7 @@ const VoidStructFieldsFoo = struct {...@@ -334,6 +348,7 @@ const VoidStructFieldsFoo = struct {
334};348};
335349
336test "return empty struct from fn" {350test "return empty struct from fn" {
351 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
337 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO352 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
338 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO353 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
339 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO354 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -347,6 +362,7 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 {...@@ -347,6 +362,7 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 {
347}362}
348363
349test "pass slice of empty struct to fn" {364test "pass slice of empty struct to fn" {
365 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
350 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO366 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
351 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO367 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
352 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO368 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -359,6 +375,7 @@ fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {...@@ -359,6 +375,7 @@ fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
359}375}
360376
361test "self-referencing struct via array member" {377test "self-referencing struct via array member" {
378 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
362 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO379 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
363 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO380 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
364 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO381 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -389,6 +406,7 @@ const EmptyStruct = struct {...@@ -389,6 +406,7 @@ const EmptyStruct = struct {
389};406};
390407
391test "align 1 field before self referential align 8 field as slice return type" {408test "align 1 field before self referential align 8 field as slice return type" {
409 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
392 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO410 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
393 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO411 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
394 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO412 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -413,6 +431,7 @@ const APackedStruct = packed struct {...@@ -413,6 +431,7 @@ const APackedStruct = packed struct {
413};431};
414432
415test "packed struct" {433test "packed struct" {
434 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
416 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO435 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
417 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO436 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
418 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO437 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -438,6 +457,7 @@ const Foo96Bits = packed struct {...@@ -438,6 +457,7 @@ const Foo96Bits = packed struct {
438};457};
439458
440test "packed struct 24bits" {459test "packed struct 24bits" {
460 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
441 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO461 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
442 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO462 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
443 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO463 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -484,6 +504,7 @@ test "packed struct 24bits" {...@@ -484,6 +504,7 @@ test "packed struct 24bits" {
484}504}
485505
486test "runtime struct initialization of bitfield" {506test "runtime struct initialization of bitfield" {
507 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
487 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO508 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
488 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO509 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
489 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO510 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -523,6 +544,7 @@ const Bitfields = packed struct {...@@ -523,6 +544,7 @@ const Bitfields = packed struct {
523};544};
524545
525test "native bit field understands endianness" {546test "native bit field understands endianness" {
547 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
526 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO548 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
527 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO549 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
528 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO550 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -546,6 +568,7 @@ test "native bit field understands endianness" {...@@ -546,6 +568,7 @@ test "native bit field understands endianness" {
546}568}
547569
548test "implicit cast packed struct field to const ptr" {570test "implicit cast packed struct field to const ptr" {
571 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
549 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO572 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
550 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO573 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
551 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO574 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -581,6 +604,7 @@ test "zero-bit field in packed struct" {...@@ -581,6 +604,7 @@ test "zero-bit field in packed struct" {
581}604}
582605
583test "packed struct with non-ABI-aligned field" {606test "packed struct with non-ABI-aligned field" {
607 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
584 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO608 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
585 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO609 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
586 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO610 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -610,6 +634,7 @@ const bit_field_1 = BitField1{...@@ -610,6 +634,7 @@ const bit_field_1 = BitField1{
610};634};
611635
612test "bit field access" {636test "bit field access" {
637 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
613 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO638 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
614 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO639 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
615 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO640 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -642,6 +667,7 @@ fn getC(data: *const BitField1) u2 {...@@ -642,6 +667,7 @@ fn getC(data: *const BitField1) u2 {
642}667}
643668
644test "default struct initialization fields" {669test "default struct initialization fields" {
670 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
645 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO671 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
646 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO672 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
647 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO673 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -907,6 +933,7 @@ test "packed struct field passed to generic function" {...@@ -907,6 +933,7 @@ test "packed struct field passed to generic function" {
907}933}
908934
909test "anonymous struct literal syntax" {935test "anonymous struct literal syntax" {
936 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
910 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO937 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
911 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO938 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
912 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO939 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -1100,6 +1127,7 @@ test "type coercion of pointer to anon struct literal to pointer to struct" {...@@ -1100,6 +1127,7 @@ test "type coercion of pointer to anon struct literal to pointer to struct" {
1100}1127}
11011128
1102test "packed struct with undefined initializers" {1129test "packed struct with undefined initializers" {
1130 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1103 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1131 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1104 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1132 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1133 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/truncate.zig+9
...@@ -3,6 +3,7 @@ const builtin = @import("builtin");...@@ -3,6 +3,7 @@ const builtin = @import("builtin");
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5test "truncate u0 to larger integer allowed and has comptime known result" {5test "truncate u0 to larger integer allowed and has comptime known result" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
78
8 var x: u0 = 0;9 var x: u0 = 0;
...@@ -11,6 +12,7 @@ test "truncate u0 to larger integer allowed and has comptime known result" {...@@ -11,6 +12,7 @@ test "truncate u0 to larger integer allowed and has comptime known result" {
11}12}
1213
13test "truncate.u0.literal" {14test "truncate.u0.literal" {
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1517
16 var z = @truncate(u0, 0);18 var z = @truncate(u0, 0);
...@@ -18,6 +20,7 @@ test "truncate.u0.literal" {...@@ -18,6 +20,7 @@ test "truncate.u0.literal" {
18}20}
1921
20test "truncate.u0.const" {22test "truncate.u0.const" {
23 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2225
23 const c0: usize = 0;26 const c0: usize = 0;
...@@ -26,6 +29,7 @@ test "truncate.u0.const" {...@@ -26,6 +29,7 @@ test "truncate.u0.const" {
26}29}
2730
28test "truncate.u0.var" {31test "truncate.u0.var" {
32 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;33 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3034
31 var d: u8 = 2;35 var d: u8 = 2;
...@@ -34,6 +38,7 @@ test "truncate.u0.var" {...@@ -34,6 +38,7 @@ test "truncate.u0.var" {
34}38}
3539
36test "truncate i0 to larger integer allowed and has comptime known result" {40test "truncate i0 to larger integer allowed and has comptime known result" {
41 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3843
39 var x: i0 = 0;44 var x: i0 = 0;
...@@ -42,6 +47,7 @@ test "truncate i0 to larger integer allowed and has comptime known result" {...@@ -42,6 +47,7 @@ test "truncate i0 to larger integer allowed and has comptime known result" {
42}47}
4348
44test "truncate.i0.literal" {49test "truncate.i0.literal" {
50 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
45 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
4652
47 var z = @truncate(i0, 0);53 var z = @truncate(i0, 0);
...@@ -49,6 +55,7 @@ test "truncate.i0.literal" {...@@ -49,6 +55,7 @@ test "truncate.i0.literal" {
49}55}
5056
51test "truncate.i0.const" {57test "truncate.i0.const" {
58 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;59 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
5360
54 const c0: isize = 0;61 const c0: isize = 0;
...@@ -57,6 +64,7 @@ test "truncate.i0.const" {...@@ -57,6 +64,7 @@ test "truncate.i0.const" {
57}64}
5865
59test "truncate.i0.var" {66test "truncate.i0.var" {
67 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
60 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;68 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6169
62 var d: i8 = 2;70 var d: i8 = 2;
...@@ -65,6 +73,7 @@ test "truncate.i0.var" {...@@ -65,6 +73,7 @@ test "truncate.i0.var" {
65}73}
6674
67test "truncate on comptime integer" {75test "truncate on comptime integer" {
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
68 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6978
70 var x = @truncate(u16, 9999);79 var x = @truncate(u16, 9999);
test/behavior/var_args.zig+3
...@@ -25,6 +25,7 @@ fn readFirstVarArg(args: anytype) void {...@@ -25,6 +25,7 @@ fn readFirstVarArg(args: anytype) void {
25}25}
2626
27test "send void arg to var args" {27test "send void arg to var args" {
28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
28 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
29 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO30 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -84,6 +85,7 @@ fn foo2(args: anytype) bool {...@@ -84,6 +85,7 @@ fn foo2(args: anytype) bool {
84}85}
8586
86test "array of var args functions" {87test "array of var args functions" {
88 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
87 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO89 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO90 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
89 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO91 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -93,6 +95,7 @@ test "array of var args functions" {...@@ -93,6 +95,7 @@ test "array of var args functions" {
93}95}
9496
95test "pass zero length array to var args param" {97test "pass zero length array to var args param" {
98 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
96 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO99 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
97 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO100 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
98 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/stage2/aarch64.zig+69-18
...@@ -17,15 +17,8 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -17,15 +17,8 @@ pub fn addCases(ctx: *TestContext) !void {
17 var case = ctx.exe("linux_aarch64 hello world", linux_aarch64);17 var case = ctx.exe("linux_aarch64 hello world", linux_aarch64);
18 // Regular old hello world18 // Regular old hello world
19 case.addCompareOutput(19 case.addCompareOutput(
20 \\pub export fn _start() noreturn {20 \\pub fn main() void {
21 \\ print();21 \\ print();
22 \\ exit();
23 \\}
24 \\
25 \\fn doNothing() void {}
26 \\
27 \\fn answer() u64 {
28 \\ return 0x1234abcd1234abcd;
29 \\}22 \\}
30 \\23 \\
31 \\fn print() void {24 \\fn print() void {
...@@ -38,16 +31,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -38,16 +31,6 @@ pub fn addCases(ctx: *TestContext) !void {
38 \\ : "memory", "cc"31 \\ : "memory", "cc"
39 \\ );32 \\ );
40 \\}33 \\}
41 \\
42 \\fn exit() noreturn {
43 \\ asm volatile ("svc #0"
44 \\ :
45 \\ : [number] "{x8}" (93),
46 \\ [arg1] "{x0}" (0)
47 \\ : "memory", "cc"
48 \\ );
49 \\ unreachable;
50 \\}
51 ,34 ,
52 "Hello, World!\n",35 "Hello, World!\n",
53 );36 );
...@@ -102,6 +85,74 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -102,6 +85,74 @@ pub fn addCases(ctx: *TestContext) !void {
102 ,85 ,
103 "Hello, World!\n",86 "Hello, World!\n",
104 );87 );
88
89 case.addCompareOutput(
90 \\pub fn main() void {
91 \\ foo(true);
92 \\}
93 \\
94 \\fn foo(x: bool) void {
95 \\ if (x) {
96 \\ print();
97 \\ }
98 \\}
99 \\
100 \\fn print() void {
101 \\ asm volatile ("svc #0"
102 \\ :
103 \\ : [number] "{x8}" (64),
104 \\ [arg1] "{x0}" (1),
105 \\ [arg2] "{x1}" (@ptrToInt("Hello, World!\n")),
106 \\ [arg3] "{x2}" ("Hello, World!\n".len),
107 \\ : "memory", "cc"
108 \\ );
109 \\}
110 ,
111 "Hello, World!\n",
112 );
113 }
114
115 {
116 var case = ctx.exe("large add function", linux_aarch64);
117
118 case.addCompareOutput(
119 \\pub fn main() void {
120 \\ assert(add(3, 4) == 791);
121 \\}
122 \\
123 \\fn add(a: u32, b: u32) u32 {
124 \\ const x: u32 = blk: {
125 \\ const c = a + b; // 7
126 \\ const d = a + c; // 10
127 \\ const e = d + b; // 14
128 \\ const f = d + e; // 24
129 \\ const g = e + f; // 38
130 \\ const h = f + g; // 62
131 \\ const i = g + h; // 100
132 \\ const j = i + d; // 110
133 \\ const k = i + j; // 210
134 \\ const l = k + c; // 217
135 \\ const m = l + d; // 227
136 \\ const n = m + e; // 241
137 \\ const o = n + f; // 265
138 \\ const p = o + g; // 303
139 \\ const q = p + h; // 365
140 \\ const r = q + i; // 465
141 \\ const s = r + j; // 575
142 \\ const t = s + k; // 785
143 \\ break :blk t;
144 \\ };
145 \\ const y = x + a; // 788
146 \\ const z = y + a; // 791
147 \\ return z;
148 \\}
149 \\
150 \\fn assert(ok: bool) void {
151 \\ if (!ok) unreachable;
152 \\}
153 ,
154 "",
155 );
105 }156 }
106157
107 // macOS tests158 // macOS tests