authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-27 20:22:54+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-09-09 19:17:17+02:00
log261fec8036e1e5518951d91c5fc27b53c1a511d8
tree03e2856039842234617a97d32233551c447e9795
parente2b029e2c8ad761c32886d27aa0227655a60eb9e
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: amend implementation of various AIR instructions

- unwrap_errunion_err for registers - unwrap_errunion_payload for registers - ptr_slice_len_ptr for all MCValues - ptr_slice_ptr_ptr for all MCValues

15 files changed, 208 insertions(+), 119 deletions(-)

src/arch/arm/CodeGen.zig+208-89
...@@ -451,9 +451,7 @@ fn gen(self: *Self) !void {...@@ -451,9 +451,7 @@ fn gen(self: *Self) !void {
451 // The address of where to store the return value is in451 // The address of where to store the return value is in
452 // r0. As this register might get overwritten along the452 // r0. As this register might get overwritten along the
453 // way, save the address to the stack.453 // way, save the address to the stack.
454 const stack_offset = mem.alignForwardGeneric(u32, self.next_stack_offset, 4) + 4;454 const stack_offset = try self.allocMem(4, 4, null);
455 self.next_stack_offset = stack_offset;
456 self.max_end_stack = @maximum(self.max_end_stack, self.next_stack_offset);
457455
458 try self.genSetStack(Type.usize, stack_offset, MCValue{ .register = .r0 });456 try self.genSetStack(Type.usize, stack_offset, MCValue{ .register = .r0 });
459 self.ret_mcv = MCValue{ .stack_offset = stack_offset };457 self.ret_mcv = MCValue{ .stack_offset = stack_offset };
...@@ -893,17 +891,30 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {...@@ -893,17 +891,30 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {
893 try table.ensureUnusedCapacity(self.gpa, additional_count);891 try table.ensureUnusedCapacity(self.gpa, additional_count);
894}892}
895893
896fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u32 {894fn allocMem(
895 self: *Self,
896 abi_size: u32,
897 abi_align: u32,
898 maybe_inst: ?Air.Inst.Index,
899) !u32 {
900 assert(abi_size > 0);
901 assert(abi_align > 0);
902
897 if (abi_align > self.stack_align)903 if (abi_align > self.stack_align)
898 self.stack_align = abi_align;904 self.stack_align = abi_align;
905
899 // TODO find a free slot instead of always appending906 // TODO find a free slot instead of always appending
900 const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size;907 const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size;
901 self.next_stack_offset = offset;908 self.next_stack_offset = offset;
902 self.max_end_stack = @maximum(self.max_end_stack, self.next_stack_offset);909 self.max_end_stack = @maximum(self.max_end_stack, self.next_stack_offset);
903 try self.stack.putNoClobber(self.gpa, offset, .{910
904 .inst = inst,911 if (maybe_inst) |inst| {
905 .size = abi_size,912 try self.stack.putNoClobber(self.gpa, offset, .{
906 });913 .inst = inst,
914 .size = abi_size,
915 });
916 }
917
907 return offset;918 return offset;
908}919}
909920
...@@ -925,7 +936,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {...@@ -925,7 +936,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
925 };936 };
926 // TODO swap this for inst.ty.ptrAlign937 // TODO swap this for inst.ty.ptrAlign
927 const abi_align = elem_ty.abiAlignment(self.target.*);938 const abi_align = elem_ty.abiAlignment(self.target.*);
928 return self.allocMem(inst, abi_size, abi_align);939 return self.allocMem(abi_size, abi_align, inst);
929}940}
930941
931fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {942fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
...@@ -948,7 +959,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -948,7 +959,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
948 }959 }
949 }960 }
950 }961 }
951 const stack_offset = try self.allocMem(inst, abi_size, abi_align);962 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
952 return MCValue{ .stack_offset = stack_offset };963 return MCValue{ .stack_offset = stack_offset };
953}964}
954965
...@@ -1182,29 +1193,32 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {...@@ -1182,29 +1193,32 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
1182fn airNot(self: *Self, inst: Air.Inst.Index) !void {1193fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1183 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1194 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1184 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1195 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1185 const operand = try self.resolveInst(ty_op.operand);1196 const operand_bind: ReadArg.Bind = .{ .inst = ty_op.operand };
1186 const operand_ty = self.air.typeOf(ty_op.operand);1197 const operand_ty = self.air.typeOf(ty_op.operand);
1187 switch (operand) {1198 switch (try operand_bind.resolveToMcv(self)) {
1188 .dead => unreachable,1199 .dead => unreachable,
1189 .unreach => unreachable,1200 .unreach => unreachable,
1190 .cpsr_flags => |cond| break :result MCValue{ .cpsr_flags = cond.negate() },1201 .cpsr_flags => |cond| break :result MCValue{ .cpsr_flags = cond.negate() },
1191 else => {1202 else => {
1192 switch (operand_ty.zigTypeTag()) {1203 switch (operand_ty.zigTypeTag()) {
1193 .Bool => {1204 .Bool => {
1194 const op_reg = switch (operand) {1205 var op_reg: Register = undefined;
1195 .register => |r| r,1206 var dest_reg: Register = undefined;
1196 else => try self.copyToTmpRegister(operand_ty, operand),
1197 };
1198 const op_reg_lock = self.register_manager.lockRegAssumeUnused(op_reg);
1199 defer self.register_manager.unlockReg(op_reg_lock);
1200
1201 const dest_reg = blk: {
1202 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1203 break :blk op_reg;
1204 }
12051207
1206 break :blk try self.register_manager.allocReg(null, gp);1208 const read_args = [_]ReadArg{
1209 .{ .ty = operand_ty, .bind = operand_bind, .class = gp, .reg = &op_reg },
1210 };
1211 const write_args = [_]WriteArg{
1212 .{ .ty = operand_ty, .bind = .none, .class = gp, .reg = &dest_reg },
1207 };1213 };
1214 try self.allocRegs(
1215 &read_args,
1216 &write_args,
1217 ReuseMetadata{
1218 .corresponding_inst = inst,
1219 .operand_mapping = &.{0},
1220 },
1221 );
12081222
1209 _ = try self.addInst(.{1223 _ = try self.addInst(.{
1210 .tag = .eor,1224 .tag = .eor,
...@@ -1221,20 +1235,23 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1221,20 +1235,23 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1221 .Int => {1235 .Int => {
1222 const int_info = operand_ty.intInfo(self.target.*);1236 const int_info = operand_ty.intInfo(self.target.*);
1223 if (int_info.bits <= 32) {1237 if (int_info.bits <= 32) {
1224 const op_reg = switch (operand) {1238 var op_reg: Register = undefined;
1225 .register => |r| r,1239 var dest_reg: Register = undefined;
1226 else => try self.copyToTmpRegister(operand_ty, operand),
1227 };
1228 const op_reg_lock = self.register_manager.lockRegAssumeUnused(op_reg);
1229 defer self.register_manager.unlockReg(op_reg_lock);
1230
1231 const dest_reg = blk: {
1232 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1233 break :blk op_reg;
1234 }
12351240
1236 break :blk try self.register_manager.allocReg(null, gp);1241 const read_args = [_]ReadArg{
1242 .{ .ty = operand_ty, .bind = operand_bind, .class = gp, .reg = &op_reg },
1243 };
1244 const write_args = [_]WriteArg{
1245 .{ .ty = operand_ty, .bind = .none, .class = gp, .reg = &dest_reg },
1237 };1246 };
1247 try self.allocRegs(
1248 &read_args,
1249 &write_args,
1250 ReuseMetadata{
1251 .corresponding_inst = inst,
1252 .operand_mapping = &.{0},
1253 },
1254 );
12381255
1239 _ = try self.addInst(.{1256 _ = try self.addInst(.{
1240 .tag = .mvn,1257 .tag = .mvn,
...@@ -1384,7 +1401,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -1384,7 +1401,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
1384 const len = try self.resolveInst(bin_op.rhs);1401 const len = try self.resolveInst(bin_op.rhs);
1385 const len_ty = self.air.typeOf(bin_op.rhs);1402 const len_ty = self.air.typeOf(bin_op.rhs);
13861403
1387 const stack_offset = try self.allocMem(inst, 8, 4);1404 const stack_offset = try self.allocMem(8, 4, inst);
1388 try self.genSetStack(ptr_ty, stack_offset, ptr);1405 try self.genSetStack(ptr_ty, stack_offset, ptr);
1389 try self.genSetStack(len_ty, stack_offset - 4, len);1406 try self.genSetStack(len_ty, stack_offset - 4, len);
1390 break :result MCValue{ .stack_offset = stack_offset };1407 break :result MCValue{ .stack_offset = stack_offset };
...@@ -1496,7 +1513,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1496,7 +1513,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1496 assert(lhs_ty.eql(rhs_ty, mod));1513 assert(lhs_ty.eql(rhs_ty, mod));
1497 const int_info = lhs_ty.intInfo(self.target.*);1514 const int_info = lhs_ty.intInfo(self.target.*);
1498 if (int_info.bits < 32) {1515 if (int_info.bits < 32) {
1499 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1516 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
15001517
1501 try self.spillCompareFlagsIfOccupied();1518 try self.spillCompareFlagsIfOccupied();
15021519
...@@ -1609,7 +1626,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1609,7 +1626,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1609 assert(lhs_ty.eql(rhs_ty, mod));1626 assert(lhs_ty.eql(rhs_ty, mod));
1610 const int_info = lhs_ty.intInfo(self.target.*);1627 const int_info = lhs_ty.intInfo(self.target.*);
1611 if (int_info.bits <= 16) {1628 if (int_info.bits <= 16) {
1612 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1629 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
16131630
1614 try self.spillCompareFlagsIfOccupied();1631 try self.spillCompareFlagsIfOccupied();
16151632
...@@ -1644,7 +1661,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1644,7 +1661,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
16441661
1645 break :result MCValue{ .stack_offset = stack_offset };1662 break :result MCValue{ .stack_offset = stack_offset };
1646 } else if (int_info.bits <= 32) {1663 } else if (int_info.bits <= 32) {
1647 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1664 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
16481665
1649 try self.spillCompareFlagsIfOccupied();1666 try self.spillCompareFlagsIfOccupied();
16501667
...@@ -1769,7 +1786,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1769,7 +1786,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1769 .Int => {1786 .Int => {
1770 const int_info = lhs_ty.intInfo(self.target.*);1787 const int_info = lhs_ty.intInfo(self.target.*);
1771 if (int_info.bits <= 32) {1788 if (int_info.bits <= 32) {
1772 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1789 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
17731790
1774 try self.spillCompareFlagsIfOccupied();1791 try self.spillCompareFlagsIfOccupied();
17751792
...@@ -1926,19 +1943,57 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -1926,19 +1943,57 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
1926}1943}
19271944
1928/// Given an error union, returns the error1945/// Given an error union, returns the error
1929fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {1946fn errUnionErr(
1947 self: *Self,
1948 error_union_bind: ReadArg.Bind,
1949 error_union_ty: Type,
1950 maybe_inst: ?Air.Inst.Index,
1951) !MCValue {
1930 const err_ty = error_union_ty.errorUnionSet();1952 const err_ty = error_union_ty.errorUnionSet();
1931 const payload_ty = error_union_ty.errorUnionPayload();1953 const payload_ty = error_union_ty.errorUnionPayload();
1932 if (err_ty.errorSetIsEmpty()) {1954 if (err_ty.errorSetIsEmpty()) {
1933 return MCValue{ .immediate = 0 };1955 return MCValue{ .immediate = 0 };
1934 }1956 }
1935 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1957 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1936 return error_union_mcv;1958 return try error_union_bind.resolveToMcv(self);
1937 }1959 }
19381960
1939 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, self.target.*));1961 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, self.target.*));
1940 switch (error_union_mcv) {1962 switch (try error_union_bind.resolveToMcv(self)) {
1941 .register => return self.fail("TODO errUnionErr for registers", .{}),1963 .register => {
1964 var operand_reg: Register = undefined;
1965 var dest_reg: Register = undefined;
1966
1967 const read_args = [_]ReadArg{
1968 .{ .ty = error_union_ty, .bind = error_union_bind, .class = gp, .reg = &operand_reg },
1969 };
1970 const write_args = [_]WriteArg{
1971 .{ .ty = err_ty, .bind = .none, .class = gp, .reg = &dest_reg },
1972 };
1973 try self.allocRegs(
1974 &read_args,
1975 &write_args,
1976 if (maybe_inst) |inst| .{
1977 .corresponding_inst = inst,
1978 .operand_mapping = &.{0},
1979 } else null,
1980 );
1981
1982 const err_bit_offset = err_offset * 8;
1983 const err_bit_size = @intCast(u32, err_ty.abiSize(self.target.*)) * 8;
1984
1985 _ = try self.addInst(.{
1986 .tag = .ubfx, // errors are unsigned integers
1987 .data = .{ .rr_lsb_width = .{
1988 .rd = dest_reg,
1989 .rn = operand_reg,
1990 .lsb = @intCast(u5, err_bit_offset),
1991 .width = @intCast(u6, err_bit_size),
1992 } },
1993 });
1994
1995 return MCValue{ .register = dest_reg };
1996 },
1942 .stack_argument_offset => |off| {1997 .stack_argument_offset => |off| {
1943 return MCValue{ .stack_argument_offset = off + err_offset };1998 return MCValue{ .stack_argument_offset = off + err_offset };
1944 },1999 },
...@@ -1955,27 +2010,66 @@ fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCV...@@ -1955,27 +2010,66 @@ fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCV
1955fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {2010fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
1956 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2011 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1957 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2012 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2013 const error_union_bind: ReadArg.Bind = .{ .inst = ty_op.operand };
1958 const error_union_ty = self.air.typeOf(ty_op.operand);2014 const error_union_ty = self.air.typeOf(ty_op.operand);
1959 const mcv = try self.resolveInst(ty_op.operand);2015
1960 break :result try self.errUnionErr(mcv, error_union_ty);2016 break :result try self.errUnionErr(error_union_bind, error_union_ty, inst);
1961 };2017 };
1962 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2018 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1963}2019}
19642020
1965/// Given an error union, returns the payload2021/// Given an error union, returns the payload
1966fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {2022fn errUnionPayload(
2023 self: *Self,
2024 error_union_bind: ReadArg.Bind,
2025 error_union_ty: Type,
2026 maybe_inst: ?Air.Inst.Index,
2027) !MCValue {
1967 const err_ty = error_union_ty.errorUnionSet();2028 const err_ty = error_union_ty.errorUnionSet();
1968 const payload_ty = error_union_ty.errorUnionPayload();2029 const payload_ty = error_union_ty.errorUnionPayload();
1969 if (err_ty.errorSetIsEmpty()) {2030 if (err_ty.errorSetIsEmpty()) {
1970 return error_union_mcv;2031 return try error_union_bind.resolveToMcv(self);
1971 }2032 }
1972 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {2033 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1973 return MCValue.none;2034 return MCValue.none;
1974 }2035 }
19752036
1976 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*));2037 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*));
1977 switch (error_union_mcv) {2038 switch (try error_union_bind.resolveToMcv(self)) {
1978 .register => return self.fail("TODO errUnionPayload for registers", .{}),2039 .register => {
2040 var operand_reg: Register = undefined;
2041 var dest_reg: Register = undefined;
2042
2043 const read_args = [_]ReadArg{
2044 .{ .ty = error_union_ty, .bind = error_union_bind, .class = gp, .reg = &operand_reg },
2045 };
2046 const write_args = [_]WriteArg{
2047 .{ .ty = err_ty, .bind = .none, .class = gp, .reg = &dest_reg },
2048 };
2049 try self.allocRegs(
2050 &read_args,
2051 &write_args,
2052 if (maybe_inst) |inst| .{
2053 .corresponding_inst = inst,
2054 .operand_mapping = &.{0},
2055 } else null,
2056 );
2057
2058 const payload_bit_offset = payload_offset * 8;
2059 const payload_bit_size = @intCast(u32, payload_ty.abiSize(self.target.*)) * 8;
2060
2061 _ = try self.addInst(.{
2062 .tag = if (payload_ty.isSignedInt()) Mir.Inst.Tag.sbfx else .ubfx,
2063 .data = .{ .rr_lsb_width = .{
2064 .rd = dest_reg,
2065 .rn = operand_reg,
2066 .lsb = @intCast(u5, payload_bit_offset),
2067 .width = @intCast(u6, payload_bit_size),
2068 } },
2069 });
2070
2071 return MCValue{ .register = dest_reg };
2072 },
1979 .stack_argument_offset => |off| {2073 .stack_argument_offset => |off| {
1980 return MCValue{ .stack_argument_offset = off + payload_offset };2074 return MCValue{ .stack_argument_offset = off + payload_offset };
1981 },2075 },
...@@ -1992,9 +2086,10 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)...@@ -1992,9 +2086,10 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)
1992fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {2086fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
1993 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2087 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1994 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2088 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2089 const error_union_bind: ReadArg.Bind = .{ .inst = ty_op.operand };
1995 const error_union_ty = self.air.typeOf(ty_op.operand);2090 const error_union_ty = self.air.typeOf(ty_op.operand);
1996 const error_union = try self.resolveInst(ty_op.operand);2091
1997 break :result try self.errUnionPayload(error_union, error_union_ty);2092 break :result try self.errUnionPayload(error_union_bind, error_union_ty, inst);
1998 };2093 };
1999 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2094 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2000}2095}
...@@ -2038,17 +2133,18 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -2038,17 +2133,18 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
2038 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2133 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2039 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2134 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2040 const error_union_ty = self.air.getRefType(ty_op.ty);2135 const error_union_ty = self.air.getRefType(ty_op.ty);
2136 const error_ty = error_union_ty.errorUnionSet();
2041 const payload_ty = error_union_ty.errorUnionPayload();2137 const payload_ty = error_union_ty.errorUnionPayload();
2042 const operand = try self.resolveInst(ty_op.operand);2138 const operand = try self.resolveInst(ty_op.operand);
2043 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand;2139 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand;
20442140
2045 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));2141 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
2046 const abi_align = error_union_ty.abiAlignment(self.target.*);2142 const abi_align = error_union_ty.abiAlignment(self.target.*);
2047 const stack_offset = @intCast(u32, try self.allocMem(inst, abi_size, abi_align));2143 const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst));
2048 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);2144 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);
2049 const err_off = errUnionErrorOffset(payload_ty, self.target.*);2145 const err_off = errUnionErrorOffset(payload_ty, self.target.*);
2050 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand);2146 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand);
2051 try self.genSetStack(Type.anyerror, stack_offset - @intCast(u32, err_off), .{ .immediate = 0 });2147 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), .{ .immediate = 0 });
20522148
2053 break :result MCValue{ .stack_offset = stack_offset };2149 break :result MCValue{ .stack_offset = stack_offset };
2054 };2150 };
...@@ -2060,16 +2156,17 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2060,16 +2156,17 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
2060 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2156 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2061 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2157 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2062 const error_union_ty = self.air.getRefType(ty_op.ty);2158 const error_union_ty = self.air.getRefType(ty_op.ty);
2159 const error_ty = error_union_ty.errorUnionSet();
2063 const payload_ty = error_union_ty.errorUnionPayload();2160 const payload_ty = error_union_ty.errorUnionPayload();
2064 const operand = try self.resolveInst(ty_op.operand);2161 const operand = try self.resolveInst(ty_op.operand);
2065 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand;2162 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand;
20662163
2067 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));2164 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
2068 const abi_align = error_union_ty.abiAlignment(self.target.*);2165 const abi_align = error_union_ty.abiAlignment(self.target.*);
2069 const stack_offset = @intCast(u32, try self.allocMem(inst, abi_size, abi_align));2166 const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst));
2070 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);2167 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);
2071 const err_off = errUnionErrorOffset(payload_ty, self.target.*);2168 const err_off = errUnionErrorOffset(payload_ty, self.target.*);
2072 try self.genSetStack(Type.anyerror, stack_offset - @intCast(u32, err_off), operand);2169 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand);
2073 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef);2170 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef);
20742171
2075 break :result MCValue{ .stack_offset = stack_offset };2172 break :result MCValue{ .stack_offset = stack_offset };
...@@ -2108,7 +2205,6 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -2108,7 +2205,6 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
2108 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2205 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2109 const mcv = try self.resolveInst(ty_op.operand);2206 const mcv = try self.resolveInst(ty_op.operand);
2110 switch (mcv) {2207 switch (mcv) {
2111 .dead, .unreach => unreachable,
2112 .register => unreachable, // a slice doesn't fit in one register2208 .register => unreachable, // a slice doesn't fit in one register
2113 .stack_argument_offset => |off| {2209 .stack_argument_offset => |off| {
2114 break :result MCValue{ .stack_argument_offset = off + 4 };2210 break :result MCValue{ .stack_argument_offset = off + 4 };
...@@ -2119,7 +2215,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -2119,7 +2215,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
2119 .memory => |addr| {2215 .memory => |addr| {
2120 break :result MCValue{ .memory = addr + 4 };2216 break :result MCValue{ .memory = addr + 4 };
2121 },2217 },
2122 else => return self.fail("TODO implement slice_len for {}", .{mcv}),2218 else => unreachable, // invalid MCValue for a slice
2123 }2219 }
2124 };2220 };
2125 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2221 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -2134,7 +2230,12 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2134,7 +2230,12 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
2134 .ptr_stack_offset => |off| {2230 .ptr_stack_offset => |off| {
2135 break :result MCValue{ .ptr_stack_offset = off - 4 };2231 break :result MCValue{ .ptr_stack_offset = off - 4 };
2136 },2232 },
2137 else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}),2233 else => {
2234 const lhs_bind: ReadArg.Bind = .{ .mcv = mcv };
2235 const rhs_bind: ReadArg.Bind = .{ .mcv = .{ .immediate = 4 } };
2236
2237 break :result try self.addSub(.add, lhs_bind, rhs_bind, Type.usize, Type.usize, null);
2238 },
2138 }2239 }
2139 };2240 };
2140 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2241 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -2149,7 +2250,13 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2149,7 +2250,13 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
2149 .ptr_stack_offset => |off| {2250 .ptr_stack_offset => |off| {
2150 break :result MCValue{ .ptr_stack_offset = off };2251 break :result MCValue{ .ptr_stack_offset = off };
2151 },2252 },
2152 else => return self.fail("TODO implement ptr_slice_ptr_ptr for {}", .{mcv}),2253 else => {
2254 if (self.reuseOperand(inst, ty_op.operand, 0, mcv)) {
2255 break :result mcv;
2256 } else {
2257 break :result MCValue{ .register = try self.copyToTmpRegister(Type.usize, mcv) };
2258 }
2259 },
2153 }2260 }
2154 };2261 };
2155 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2262 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -3891,7 +3998,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -3891,7 +3998,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
3891 .register => |reg| blk: {3998 .register => |reg| blk: {
3892 const abi_size = @intCast(u32, ty.abiSize(self.target.*));3999 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
3893 const abi_align = ty.abiAlignment(self.target.*);4000 const abi_align = ty.abiAlignment(self.target.*);
3894 const stack_offset = try self.allocMem(inst, abi_size, abi_align);4001 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
3895 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });4002 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
38964003
3897 break :blk MCValue{ .stack_offset = stack_offset };4004 break :blk MCValue{ .stack_offset = stack_offset };
...@@ -3978,7 +4085,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3978,7 +4085,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3978 const ret_ty = fn_ty.fnReturnType();4085 const ret_ty = fn_ty.fnReturnType();
3979 const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));4086 const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
3980 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));4087 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));
3981 const stack_offset = try self.allocMem(inst, ret_abi_size, ret_abi_align);4088 const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);
39824089
3983 var ptr_ty_payload: Type.Payload.ElemType = .{4090 var ptr_ty_payload: Type.Payload.ElemType = .{
3984 .base = .{ .tag = .single_mut_pointer },4091 .base = .{ .tag = .single_mut_pointer },
...@@ -4166,14 +4273,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -4166,14 +4273,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4166 const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));4273 const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
4167 const abi_align = ret_ty.abiAlignment(self.target.*);4274 const abi_align = ret_ty.abiAlignment(self.target.*);
41684275
4169 // This is essentially allocMem without the4276 const offset = try self.allocMem(abi_size, abi_align, null);
4170 // instruction tracking
4171 if (abi_align > self.stack_align)
4172 self.stack_align = abi_align;
4173 // TODO find a free slot instead of always appending
4174 const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size;
4175 self.next_stack_offset = offset;
4176 self.max_end_stack = @maximum(self.max_end_stack, self.next_stack_offset);
41774277
4178 const tmp_mcv = MCValue{ .stack_offset = offset };4278 const tmp_mcv = MCValue{ .stack_offset = offset };
4179 try self.load(tmp_mcv, ptr, ptr_ty);4279 try self.load(tmp_mcv, ptr, ptr_ty);
...@@ -4545,20 +4645,28 @@ fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -4545,20 +4645,28 @@ fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
4545 return MCValue{ .cpsr_flags = .ne };4645 return MCValue{ .cpsr_flags = .ne };
4546}4646}
45474647
4548fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {4648fn isErr(
4549 const error_type = ty.errorUnionSet();4649 self: *Self,
4650 error_union_bind: ReadArg.Bind,
4651 error_union_ty: Type,
4652) !MCValue {
4653 const error_type = error_union_ty.errorUnionSet();
45504654
4551 if (error_type.errorSetIsEmpty()) {4655 if (error_type.errorSetIsEmpty()) {
4552 return MCValue{ .immediate = 0 }; // always false4656 return MCValue{ .immediate = 0 }; // always false
4553 }4657 }
45544658
4555 const error_mcv = try self.errUnionErr(operand, ty);4659 const error_mcv = try self.errUnionErr(error_union_bind, error_union_ty, null);
4556 _ = try self.cmp(.{ .mcv = error_mcv }, .{ .mcv = .{ .immediate = 0 } }, error_type, .neq);4660 _ = try self.cmp(.{ .mcv = error_mcv }, .{ .mcv = .{ .immediate = 0 } }, error_type, .neq);
4557 return MCValue{ .cpsr_flags = .hi };4661 return MCValue{ .cpsr_flags = .hi };
4558}4662}
45594663
4560fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue {4664fn isNonErr(
4561 const is_err_result = try self.isErr(ty, operand);4665 self: *Self,
4666 error_union_bind: ReadArg.Bind,
4667 error_union_ty: Type,
4668) !MCValue {
4669 const is_err_result = try self.isErr(error_union_bind, error_union_ty);
4562 switch (is_err_result) {4670 switch (is_err_result) {
4563 .cpsr_flags => |cond| {4671 .cpsr_flags => |cond| {
4564 assert(cond == .hi);4672 assert(cond == .hi);
...@@ -4637,9 +4745,10 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4637,9 +4745,10 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
4637fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {4745fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
4638 const un_op = self.air.instructions.items(.data)[inst].un_op;4746 const un_op = self.air.instructions.items(.data)[inst].un_op;
4639 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4747 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4640 const operand = try self.resolveInst(un_op);4748 const error_union_bind: ReadArg.Bind = .{ .inst = un_op };
4641 const ty = self.air.typeOf(un_op);4749 const error_union_ty = self.air.typeOf(un_op);
4642 break :result try self.isErr(ty, operand);4750
4751 break :result try self.isErr(error_union_bind, error_union_ty);
4643 };4752 };
4644 return self.finishAir(inst, result, .{ un_op, .none, .none });4753 return self.finishAir(inst, result, .{ un_op, .none, .none });
4645}4754}
...@@ -4658,7 +4767,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4658,7 +4767,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
4658 }4767 }
4659 };4768 };
4660 try self.load(operand, operand_ptr, ptr_ty);4769 try self.load(operand, operand_ptr, ptr_ty);
4661 break :result try self.isErr(ptr_ty.elemType(), operand);4770 break :result try self.isErr(.{ .mcv = operand }, ptr_ty.elemType());
4662 };4771 };
4663 return self.finishAir(inst, result, .{ un_op, .none, .none });4772 return self.finishAir(inst, result, .{ un_op, .none, .none });
4664}4773}
...@@ -4666,9 +4775,10 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4666,9 +4775,10 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
4666fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {4775fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
4667 const un_op = self.air.instructions.items(.data)[inst].un_op;4776 const un_op = self.air.instructions.items(.data)[inst].un_op;
4668 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4777 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4669 const operand = try self.resolveInst(un_op);4778 const error_union_bind: ReadArg.Bind = .{ .inst = un_op };
4670 const ty = self.air.typeOf(un_op);4779 const error_union_ty = self.air.typeOf(un_op);
4671 break :result try self.isNonErr(ty, operand);4780
4781 break :result try self.isNonErr(error_union_bind, error_union_ty);
4672 };4782 };
4673 return self.finishAir(inst, result, .{ un_op, .none, .none });4783 return self.finishAir(inst, result, .{ un_op, .none, .none });
4674}4784}
...@@ -4687,7 +4797,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4687,7 +4797,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
4687 }4797 }
4688 };4798 };
4689 try self.load(operand, operand_ptr, ptr_ty);4799 try self.load(operand, operand_ptr, ptr_ty);
4690 break :result try self.isNonErr(ptr_ty.elemType(), operand);4800 break :result try self.isNonErr(.{ .mcv = operand }, ptr_ty.elemType());
4691 };4801 };
4692 return self.finishAir(inst, result, .{ un_op, .none, .none });4802 return self.finishAir(inst, result, .{ un_op, .none, .none });
4693}4803}
...@@ -5620,7 +5730,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -5620,7 +5730,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
5620 const array_ty = ptr_ty.childType();5730 const array_ty = ptr_ty.childType();
5621 const array_len = @intCast(u32, array_ty.arrayLen());5731 const array_len = @intCast(u32, array_ty.arrayLen());
56225732
5623 const stack_offset = try self.allocMem(inst, 8, 8);5733 const stack_offset = try self.allocMem(8, 8, inst);
5624 try self.genSetStack(ptr_ty, stack_offset, ptr);5734 try self.genSetStack(ptr_ty, stack_offset, ptr);
5625 try self.genSetStack(Type.initTag(.usize), stack_offset - 4, .{ .immediate = array_len });5735 try self.genSetStack(Type.initTag(.usize), stack_offset - 4, .{ .immediate = array_len });
5626 break :result MCValue{ .stack_offset = stack_offset };5736 break :result MCValue{ .stack_offset = stack_offset };
...@@ -5774,15 +5884,24 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {...@@ -5774,15 +5884,24 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {
5774 const extra = self.air.extraData(Air.Try, pl_op.payload);5884 const extra = self.air.extraData(Air.Try, pl_op.payload);
5775 const body = self.air.extra[extra.end..][0..extra.data.body_len];5885 const body = self.air.extra[extra.end..][0..extra.data.body_len];
5776 const result: MCValue = result: {5886 const result: MCValue = result: {
5887 const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand };
5777 const error_union_ty = self.air.typeOf(pl_op.operand);5888 const error_union_ty = self.air.typeOf(pl_op.operand);
5778 const error_union = try self.resolveInst(pl_op.operand);5889 const error_union_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
5779 const is_err_result = try self.isErr(error_union_ty, error_union);5890 const error_union_align = error_union_ty.abiAlignment(self.target.*);
5891
5892 // The error union will die in the body. However, we need the
5893 // error union after the body in order to extract the payload
5894 // of the error union, so we create a copy of it
5895 const error_union_copy = try self.allocMem(error_union_size, error_union_align, null);
5896 try self.genSetStack(error_union_ty, error_union_copy, try error_union_bind.resolveToMcv(self));
5897
5898 const is_err_result = try self.isErr(error_union_bind, error_union_ty);
5780 const reloc = try self.condBr(is_err_result);5899 const reloc = try self.condBr(is_err_result);
57815900
5782 try self.genBody(body);5901 try self.genBody(body);
5783
5784 try self.performReloc(reloc);5902 try self.performReloc(reloc);
5785 break :result try self.errUnionPayload(error_union, error_union_ty);5903
5904 break :result try self.errUnionPayload(.{ .mcv = .{ .stack_offset = error_union_copy } }, error_union_ty, null);
5786 };5905 };
5787 return self.finishAir(inst, result, .{ pl_op.operand, .none, .none });5906 return self.finishAir(inst, result, .{ pl_op.operand, .none, .none });
5788}5907}
test/behavior/alignof.zig-1
...@@ -13,7 +13,6 @@ const Foo = struct {...@@ -13,7 +13,6 @@ const Foo = struct {
13test "@alignOf(T) before referencing T" {13test "@alignOf(T) before referencing T" {
14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
17 comptime try expect(@alignOf(Foo) != maxInt(usize));16 comptime try expect(@alignOf(Foo) != maxInt(usize));
18 if (native_arch == .x86_64) {17 if (native_arch == .x86_64) {
19 comptime try expect(@alignOf(Foo) == 4);18 comptime try expect(@alignOf(Foo) == 4);
test/behavior/basic.zig-1
...@@ -1060,7 +1060,6 @@ comptime {...@@ -1060,7 +1060,6 @@ comptime {
10601060
1061test "switch inside @as gets correct type" {1061test "switch inside @as gets correct type" {
1062 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1062 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1063 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10641063
1065 var a: u32 = 0;1064 var a: u32 = 0;
1066 var b: [2]u32 = undefined;1065 var b: [2]u32 = undefined;
test/behavior/cast.zig-7
...@@ -523,7 +523,6 @@ fn testCastConstArrayRefToConstSlice() !void {...@@ -523,7 +523,6 @@ fn testCastConstArrayRefToConstSlice() !void {
523523
524test "peer type resolution: error and [N]T" {524test "peer type resolution: error and [N]T" {
525 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;525 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
526 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
527526
528 try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));527 try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
529 comptime try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));528 comptime try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
...@@ -548,7 +547,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {...@@ -548,7 +547,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
548test "single-item pointer of array to slice to unknown length pointer" {547test "single-item pointer of array to slice to unknown length pointer" {
549 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;548 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
550 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO549 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
551 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
552550
553 try testCastPtrOfArrayToSliceAndPtr();551 try testCastPtrOfArrayToSliceAndPtr();
554 comptime try testCastPtrOfArrayToSliceAndPtr();552 comptime try testCastPtrOfArrayToSliceAndPtr();
...@@ -649,7 +647,6 @@ test "@floatCast cast down" {...@@ -649,7 +647,6 @@ test "@floatCast cast down" {
649test "peer type resolution: unreachable, error set, unreachable" {647test "peer type resolution: unreachable, error set, unreachable" {
650 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO648 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
651 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO649 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
652 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
653650
654 const Error = error{651 const Error = error{
655 FileDescriptorAlreadyPresentInSet,652 FileDescriptorAlreadyPresentInSet,
...@@ -964,7 +961,6 @@ test "peer cast [:x]T to [*:x]T" {...@@ -964,7 +961,6 @@ test "peer cast [:x]T to [*:x]T" {
964961
965test "peer type resolution implicit cast to return type" {962test "peer type resolution implicit cast to return type" {
966 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;963 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
967 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
968964
969 const S = struct {965 const S = struct {
970 fn doTheTest() !void {966 fn doTheTest() !void {
...@@ -984,7 +980,6 @@ test "peer type resolution implicit cast to return type" {...@@ -984,7 +980,6 @@ test "peer type resolution implicit cast to return type" {
984980
985test "peer type resolution implicit cast to variable type" {981test "peer type resolution implicit cast to variable type" {
986 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;982 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
987 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
988 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO983 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
989984
990 const S = struct {985 const S = struct {
...@@ -1026,7 +1021,6 @@ test "cast between C pointer with different but compatible types" {...@@ -1026,7 +1021,6 @@ test "cast between C pointer with different but compatible types" {
10261021
1027test "peer type resolve string lit with sentinel-terminated mutable slice" {1022test "peer type resolve string lit with sentinel-terminated mutable slice" {
1028 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1023 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1030 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1024 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10311025
1032 var array: [4:0]u8 = undefined;1026 var array: [4:0]u8 = undefined;
...@@ -1079,7 +1073,6 @@ test "comptime float casts" {...@@ -1079,7 +1073,6 @@ test "comptime float casts" {
1079test "pointer reinterpret const float to int" {1073test "pointer reinterpret const float to int" {
1080 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1074 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1081 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1075 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1082 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10831076
1084 // The hex representation is 0x3fe3333333333303.1077 // The hex representation is 0x3fe3333333333303.
1085 const float: f64 = 5.99999999999994648725e-01;1078 const float: f64 = 5.99999999999994648725e-01;
test/behavior/comptime_memory.zig-2
...@@ -87,7 +87,6 @@ fn bigToNativeEndian(comptime T: type, v: T) T {...@@ -87,7 +87,6 @@ fn bigToNativeEndian(comptime T: type, v: T) T {
87test "type pun endianness" {87test "type pun endianness" {
88 if (builtin.zig_backend == .stage1) return error.SkipZigTest;88 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
89 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO89 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
90 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9190
92 comptime {91 comptime {
93 const StructOfBytes = extern struct { x: [4]u8 };92 const StructOfBytes = extern struct { x: [4]u8 };
...@@ -398,7 +397,6 @@ test "offset field ptr by enclosing array element size" {...@@ -398,7 +397,6 @@ test "offset field ptr by enclosing array element size" {
398test "accessing reinterpreted memory of parent object" {397test "accessing reinterpreted memory of parent object" {
399 if (builtin.zig_backend == .stage1) return error.SkipZigTest;398 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
400 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO399 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
401 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
402 const S = extern struct {400 const S = extern struct {
403 a: f32,401 a: f32,
404 b: [4]u8,402 b: [4]u8,
test/behavior/enum.zig-5
...@@ -606,7 +606,6 @@ fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {...@@ -606,7 +606,6 @@ fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {
606}606}
607607
608test "enum with specified tag values" {608test "enum with specified tag values" {
609 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
610 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;609 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
611610
612 try testEnumWithSpecifiedTagValues(MultipleChoice.C);611 try testEnumWithSpecifiedTagValues(MultipleChoice.C);
...@@ -614,7 +613,6 @@ test "enum with specified tag values" {...@@ -614,7 +613,6 @@ test "enum with specified tag values" {
614}613}
615614
616test "non-exhaustive enum" {615test "non-exhaustive enum" {
617 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
618 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;616 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
619617
620 const S = struct {618 const S = struct {
...@@ -677,7 +675,6 @@ test "empty non-exhaustive enum" {...@@ -677,7 +675,6 @@ test "empty non-exhaustive enum" {
677}675}
678676
679test "single field non-exhaustive enum" {677test "single field non-exhaustive enum" {
680 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
681 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;678 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
682679
683 const S = struct {680 const S = struct {
...@@ -741,7 +738,6 @@ test "cast integer literal to enum" {...@@ -741,7 +738,6 @@ test "cast integer literal to enum" {
741}738}
742739
743test "enum with specified and unspecified tag values" {740test "enum with specified and unspecified tag values" {
744 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
745 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;741 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
746742
747 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);743 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
...@@ -925,7 +921,6 @@ test "enum literal casting to tagged union" {...@@ -925,7 +921,6 @@ test "enum literal casting to tagged union" {
925const Bar = enum { A, B, C, D };921const Bar = enum { A, B, C, D };
926922
927test "enum literal casting to error union with payload enum" {923test "enum literal casting to error union with payload enum" {
928 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
929 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;924 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
930925
931 var bar: error{B}!Bar = undefined;926 var bar: error{B}!Bar = undefined;
test/behavior/error.zig-4
...@@ -222,7 +222,6 @@ fn testErrorSetType() !void {...@@ -222,7 +222,6 @@ fn testErrorSetType() !void {
222222
223test "explicit error set cast" {223test "explicit error set cast" {
224 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO224 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
225 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
226 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO225 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
227226
228 try testExplicitErrorSetCast(Set1.A);227 try testExplicitErrorSetCast(Set1.A);
...@@ -282,7 +281,6 @@ test "inferred empty error set comptime catch" {...@@ -282,7 +281,6 @@ test "inferred empty error set comptime catch" {
282}281}
283282
284test "error union peer type resolution" {283test "error union peer type resolution" {
285 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
286 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO284 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
287285
288 try testErrorUnionPeerTypeResolution(1);286 try testErrorUnionPeerTypeResolution(1);
...@@ -327,7 +325,6 @@ fn foo3(b: usize) Error!usize {...@@ -327,7 +325,6 @@ fn foo3(b: usize) Error!usize {
327325
328test "error: Infer error set from literals" {326test "error: Infer error set from literals" {
329 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;327 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
330 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
331328
332 _ = nullLiteral("n") catch |err| handleErrors(err);329 _ = nullLiteral("n") catch |err| handleErrors(err);
333 _ = floatLiteral("n") catch |err| handleErrors(err);330 _ = floatLiteral("n") catch |err| handleErrors(err);
...@@ -700,7 +697,6 @@ test "ret_ptr doesn't cause own inferred error set to be resolved" {...@@ -700,7 +697,6 @@ test "ret_ptr doesn't cause own inferred error set to be resolved" {
700697
701test "simple else prong allowed even when all errors handled" {698test "simple else prong allowed even when all errors handled" {
702 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO699 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
703 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
704 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO700 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
705701
706 const S = struct {702 const S = struct {
test/behavior/eval.zig-2
...@@ -69,7 +69,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {...@@ -69,7 +69,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
69}69}
7070
71test "constant expressions" {71test "constant expressions" {
72 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
73 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO72 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7473
75 var array: [array_size]u8 = undefined;74 var array: [array_size]u8 = undefined;
...@@ -565,7 +564,6 @@ test "inlined loop has array literal with elided runtime scope on first iteratio...@@ -565,7 +564,6 @@ test "inlined loop has array literal with elided runtime scope on first iteratio
565}564}
566565
567test "ptr to local array argument at comptime" {566test "ptr to local array argument at comptime" {
568 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
569 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO567 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
570568
571 comptime {569 comptime {
test/behavior/merge_error_sets.zig-1
...@@ -12,7 +12,6 @@ fn foo() C!void {...@@ -12,7 +12,6 @@ fn foo() C!void {
12}12}
1313
14test "merge error sets" {14test "merge error sets" {
15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
16 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;16 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
18 if (foo()) {17 if (foo()) {
test/behavior/slice.zig-2
...@@ -28,7 +28,6 @@ comptime {...@@ -28,7 +28,6 @@ comptime {
2828
29test "slicing" {29test "slicing" {
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3231
33 var array: [20]i32 = undefined;32 var array: [20]i32 = undefined;
3433
...@@ -283,7 +282,6 @@ test "slice type with custom alignment" {...@@ -283,7 +282,6 @@ test "slice type with custom alignment" {
283282
284test "obtaining a null terminated slice" {283test "obtaining a null terminated slice" {
285 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;284 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
286 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
287285
288 // here we have a normal array286 // here we have a normal array
289 var buf: [50]u8 = undefined;287 var buf: [50]u8 = undefined;
test/behavior/struct.zig-1
...@@ -104,7 +104,6 @@ fn testMutation(foo: *StructFoo) void {...@@ -104,7 +104,6 @@ fn testMutation(foo: *StructFoo) void {
104104
105test "struct byval assign" {105test "struct byval assign" {
106 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;106 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
108107
109 var foo1: StructFoo = undefined;108 var foo1: StructFoo = undefined;
110 var foo2: StructFoo = undefined;109 var foo2: StructFoo = undefined;
test/behavior/switch.zig-1
...@@ -490,7 +490,6 @@ test "switch prongs with error set cases make a new error set type for capture v...@@ -490,7 +490,6 @@ test "switch prongs with error set cases make a new error set type for capture v
490}490}
491491
492test "return result loc and then switch with range implicit casted to error union" {492test "return result loc and then switch with range implicit casted to error union" {
493 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
494 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO493 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
495494
496 const S = struct {495 const S = struct {
test/behavior/this.zig-1
...@@ -25,7 +25,6 @@ test "this refer to module call private fn" {...@@ -25,7 +25,6 @@ test "this refer to module call private fn" {
25}25}
2626
27test "this refer to container" {27test "this refer to container" {
28 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
3029
31 var pt: Point(i32) = undefined;30 var pt: Point(i32) = undefined;
test/behavior/try.zig-1
...@@ -3,7 +3,6 @@ const builtin = @import("builtin");...@@ -3,7 +3,6 @@ const builtin = @import("builtin");
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5test "try on error union" {5test "try on error union" {
6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
87
9 try tryOnErrorUnionImpl();8 try tryOnErrorUnionImpl();
test/behavior/while.zig-1
...@@ -175,7 +175,6 @@ test "while with optional as condition with else" {...@@ -175,7 +175,6 @@ test "while with optional as condition with else" {
175175
176test "while with error union condition" {176test "while with error union condition" {
177 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;177 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
178 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;178 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
180179
181 numbers_left = 10;180 numbers_left = 10;