| author | |
| committer | |
| log | be98f30a2d647075564e02791813ddfb599f6cd7 |
| tree | 7cb73181d19a46ef8c1fbf671ce85a17fe0c9644 |
| parent | dc6553d93eb856a1593d43f0d1ea387c74fa7b44 |
| parent | 6c195db03a502074952181261807cf9a8e140d8d |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
stage2 AArch64: get zig test working; enable behavior tests33 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 -fLLVM | 7 | $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-bin | 8 | $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=c | 9 | $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-bin | 10 | $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-bin | 11 | $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 test | 13 | $ZIG test test/behavior.zig -fno-stage1 -I test |
| 13 | 14 | ||
| 14 | $ZIG build test-behavior -fqemu -fwasmtime | 15 | $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 { |
| 511 | 511 | ||
| 512 | switch (air_tags[inst]) { | 512 | switch (air_tags[inst]) { |
| 513 | // zig fmt: off | 513 | // 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 | } |
| 933 | 941 | ||
| 934 | fn airMin(self: *Self, inst: Air.Inst.Index) !void { | 942 | fn 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 | } |
| 952 | 960 | ||
| 953 | fn 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. | ||
| 969 | fn 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. | ||
| 1079 | fn 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. | ||
| 1164 | fn 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 | |||
| 1252 | fn 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 | } |
| 958 | 1263 | ||
| ... | @@ -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 | } |
| 970 | 1275 | ||
| 971 | fn 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 | |||
| 977 | fn airSubWrap(self: *Self, inst: Air.Inst.Index) !void { | 1276 | fn 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 { |
| 1098 | 1397 | ||
| 1099 | fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { | 1398 | fn 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 | } |
| 1104 | 1410 | ||
| 1105 | fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { | 1411 | fn 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 | } |
| 1110 | 1422 | ||
| ... | @@ -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!T | 1458 | /// E to E!T |
| 1147 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | 1459 | fn 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 | } |
| 1152 | 1471 | ||
| ... | @@ -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 { |
| 1158 | 1477 | ||
| 1159 | fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { | 1478 | fn 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 | } |
| 1164 | 1496 | ||
| ... | @@ -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 { |
| 1177 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | 1509 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1178 | const is_volatile = false; // TODO | 1510 | 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 | } |
| 1183 | 1571 | ||
| 1572 | fn 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 | |||
| 1184 | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { | 1620 | fn 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 | } |
| 1313 | 1815 | ||
| 1816 | fn 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 | |||
| 1314 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | 1894 | fn 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 | } |
| 1339 | 1919 | ||
| 1340 | fn airStore(self: *Self, inst: Air.Inst.Index) !void { | 1920 | fn 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 | |||
| 1952 | fn 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 | } |
| 1376 | 1963 | ||
| 1377 | fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void { | 1964 | fn 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 | } |
| 1382 | 1970 | ||
| 1383 | fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { | 1971 | fn 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 | } |
| 1387 | fn structFieldPtr(self: *Self, operand: Air.Inst.Ref, ty: Air.Inst.Ref, index: u32) !void { | 1976 | |
| 1388 | _ = self; | 1977 | fn 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 | } |
| 1395 | 1993 | ||
| 1396 | fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | 1994 | fn 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 { |
| 1487 | 2085 | ||
| 1488 | fn airCall(self: *Self, inst: Air.Inst.Index) !void { | 2086 | fn 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 | }; | ||
| 1494 | 2098 | ||
| 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); |
| 1497 | 2101 | ||
| 1498 | // Due to incremental compilation, how function calls are generated depends | 2102 | 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, |
| 1505 | 2109 | .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 | } | ||
| 1531 | 2132 | ||
| 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 storing | 2163 | // 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 | } | ||
| 1688 | 2227 | ||
| 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 { |
| 1741 | 2280 | ||
| 1742 | fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | 2281 | fn 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 | }; | ||
| 1750 | 2300 | ||
| 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 | } |
| 1824 | 2373 | ||
| 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 | }; |
| 1881 | 2445 | ||
| 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 | } |
| 2010 | 2574 | ||
| 2011 | fn isErr(self: *Self, operand: MCValue) !MCValue { | 2575 | fn 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 default | 2577 | |
| 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 | } |
| 2017 | 2606 | ||
| 2018 | fn isNonErr(self: *Self, operand: MCValue) !MCValue { | 2607 | fn 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 default | 2609 | 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 | } |
| 2024 | 2621 | ||
| 2025 | fn airIsNull(self: *Self, inst: Air.Inst.Index) !void { | 2622 | fn 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 { |
| 2184 | fn performReloc(self: *Self, inst: Mir.Inst.Index) !void { | 2785 | fn 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. |
| 2414 | 3025 | ||
| 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 |
| 2445 | 3109 | ||
| 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 | } |
| 2715 | 3378 | ||
| 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. | ||
| 2721 | fn 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 | |||
| 2737 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { | 3379 | fn 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; | ||
| 2868 | 3501 | ||
| 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 | } | ||
| 2873 | 3507 | ||
| 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 | } |
| 3016 | 3659 | ||
| 3017 | fn registerAlias(reg: Register, size_bytes: u32) Register { | 3660 | fn registerAlias(reg: Register, size_bytes: u32) Register { |
| 3018 | _ = size_bytes; | 3661 | if (size_bytes == 0) { |
| 3019 | 3662 | 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 | } |
| 3022 | 3671 | ||
| 3023 | /// For most architectures this does nothing. For x86_64 it resolves any aliased registers | 3672 | /// Resolves any aliased registers to the 64-bit wide ones. |
| 3024 | /// to the 64-bit wide ones. | ||
| 3025 | fn toCanonicalReg(reg: Register) Register { | 3673 | fn 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 | }; |
| 51 | 51 | ||
| 52 | const BranchType = enum { | 52 | const BranchType = enum { |
| 53 | cbz, | ||
| 53 | b_cond, | 54 | b_cond, |
| 54 | unconditional_branch_immediate, | 55 | unconditional_branch_immediate, |
| 55 | 56 | ||
| 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), |
| 85 | 87 | ||
| 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), |
| 88 | 92 | ||
| ... | @@ -91,7 +95,9 @@ pub fn emitMir( | ... | @@ -91,7 +95,9 @@ pub fn emitMir( |
| 91 | 95 | ||
| 92 | .call_extern => try emit.mirCallExtern(inst), | 96 | .call_extern => try emit.mirCallExtern(inst), |
| 93 | 97 | ||
| 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), | ||
| 95 | 101 | ||
| 96 | .cset => try emit.mirConditionalSelect(inst), | 102 | .cset => try emit.mirConditionalSelect(inst), |
| 97 | 103 | ||
| ... | @@ -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(), |
| 102 | 108 | ||
| 109 | .eor_shifted_register => try emit.mirLogicalShiftedRegister(inst), | ||
| 110 | |||
| 103 | .load_memory => try emit.mirLoadMemory(inst), | 111 | .load_memory => try emit.mirLoadMemory(inst), |
| 104 | 112 | ||
| 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( |
| 128 | 136 | ||
| 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), | ||
| 131 | 140 | ||
| 132 | .movk => try emit.mirMoveWideImmediate(inst), | 141 | .movk => try emit.mirMoveWideImmediate(inst), |
| 133 | .movz => try emit.mirMoveWideImmediate(inst), | 142 | .movz => try emit.mirMoveWideImmediate(inst), |
| 134 | 143 | ||
| 144 | .mul => try emit.mirDataProcessing3Source(inst), | ||
| 145 | |||
| 135 | .nop => try emit.mirNop(), | 146 | .nop => try emit.mirNop(), |
| 136 | 147 | ||
| 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); |
| 157 | 168 | ||
| 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 { |
| 179 | 197 | ||
| 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 | } |
| 186 | 206 | ||
| ... | @@ -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 { |
| 212 | 238 | ||
| 213 | fn isBranch(tag: Mir.Inst.Tag) bool { | 239 | fn 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]; |
| 222 | 252 | ||
| 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 { |
| 414 | 445 | ||
| 415 | fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void { | 446 | fn 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 | } |
| 483 | 517 | ||
| 518 | fn 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 | |||
| 484 | fn mirUnconditionalBranchRegister(emit: *Emit, inst: Mir.Inst.Index) !void { | 535 | fn 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 { |
| 565 | fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void { | 616 | fn 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; | ||
| 568 | 624 | ||
| 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 | } |
| 580 | 632 | ||
| 581 | fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void { | 633 | fn 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 | |||
| 644 | fn 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; | ||
| 584 | 652 | ||
| 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 { |
| 653 | fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void { | 716 | fn 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; | ||
| 656 | 723 | ||
| 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 { |
| 782 | 839 | ||
| 783 | fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void { | 840 | fn 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 | } |
| 804 | 869 | ||
| 870 | fn 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 | |||
| 805 | fn mirNop(emit: *Emit) !void { | 880 | fn 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 conditionally | 31 | /// Branch conditionally |
| 30 | b_cond, | 32 | b_cond, |
| 31 | /// Branch | 33 | /// 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 extern | 41 | /// 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 line | 55 | /// 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 memory | 59 | /// 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 zero | 89 | /// Move wide with zero |
| 84 | movz, | 90 | movz, |
| 91 | /// Multiply | ||
| 92 | mul, | ||
| 93 | /// Bitwise NOT | ||
| 94 | mvn, | ||
| 85 | /// No Operation | 95 | /// No Operation |
| 86 | nop, | 96 | nop, |
| 87 | /// Pseudo-instruction: Pop multiple registers | 97 | /// 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 Call | 127 | /// 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 registers | 200 | /// Two registers |
| 175 | /// | 201 | /// |
| 176 | /// Used by e.g. mov_register | 202 | /// 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 shift | 215 | /// Two registers, an unsigned 12-bit immediate, and an optional shift |
| 182 | /// | 216 | /// |
| 183 | /// Used by e.g. sub_immediate | 217 | /// 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_register | 243 | /// 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 condition | 251 | /// Three registers and a shift (logical instruction version) |
| 252 | /// (shift type and 6-bit amount) | ||
| 201 | /// | 253 | /// |
| 202 | /// Used by e.g. cset | 254 | /// 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 LoadStoreOffsetImmediate | 262 | /// Two registers and a LoadStoreOffsetImmediate |
| 210 | /// | 263 | /// |
| 211 | /// Used by e.g. str_register | 264 | /// 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 offset | 278 | /// A registers and a stack offset |
| 226 | /// | 279 | /// |
| 227 | /// Used by e.g. str_register | 280 | /// 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 | }, |
| 335 | 335 | 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, |
| 339 | 339 | 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 | }; | ||
| 352 | 346 | ||
| 353 | pub const Condition = enum(u4) { | 347 | pub const Condition = enum(u4) { |
| 354 | /// Integer: Equal | 348 | /// 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 | } |
| 475 | 470 | ||
| ... | @@ -807,25 +802,28 @@ pub const Instruction = union(enum) { | ... | @@ -807,25 +802,28 @@ pub const Instruction = union(enum) { |
| 807 | }; | 802 | }; |
| 808 | } | 803 | } |
| 809 | 804 | ||
| 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 | } |
| 969 | 967 | ||
| 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 functions | 995 | // Helper functions for assembly syntax functions |
| 971 | 996 | ||
| 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) { |
| 1120 | 1145 | ||
| 1121 | // Logical (shifted register) | 1146 | // Logical (shifted register) |
| 1122 | 1147 | ||
| 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 | } |
| 1126 | 1157 | ||
| 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 | } |
| 1130 | 1167 | ||
| 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 | } |
| 1134 | 1177 | ||
| 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 | } |
| 1138 | 1187 | ||
| 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 | } |
| 1142 | 1197 | ||
| 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 | } |
| 1146 | 1207 | ||
| 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 | } |
| 1150 | 1217 | ||
| 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 | } |
| 1154 | 1227 | ||
| 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 | }; |
| 1249 | 1340 | ||
| 1250 | test { | 1341 | test { |
| ... | @@ -1259,11 +1350,11 @@ test "serialize instructions" { | ... | @@ -1259,11 +1350,11 @@ test "serialize instructions" { |
| 1259 | 1350 | ||
| 1260 | const testcases = [_]Testcase{ | 1351 | const testcases = [_]Testcase{ |
| 1261 | .{ // orr x0, xzr, x1 | 1352 | .{ // 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, x1 | 1356 | .{ // 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, #4 | 1360 | .{ // 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, x2 | 1476 | .{ // 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 #0x8 | 1480 | .{ // 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, #10 | 1484 | .{ // 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 | }; |
| 1418 | 1513 | ||
| 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 | } |
| 56 | 56 | ||
| 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 | } |
| 28 | 28 | ||
| 29 | test "implicitly decreasing pointer alignment" { | 29 | test "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 | } |
| 38 | 39 | ||
| 39 | test "@alignCast pointers" { | 40 | test "@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 | } |
| 103 | 105 | ||
| 104 | test "implicitly decreasing slice alignment" { | 106 | test "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; |
| 106 | 109 | ||
| 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 | } |
| 114 | 117 | ||
| 115 | test "specifying alignment allows pointer cast" { | 118 | test "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; |
| 117 | 121 | ||
| 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 | } |
| 125 | 129 | ||
| 126 | test "@alignCast slices" { | 130 | test "@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; |
| 128 | 133 | ||
| 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 | } |
| 140 | 145 | ||
| 141 | test "return error union with 128-bit integer" { | 146 | test "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; |
| 143 | 149 | ||
| 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 | } |
| 149 | 155 | ||
| 150 | test "page aligned array on stack" { | 156 | test "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 {} |
| 173 | fn noop4() align(4) void {} | 180 | fn noop4() align(4) void {} |
| 174 | 181 | ||
| 175 | test "function alignment" { | 182 | test "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 | } |
| 190 | 198 | ||
| 191 | test "implicitly decreasing fn alignment" { | 199 | test "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 | } |
| 217 | 226 | ||
| 218 | test "@alignCast functions" { | 227 | test "@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 | } |
| 240 | 250 | ||
| 241 | test "generic function with align param" { | 251 | test "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 | } |
| 261 | 272 | ||
| 262 | test "runtime known array index has best alignment possible" { | 273 | test "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 | } |
| 303 | 315 | ||
| 304 | test "alignment of function with c calling convention" { | 316 | test "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; |
| 306 | 319 | ||
| 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 | }; |
| 319 | 332 | ||
| 320 | test "read 128-bit field from default aligned struct in stack memory" { | 333 | test "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 | }; |
| 338 | 352 | ||
| 339 | test "read 128-bit field from default aligned struct in global memory" { | 353 | test "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 | } |
| 349 | 364 | ||
| 350 | test "struct field explicit alignment" { | 365 | test "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 | } |
| 370 | 386 | ||
| 371 | test "align(@alignOf(T)) T does not force resolution of T" { | 387 | test "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 | } |
| 398 | 415 | ||
| 399 | test "align(N) on functions" { | 416 | test "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 | }; |
| 12 | 12 | ||
| 13 | test "@alignOf(T) before referencing T" { | 13 | test "@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; |
| 6 | const expectEqual = testing.expectEqual; | 6 | const expectEqual = testing.expectEqual; |
| 7 | 7 | ||
| 8 | test "array to slice" { | 8 | test "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; |
| 10 | 11 | ||
| 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 | } |
| 21 | 22 | ||
| 22 | test "arrays" { | 23 | test "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; |
| 24 | 26 | ||
| 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 | } |
| 47 | 49 | ||
| 48 | test "array init with mult" { | 50 | test "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; |
| 50 | 53 | ||
| 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 | } |
| 58 | 61 | ||
| 59 | test "array literal with explicit type" { | 62 | test "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; |
| 61 | 65 | ||
| 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 { |
| 86 | const some_array = [_]u8{ 0, 1, 2, 3 }; | 90 | const some_array = [_]u8{ 0, 1, 2, 3 }; |
| 87 | 91 | ||
| 88 | test "array literal with specified size" { | 92 | test "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; |
| 90 | 95 | ||
| 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 | } |
| 95 | 100 | ||
| 96 | test "array len field" { | 101 | test "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; |
| 98 | 104 | ||
| 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 | } |
| 106 | 112 | ||
| 107 | test "array with sentinels" { | 113 | test "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; |
| 109 | 116 | ||
| 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 | } |
| 135 | 142 | ||
| 136 | test "void arrays" { | 143 | test "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; |
| 138 | 146 | ||
| 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 | } |
| 145 | 153 | ||
| 146 | test "nested arrays" { | 154 | test "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; |
| 148 | 157 | ||
| 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 | } |
| 158 | 167 | ||
| 159 | test "implicit comptime in array type size" { | 168 | test "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; |
| 161 | 171 | ||
| 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 | } |
| 169 | 179 | ||
| 170 | test "single-item pointer to array indexing and slicing" { | 180 | test "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; |
| 172 | 183 | ||
| 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 | } |
| 194 | 205 | ||
| 195 | test "implicit cast zero sized array ptr to slice" { | 206 | test "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; |
| 197 | 209 | ||
| 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 | } |
| 209 | 221 | ||
| 210 | test "anonymous list literal syntax" { | 222 | test "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; |
| 212 | 225 | ||
| 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; |
| 227 | const Sub = struct { b: u8 }; | 240 | const Sub = struct { b: u8 }; |
| 228 | const Str = struct { a: []Sub }; | 241 | const Str = struct { a: []Sub }; |
| 229 | test "set global var array via slice embedded in struct" { | 242 | test "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; // TODO | 244 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 231 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 245 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 232 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 246 | 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 | } |
| 244 | 258 | ||
| 245 | test "read/write through global variable array of struct fields initialized via array mult" { | 259 | test "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; // TODO | 261 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 247 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 262 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 248 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 263 | 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 | } |
| 265 | 280 | ||
| 266 | test "implicit cast single-item pointer" { | 281 | test "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; // TODO | 283 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 268 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 284 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 269 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 285 | 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 | } |
| 285 | 301 | ||
| 286 | test "comptime evaluating function that takes array by value" { | 302 | test "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; // TODO | 304 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 288 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 305 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 289 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 306 | 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 | } |
| 297 | 314 | ||
| 298 | test "runtime initialize array elem and then implicit cast to slice" { | 315 | test "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; // TODO | 317 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 300 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 318 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 301 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 319 | 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 | } |
| 307 | 325 | ||
| 308 | test "array literal as argument to function" { | 326 | test "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; // TODO | 328 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 310 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 329 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 311 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 330 | 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 | } |
| 335 | 354 | ||
| 336 | test "double nested array to const slice cast in array literal" { | 355 | test "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; // TODO | 357 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 338 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 358 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 339 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 359 | 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 | } |
| 396 | 416 | ||
| 397 | test "anonymous literal in array" { | 417 | test "anonymous literal in array" { |
| 418 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 398 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 419 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 399 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 420 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 400 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 421 | 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 | } |
| 421 | 442 | ||
| 422 | test "access the null element of a null terminated array" { | 443 | test "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; // TODO | 445 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 424 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 446 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 425 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 447 | 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 | } |
| 438 | 460 | ||
| 439 | test "type deduction for array subscript expression" { | 461 | test "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; // TODO | 463 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 441 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 464 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 442 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 465 | 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 | } |
| 456 | 479 | ||
| 457 | test "sentinel element count towards the ABI size calculation" { | 480 | test "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; // TODO | 482 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO |
| 459 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 483 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 460 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 484 | 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 | } |
| 482 | 506 | ||
| 483 | test "zero-sized array with recursive type definition" { | 507 | test "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; // TODO | 509 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO |
| 485 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 510 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 486 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 511 | 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 | } |
| 506 | 531 | ||
| 507 | test "type coercion of anon struct literal to array" { | 532 | test "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; // TODO | 534 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 509 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 535 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 510 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 536 | 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 | } |
| 541 | 567 | ||
| 542 | test "type coercion of pointer to anon struct literal to pointer to array" { | 568 | test "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; // TODO | 570 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO |
| 544 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 571 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 545 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 572 | 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 | } |
| 16 | 16 | ||
| 17 | test "truncate" { | 17 | test "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; |
| 19 | 20 | ||
| 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 | } |
| 26 | 27 | ||
| 27 | test "truncate to non-power-of-two integers" { | 28 | test "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; |
| 29 | 31 | ||
| 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; |
| 46 | var g2: i32 = 0; | 48 | var g2: i32 = 0; |
| 47 | 49 | ||
| 48 | test "global variables" { | 50 | test "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 | } |
| 113 | 116 | ||
| 114 | test "return string from function" { | 117 | test "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; |
| 117 | 121 | ||
| ... | @@ -119,12 +123,14 @@ test "return string from function" { | ... | @@ -119,12 +123,14 @@ test "return string from function" { |
| 119 | } | 123 | } |
| 120 | 124 | ||
| 121 | test "hex escape" { | 125 | test "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; |
| 123 | 128 | ||
| 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 | } |
| 126 | 131 | ||
| 127 | test "multiline string" { | 132 | test "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; |
| 129 | 135 | ||
| 130 | const s1 = | 136 | const s1 = |
| ... | @@ -137,6 +143,7 @@ test "multiline string" { | ... | @@ -137,6 +143,7 @@ test "multiline string" { |
| 137 | } | 143 | } |
| 138 | 144 | ||
| 139 | test "multiline string comments at start" { | 145 | test "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; |
| 141 | 148 | ||
| 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 | } |
| 150 | 157 | ||
| 151 | test "multiline string comments at end" { | 158 | test "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; |
| 153 | 161 | ||
| 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 | } |
| 162 | 170 | ||
| 163 | test "multiline string comments in middle" { | 171 | test "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; |
| 165 | 174 | ||
| 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 | } |
| 174 | 183 | ||
| 175 | test "multiline string comments at multiple places" { | 184 | test "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; |
| 177 | 187 | ||
| 178 | const s1 = | 188 | const s1 = |
| ... | @@ -191,6 +201,7 @@ test "string concatenation" { | ... | @@ -191,6 +201,7 @@ test "string concatenation" { |
| 191 | } | 201 | } |
| 192 | 202 | ||
| 193 | test "array mult operator" { | 203 | test "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; |
| 195 | 206 | ||
| 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 | } |
| 217 | 228 | ||
| 218 | test "cast undefined" { | 229 | test "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; |
| 220 | 232 | ||
| 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 | } |
| 228 | 240 | ||
| 229 | test "implicit cast after unreachable" { | 241 | test "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; |
| 231 | 244 | ||
| 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 | } |
| 285 | 298 | ||
| 286 | test "call function pointer in struct" { | 299 | test "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; |
| 289 | 303 | ||
| ... | @@ -310,6 +324,7 @@ const FnPtrWrapper = struct { | ... | @@ -310,6 +324,7 @@ const FnPtrWrapper = struct { |
| 310 | }; | 324 | }; |
| 311 | 325 | ||
| 312 | test "const ptr from var variable" { | 326 | test "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; |
| 314 | 329 | ||
| 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 | } |
| 327 | 342 | ||
| 328 | test "call result of if else expression" { | 343 | test "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; // TODO | 347 | 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 | } |
| 340 | 356 | ||
| 341 | test "memcpy and memset intrinsics" { | 357 | test "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; // TODO | 361 | 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 | } |
| 362 | 379 | ||
| 363 | test "variable is allowed to be a pointer to an opaque type" { | 380 | test "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; // TODO | 384 | 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 | } |
| 375 | 393 | ||
| 376 | test "take address of parameter" { | 394 | test "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; |
| 379 | 398 | ||
| ... | @@ -400,6 +419,7 @@ fn testPointerToVoidReturnType2() *const void { | ... | @@ -400,6 +419,7 @@ fn testPointerToVoidReturnType2() *const void { |
| 400 | } | 419 | } |
| 401 | 420 | ||
| 402 | test "array 2D const double ptr" { | 421 | test "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; |
| 405 | 425 | ||
| ... | @@ -419,6 +439,7 @@ fn testArray2DConstDoublePtr(ptr: *const f32) !void { | ... | @@ -419,6 +439,7 @@ fn testArray2DConstDoublePtr(ptr: *const f32) !void { |
| 419 | } | 439 | } |
| 420 | 440 | ||
| 421 | test "double implicit cast in same expression" { | 441 | test "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; |
| 424 | 445 | ||
| ... | @@ -430,6 +451,7 @@ fn nine() u8 { | ... | @@ -430,6 +451,7 @@ fn nine() u8 { |
| 430 | } | 451 | } |
| 431 | 452 | ||
| 432 | test "struct inside function" { | 453 | test "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; |
| 434 | 456 | ||
| 435 | try testStructInFn(); | 457 | try testStructInFn(); |
| ... | @@ -451,6 +473,7 @@ fn testStructInFn() !void { | ... | @@ -451,6 +473,7 @@ fn testStructInFn() !void { |
| 451 | } | 473 | } |
| 452 | 474 | ||
| 453 | test "fn call returning scalar optional in equality expression" { | 475 | test "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 | } |
| 456 | 479 | ||
| ... | @@ -459,6 +482,7 @@ fn getNull() ?*i32 { | ... | @@ -459,6 +482,7 @@ fn getNull() ?*i32 { |
| 459 | } | 482 | } |
| 460 | 483 | ||
| 461 | test "global variable assignment with optional unwrapping with var initialized to undefined" { | 484 | test "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; |
| 463 | 487 | ||
| 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 |
| 476 | var global_foo: *i32 = undefined; | 500 | var global_foo: *i32 = undefined; |
| 477 | 501 | ||
| 478 | test "peer result location with typed parent, runtime condition, comptime prongs" { | 502 | test "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; |
| 481 | 506 | ||
| ... | @@ -550,6 +575,7 @@ test "comptime cast fn to ptr" { | ... | @@ -550,6 +575,7 @@ test "comptime cast fn to ptr" { |
| 550 | } | 575 | } |
| 551 | 576 | ||
| 552 | test "equality compare fn ptrs" { | 577 | test "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; |
| 554 | 580 | ||
| 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 | } |
| 558 | 584 | ||
| 559 | test "self reference through fn ptr field" { | 585 | test "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; |
| 562 | 589 | ||
| ... | @@ -576,6 +603,7 @@ test "self reference through fn ptr field" { | ... | @@ -576,6 +603,7 @@ test "self reference through fn ptr field" { |
| 576 | } | 603 | } |
| 577 | 604 | ||
| 578 | test "global variable initialized to global variable array element" { | 605 | test "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; |
| 581 | 609 | ||
| ... | @@ -593,6 +621,7 @@ var gdt = [_]GDTEntry{ | ... | @@ -593,6 +621,7 @@ var gdt = [_]GDTEntry{ |
| 593 | var global_ptr = &gdt[0]; | 621 | var global_ptr = &gdt[0]; |
| 594 | 622 | ||
| 595 | test "global constant is loaded with a runtime-known index" { | 623 | test "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; |
| 597 | 626 | ||
| 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 | } |
| 611 | 640 | ||
| 612 | test "multiline string literal is null terminated" { | 641 | test "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; |
| 615 | 645 | ||
| ... | @@ -643,6 +673,7 @@ test "explicit cast optional pointers" { | ... | @@ -643,6 +673,7 @@ test "explicit cast optional pointers" { |
| 643 | } | 673 | } |
| 644 | 674 | ||
| 645 | test "pointer comparison" { | 675 | test "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; |
| 648 | 679 | ||
| ... | @@ -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 | } |
| 656 | 687 | ||
| 657 | test "string concatenation" { | 688 | test "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; |
| 660 | 692 |
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 | } |
| 62 | 62 | ||
| 63 | test "sharded table" { | 63 | test "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 | }; |
| 13 | 13 | ||
| 14 | test "union that needs padding bytes inside an array" { | 14 | test "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 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 2 | const expect = std.testing.expect; |
| 3 | const builtin = @import("builtin"); | ||
| 3 | 4 | ||
| 4 | const ptr = &global; | 5 | const ptr = &global; |
| 5 | var global: usize = 123; | 6 | var global: usize = 123; |
| 6 | 7 | ||
| 7 | test "constant pointer to global variable causes runtime load" { | 8 | test "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 | }; |
| 43 | 43 | ||
| 44 | test "initialization" { | 44 | test "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"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | 3 | ||
| 4 | test "fixed" { | 4 | test "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 | }; |
| 8 | test "bug 2006" { | 8 | test "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 | } |
| 13 | 13 | ||
| 14 | test "fixed" { | 14 | test "fixed" { |
| 15 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 15 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 16 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 16 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 17 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 17 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 18 | 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 | } |
| 20 | 20 | ||
| 21 | test "fixed" { | 21 | test "fixed" { |
| 22 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 22 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 23 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 23 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 24 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 24 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 25 | 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 | } |
| 13 | 13 | ||
| 14 | test "zig test crash" { | 14 | test "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 | }; |
| 11 | 11 | ||
| 12 | test "container member access usingnamespace decls" { | 12 | test "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; |
| 11 | const builtin = @import("builtin"); | 11 | const builtin = @import("builtin"); |
| 12 | 12 | ||
| 13 | test "bug 394 fixed" { | 13 | test "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 | }; |
| 12 | 12 | ||
| 13 | test "optional if after an if in a switch prong of a switch with 2 prongs in an else" { | 13 | test "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 | }; |
| 15 | 15 | ||
| 16 | test "reference a global threadlocal variable" { | 16 | test "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 | } |
| 19 | 19 | ||
| 20 | test "peer type resolution: ?T and T" { | 20 | test "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; |
| 22 | 23 | ||
| 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 | } |
| 95 | 96 | ||
| 96 | test "@floatToInt" { | 97 | test "@floatToInt" { |
| 98 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 97 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 99 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 98 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 100 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 99 | 101 | ||
| ... | @@ -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 | } |
| 117 | 119 | ||
| 118 | test "implicitly cast indirect pointer to maybe-indirect pointer" { | 120 | test "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; |
| 120 | 123 | ||
| 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 | } |
| 175 | 178 | ||
| 176 | test "coerce undefined to optional" { | 179 | test "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; |
| 178 | 182 | ||
| 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 | } |
| 194 | 198 | ||
| 195 | test "implicit cast from *[N]T to [*c]T" { | 199 | test "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; |
| 197 | 202 | ||
| 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 | } |
| 206 | 211 | ||
| 207 | test "*usize to *void" { | 212 | test "*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 | } |
| 231 | 237 | ||
| 232 | test "peer result null and comptime_int" { | 238 | test "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; |
| 234 | 241 | ||
| 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 | } |
| 254 | 261 | ||
| 255 | test "*const ?[*]const T to [*c]const [*c]const T" { | 262 | test "*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; |
| 257 | 265 | ||
| 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 | } |
| 265 | 273 | ||
| 266 | test "array coersion to undefined at runtime" { | 274 | test "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; |
| 268 | 277 | ||
| 269 | @setRuntimeSafety(true); | 278 | @setRuntimeSafety(true); |
| ... | @@ -293,6 +302,7 @@ fn implicitIntLitToOptional() void { | ... | @@ -293,6 +302,7 @@ fn implicitIntLitToOptional() void { |
| 293 | } | 302 | } |
| 294 | 303 | ||
| 295 | test "return u8 coercing into ?u32 return type" { | 304 | test "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; |
| 297 | 307 | ||
| 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 | } |
| 314 | 324 | ||
| 315 | test "peer type unsigned int to signed" { | 325 | test "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; |
| 318 | 329 | ||
| ... | @@ -325,6 +336,7 @@ test "peer type unsigned int to signed" { | ... | @@ -325,6 +336,7 @@ test "peer type unsigned int to signed" { |
| 325 | } | 336 | } |
| 326 | 337 | ||
| 327 | test "expected [*c]const u8, found [*:0]const u8" { | 338 | test "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; |
| 330 | 342 | ||
| ... | @@ -384,6 +396,7 @@ fn castToOptionalTypeError(z: i32) !void { | ... | @@ -384,6 +396,7 @@ fn castToOptionalTypeError(z: i32) !void { |
| 384 | } | 396 | } |
| 385 | 397 | ||
| 386 | test "implicitly cast from [0]T to anyerror![]T" { | 398 | test "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; // TODO | 400 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 388 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 401 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 389 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 402 | 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 | } |
| 456 | 469 | ||
| 457 | test "peer type resolution: error and [N]T" { | 470 | test "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; // TODO | 472 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 459 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 473 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 460 | 474 | ||
| ... | @@ -689,6 +703,7 @@ test "type coercion related to sentinel-termination" { | ... | @@ -689,6 +703,7 @@ test "type coercion related to sentinel-termination" { |
| 689 | } | 703 | } |
| 690 | 704 | ||
| 691 | test "peer type resolution implicit cast to return type" { | 705 | test "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; // TODO | 707 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 693 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 708 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 694 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 709 | 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 | } |
| 711 | 726 | ||
| 712 | test "peer type resolution implicit cast to variable type" { | 727 | test "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; // TODO | 729 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 714 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 730 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 715 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 731 | 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 | } |
| 807 | 823 | ||
| 808 | test "pointer reinterpret const float to int" { | 824 | test "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; // TODO | 826 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 810 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 827 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 811 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 828 | 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 | } |
| 823 | 840 | ||
| 824 | test "implicit cast from [*]T to ?*anyopaque" { | 841 | test "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; // TODO | 843 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 826 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 844 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 827 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 845 | 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 | } |
| 841 | 859 | ||
| 842 | test "compile time int to ptr of function" { | 860 | test "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; // TODO | 863 | 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; // TODO | 864 | 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 | } |
| 858 | 877 | ||
| 859 | test "implicit ptr to *anyopaque" { | 878 | test "implicit ptr to *anyopaque" { |
| 879 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 860 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 880 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 861 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 881 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 862 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 882 | 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 | } |
| 872 | 892 | ||
| 873 | test "return null from fn() anyerror!?&T" { | 893 | test "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; // TODO | 895 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 875 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 896 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 876 | 897 | ||
| ... | @@ -887,6 +908,7 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { | ... | @@ -887,6 +908,7 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { |
| 887 | } | 908 | } |
| 888 | 909 | ||
| 889 | test "peer type resolution: [0]u8 and []const u8" { | 910 | test "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; // TODO | 912 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 891 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 913 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 892 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 914 | 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 | } |
| 908 | 930 | ||
| 909 | test "implicitly cast from [N]T to ?[]const T" { | 931 | test "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; // TODO | 933 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 911 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 934 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 912 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 935 | 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 | } |
| 921 | 944 | ||
| 922 | test "cast u128 to f128 and back" { | 945 | test "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; // TODO | 947 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 924 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 948 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 925 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 949 | 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 | } |
| 942 | 966 | ||
| 943 | test "implicit cast from *[N]T to ?[*]T" { | 967 | test "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; // TODO | 969 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 945 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 970 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 946 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 971 | 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 | } |
| 957 | 982 | ||
| 958 | test "implicit cast from *T to ?*anyopaque" { | 983 | test "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; // TODO | 985 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 960 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 986 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 961 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 987 | 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 | } |
| 971 | 997 | ||
| 972 | test "implicit cast *[0]T to E![]const u8" { | 998 | test "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; // TODO | 1000 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 974 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1001 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 975 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1002 | 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 | } |
| 989 | test "cast from array reference to fn: runtime fn ptr" { | 1016 | test "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; // TODO | 1018 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 991 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1019 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 992 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1020 | 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 | } |
| 997 | 1025 | ||
| 998 | test "*const [N]null u8 to ?[]const u8" { | 1026 | test "*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; // TODO | 1028 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1000 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1029 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1001 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1030 | 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" { |
| 1034 | 1063 | ||
| 1035 | var global_struct: struct { f0: usize } = undefined; | 1064 | var global_struct: struct { f0: usize } = undefined; |
| 1036 | test "assignment to optional pointer result loc" { | 1065 | test "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; // TODO | 1067 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1038 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1068 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1039 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1069 | 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 | } |
| 1044 | 1074 | ||
| 1045 | test "cast between *[N]void and []void" { | 1075 | test "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; // TODO | 1077 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1047 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1078 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1048 | 1079 | ||
| ... | @@ -1052,6 +1083,7 @@ test "cast between *[N]void and []void" { | ... | @@ -1052,6 +1083,7 @@ test "cast between *[N]void and []void" { |
| 1052 | } | 1083 | } |
| 1053 | 1084 | ||
| 1054 | test "peer resolve arrays of different size to const slice" { | 1085 | test "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; // TODO | 1087 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1056 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1088 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1057 | 1089 | ||
| ... | @@ -1065,6 +1097,7 @@ fn boolToStr(b: bool) []const u8 { | ... | @@ -1065,6 +1097,7 @@ fn boolToStr(b: bool) []const u8 { |
| 1065 | } | 1097 | } |
| 1066 | 1098 | ||
| 1067 | test "cast f16 to wider types" { | 1099 | test "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; // TODO | 1101 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1069 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1102 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1070 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1103 | 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 | } |
| 1084 | 1117 | ||
| 1085 | test "cast f128 to narrower types" { | 1118 | test "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; // TODO | 1120 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1087 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1121 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1088 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1122 | 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 | } |
| 1102 | 1136 | ||
| 1103 | test "peer type resolution: unreachable, null, slice" { | 1137 | test "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; // TODO | 1139 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1105 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1140 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1106 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1141 | 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 | } |
| 1120 | 1155 | ||
| 1121 | test "cast i8 fn call peers to i32 result" { | 1156 | test "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; // TODO | 1158 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1123 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1159 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1124 | 1160 |
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 | } |
| 33 | 33 | ||
| 34 | test "fn delegation" { | 34 | test "fn delegation" { |
| 35 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 35 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 36 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 36 | 37 | ||
| 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 | } |
| 19 | 19 | ||
| 20 | test "ir block deps" { | 20 | test "ir block deps" { |
| 21 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 21 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 22 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 22 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 23 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 23 | 24 |
test/behavior/optional.zig+10| ... | @@ -5,6 +5,7 @@ const expect = testing.expect; | ... | @@ -5,6 +5,7 @@ const expect = testing.expect; |
| 5 | const expectEqual = testing.expectEqual; | 5 | const expectEqual = testing.expectEqual; |
| 6 | 6 | ||
| 7 | test "passing an optional integer as a parameter" { | 7 | test "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; // TODO | 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 10 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 10 | 11 | ||
| ... | @@ -25,6 +26,7 @@ test "passing an optional integer as a parameter" { | ... | @@ -25,6 +26,7 @@ test "passing an optional integer as a parameter" { |
| 25 | pub const EmptyStruct = struct {}; | 26 | pub const EmptyStruct = struct {}; |
| 26 | 27 | ||
| 27 | test "optional pointer to size zero struct" { | 28 | test "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; // TODO | 30 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 29 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 31 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 30 | 32 | ||
| ... | @@ -34,6 +36,7 @@ test "optional pointer to size zero struct" { | ... | @@ -34,6 +36,7 @@ test "optional pointer to size zero struct" { |
| 34 | } | 36 | } |
| 35 | 37 | ||
| 36 | test "equality compare optional pointers" { | 38 | test "equality compare optional pointers" { |
| 39 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 37 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 40 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 38 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 41 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 39 | 42 | ||
| ... | @@ -58,6 +61,7 @@ fn testNullPtrsEql() !void { | ... | @@ -58,6 +61,7 @@ fn testNullPtrsEql() !void { |
| 58 | } | 61 | } |
| 59 | 62 | ||
| 60 | test "optional with void type" { | 63 | test "optional with void type" { |
| 64 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 61 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 65 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 62 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 66 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 63 | 67 | ||
| ... | @@ -69,6 +73,7 @@ test "optional with void type" { | ... | @@ -69,6 +73,7 @@ test "optional with void type" { |
| 69 | } | 73 | } |
| 70 | 74 | ||
| 71 | test "address of unwrap optional" { | 75 | test "address of unwrap optional" { |
| 76 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 72 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 77 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 73 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 78 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 74 | 79 | ||
| ... | @@ -89,6 +94,7 @@ test "address of unwrap optional" { | ... | @@ -89,6 +94,7 @@ test "address of unwrap optional" { |
| 89 | } | 94 | } |
| 90 | 95 | ||
| 91 | test "nested optional field in struct" { | 96 | test "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; // TODO | 98 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 93 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 99 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 94 | 100 | ||
| ... | @@ -105,6 +111,7 @@ test "nested optional field in struct" { | ... | @@ -105,6 +111,7 @@ test "nested optional field in struct" { |
| 105 | } | 111 | } |
| 106 | 112 | ||
| 107 | test "equality compare optional with non-optional" { | 113 | test "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; // TODO | 115 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 109 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 116 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 110 | 117 | ||
| ... | @@ -142,6 +149,7 @@ fn test_cmp_optional_non_optional() !void { | ... | @@ -142,6 +149,7 @@ fn test_cmp_optional_non_optional() !void { |
| 142 | } | 149 | } |
| 143 | 150 | ||
| 144 | test "unwrap function call with optional pointer return value" { | 151 | test "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; // TODO | 153 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 146 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 154 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 147 | 155 | ||
| ... | @@ -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 | } |
| 164 | 172 | ||
| 165 | test "nested orelse" { | 173 | test "nested orelse" { |
| 174 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 166 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 175 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 167 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 176 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 168 | 177 | ||
| ... | @@ -189,6 +198,7 @@ test "nested orelse" { | ... | @@ -189,6 +198,7 @@ test "nested orelse" { |
| 189 | } | 198 | } |
| 190 | 199 | ||
| 191 | test "self-referential struct through a slice of optional" { | 200 | test "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; // TODO | 202 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 193 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 203 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 194 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 204 | 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 | } |
| 29 | 29 | ||
| 30 | test "reflection: @field" { | 30 | test "reflection: @field" { |
| 31 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 31 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 32 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 32 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 33 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 33 | 34 |
test/behavior/slice.zig+14| ... | @@ -27,6 +27,7 @@ comptime { | ... | @@ -27,6 +27,7 @@ comptime { |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | test "slicing" { | 29 | test "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; // TODO | 33 | 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 | } |
| 69 | 70 | ||
| 70 | test "implicitly cast array of size 0 to slice" { | 71 | test "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; // TODO | 73 | 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; |
| 73 | 75 | ||
| ... | @@ -80,6 +82,7 @@ fn assertLenIsZero(msg: []const u8) !void { | ... | @@ -80,6 +82,7 @@ fn assertLenIsZero(msg: []const u8) !void { |
| 80 | } | 82 | } |
| 81 | 83 | ||
| 82 | test "access len index of sentinel-terminated slice" { | 84 | test "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; // TODO | 86 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 84 | 87 | ||
| 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 | } |
| 130 | 133 | ||
| 131 | test "generic malloc free" { | 134 | test "generic malloc free" { |
| 135 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 132 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 136 | 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 | } |
| 188 | 192 | ||
| 189 | test "slicing zero length array" { | 193 | test "slicing zero length array" { |
| 194 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 190 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 195 | 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" { |
| 202 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; | 207 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; |
| 203 | const y = x[0x100..]; | 208 | const y = x[0x100..]; |
| 204 | test "compile time slice of pointer to hard coded address" { | 209 | test "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; // TODO | 211 | 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 | } |
| 216 | 222 | ||
| 217 | test "slice string literal has correct type" { | 223 | test "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; |
| 220 | 227 | ||
| ... | @@ -230,6 +237,7 @@ test "slice string literal has correct type" { | ... | @@ -230,6 +237,7 @@ test "slice string literal has correct type" { |
| 230 | } | 237 | } |
| 231 | 238 | ||
| 232 | test "result location zero sized array inside struct field implicit cast to slice" { | 239 | test "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; // TODO | 241 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 234 | 242 | ||
| 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 | } |
| 241 | 249 | ||
| 242 | test "runtime safety lets us slice from len..len" { | 250 | test "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; |
| 245 | 254 | ||
| ... | @@ -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 | } |
| 253 | 262 | ||
| 254 | test "C pointer" { | 263 | test "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; |
| 257 | 267 | ||
| ... | @@ -262,6 +272,7 @@ test "C pointer" { | ... | @@ -262,6 +272,7 @@ test "C pointer" { |
| 262 | } | 272 | } |
| 263 | 273 | ||
| 264 | test "C pointer slice access" { | 274 | test "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; |
| 267 | 278 | ||
| ... | @@ -291,6 +302,7 @@ fn sliceSum(comptime q: []const u8) i32 { | ... | @@ -291,6 +302,7 @@ fn sliceSum(comptime q: []const u8) i32 { |
| 291 | } | 302 | } |
| 292 | 303 | ||
| 293 | test "slice type with custom alignment" { | 304 | test "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; |
| 296 | 308 | ||
| ... | @@ -305,6 +317,7 @@ test "slice type with custom alignment" { | ... | @@ -305,6 +317,7 @@ test "slice type with custom alignment" { |
| 305 | } | 317 | } |
| 306 | 318 | ||
| 307 | test "obtaining a null terminated slice" { | 319 | test "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; // TODO | 323 | 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 | } |
| 351 | 364 | ||
| 352 | test "@ptrCast slice to pointer" { | 365 | test "@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; |
| 355 | 369 |
test/behavior/struct.zig+28| ... | @@ -9,6 +9,7 @@ const maxInt = std.math.maxInt; | ... | @@ -9,6 +9,7 @@ const maxInt = std.math.maxInt; |
| 9 | top_level_field: i32, | 9 | top_level_field: i32, |
| 10 | 10 | ||
| 11 | test "top level fields" { | 11 | test "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; |
| 13 | 14 | ||
| 14 | var instance = @This(){ | 15 | var instance = @This(){ |
| ... | @@ -42,6 +43,7 @@ const StructWithFields = struct { | ... | @@ -42,6 +43,7 @@ const StructWithFields = struct { |
| 42 | }; | 43 | }; |
| 43 | 44 | ||
| 44 | test "non-packed struct has fields padded out to the required alignment" { | 45 | test "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; |
| 46 | 48 | ||
| 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 | }; |
| 66 | 68 | ||
| 67 | test "lower unnamed constants" { | 69 | test "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 | }; |
| 84 | 87 | ||
| 85 | test "structs" { | 88 | test "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; |
| 87 | 91 | ||
| 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 | } |
| 102 | 106 | ||
| 103 | test "struct byval assign" { | 107 | test "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; |
| 105 | 110 | ||
| 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 | } |
| 135 | 140 | ||
| 136 | test "fn call of struct field" { | 141 | test "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; |
| 138 | 144 | ||
| 139 | const Foo = struct { | 145 | const Foo = struct { |
| ... | @@ -165,12 +171,14 @@ const MemberFnTestFoo = struct { | ... | @@ -165,12 +171,14 @@ const MemberFnTestFoo = struct { |
| 165 | }; | 171 | }; |
| 166 | 172 | ||
| 167 | test "call member function directly" { | 173 | test "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 | } |
| 172 | 179 | ||
| 173 | test "store member function in variable" { | 180 | test "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 | } |
| 179 | 187 | ||
| 180 | test "member functions" { | 188 | test "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 | }; |
| 190 | 199 | ||
| 191 | test "return struct byval from function" { | 200 | test "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; |
| 193 | 203 | ||
| 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 | } |
| 207 | 217 | ||
| 208 | test "call method with mutable reference to struct with no fields" { | 218 | test "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; |
| 210 | 221 | ||
| 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 | } |
| 239 | 250 | ||
| 240 | test "struct field init with catch" { | 251 | test "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; |
| 242 | 254 | ||
| 243 | const S = struct { | 255 | const S = struct { |
| ... | @@ -296,6 +308,7 @@ const Val = struct { | ... | @@ -296,6 +308,7 @@ const Val = struct { |
| 296 | }; | 308 | }; |
| 297 | 309 | ||
| 298 | test "struct point to self" { | 310 | test "struct point to self" { |
| 311 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 299 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 312 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 300 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 313 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 301 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 314 | 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 | } |
| 315 | 328 | ||
| 316 | test "void struct fields" { | 329 | test "void struct fields" { |
| 330 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 317 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 331 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 318 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 332 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 319 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 333 | 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 | }; |
| 335 | 349 | ||
| 336 | test "return empty struct from fn" { | 350 | test "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; // TODO | 352 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 338 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 353 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 339 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 354 | 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 | } |
| 348 | 363 | ||
| 349 | test "pass slice of empty struct to fn" { | 364 | test "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; // TODO | 366 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 351 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 367 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 352 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 368 | 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 | } |
| 360 | 376 | ||
| 361 | test "self-referencing struct via array member" { | 377 | test "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; // TODO | 379 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 363 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 380 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 364 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 381 | 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 | }; |
| 390 | 407 | ||
| 391 | test "align 1 field before self referential align 8 field as slice return type" { | 408 | test "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; // TODO | 410 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 393 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 411 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 394 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 412 | 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 | }; |
| 414 | 432 | ||
| 415 | test "packed struct" { | 433 | test "packed struct" { |
| 434 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 416 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 435 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 417 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 436 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 418 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 437 | 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 | }; |
| 439 | 458 | ||
| 440 | test "packed struct 24bits" { | 459 | test "packed struct 24bits" { |
| 460 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 441 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 461 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 442 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 462 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 443 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 463 | 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 | } |
| 485 | 505 | ||
| 486 | test "runtime struct initialization of bitfield" { | 506 | test "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; // TODO | 508 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 488 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 509 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 489 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 510 | 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 | }; |
| 524 | 545 | ||
| 525 | test "native bit field understands endianness" { | 546 | test "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; // TODO | 548 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 527 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 549 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 528 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 550 | 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 | } |
| 547 | 569 | ||
| 548 | test "implicit cast packed struct field to const ptr" { | 570 | test "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; // TODO | 572 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 550 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 573 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 551 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 574 | 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 | } |
| 582 | 605 | ||
| 583 | test "packed struct with non-ABI-aligned field" { | 606 | test "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; // TODO | 608 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 585 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 609 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 586 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 610 | 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 | }; |
| 611 | 635 | ||
| 612 | test "bit field access" { | 636 | test "bit field access" { |
| 637 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 613 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 638 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 614 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 639 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 615 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 640 | 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 | } |
| 643 | 668 | ||
| 644 | test "default struct initialization fields" { | 669 | test "default struct initialization fields" { |
| 670 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 645 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 671 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 646 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 672 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 647 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 673 | 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 | } |
| 908 | 934 | ||
| 909 | test "anonymous struct literal syntax" { | 935 | test "anonymous struct literal syntax" { |
| 936 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 910 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 937 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 911 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 938 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 912 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 939 | 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 | } |
| 1101 | 1128 | ||
| 1102 | test "packed struct with undefined initializers" { | 1129 | test "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; // TODO | 1131 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1104 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 1132 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1105 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1133 | 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"); |
| 3 | const expect = std.testing.expect; | 3 | const expect = std.testing.expect; |
| 4 | 4 | ||
| 5 | test "truncate u0 to larger integer allowed and has comptime known result" { | 5 | test "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; |
| 7 | 8 | ||
| 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 | } |
| 12 | 13 | ||
| 13 | test "truncate.u0.literal" { | 14 | test "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; |
| 15 | 17 | ||
| 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 | } |
| 19 | 21 | ||
| 20 | test "truncate.u0.const" { | 22 | test "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; |
| 22 | 25 | ||
| 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 | } |
| 27 | 30 | ||
| 28 | test "truncate.u0.var" { | 31 | test "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; |
| 30 | 34 | ||
| 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 | } |
| 35 | 39 | ||
| 36 | test "truncate i0 to larger integer allowed and has comptime known result" { | 40 | test "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; |
| 38 | 43 | ||
| 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 | } |
| 43 | 48 | ||
| 44 | test "truncate.i0.literal" { | 49 | test "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; |
| 46 | 52 | ||
| 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 | } |
| 50 | 56 | ||
| 51 | test "truncate.i0.const" { | 57 | test "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; |
| 53 | 60 | ||
| 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 | } |
| 58 | 65 | ||
| 59 | test "truncate.i0.var" { | 66 | test "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; |
| 61 | 69 | ||
| 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 | } |
| 66 | 74 | ||
| 67 | test "truncate on comptime integer" { | 75 | test "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; |
| 69 | 78 | ||
| 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 | } |
| 26 | 26 | ||
| 27 | test "send void arg to var args" { | 27 | test "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; // TODO | 29 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 29 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 30 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 30 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 31 | 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 | } |
| 85 | 86 | ||
| 86 | test "array of var args functions" { | 87 | test "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; // TODO | 89 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 88 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 90 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 89 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 91 | 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 | } |
| 94 | 96 | ||
| 95 | test "pass zero length array to var args param" { | 97 | test "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; // TODO | 99 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 97 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 100 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 98 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 101 | 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 world | 18 | // 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 | } |
| 106 | 157 | ||
| 107 | // macOS tests | 158 | // macOS tests |