authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-09-14 20:00:38-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-09-14 20:00:38-04:00
log78cd7b57ef7a3c8c645aab5c30b3fbf3834e6970
tree7523ab6cb09ccc1d171c5014eeb324809261bde2
parent17596c79a9239edec533a041f9a4da3a7af0d980
parent86dc982e74dd17633d2bdc0f5ba8e36c55f78053
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12206 from koachan/sparc64-codegen

stage2: sparc64: Another batch of Air lowerings, bugfixes, etc.

7 files changed, 515 insertions(+), 153 deletions(-)

src/arch/sparc64/CodeGen.zig+452-140
...@@ -499,20 +499,29 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -499,20 +499,29 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
499 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),499 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),
500500
501 .add => try self.airBinOp(inst, .add),501 .add => try self.airBinOp(inst, .add),
502 .addwrap => @panic("TODO try self.airAddWrap(inst)"),502 .addwrap => try self.airBinOp(inst, .addwrap),
503 .add_sat => @panic("TODO try self.airAddSat(inst)"),503 .sub => try self.airBinOp(inst, .sub),
504 .sub => @panic("TODO try self.airBinOp(inst)"),504 .subwrap => try self.airBinOp(inst, .subwrap),
505 .subwrap => @panic("TODO try self.airSubWrap(inst)"),505 .mul => try self.airBinOp(inst, .mul),
506 .sub_sat => @panic("TODO try self.airSubSat(inst)"),506 .mulwrap => try self.airBinOp(inst, .mulwrap),
507 .mul => @panic("TODO try self.airMul(inst)"),507 .shl => try self.airBinOp(inst, .shl),
508 .mulwrap => @panic("TODO try self.airMulWrap(inst)"),508 .shl_exact => try self.airBinOp(inst, .shl_exact),
509 .mul_sat => @panic("TODO try self.airMulSat(inst)"),509 .shr => try self.airBinOp(inst, .shr),
510 .rem => try self.airRem(inst),510 .shr_exact => try self.airBinOp(inst, .shr_exact),
511 .mod => try self.airMod(inst),511 .bool_and => try self.airBinOp(inst, .bool_and),
512 .shl, .shl_exact => @panic("TODO try self.airShl(inst)"),512 .bool_or => try self.airBinOp(inst, .bool_or),
513 .shl_sat => @panic("TODO try self.airShlSat(inst)"),513 .bit_and => try self.airBinOp(inst, .bit_and),
514 .bit_or => try self.airBinOp(inst, .bit_or),
515 .xor => try self.airBinOp(inst, .xor),
516
517 .add_sat => try self.airAddSat(inst),
518 .sub_sat => try self.airSubSat(inst),
519 .mul_sat => try self.airMulSat(inst),
520 .shl_sat => try self.airShlSat(inst),
514 .min => @panic("TODO try self.airMin(inst)"),521 .min => @panic("TODO try self.airMin(inst)"),
515 .max => @panic("TODO try self.airMax(inst)"),522 .max => @panic("TODO try self.airMax(inst)"),
523 .rem => try self.airRem(inst),
524 .mod => try self.airMod(inst),
516 .slice => try self.airSlice(inst),525 .slice => try self.airSlice(inst),
517526
518 .sqrt,527 .sqrt,
...@@ -530,12 +539,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -530,12 +539,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
530 .round,539 .round,
531 .trunc_float,540 .trunc_float,
532 .neg,541 .neg,
533 => @panic("TODO try self.airUnaryMath(inst)"),542 => try self.airUnaryMath(inst),
534543
535 .add_with_overflow => try self.airAddSubWithOverflow(inst),544 .add_with_overflow => try self.airAddSubWithOverflow(inst),
536 .sub_with_overflow => try self.airAddSubWithOverflow(inst),545 .sub_with_overflow => try self.airAddSubWithOverflow(inst),
537 .mul_with_overflow => @panic("TODO try self.airMulWithOverflow(inst)"),546 .mul_with_overflow => try self.airMulWithOverflow(inst),
538 .shl_with_overflow => @panic("TODO try self.airShlWithOverflow(inst)"),547 .shl_with_overflow => try self.airShlWithOverflow(inst),
539548
540 .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst),549 .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst),
541550
...@@ -546,14 +555,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -546,14 +555,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
546 .cmp_gt => try self.airCmp(inst, .gt),555 .cmp_gt => try self.airCmp(inst, .gt),
547 .cmp_neq => try self.airCmp(inst, .neq),556 .cmp_neq => try self.airCmp(inst, .neq),
548 .cmp_vector => @panic("TODO try self.airCmpVector(inst)"),557 .cmp_vector => @panic("TODO try self.airCmpVector(inst)"),
549 .cmp_lt_errors_len => @panic("TODO try self.airCmpLtErrorsLen(inst)"),558 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
550
551 .bool_and => @panic("TODO try self.airBoolOp(inst)"),
552 .bool_or => @panic("TODO try self.airBoolOp(inst)"),
553 .bit_and => try self.airBinOp(inst, .bit_and),
554 .bit_or => try self.airBinOp(inst, .bit_or),
555 .xor => try self.airBinOp(inst, .xor),
556 .shr, .shr_exact => @panic("TODO try self.airShr(inst)"),
557559
558 .alloc => try self.airAlloc(inst),560 .alloc => try self.airAlloc(inst),
559 .ret_ptr => try self.airRetPtr(inst),561 .ret_ptr => try self.airRetPtr(inst),
...@@ -584,15 +586,15 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -584,15 +586,15 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
584 .load => try self.airLoad(inst),586 .load => try self.airLoad(inst),
585 .loop => try self.airLoop(inst),587 .loop => try self.airLoop(inst),
586 .not => try self.airNot(inst),588 .not => try self.airNot(inst),
587 .ptrtoint => @panic("TODO try self.airPtrToInt(inst)"),589 .ptrtoint => try self.airPtrToInt(inst),
588 .ret => try self.airRet(inst),590 .ret => try self.airRet(inst),
589 .ret_load => try self.airRetLoad(inst),591 .ret_load => try self.airRetLoad(inst),
590 .store => try self.airStore(inst),592 .store => try self.airStore(inst),
591 .struct_field_ptr=> @panic("TODO try self.airStructFieldPtr(inst)"),593 .struct_field_ptr=> @panic("TODO try self.airStructFieldPtr(inst)"),
592 .struct_field_val=> try self.airStructFieldVal(inst),594 .struct_field_val=> try self.airStructFieldVal(inst),
593 .array_to_slice => try self.airArrayToSlice(inst),595 .array_to_slice => try self.airArrayToSlice(inst),
594 .int_to_float => @panic("TODO try self.airIntToFloat(inst)"),596 .int_to_float => try self.airIntToFloat(inst),
595 .float_to_int => @panic("TODO try self.airFloatToInt(inst)"),597 .float_to_int => try self.airFloatToInt(inst),
596 .cmpxchg_strong => @panic("TODO try self.airCmpxchg(inst)"),598 .cmpxchg_strong => @panic("TODO try self.airCmpxchg(inst)"),
597 .cmpxchg_weak => @panic("TODO try self.airCmpxchg(inst)"),599 .cmpxchg_weak => @panic("TODO try self.airCmpxchg(inst)"),
598 .atomic_rmw => @panic("TODO try self.airAtomicRmw(inst)"),600 .atomic_rmw => @panic("TODO try self.airAtomicRmw(inst)"),
...@@ -601,12 +603,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -601,12 +603,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
601 .memset => try self.airMemset(inst),603 .memset => try self.airMemset(inst),
602 .set_union_tag => @panic("TODO try self.airSetUnionTag(inst)"),604 .set_union_tag => @panic("TODO try self.airSetUnionTag(inst)"),
603 .get_union_tag => @panic("TODO try self.airGetUnionTag(inst)"),605 .get_union_tag => @panic("TODO try self.airGetUnionTag(inst)"),
604 .clz => @panic("TODO try self.airClz(inst)"),606 .clz => try self.airClz(inst),
605 .ctz => @panic("TODO try self.airCtz(inst)"),607 .ctz => try self.airCtz(inst),
606 .popcount => @panic("TODO try self.airPopcount(inst)"),608 .popcount => try self.airPopcount(inst),
607 .byte_swap => @panic("TODO try self.airByteSwap(inst)"),609 .byte_swap => @panic("TODO try self.airByteSwap(inst)"),
608 .bit_reverse => @panic("TODO try self.airBitReverse(inst)"),610 .bit_reverse => @panic("TODO try self.airBitReverse(inst)"),
609 .tag_name => @panic("TODO try self.airTagName(inst)"),611 .tag_name => try self.airTagName(inst),
610 .error_name => @panic("TODO try self.airErrorName(inst)"),612 .error_name => @panic("TODO try self.airErrorName(inst)"),
611 .splat => @panic("TODO try self.airSplat(inst)"),613 .splat => @panic("TODO try self.airSplat(inst)"),
612 .select => @panic("TODO try self.airSelect(inst)"),614 .select => @panic("TODO try self.airSelect(inst)"),
...@@ -614,7 +616,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -614,7 +616,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
614 .reduce => @panic("TODO try self.airReduce(inst)"),616 .reduce => @panic("TODO try self.airReduce(inst)"),
615 .aggregate_init => try self.airAggregateInit(inst),617 .aggregate_init => try self.airAggregateInit(inst),
616 .union_init => @panic("TODO try self.airUnionInit(inst)"),618 .union_init => @panic("TODO try self.airUnionInit(inst)"),
617 .prefetch => @panic("TODO try self.airPrefetch(inst)"),619 .prefetch => try self.airPrefetch(inst),
618 .mul_add => @panic("TODO try self.airMulAdd(inst)"),620 .mul_add => @panic("TODO try self.airMulAdd(inst)"),
619621
620 .@"try" => try self.airTry(inst),622 .@"try" => try self.airTry(inst),
...@@ -650,7 +652,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -650,7 +652,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
650 .field_parent_ptr => @panic("TODO try self.airFieldParentPtr(inst)"),652 .field_parent_ptr => @panic("TODO try self.airFieldParentPtr(inst)"),
651653
652 .switch_br => try self.airSwitch(inst),654 .switch_br => try self.airSwitch(inst),
653 .slice_ptr => @panic("TODO try self.airSlicePtr(inst)"),655 .slice_ptr => try self.airSlicePtr(inst),
654 .slice_len => try self.airSliceLen(inst),656 .slice_len => try self.airSliceLen(inst),
655657
656 .ptr_slice_len_ptr => @panic("TODO try self.airPtrSliceLenPtr(inst)"),658 .ptr_slice_len_ptr => @panic("TODO try self.airPtrSliceLenPtr(inst)"),
...@@ -659,16 +661,16 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -659,16 +661,16 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
659 .array_elem_val => try self.airArrayElemVal(inst),661 .array_elem_val => try self.airArrayElemVal(inst),
660 .slice_elem_val => try self.airSliceElemVal(inst),662 .slice_elem_val => try self.airSliceElemVal(inst),
661 .slice_elem_ptr => @panic("TODO try self.airSliceElemPtr(inst)"),663 .slice_elem_ptr => @panic("TODO try self.airSliceElemPtr(inst)"),
662 .ptr_elem_val => @panic("TODO try self.airPtrElemVal(inst)"),664 .ptr_elem_val => try self.airPtrElemVal(inst),
663 .ptr_elem_ptr => try self.airPtrElemPtr(inst),665 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
664666
665 .constant => unreachable, // excluded from function bodies667 .constant => unreachable, // excluded from function bodies
666 .const_ty => unreachable, // excluded from function bodies668 .const_ty => unreachable, // excluded from function bodies
667 .unreach => self.finishAirBookkeeping(),669 .unreach => self.finishAirBookkeeping(),
668670
669 .optional_payload => @panic("TODO try self.airOptionalPayload(inst)"),671 .optional_payload => try self.airOptionalPayload(inst),
670 .optional_payload_ptr => @panic("TODO try self.airOptionalPayloadPtr(inst)"),672 .optional_payload_ptr => try self.airOptionalPayloadPtr(inst),
671 .optional_payload_ptr_set => @panic("TODO try self.airOptionalPayloadPtrSet(inst)"),673 .optional_payload_ptr_set => try self.airOptionalPayloadPtrSet(inst),
672 .unwrap_errunion_err => try self.airUnwrapErrErr(inst),674 .unwrap_errunion_err => try self.airUnwrapErrErr(inst),
673 .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst),675 .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst),
674 .unwrap_errunion_err_ptr => @panic("TODO try self.airUnwrapErrErrPtr(inst)"),676 .unwrap_errunion_err_ptr => @panic("TODO try self.airUnwrapErrErrPtr(inst)"),
...@@ -677,7 +679,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -677,7 +679,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
677 .err_return_trace => @panic("TODO try self.airErrReturnTrace(inst)"),679 .err_return_trace => @panic("TODO try self.airErrReturnTrace(inst)"),
678 .set_err_return_trace => @panic("TODO try self.airSetErrReturnTrace(inst)"),680 .set_err_return_trace => @panic("TODO try self.airSetErrReturnTrace(inst)"),
679681
680 .wrap_optional => @panic("TODO try self.airWrapOptional(inst)"),682 .wrap_optional => try self.airWrapOptional(inst),
681 .wrap_errunion_payload => @panic("TODO try self.airWrapErrUnionPayload(inst)"),683 .wrap_errunion_payload => @panic("TODO try self.airWrapErrUnionPayload(inst)"),
682 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),684 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
683685
...@@ -723,6 +725,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -723,6 +725,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
723 }725 }
724}726}
725727
728fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
729 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
730 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement add_sat for {}", .{self.target.cpu.arch});
731 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
732}
733
726fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {734fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
727 const tag = self.air.instructions.items(.tag)[inst];735 const tag = self.air.instructions.items(.tag)[inst];
728 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;736 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
...@@ -763,7 +771,6 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -763,7 +771,6 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
763 };771 };
764772
765 try self.spillConditionFlagsIfOccupied();773 try self.spillConditionFlagsIfOccupied();
766 self.condition_flags_inst = inst;
767774
768 const dest = blk: {775 const dest = blk: {
769 if (rhs_immediate_ok) {776 if (rhs_immediate_ok) {
...@@ -1241,6 +1248,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -1241,6 +1248,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
1241 return bt.finishAir(result);1248 return bt.finishAir(result);
1242}1249}
12431250
1251fn airClz(self: *Self, inst: Air.Inst.Index) !void {
1252 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1253 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airClz for {}", .{self.target.cpu.arch});
1254 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1255}
1256
1244fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {1257fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1245 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1258 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1246 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1259 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
...@@ -1299,6 +1312,14 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -1299,6 +1312,14 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1299 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1312 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1300}1313}
13011314
1315fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
1316 const un_op = self.air.instructions.items(.data)[inst].un_op;
1317 const operand = try self.resolveInst(un_op);
1318 _ = operand;
1319 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airCmpLtErrorsLen for {}", .{self.target.cpu.arch});
1320 return self.finishAir(inst, result, .{ un_op, .none, .none });
1321}
1322
1302fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {1323fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1303 const pl_op = self.air.instructions.items(.data)[inst].pl_op;1324 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
1304 const condition = try self.resolveInst(pl_op.operand);1325 const condition = try self.resolveInst(pl_op.operand);
...@@ -1446,6 +1467,12 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1446,6 +1467,12 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1446 return self.finishAir(inst, .unreach, .{ .none, .none, .none });1467 return self.finishAir(inst, .unreach, .{ .none, .none, .none });
1447}1468}
14481469
1470fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
1471 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1472 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airCtz for {}", .{self.target.cpu.arch});
1473 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1474}
1475
1449fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {1476fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
1450 // TODO emit debug info lexical block1477 // TODO emit debug info lexical block
1451 return self.finishAir(inst, .dead, .{ .none, .none, .none });1478 return self.finishAir(inst, .dead, .{ .none, .none, .none });
...@@ -1519,6 +1546,14 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void {...@@ -1519,6 +1546,14 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void {
1519 return self.finishAir(inst, .dead, .{ .none, .none, .none });1546 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1520}1547}
15211548
1549fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
1550 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1551 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airFloatToInt for {}", .{
1552 self.target.cpu.arch,
1553 });
1554 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1555}
1556
1522fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {1557fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
1523 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1558 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1524 if (self.liveness.isUnused(inst))1559 if (self.liveness.isUnused(inst))
...@@ -1537,6 +1572,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -1537,6 +1572,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
1537 return self.fail("TODO implement intCast for {}", .{self.target.cpu.arch});1572 return self.fail("TODO implement intCast for {}", .{self.target.cpu.arch});
1538}1573}
15391574
1575fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
1576 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1577 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airIntToFloat for {}", .{
1578 self.target.cpu.arch,
1579 });
1580 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1581}
1582
1540fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {1583fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
1541 const un_op = self.air.instructions.items(.data)[inst].un_op;1584 const un_op = self.air.instructions.items(.data)[inst].un_op;
1542 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1585 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
...@@ -1768,6 +1811,78 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {...@@ -1768,6 +1811,78 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
1768 return self.finishAir(inst, .{ .register = mod_reg }, .{ bin_op.lhs, bin_op.rhs, .none });1811 return self.finishAir(inst, .{ .register = mod_reg }, .{ bin_op.lhs, bin_op.rhs, .none });
1769}1812}
17701813
1814fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
1815 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1816 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement mul_sat for {}", .{self.target.cpu.arch});
1817 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1818}
1819
1820fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1821 //const tag = self.air.instructions.items(.tag)[inst];
1822 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1823 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
1824 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1825 const lhs = try self.resolveInst(extra.lhs);
1826 const rhs = try self.resolveInst(extra.rhs);
1827 const lhs_ty = self.air.typeOf(extra.lhs);
1828 const rhs_ty = self.air.typeOf(extra.rhs);
1829
1830 switch (lhs_ty.zigTypeTag()) {
1831 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
1832 .Int => {
1833 const mod = self.bin_file.options.module.?;
1834 assert(lhs_ty.eql(rhs_ty, mod));
1835 const int_info = lhs_ty.intInfo(self.target.*);
1836 switch (int_info.bits) {
1837 1...32 => {
1838 try self.spillConditionFlagsIfOccupied();
1839
1840 const dest = try self.binOp(.mul, lhs, rhs, lhs_ty, rhs_ty, null);
1841
1842 const dest_reg = dest.register;
1843 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
1844 defer self.register_manager.unlockReg(dest_reg_lock);
1845
1846 const truncated_reg = try self.register_manager.allocReg(null, gp);
1847 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
1848 defer self.register_manager.unlockReg(truncated_reg_lock);
1849
1850 try self.truncRegister(
1851 dest_reg,
1852 truncated_reg,
1853 int_info.signedness,
1854 int_info.bits,
1855 );
1856
1857 _ = try self.addInst(.{
1858 .tag = .cmp,
1859 .data = .{ .arithmetic_2op = .{
1860 .is_imm = false,
1861 .rs1 = dest_reg,
1862 .rs2_or_imm = .{ .rs2 = truncated_reg },
1863 } },
1864 });
1865
1866 const cond = Instruction.ICondition.ne;
1867 const ccr = Instruction.CCR.xcc;
1868
1869 break :result MCValue{ .register_with_overflow = .{
1870 .reg = truncated_reg,
1871 .flag = .{ .cond = cond, .ccr = ccr },
1872 } };
1873 },
1874 // XXX DO NOT call __multi3 directly as it'll result in us doing six multiplications,
1875 // which is far more than strictly necessary
1876 33...64 => return self.fail("TODO copy compiler-rt's mulddi3 for a 64x64->128 multiply", .{}),
1877 else => return self.fail("TODO overflow operations on other integer sizes", .{}),
1878 }
1879 },
1880 else => unreachable,
1881 }
1882 };
1883 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
1884}
1885
1771fn airNot(self: *Self, inst: Air.Inst.Index) !void {1886fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1772 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1887 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1773 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1888 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
...@@ -1863,6 +1978,43 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1863,6 +1978,43 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1863 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1978 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1864}1979}
18651980
1981fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
1982 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1983 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .optional_payload for {}", .{self.target.cpu.arch});
1984 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1985}
1986
1987fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
1988 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1989 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .optional_payload_ptr for {}", .{self.target.cpu.arch});
1990 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1991}
1992
1993fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
1994 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1995 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .optional_payload_ptr_set for {}", .{self.target.cpu.arch});
1996 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1997}
1998
1999fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
2000 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2001 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airPopcount for {}", .{self.target.cpu.arch});
2002 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2003}
2004
2005fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
2006 const prefetch = self.air.instructions.items(.data)[inst].prefetch;
2007 // TODO Emit a PREFETCH/IPREFETCH as necessary, see A.7 and A.42
2008 return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none });
2009}
2010
2011fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
2012 const is_volatile = false; // TODO
2013 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2014 const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_elem_val for {}", .{self.target.cpu.arch});
2015 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2016}
2017
1866fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {2018fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
1867 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2019 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1868 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2020 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
...@@ -1870,6 +2022,12 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1870,6 +2022,12 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
1870 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });2022 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
1871}2023}
18722024
2025fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {
2026 const un_op = self.air.instructions.items(.data)[inst].un_op;
2027 const result = try self.resolveInst(un_op);
2028 return self.finishAir(inst, result, .{ un_op, .none, .none });
2029}
2030
1873fn airRem(self: *Self, inst: Air.Inst.Index) !void {2031fn airRem(self: *Self, inst: Air.Inst.Index) !void {
1874 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2032 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1875 const lhs = try self.resolveInst(bin_op.lhs);2033 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -1911,6 +2069,101 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1911,6 +2069,101 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
1911 return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none });2069 return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none });
1912}2070}
19132071
2072fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
2073 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2074 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
2075 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2076}
2077
2078fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2079 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2080 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2081 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2082 const lhs = try self.resolveInst(extra.lhs);
2083 const rhs = try self.resolveInst(extra.rhs);
2084 const lhs_ty = self.air.typeOf(extra.lhs);
2085 const rhs_ty = self.air.typeOf(extra.rhs);
2086
2087 switch (lhs_ty.zigTypeTag()) {
2088 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
2089 .Int => {
2090 const int_info = lhs_ty.intInfo(self.target.*);
2091 if (int_info.bits <= 64) {
2092 try self.spillConditionFlagsIfOccupied();
2093
2094 const lhs_lock: ?RegisterLock = if (lhs == .register)
2095 self.register_manager.lockRegAssumeUnused(lhs.register)
2096 else
2097 null;
2098 // TODO this currently crashes stage1
2099 // defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
2100
2101 // Increase shift amount (i.e, rhs) by shamt_bits - int_info.bits
2102 // e.g if shifting a i48 then use sr*x (shamt_bits == 64) but increase rhs by 16
2103 // and if shifting a i24 then use sr* (shamt_bits == 32) but increase rhs by 8
2104 const new_rhs = switch (int_info.bits) {
2105 1...31 => if (rhs == .immediate) MCValue{
2106 .immediate = rhs.immediate + 32 - int_info.bits,
2107 } else try self.binOp(.add, rhs, .{ .immediate = 32 - int_info.bits }, rhs_ty, rhs_ty, null),
2108 33...63 => if (rhs == .immediate) MCValue{
2109 .immediate = rhs.immediate + 64 - int_info.bits,
2110 } else try self.binOp(.add, rhs, .{ .immediate = 64 - int_info.bits }, rhs_ty, rhs_ty, null),
2111 32, 64 => rhs,
2112 else => unreachable,
2113 };
2114
2115 const new_rhs_lock: ?RegisterLock = if (new_rhs == .register)
2116 self.register_manager.lockRegAssumeUnused(new_rhs.register)
2117 else
2118 null;
2119 // TODO this currently crashes stage1
2120 // defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
2121
2122 const dest = try self.binOp(.shl, lhs, new_rhs, lhs_ty, rhs_ty, null);
2123 const dest_reg = dest.register;
2124 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
2125 defer self.register_manager.unlockReg(dest_reg_lock);
2126
2127 const shr = try self.binOp(.shr, dest, new_rhs, lhs_ty, rhs_ty, null);
2128
2129 _ = try self.addInst(.{
2130 .tag = .cmp,
2131 .data = .{ .arithmetic_2op = .{
2132 .is_imm = false,
2133 .rs1 = dest_reg,
2134 .rs2_or_imm = .{ .rs2 = shr.register },
2135 } },
2136 });
2137
2138 const cond = Instruction.ICondition.ne;
2139 const ccr = switch (int_info.bits) {
2140 1...32 => Instruction.CCR.icc,
2141 33...64 => Instruction.CCR.xcc,
2142 else => unreachable,
2143 };
2144
2145 // TODO Those should really be written as defers, however stage1 currently
2146 // panics when those are turned into defer statements so those are
2147 // written here at the end as ordinary statements.
2148 // Because of that, on failure, the lock on those registers wouldn't be
2149 // released.
2150 if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
2151 if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
2152
2153 break :result MCValue{ .register_with_overflow = .{
2154 .reg = dest_reg,
2155 .flag = .{ .cond = cond, .ccr = ccr },
2156 } };
2157 } else {
2158 return self.fail("TODO overflow operations on other integer sizes", .{});
2159 }
2160 },
2161 else => unreachable,
2162 }
2163 };
2164 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2165}
2166
1914fn airSlice(self: *Self, inst: Air.Inst.Index) !void {2167fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
1915 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2168 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1916 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2169 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
...@@ -1996,6 +2249,25 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -1996,6 +2249,25 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
1996 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2249 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1997}2250}
19982251
2252fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
2253 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2254 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2255 const mcv = try self.resolveInst(ty_op.operand);
2256 switch (mcv) {
2257 .dead, .unreach, .none => unreachable,
2258 .register => unreachable, // a slice doesn't fit in one register
2259 .stack_offset => |off| {
2260 break :result MCValue{ .stack_offset = off };
2261 },
2262 .memory => |addr| {
2263 break :result MCValue{ .memory = addr };
2264 },
2265 else => return self.fail("TODO implement slice_len for {}", .{mcv}),
2266 }
2267 };
2268 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2269}
2270
1999fn airStore(self: *Self, inst: Air.Inst.Index) !void {2271fn airStore(self: *Self, inst: Air.Inst.Index) !void {
2000 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2272 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2001 const ptr = try self.resolveInst(bin_op.lhs);2273 const ptr = try self.resolveInst(bin_op.lhs);
...@@ -2083,11 +2355,27 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2083,11 +2355,27 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2083 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });2355 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
2084}2356}
20852357
2358fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
2359 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2360 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement sub_sat for {}", .{self.target.cpu.arch});
2361 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2362}
2363
2086fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {2364fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
2087 _ = inst;2365 _ = inst;
2088 return self.fail("TODO implement switch for {}", .{self.target.cpu.arch});2366 return self.fail("TODO implement switch for {}", .{self.target.cpu.arch});
2089}2367}
20902368
2369fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
2370 const un_op = self.air.instructions.items(.data)[inst].un_op;
2371 const operand = try self.resolveInst(un_op);
2372 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else {
2373 _ = operand;
2374 return self.fail("TODO implement airTagName for {}", .{self.target.cpu.arch});
2375 };
2376 return self.finishAir(inst, result, .{ un_op, .none, .none });
2377}
2378
2091fn airTry(self: *Self, inst: Air.Inst.Index) !void {2379fn airTry(self: *Self, inst: Air.Inst.Index) !void {
2092 const pl_op = self.air.instructions.items(.data)[inst].pl_op;2380 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
2093 const extra = self.air.extraData(Air.Try, pl_op.payload);2381 const extra = self.air.extraData(Air.Try, pl_op.payload);
...@@ -2106,6 +2394,15 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {...@@ -2106,6 +2394,15 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {
2106 return self.finishAir(inst, result, .{ pl_op.operand, .none, .none });2394 return self.finishAir(inst, result, .{ pl_op.operand, .none, .none });
2107}2395}
21082396
2397fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
2398 const un_op = self.air.instructions.items(.data)[inst].un_op;
2399 const result: MCValue = if (self.liveness.isUnused(inst))
2400 .dead
2401 else
2402 return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});
2403 return self.finishAir(inst, result, .{ un_op, .none, .none });
2404}
2405
2109fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {2406fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
2110 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2407 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2111 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2408 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
...@@ -2145,6 +2442,20 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2145,6 +2442,20 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
2145 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2442 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2146}2443}
21472444
2445fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
2446 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2447 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2448 const optional_ty = self.air.typeOfIndex(inst);
2449
2450 // Optional with a zero-bit payload type is just a boolean true
2451 if (optional_ty.abiSize(self.target.*) == 1)
2452 break :result MCValue{ .immediate = 1 };
2453
2454 return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch});
2455 };
2456 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2457}
2458
2148// Common helper functions2459// Common helper functions
21492460
2150/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,2461/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
...@@ -2264,6 +2575,10 @@ fn binOp(...@@ -2264,6 +2575,10 @@ fn binOp(
2264 switch (tag) {2575 switch (tag) {
2265 .add,2576 .add,
2266 .sub,2577 .sub,
2578 .mul,
2579 .bit_and,
2580 .bit_or,
2581 .xor,
2267 .cmp_eq,2582 .cmp_eq,
2268 => {2583 => {
2269 switch (lhs_ty.zigTypeTag()) {2584 switch (lhs_ty.zigTypeTag()) {
...@@ -2278,12 +2593,20 @@ fn binOp(...@@ -2278,12 +2593,20 @@ fn binOp(
2278 // operands2593 // operands
2279 const lhs_immediate_ok = switch (tag) {2594 const lhs_immediate_ok = switch (tag) {
2280 .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),2595 .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2596 .mul => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2597 .bit_and => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2598 .bit_or => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2599 .xor => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2281 .sub, .cmp_eq => false,2600 .sub, .cmp_eq => false,
2282 else => unreachable,2601 else => unreachable,
2283 };2602 };
2284 const rhs_immediate_ok = switch (tag) {2603 const rhs_immediate_ok = switch (tag) {
2285 .add,2604 .add,
2286 .sub,2605 .sub,
2606 .mul,
2607 .bit_and,
2608 .bit_or,
2609 .xor,
2287 .cmp_eq,2610 .cmp_eq,
2288 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),2611 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
2289 else => unreachable,2612 else => unreachable,
...@@ -2292,6 +2615,10 @@ fn binOp(...@@ -2292,6 +2615,10 @@ fn binOp(
2292 const mir_tag: Mir.Inst.Tag = switch (tag) {2615 const mir_tag: Mir.Inst.Tag = switch (tag) {
2293 .add => .add,2616 .add => .add,
2294 .sub => .sub,2617 .sub => .sub,
2618 .mul => .mulx,
2619 .bit_and => .@"and",
2620 .bit_or => .@"or",
2621 .xor => .xor,
2295 .cmp_eq => .cmp,2622 .cmp_eq => .cmp,
2296 else => unreachable,2623 else => unreachable,
2297 };2624 };
...@@ -2313,72 +2640,60 @@ fn binOp(...@@ -2313,72 +2640,60 @@ fn binOp(
2313 }2640 }
2314 },2641 },
23152642
2316 .div_trunc => {2643 .addwrap,
2644 .subwrap,
2645 .mulwrap,
2646 => {
2647 const base_tag: Air.Inst.Tag = switch (tag) {
2648 .addwrap => .add,
2649 .subwrap => .sub,
2650 .mulwrap => .mul,
2651 else => unreachable,
2652 };
2653
2654 // Generate the base operation
2655 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2656
2657 // Truncate if necessary
2317 switch (lhs_ty.zigTypeTag()) {2658 switch (lhs_ty.zigTypeTag()) {
2318 .Vector => return self.fail("TODO binary operations on vectors", .{}),2659 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2319 .Int => {2660 .Int => {
2320 assert(lhs_ty.eql(rhs_ty, mod));
2321 const int_info = lhs_ty.intInfo(self.target.*);2661 const int_info = lhs_ty.intInfo(self.target.*);
2322 if (int_info.bits <= 64) {2662 if (int_info.bits <= 64) {
2323 const rhs_immediate_ok = switch (tag) {2663 const result_reg = result.register;
2324 .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),2664 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
2325 else => unreachable,2665 return result;
2326 };
2327
2328 const mir_tag: Mir.Inst.Tag = switch (tag) {
2329 .div_trunc => switch (int_info.signedness) {
2330 .signed => Mir.Inst.Tag.sdivx,
2331 .unsigned => Mir.Inst.Tag.udivx,
2332 },
2333 else => unreachable,
2334 };
2335
2336 if (rhs_immediate_ok) {
2337 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, true, metadata);
2338 } else {
2339 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2340 }
2341 } else {2666 } else {
2342 return self.fail("TODO binary operations on int with bits > 64", .{});2667 return self.fail("TODO binary operations on integers > u64/i64", .{});
2343 }2668 }
2344 },2669 },
2345 else => unreachable,2670 else => unreachable,
2346 }2671 }
2347 },2672 },
23482673
2349 .mul => {2674 .div_trunc => {
2350 switch (lhs_ty.zigTypeTag()) {2675 switch (lhs_ty.zigTypeTag()) {
2351 .Vector => return self.fail("TODO binary operations on vectors", .{}),2676 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2352 .Int => {2677 .Int => {
2353 assert(lhs_ty.eql(rhs_ty, mod));2678 assert(lhs_ty.eql(rhs_ty, mod));
2354 const int_info = lhs_ty.intInfo(self.target.*);2679 const int_info = lhs_ty.intInfo(self.target.*);
2355 if (int_info.bits <= 64) {2680 if (int_info.bits <= 64) {
2356 // Only say yes if the operation is
2357 // commutative, i.e. we can swap both of the
2358 // operands
2359 const lhs_immediate_ok = switch (tag) {
2360 .mul => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2361 else => unreachable,
2362 };
2363 const rhs_immediate_ok = switch (tag) {2681 const rhs_immediate_ok = switch (tag) {
2364 .mul => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),2682 .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
2365 else => unreachable,2683 else => unreachable,
2366 };2684 };
23672685
2368 const mir_tag: Mir.Inst.Tag = switch (tag) {2686 const mir_tag: Mir.Inst.Tag = switch (tag) {
2369 .mul => .mulx,2687 .div_trunc => switch (int_info.signedness) {
2688 .signed => Mir.Inst.Tag.sdivx,
2689 .unsigned => Mir.Inst.Tag.udivx,
2690 },
2370 else => unreachable,2691 else => unreachable,
2371 };2692 };
23722693
2373 if (rhs_immediate_ok) {2694 if (rhs_immediate_ok) {
2374 // At this point, rhs is an immediate2695 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, true, metadata);
2375 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata);
2376 } else if (lhs_immediate_ok) {
2377 // swap lhs and rhs
2378 // At this point, lhs is an immediate
2379 return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata);
2380 } else {2696 } else {
2381 // TODO convert large immediates to register before adding
2382 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);2697 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2383 }2698 }
2384 } else {2699 } else {
...@@ -2419,88 +2734,61 @@ fn binOp(...@@ -2419,88 +2734,61 @@ fn binOp(
2419 }2734 }
2420 },2735 },
24212736
2422 .bit_and,2737 .bool_and,
2423 .bit_or,2738 .bool_or,
2424 .xor,
2425 => {2739 => {
2426 switch (lhs_ty.zigTypeTag()) {2740 switch (lhs_ty.zigTypeTag()) {
2427 .Vector => return self.fail("TODO binary operations on vectors", .{}),2741 .Bool => {
2428 .Int => {2742 assert(lhs != .immediate); // should have been handled by Sema
2429 assert(lhs_ty.eql(rhs_ty, mod));2743 assert(rhs != .immediate); // should have been handled by Sema
2430 const int_info = lhs_ty.intInfo(self.target.*);2744
2431 if (int_info.bits <= 64) {2745 const mir_tag: Mir.Inst.Tag = switch (tag) {
2432 // Only say yes if the operation is2746 .bool_and => .@"and",
2433 // commutative, i.e. we can swap both of the2747 .bool_or => .@"or",
2434 // operands2748 else => unreachable,
2435 const lhs_immediate_ok = switch (tag) {2749 };
2436 .bit_and,
2437 .bit_or,
2438 .xor,
2439 => lhs == .immediate and lhs.immediate <= std.math.maxInt(u13),
2440 else => unreachable,
2441 };
2442 const rhs_immediate_ok = switch (tag) {
2443 .bit_and,
2444 .bit_or,
2445 .xor,
2446 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u13),
2447 else => unreachable,
2448 };
2449
2450 const mir_tag: Mir.Inst.Tag = switch (tag) {
2451 .bit_and => .@"and",
2452 .bit_or => .@"or",
2453 .xor => .xor,
2454 else => unreachable,
2455 };
24562750
2457 if (rhs_immediate_ok) {2751 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2458 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata);
2459 } else if (lhs_immediate_ok) {
2460 // swap lhs and rhs
2461 return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata);
2462 } else {
2463 // TODO convert large immediates to register before adding
2464 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2465 }
2466 } else {
2467 return self.fail("TODO binary operations on int with bits > 64", .{});
2468 }
2469 },2752 },
2470 else => unreachable,2753 else => unreachable,
2471 }2754 }
2472 },2755 },
24732756
2474 .shl => {2757 .shl,
2758 .shr,
2759 => {
2475 const base_tag: Air.Inst.Tag = switch (tag) {2760 const base_tag: Air.Inst.Tag = switch (tag) {
2476 .shl => .shl_exact,2761 .shl => .shl_exact,
2762 .shr => .shr_exact,
2477 else => unreachable,2763 else => unreachable,
2478 };2764 };
24792765
2480 // Generate a shl_exact/shr_exact2766 // Generate the base operation
2481 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);2767 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
24822768
2483 // Truncate if necessary2769 // Truncate if necessary
2484 switch (tag) {2770 switch (lhs_ty.zigTypeTag()) {
2485 .shl => switch (lhs_ty.zigTypeTag()) {2771 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2486 .Vector => return self.fail("TODO binary operations on vectors", .{}),2772 .Int => {
2487 .Int => {2773 const int_info = lhs_ty.intInfo(self.target.*);
2488 const int_info = lhs_ty.intInfo(self.target.*);2774 if (int_info.bits <= 64) {
2489 if (int_info.bits <= 64) {2775 // 32 and 64 bit operands doesn't need truncating
2490 const result_reg = result.register;2776 if (int_info.bits == 32 or int_info.bits == 64) return result;
2491 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);2777
2492 return result;2778 const result_reg = result.register;
2493 } else {2779 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
2494 return self.fail("TODO binary operations on integers > u64/i64", .{});2780 return result;
2495 }2781 } else {
2496 },2782 return self.fail("TODO binary operations on integers > u64/i64", .{});
2497 else => unreachable,2783 }
2498 },2784 },
2499 else => unreachable,2785 else => unreachable,
2500 }2786 }
2501 },2787 },
25022788
2503 .shl_exact => {2789 .shl_exact,
2790 .shr_exact,
2791 => {
2504 switch (lhs_ty.zigTypeTag()) {2792 switch (lhs_ty.zigTypeTag()) {
2505 .Vector => return self.fail("TODO binary operations on vectors", .{}),2793 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2506 .Int => {2794 .Int => {
...@@ -2509,7 +2797,11 @@ fn binOp(...@@ -2509,7 +2797,11 @@ fn binOp(
2509 const rhs_immediate_ok = rhs == .immediate;2797 const rhs_immediate_ok = rhs == .immediate;
25102798
2511 const mir_tag: Mir.Inst.Tag = switch (tag) {2799 const mir_tag: Mir.Inst.Tag = switch (tag) {
2512 .shl_exact => .sllx,2800 .shl_exact => if (int_info.bits <= 32) Mir.Inst.Tag.sll else Mir.Inst.Tag.sllx,
2801 .shr_exact => switch (int_info.signedness) {
2802 .signed => if (int_info.bits <= 32) Mir.Inst.Tag.sra else Mir.Inst.Tag.srax,
2803 .unsigned => if (int_info.bits <= 32) Mir.Inst.Tag.srl else Mir.Inst.Tag.srlx,
2804 },
2513 else => unreachable,2805 else => unreachable,
2514 };2806 };
25152807
...@@ -2616,7 +2908,21 @@ fn binOpImmediate(...@@ -2616,7 +2908,21 @@ fn binOpImmediate(
2616 .rs2_or_imm = .{ .imm = @intCast(u12, rhs.immediate) },2908 .rs2_or_imm = .{ .imm = @intCast(u12, rhs.immediate) },
2617 },2909 },
2618 },2910 },
2619 .sllx => .{2911 .sll,
2912 .srl,
2913 .sra,
2914 => .{
2915 .shift = .{
2916 .is_imm = true,
2917 .rd = dest_reg,
2918 .rs1 = lhs_reg,
2919 .rs2_or_imm = .{ .imm = @intCast(u5, rhs.immediate) },
2920 },
2921 },
2922 .sllx,
2923 .srlx,
2924 .srax,
2925 => .{
2620 .shift = .{2926 .shift = .{
2621 .is_imm = true,2927 .is_imm = true,
2622 .rd = dest_reg,2928 .rd = dest_reg,
...@@ -2740,7 +3046,13 @@ fn binOpRegister(...@@ -2740,7 +3046,13 @@ fn binOpRegister(
2740 .rs2_or_imm = .{ .rs2 = rhs_reg },3046 .rs2_or_imm = .{ .rs2 = rhs_reg },
2741 },3047 },
2742 },3048 },
2743 .sllx => .{3049 .sll,
3050 .srl,
3051 .sra,
3052 .sllx,
3053 .srlx,
3054 .srax,
3055 => .{
2744 .shift = .{3056 .shift = .{
2745 .is_imm = false,3057 .is_imm = false,
2746 .rd = dest_reg,3058 .rd = dest_reg,
src/arch/sparc64/Mir.zig+1-1
...@@ -218,7 +218,7 @@ pub const Inst = struct {...@@ -218,7 +218,7 @@ pub const Inst = struct {
218 /// Used by e.g. call218 /// Used by e.g. call
219 branch_link: struct {219 branch_link: struct {
220 inst: Index,220 inst: Index,
221 link: Register = .o7,221 // link is always %o7
222 },222 },
223223
224 /// Branch with prediction, checking the integer status code224 /// Branch with prediction, checking the integer status code
src/arch/sparc64/bits.zig+12-12
...@@ -1339,48 +1339,48 @@ pub const Instruction = union(enum) {...@@ -1339,48 +1339,48 @@ pub const Instruction = union(enum) {
13391339
1340 pub fn sll(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {1340 pub fn sll(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1341 return switch (s2) {1341 return switch (s2) {
1342 Register => format3k(0b11, 0b10_0101, .shift32, rs1, rs2, rd),1342 Register => format3k(0b10, 0b10_0101, .shift32, rs1, rs2, rd),
1343 u5 => format3l(0b11, 0b10_0101, rs1, rs2, rd),1343 u5 => format3l(0b10, 0b10_0101, rs1, rs2, rd),
1344 else => unreachable,1344 else => unreachable,
1345 };1345 };
1346 }1346 }
13471347
1348 pub fn srl(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {1348 pub fn srl(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1349 return switch (s2) {1349 return switch (s2) {
1350 Register => format3k(0b11, 0b10_0110, .shift32, rs1, rs2, rd),1350 Register => format3k(0b10, 0b10_0110, .shift32, rs1, rs2, rd),
1351 u5 => format3l(0b11, 0b10_0110, rs1, rs2, rd),1351 u5 => format3l(0b10, 0b10_0110, rs1, rs2, rd),
1352 else => unreachable,1352 else => unreachable,
1353 };1353 };
1354 }1354 }
13551355
1356 pub fn sra(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {1356 pub fn sra(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1357 return switch (s2) {1357 return switch (s2) {
1358 Register => format3k(0b11, 0b10_0111, .shift32, rs1, rs2, rd),1358 Register => format3k(0b10, 0b10_0111, .shift32, rs1, rs2, rd),
1359 u5 => format3l(0b11, 0b10_0111, rs1, rs2, rd),1359 u5 => format3l(0b10, 0b10_0111, rs1, rs2, rd),
1360 else => unreachable,1360 else => unreachable,
1361 };1361 };
1362 }1362 }
13631363
1364 pub fn sllx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {1364 pub fn sllx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1365 return switch (s2) {1365 return switch (s2) {
1366 Register => format3k(0b11, 0b10_0101, .shift64, rs1, rs2, rd),1366 Register => format3k(0b10, 0b10_0101, .shift64, rs1, rs2, rd),
1367 u6 => format3m(0b11, 0b10_0101, rs1, rs2, rd),1367 u6 => format3m(0b10, 0b10_0101, rs1, rs2, rd),
1368 else => unreachable,1368 else => unreachable,
1369 };1369 };
1370 }1370 }
13711371
1372 pub fn srlx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {1372 pub fn srlx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1373 return switch (s2) {1373 return switch (s2) {
1374 Register => format3k(0b11, 0b10_0110, .shift64, rs1, rs2, rd),1374 Register => format3k(0b10, 0b10_0110, .shift64, rs1, rs2, rd),
1375 u6 => format3m(0b11, 0b10_0110, rs1, rs2, rd),1375 u6 => format3m(0b10, 0b10_0110, rs1, rs2, rd),
1376 else => unreachable,1376 else => unreachable,
1377 };1377 };
1378 }1378 }
13791379
1380 pub fn srax(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {1380 pub fn srax(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1381 return switch (s2) {1381 return switch (s2) {
1382 Register => format3k(0b11, 0b10_0111, .shift64, rs1, rs2, rd),1382 Register => format3k(0b10, 0b10_0111, .shift64, rs1, rs2, rd),
1383 u6 => format3m(0b11, 0b10_0111, rs1, rs2, rd),1383 u6 => format3m(0b10, 0b10_0111, rs1, rs2, rd),
1384 else => unreachable,1384 else => unreachable,
1385 };1385 };
1386 }1386 }
test/behavior/error.zig+1
...@@ -223,6 +223,7 @@ fn testErrorSetType() !void {...@@ -223,6 +223,7 @@ fn testErrorSetType() !void {
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_aarch64) return error.SkipZigTest; // TODO225 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
226 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
226227
227 try testExplicitErrorSetCast(Set1.A);228 try testExplicitErrorSetCast(Set1.A);
228 comptime try testExplicitErrorSetCast(Set1.A);229 comptime try testExplicitErrorSetCast(Set1.A);
test/behavior/math.zig+2
...@@ -1166,6 +1166,7 @@ test "remainder division" {...@@ -1166,6 +1166,7 @@ test "remainder division" {
1166 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1166 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1168 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1168 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1169 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1169 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1170 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1170 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/126021171 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/12602
11711172
...@@ -1198,6 +1199,7 @@ test "float remainder division using @rem" {...@@ -1198,6 +1199,7 @@ test "float remainder division using @rem" {
1198 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1199 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1199 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1200 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1201 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1202 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1201 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1203 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1202 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/126021204 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/12602
12031205
test/behavior/packed-struct.zig+4
...@@ -155,6 +155,7 @@ test "correct sizeOf and offsets in packed structs" {...@@ -155,6 +155,7 @@ test "correct sizeOf and offsets in packed structs" {
155 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO155 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
156 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO156 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
158159
159 const PStruct = packed struct {160 const PStruct = packed struct {
160 bool_a: bool,161 bool_a: bool,
...@@ -225,6 +226,7 @@ test "nested packed structs" {...@@ -225,6 +226,7 @@ test "nested packed structs" {
225 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO226 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
226 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO227 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
227 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO228 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
229 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
228230
229 const S1 = packed struct { a: u8, b: u8, c: u8 };231 const S1 = packed struct { a: u8, b: u8, c: u8 };
230232
...@@ -272,6 +274,7 @@ test "regular in irregular packed struct" {...@@ -272,6 +274,7 @@ test "regular in irregular packed struct" {
272 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;274 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
273 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;275 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
274 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;276 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
277 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
275278
276 const Irregular = packed struct {279 const Irregular = packed struct {
277 bar: Regular = Regular{},280 bar: Regular = Regular{},
...@@ -294,6 +297,7 @@ test "byte-aligned field pointer offsets" {...@@ -294,6 +297,7 @@ test "byte-aligned field pointer offsets" {
294 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;297 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
295 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;298 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
296 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;299 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
300 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
297301
298 const S = struct {302 const S = struct {
299 const A = packed struct {303 const A = packed struct {
test/behavior/struct.zig+43
...@@ -10,6 +10,7 @@ top_level_field: i32,...@@ -10,6 +10,7 @@ top_level_field: i32,
1010
11test "top level fields" {11test "top level fields" {
12 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;12 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1314
14 var instance = @This(){15 var instance = @This(){
15 .top_level_field = 1234,16 .top_level_field = 1234,
...@@ -85,6 +86,7 @@ const StructFoo = struct {...@@ -85,6 +86,7 @@ const StructFoo = struct {
85test "structs" {86test "structs" {
86 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;87 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
87 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;88 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
89 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8890
89 var foo: StructFoo = undefined;91 var foo: StructFoo = undefined;
90 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));92 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
...@@ -103,6 +105,7 @@ fn testMutation(foo: *StructFoo) void {...@@ -103,6 +105,7 @@ fn testMutation(foo: *StructFoo) void {
103105
104test "struct byval assign" {106test "struct byval assign" {
105 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;107 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
106109
107 var foo1: StructFoo = undefined;110 var foo1: StructFoo = undefined;
108 var foo2: StructFoo = undefined;111 var foo2: StructFoo = undefined;
...@@ -136,6 +139,7 @@ fn returnEmptyStructInstance() StructWithNoFields {...@@ -136,6 +139,7 @@ fn returnEmptyStructInstance() StructWithNoFields {
136139
137test "fn call of struct field" {140test "fn call of struct field" {
138 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;141 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
142 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
139143
140 const Foo = struct {144 const Foo = struct {
141 ptr: fn () i32,145 ptr: fn () i32,
...@@ -191,6 +195,7 @@ const MemberFnRand = struct {...@@ -191,6 +195,7 @@ const MemberFnRand = struct {
191195
192test "return struct byval from function" {196test "return struct byval from function" {
193 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;197 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
198 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
194199
195 const bar = makeBar2(1234, 5678);200 const bar = makeBar2(1234, 5678);
196 try expect(bar.y == 5678);201 try expect(bar.y == 5678);
...@@ -238,6 +243,7 @@ test "usingnamespace within struct scope" {...@@ -238,6 +243,7 @@ test "usingnamespace within struct scope" {
238243
239test "struct field init with catch" {244test "struct field init with catch" {
240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;245 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
246 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
241247
242 const S = struct {248 const S = struct {
243 fn doTheTest() !void {249 fn doTheTest() !void {
...@@ -263,6 +269,7 @@ const blah: packed struct {...@@ -263,6 +269,7 @@ const blah: packed struct {
263} = undefined;269} = undefined;
264270
265test "bit field alignment" {271test "bit field alignment" {
272 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
266 try expect(@TypeOf(&blah.b) == *align(1:3:1) const u3);273 try expect(@TypeOf(&blah.b) == *align(1:3:1) const u3);
267}274}
268275
...@@ -278,6 +285,7 @@ const Val = struct {...@@ -278,6 +285,7 @@ const Val = struct {
278test "struct point to self" {285test "struct point to self" {
279 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;286 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
280 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO287 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
288 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
281289
282 var root: Node = undefined;290 var root: Node = undefined;
283 root.val.x = 1;291 root.val.x = 1;
...@@ -293,6 +301,7 @@ test "struct point to self" {...@@ -293,6 +301,7 @@ test "struct point to self" {
293301
294test "void struct fields" {302test "void struct fields" {
295 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
296305
297 const foo = VoidStructFieldsFoo{306 const foo = VoidStructFieldsFoo{
298 .a = void{},307 .a = void{},
...@@ -311,6 +320,7 @@ const VoidStructFieldsFoo = struct {...@@ -311,6 +320,7 @@ const VoidStructFieldsFoo = struct {
311test "return empty struct from fn" {320test "return empty struct from fn" {
312 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;321 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
313 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO322 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
323 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
314324
315 _ = testReturnEmptyStructFromFn();325 _ = testReturnEmptyStructFromFn();
316}326}
...@@ -322,6 +332,7 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 {...@@ -322,6 +332,7 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 {
322test "pass slice of empty struct to fn" {332test "pass slice of empty struct to fn" {
323 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;333 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
324 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO334 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
335 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
325336
326 try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1);337 try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1);
327}338}
...@@ -334,6 +345,7 @@ test "self-referencing struct via array member" {...@@ -334,6 +345,7 @@ test "self-referencing struct via array member" {
334 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO345 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
335 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO346 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
336 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO347 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
348 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
337349
338 const T = struct {350 const T = struct {
339 children: [1]*@This(),351 children: [1]*@This(),
...@@ -359,6 +371,7 @@ const EmptyStruct = struct {...@@ -359,6 +371,7 @@ const EmptyStruct = struct {
359test "align 1 field before self referential align 8 field as slice return type" {371test "align 1 field before self referential align 8 field as slice return type" {
360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;372 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
361 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO373 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
374 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
362375
363 const result = alloc(Expr);376 const result = alloc(Expr);
364 try expect(result.len == 0);377 try expect(result.len == 0);
...@@ -384,6 +397,7 @@ test "packed struct" {...@@ -384,6 +397,7 @@ test "packed struct" {
384 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO397 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
385 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO398 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
386 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO399 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
400 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
387401
388 var foo = APackedStruct{402 var foo = APackedStruct{
389 .x = 1,403 .x = 1,
...@@ -412,6 +426,7 @@ test "packed struct 24bits" {...@@ -412,6 +426,7 @@ test "packed struct 24bits" {
412 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO426 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
413 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO427 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO
414 if (builtin.cpu.arch == .arm) return error.SkipZigTest; // TODO428 if (builtin.cpu.arch == .arm) return error.SkipZigTest; // TODO
429 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
415430
416 comptime {431 comptime {
417 // stage1 gets the wrong answer for sizeof432 // stage1 gets the wrong answer for sizeof
...@@ -458,6 +473,7 @@ test "runtime struct initialization of bitfield" {...@@ -458,6 +473,7 @@ test "runtime struct initialization of bitfield" {
458 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO473 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
459 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO474 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
460 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO475 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
476 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
461477
462 const s1 = Nibbles{478 const s1 = Nibbles{
463 .x = x1,479 .x = x1,
...@@ -502,6 +518,7 @@ test "packed struct fields are ordered from LSB to MSB" {...@@ -502,6 +518,7 @@ test "packed struct fields are ordered from LSB to MSB" {
502 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO518 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
503 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO519 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
504 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO520 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
521 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
505522
506 var all: u64 = 0x7765443322221111;523 var all: u64 = 0x7765443322221111;
507 var bytes: [8]u8 = undefined;524 var bytes: [8]u8 = undefined;
...@@ -523,6 +540,7 @@ test "implicit cast packed struct field to const ptr" {...@@ -523,6 +540,7 @@ test "implicit cast packed struct field to const ptr" {
523 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO540 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
524 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO541 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
525 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO542 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
543 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
526544
527 const LevelUpMove = packed struct {545 const LevelUpMove = packed struct {
528 move_id: u9,546 move_id: u9,
...@@ -543,6 +561,7 @@ test "zero-bit field in packed struct" {...@@ -543,6 +561,7 @@ test "zero-bit field in packed struct" {
543 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO561 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
544 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO562 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
545 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO563 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
564 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
546565
547 const S = packed struct {566 const S = packed struct {
548 x: u10,567 x: u10,
...@@ -554,6 +573,7 @@ test "zero-bit field in packed struct" {...@@ -554,6 +573,7 @@ test "zero-bit field in packed struct" {
554573
555test "packed struct with non-ABI-aligned field" {574test "packed struct with non-ABI-aligned field" {
556 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;575 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
576 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
557 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO577 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
558 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO578 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
559 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO579 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -588,6 +608,7 @@ test "bit field access" {...@@ -588,6 +608,7 @@ test "bit field access" {
588 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO608 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
589 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO609 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
590 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO610 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
611 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
591612
592 var data = bit_field_1;613 var data = bit_field_1;
593 try expect(getA(&data) == 1);614 try expect(getA(&data) == 1);
...@@ -618,6 +639,7 @@ fn getC(data: *const BitField1) u2 {...@@ -618,6 +639,7 @@ fn getC(data: *const BitField1) u2 {
618test "default struct initialization fields" {639test "default struct initialization fields" {
619 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;640 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
620 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO641 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
642 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
621643
622 const S = struct {644 const S = struct {
623 a: i32 = 1234,645 a: i32 = 1234,
...@@ -645,6 +667,7 @@ test "packed array 24bits" {...@@ -645,6 +667,7 @@ test "packed array 24bits" {
645 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;667 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
646 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;668 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
647 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;669 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
670 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
648671
649 comptime {672 comptime {
650 try expect(@sizeOf([9]Foo32Bits) == 9 * 4);673 try expect(@sizeOf([9]Foo32Bits) == 9 * 4);
...@@ -701,6 +724,7 @@ const FooArray24Bits = packed struct {...@@ -701,6 +724,7 @@ const FooArray24Bits = packed struct {
701test "aligned array of packed struct" {724test "aligned array of packed struct" {
702 // Stage2 has different packed struct semantics.725 // Stage2 has different packed struct semantics.
703 if (builtin.zig_backend != .stage1) return error.SkipZigTest;726 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
727 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
704728
705 comptime {729 comptime {
706 try expect(@sizeOf(FooStructAligned) == 2);730 try expect(@sizeOf(FooStructAligned) == 2);
...@@ -730,6 +754,7 @@ test "pointer to packed struct member in a stack variable" {...@@ -730,6 +754,7 @@ test "pointer to packed struct member in a stack variable" {
730 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO754 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
731 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO755 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
732 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO756 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
757 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
733758
734 const S = packed struct {759 const S = packed struct {
735 a: u2,760 a: u2,
...@@ -747,6 +772,7 @@ test "packed struct with u0 field access" {...@@ -747,6 +772,7 @@ test "packed struct with u0 field access" {
747 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO772 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
748 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO773 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
749 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO774 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
775 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
750776
751 const S = packed struct {777 const S = packed struct {
752 f0: u0,778 f0: u0,
...@@ -758,6 +784,7 @@ test "packed struct with u0 field access" {...@@ -758,6 +784,7 @@ test "packed struct with u0 field access" {
758test "access to global struct fields" {784test "access to global struct fields" {
759 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
760 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO786 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
787 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
761788
762 g_foo.bar.value = 42;789 g_foo.bar.value = 42;
763 try expect(g_foo.bar.value == 42);790 try expect(g_foo.bar.value == 42);
...@@ -782,6 +809,7 @@ test "packed struct with fp fields" {...@@ -782,6 +809,7 @@ test "packed struct with fp fields" {
782 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO809 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
783 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO810 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
784 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO811 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
812 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
785 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO813 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
786814
787 const S = packed struct {815 const S = packed struct {
...@@ -859,6 +887,7 @@ test "packed struct field passed to generic function" {...@@ -859,6 +887,7 @@ test "packed struct field passed to generic function" {
859 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO887 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
860 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO888 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
861 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO889 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
890 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
862891
863 const S = struct {892 const S = struct {
864 const P = packed struct {893 const P = packed struct {
...@@ -975,6 +1004,7 @@ test "tuple element initialized with fn call" {...@@ -975,6 +1004,7 @@ test "tuple element initialized with fn call" {
975 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1004 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
976 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1005 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
977 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1006 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1007 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9781008
979 const S = struct {1009 const S = struct {
980 fn doTheTest() !void {1010 fn doTheTest() !void {
...@@ -1012,6 +1042,7 @@ test "type coercion of anon struct literal to struct" {...@@ -1012,6 +1042,7 @@ test "type coercion of anon struct literal to struct" {
1012 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1042 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1013 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1043 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1014 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1044 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1045 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10151046
1016 const S = struct {1047 const S = struct {
1017 const S2 = struct {1048 const S2 = struct {
...@@ -1050,6 +1081,7 @@ test "type coercion of pointer to anon struct literal to pointer to struct" {...@@ -1050,6 +1081,7 @@ test "type coercion of pointer to anon struct literal to pointer to struct" {
1050 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1081 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1051 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1082 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1052 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1083 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1084 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10531085
1054 const S = struct {1086 const S = struct {
1055 const S2 = struct {1087 const S2 = struct {
...@@ -1089,6 +1121,7 @@ test "packed struct with undefined initializers" {...@@ -1089,6 +1121,7 @@ test "packed struct with undefined initializers" {
1089 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1121 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1090 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1122 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1091 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1123 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10921125
1093 const S = struct {1126 const S = struct {
1094 const P = packed struct {1127 const P = packed struct {
...@@ -1119,6 +1152,7 @@ test "for loop over pointers to struct, getting field from struct pointer" {...@@ -1119,6 +1152,7 @@ test "for loop over pointers to struct, getting field from struct pointer" {
1119 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1152 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1120 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1153 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1121 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1155 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11221156
1123 const S = struct {1157 const S = struct {
1124 const Foo = struct {1158 const Foo = struct {
...@@ -1160,6 +1194,7 @@ test "anon init through error unions and optionals" {...@@ -1160,6 +1194,7 @@ test "anon init through error unions and optionals" {
1160 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1194 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1161 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1195 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1162 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1196 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1197 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11631198
1164 const S = struct {1199 const S = struct {
1165 a: u32,1200 a: u32,
...@@ -1188,6 +1223,7 @@ test "anon init through optional" {...@@ -1188,6 +1223,7 @@ test "anon init through optional" {
1188 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1223 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1224 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1190 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1225 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1226 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11911227
1192 const S = struct {1228 const S = struct {
1193 a: u32,1229 a: u32,
...@@ -1209,6 +1245,7 @@ test "anon init through error union" {...@@ -1209,6 +1245,7 @@ test "anon init through error union" {
1209 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1245 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1210 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1246 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1211 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1247 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1248 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12121249
1213 const S = struct {1250 const S = struct {
1214 a: u32,1251 a: u32,
...@@ -1230,6 +1267,7 @@ test "typed init through error unions and optionals" {...@@ -1230,6 +1267,7 @@ test "typed init through error unions and optionals" {
1230 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1267 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1231 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1268 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1232 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1269 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1270 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12331271
1234 const S = struct {1272 const S = struct {
1235 a: u32,1273 a: u32,
...@@ -1254,6 +1292,7 @@ test "typed init through error unions and optionals" {...@@ -1254,6 +1292,7 @@ test "typed init through error unions and optionals" {
12541292
1255test "initialize struct with empty literal" {1293test "initialize struct with empty literal" {
1256 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1294 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1295 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12571296
1258 const S = struct { x: i32 = 1234 };1297 const S = struct { x: i32 = 1234 };
1259 var s: S = .{};1298 var s: S = .{};
...@@ -1262,6 +1301,7 @@ test "initialize struct with empty literal" {...@@ -1262,6 +1301,7 @@ test "initialize struct with empty literal" {
12621301
1263test "loading a struct pointer perfoms a copy" {1302test "loading a struct pointer perfoms a copy" {
1264 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1304 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12651305
1266 const S = struct {1306 const S = struct {
1267 a: i32,1307 a: i32,
...@@ -1295,6 +1335,7 @@ test "packed struct aggregate init" {...@@ -1295,6 +1335,7 @@ test "packed struct aggregate init" {
1295 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1335 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1296 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1336 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1297 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1337 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1338 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12981339
1299 const S = struct {1340 const S = struct {
1300 fn foo(a: i2, b: i6) u8 {1341 fn foo(a: i2, b: i6) u8 {
...@@ -1315,6 +1356,7 @@ test "packed struct field access via pointer" {...@@ -1315,6 +1356,7 @@ test "packed struct field access via pointer" {
1315 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1356 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1316 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1357 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1317 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1358 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1359 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13181360
1319 const S = struct {1361 const S = struct {
1320 fn doTheTest() !void {1362 fn doTheTest() !void {
...@@ -1355,6 +1397,7 @@ test "store to comptime field" {...@@ -1355,6 +1397,7 @@ test "store to comptime field" {
13551397
1356test "struct field init value is size of the struct" {1398test "struct field init value is size of the struct" {
1357 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1399 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1400 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13581401
1359 const namespace = struct {1402 const namespace = struct {
1360 const S = extern struct {1403 const S = extern struct {