authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-29 10:55:50-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-04-29 10:55:50-07:00
log7baf0de807afc8c2c56cc1278e624e9103c30cfb
tree8fd39ab072376b73f2e62147a7e1bd9d75293432
parent13aaa16ab2cac5c07a970a3b49f5dd0ffd4d3539
parentccc9b8caf632bf97f7765c1b1d7821118cf34008
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #15458 from koachan/sparc64-codegen

stage2: sparc64: Yet another patchset for the selfhosted backend

14 files changed, 331 insertions(+), 12 deletions(-)

src/arch/sparc64/CodeGen.zig+205-11
...@@ -22,6 +22,7 @@ const Type = @import("../../type.zig").Type;...@@ -22,6 +22,7 @@ const Type = @import("../../type.zig").Type;
22const CodeGenError = codegen.CodeGenError;22const CodeGenError = codegen.CodeGenError;
23const Result = @import("../../codegen.zig").Result;23const Result = @import("../../codegen.zig").Result;
24const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;24const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
25const Endian = std.builtin.Endian;
2526
26const build_options = @import("build_options");27const build_options = @import("build_options");
2728
...@@ -30,6 +31,7 @@ const abi = @import("abi.zig");...@@ -30,6 +31,7 @@ const abi = @import("abi.zig");
30const errUnionPayloadOffset = codegen.errUnionPayloadOffset;31const errUnionPayloadOffset = codegen.errUnionPayloadOffset;
31const errUnionErrorOffset = codegen.errUnionErrorOffset;32const errUnionErrorOffset = codegen.errUnionErrorOffset;
32const Instruction = bits.Instruction;33const Instruction = bits.Instruction;
34const ASI = Instruction.ASI;
33const ShiftWidth = Instruction.ShiftWidth;35const ShiftWidth = Instruction.ShiftWidth;
34const RegisterManager = abi.RegisterManager;36const RegisterManager = abi.RegisterManager;
35const RegisterLock = RegisterManager.RegisterLock;37const RegisterLock = RegisterManager.RegisterLock;
...@@ -141,6 +143,8 @@ const MCValue = union(enum) {...@@ -141,6 +143,8 @@ const MCValue = union(enum) {
141 /// The value is one of the stack variables.143 /// The value is one of the stack variables.
142 /// If the type is a pointer, it means the pointer address is in the stack at this offset.144 /// If the type is a pointer, it means the pointer address is in the stack at this offset.
143 /// Note that this stores the plain value (i.e without the effects of the stack bias).145 /// Note that this stores the plain value (i.e without the effects of the stack bias).
146 /// Always convert this value into machine offsets with realStackOffset() before
147 /// lowering into asm!
144 stack_offset: u32,148 stack_offset: u32,
145 /// The value is a pointer to one of the stack variables (payload is stack offset).149 /// The value is a pointer to one of the stack variables (payload is stack offset).
146 ptr_stack_offset: u32,150 ptr_stack_offset: u32,
...@@ -595,7 +599,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -595,7 +599,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
595 .ret_load => try self.airRetLoad(inst),599 .ret_load => try self.airRetLoad(inst),
596 .store => try self.airStore(inst, false),600 .store => try self.airStore(inst, false),
597 .store_safe => try self.airStore(inst, true),601 .store_safe => try self.airStore(inst, true),
598 .struct_field_ptr=> @panic("TODO try self.airStructFieldPtr(inst)"),602 .struct_field_ptr=> try self.airStructFieldPtr(inst),
599 .struct_field_val=> try self.airStructFieldVal(inst),603 .struct_field_val=> try self.airStructFieldVal(inst),
600 .array_to_slice => try self.airArrayToSlice(inst),604 .array_to_slice => try self.airArrayToSlice(inst),
601 .int_to_float => try self.airIntToFloat(inst),605 .int_to_float => try self.airIntToFloat(inst),
...@@ -613,7 +617,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -613,7 +617,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
613 .clz => try self.airClz(inst),617 .clz => try self.airClz(inst),
614 .ctz => try self.airCtz(inst),618 .ctz => try self.airCtz(inst),
615 .popcount => try self.airPopcount(inst),619 .popcount => try self.airPopcount(inst),
616 .byte_swap => @panic("TODO try self.airByteSwap(inst)"),620 .byte_swap => try self.airByteSwap(inst),
617 .bit_reverse => try self.airBitReverse(inst),621 .bit_reverse => try self.airBitReverse(inst),
618 .tag_name => try self.airTagName(inst),622 .tag_name => try self.airTagName(inst),
619 .error_name => try self.airErrorName(inst),623 .error_name => try self.airErrorName(inst),
...@@ -663,8 +667,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -663,8 +667,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
663 .slice_ptr => try self.airSlicePtr(inst),667 .slice_ptr => try self.airSlicePtr(inst),
664 .slice_len => try self.airSliceLen(inst),668 .slice_len => try self.airSliceLen(inst),
665669
666 .ptr_slice_len_ptr => @panic("TODO try self.airPtrSliceLenPtr(inst)"),670 .ptr_slice_len_ptr => try self.airPtrSliceLenPtr(inst),
667 .ptr_slice_ptr_ptr => @panic("TODO try self.airPtrSlicePtrPtr(inst)"),671 .ptr_slice_ptr_ptr => try self.airPtrSlicePtrPtr(inst),
668672
669 .array_elem_val => try self.airArrayElemVal(inst),673 .array_elem_val => try self.airArrayElemVal(inst),
670 .slice_elem_val => try self.airSliceElemVal(inst),674 .slice_elem_val => try self.airSliceElemVal(inst),
...@@ -720,10 +724,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -720,10 +724,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
720 .error_set_has_value => @panic("TODO implement error_set_has_value"),724 .error_set_has_value => @panic("TODO implement error_set_has_value"),
721 .vector_store_elem => @panic("TODO implement vector_store_elem"),725 .vector_store_elem => @panic("TODO implement vector_store_elem"),
722726
723 .c_va_arg => @panic("TODO implement c_va_arg"),727 .c_va_arg => return self.fail("TODO implement c_va_arg", .{}),
724 .c_va_copy => @panic("TODO implement c_va_copy"),728 .c_va_copy => return self.fail("TODO implement c_va_copy", .{}),
725 .c_va_end => @panic("TODO implement c_va_end"),729 .c_va_end => return self.fail("TODO implement c_va_end", .{}),
726 .c_va_start => @panic("TODO implement c_va_start"),730 .c_va_start => return self.fail("TODO implement c_va_start", .{}),
727731
728 .wasm_memory_size => unreachable,732 .wasm_memory_size => unreachable,
729 .wasm_memory_grow => unreachable,733 .wasm_memory_grow => unreachable,
...@@ -1198,6 +1202,90 @@ fn airBreakpoint(self: *Self) !void {...@@ -1198,6 +1202,90 @@ fn airBreakpoint(self: *Self) !void {
1198 return self.finishAirBookkeeping();1202 return self.finishAirBookkeeping();
1199}1203}
12001204
1205fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
1206 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1207
1208 // We have hardware byteswapper in SPARCv9, don't let mainstream compilers mislead you.
1209 // That being said, the strategy to lower this is:
1210 // - If src is an immediate, comptime-swap it.
1211 // - If src is in memory then issue an LD*A with #ASI_P_[oppposite-endian]
1212 // - If src is a register then issue an ST*A with #ASI_P_[oppposite-endian]
1213 // to a stack slot, then follow with a normal load from said stack slot.
1214 // This is because on some implementations, ASI-tagged memory operations are non-piplelinable
1215 // and loads tend to have longer latency than stores, so the sequence will minimize stall.
1216 // The result will always be either another immediate or stored in a register.
1217 // TODO: Fold byteswap+store into a single ST*A and load+byteswap into a single LD*A.
1218 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1219 const operand = try self.resolveInst(ty_op.operand);
1220 const operand_ty = self.air.typeOf(ty_op.operand);
1221 switch (operand_ty.zigTypeTag()) {
1222 .Vector => return self.fail("TODO byteswap for vectors", .{}),
1223 .Int => {
1224 const int_info = operand_ty.intInfo(self.target.*);
1225 if (int_info.bits == 8) break :result operand;
1226
1227 const abi_size = int_info.bits >> 3;
1228 const abi_align = operand_ty.abiAlignment(self.target.*);
1229 const opposite_endian_asi = switch (self.target.cpu.arch.endian()) {
1230 Endian.Big => ASI.asi_primary_little,
1231 Endian.Little => ASI.asi_primary,
1232 };
1233
1234 switch (operand) {
1235 .immediate => |imm| {
1236 const swapped = switch (int_info.bits) {
1237 16 => @byteSwap(@intCast(u16, imm)),
1238 24 => @byteSwap(@intCast(u24, imm)),
1239 32 => @byteSwap(@intCast(u32, imm)),
1240 40 => @byteSwap(@intCast(u40, imm)),
1241 48 => @byteSwap(@intCast(u48, imm)),
1242 56 => @byteSwap(@intCast(u56, imm)),
1243 64 => @byteSwap(@intCast(u64, imm)),
1244 else => return self.fail("TODO synthesize SPARCv9 byteswap for other integer sizes", .{}),
1245 };
1246 break :result .{ .immediate = swapped };
1247 },
1248 .register => |reg| {
1249 if (int_info.bits > 64 or @popCount(int_info.bits) != 1)
1250 return self.fail("TODO synthesize SPARCv9 byteswap for other integer sizes", .{});
1251
1252 const off = try self.allocMem(inst, abi_size, abi_align);
1253 const off_reg = try self.copyToTmpRegister(operand_ty, .{ .immediate = realStackOffset(off) });
1254
1255 try self.genStoreASI(reg, .sp, off_reg, abi_size, opposite_endian_asi);
1256 try self.genLoad(reg, .sp, Register, off_reg, abi_size);
1257 break :result .{ .register = reg };
1258 },
1259 .memory => {
1260 if (int_info.bits > 64 or @popCount(int_info.bits) != 1)
1261 return self.fail("TODO synthesize SPARCv9 byteswap for other integer sizes", .{});
1262
1263 const addr_reg = try self.copyToTmpRegister(operand_ty, operand);
1264 const dst_reg = try self.register_manager.allocReg(null, gp);
1265
1266 try self.genLoadASI(dst_reg, addr_reg, .g0, abi_size, opposite_endian_asi);
1267 break :result .{ .register = dst_reg };
1268 },
1269 .stack_offset => |off| {
1270 if (int_info.bits > 64 or @popCount(int_info.bits) != 1)
1271 return self.fail("TODO synthesize SPARCv9 byteswap for other integer sizes", .{});
1272
1273 const off_reg = try self.copyToTmpRegister(operand_ty, .{ .immediate = realStackOffset(off) });
1274 const dst_reg = try self.register_manager.allocReg(null, gp);
1275
1276 try self.genLoadASI(dst_reg, .sp, off_reg, abi_size, opposite_endian_asi);
1277 break :result .{ .register = dst_reg };
1278 },
1279 else => unreachable,
1280 }
1281 },
1282 else => unreachable,
1283 }
1284 };
1285
1286 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1287}
1288
1201fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {1289fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {
1202 if (modifier == .always_tail) return self.fail("TODO implement tail calls for {}", .{self.target.cpu.arch});1290 if (modifier == .always_tail) return self.fail("TODO implement tail calls for {}", .{self.target.cpu.arch});
12031291
...@@ -2150,6 +2238,38 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2150,6 +2238,38 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
2150 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });2238 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2151}2239}
21522240
2241fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
2242 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2243 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2244 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
2245 const ptr_bytes = @divExact(ptr_bits, 8);
2246 const mcv = try self.resolveInst(ty_op.operand);
2247 switch (mcv) {
2248 .dead, .unreach, .none => unreachable,
2249 .ptr_stack_offset => |off| {
2250 break :result MCValue{ .ptr_stack_offset = off - ptr_bytes };
2251 },
2252 else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}),
2253 }
2254 };
2255 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2256}
2257
2258fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
2259 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2260 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2261 const mcv = try self.resolveInst(ty_op.operand);
2262 switch (mcv) {
2263 .dead, .unreach, .none => unreachable,
2264 .ptr_stack_offset => |off| {
2265 break :result MCValue{ .ptr_stack_offset = off };
2266 },
2267 else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}),
2268 }
2269 };
2270 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2271}
2272
2153fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {2273fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {
2154 const un_op = self.air.instructions.items(.data)[inst].un_op;2274 const un_op = self.air.instructions.items(.data)[inst].un_op;
2155 const result = try self.resolveInst(un_op);2275 const result = try self.resolveInst(un_op);
...@@ -2425,6 +2545,13 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -2425,6 +2545,13 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
2425 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });2545 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
2426}2546}
24272547
2548fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {
2549 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2550 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
2551 const result = try self.structFieldPtr(inst, extra.struct_operand, extra.field_index);
2552 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
2553}
2554
2428fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {2555fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
2429 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2556 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2430 const result = try self.structFieldPtr(inst, ty_op.operand, index);2557 const result = try self.structFieldPtr(inst, ty_op.operand, index);
...@@ -3574,6 +3701,34 @@ fn genLoad(self: *Self, value_reg: Register, addr_reg: Register, comptime off_ty...@@ -3574,6 +3701,34 @@ fn genLoad(self: *Self, value_reg: Register, addr_reg: Register, comptime off_ty
3574 }3701 }
3575}3702}
35763703
3704fn genLoadASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Register, abi_size: u64, asi: ASI) !void {
3705 switch (abi_size) {
3706 1, 2, 4, 8 => {
3707 const tag: Mir.Inst.Tag = switch (abi_size) {
3708 1 => .lduba,
3709 2 => .lduha,
3710 4 => .lduwa,
3711 8 => .ldxa,
3712 else => unreachable, // unexpected abi size
3713 };
3714
3715 _ = try self.addInst(.{
3716 .tag = tag,
3717 .data = .{
3718 .mem_asi = .{
3719 .rd = value_reg,
3720 .rs1 = addr_reg,
3721 .rs2 = off_reg,
3722 .asi = asi,
3723 },
3724 },
3725 });
3726 },
3727 3, 5, 6, 7 => return self.fail("TODO: genLoad for more abi_sizes", .{}),
3728 else => unreachable,
3729 }
3730}
3731
3577fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {3732fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {
3578 switch (mcv) {3733 switch (mcv) {
3579 .dead => unreachable,3734 .dead => unreachable,
...@@ -3644,7 +3799,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3644,7 +3799,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3644 return self.genSetReg(ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa });3799 return self.genSetReg(ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa });
3645 },3800 },
3646 .ptr_stack_offset => |off| {3801 .ptr_stack_offset => |off| {
3647 const real_offset = off + abi.stack_bias + abi.stack_reserved_area;3802 const real_offset = realStackOffset(off);
3648 const simm13 = math.cast(i13, real_offset) orelse3803 const simm13 = math.cast(i13, real_offset) orelse
3649 return self.fail("TODO larger stack offsets: {}", .{real_offset});3804 return self.fail("TODO larger stack offsets: {}", .{real_offset});
36503805
...@@ -3776,7 +3931,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3776,7 +3931,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3776 try self.genLoad(reg, reg, i13, 0, ty.abiSize(self.target.*));3931 try self.genLoad(reg, reg, i13, 0, ty.abiSize(self.target.*));
3777 },3932 },
3778 .stack_offset => |off| {3933 .stack_offset => |off| {
3779 const real_offset = off + abi.stack_bias + abi.stack_reserved_area;3934 const real_offset = realStackOffset(off);
3780 const simm13 = math.cast(i13, real_offset) orelse3935 const simm13 = math.cast(i13, real_offset) orelse
3781 return self.fail("TODO larger stack offsets: {}", .{real_offset});3936 return self.fail("TODO larger stack offsets: {}", .{real_offset});
3782 try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(self.target.*));3937 try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(self.target.*));
...@@ -3810,7 +3965,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3810,7 +3965,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3810 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });3965 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
3811 },3966 },
3812 .register => |reg| {3967 .register => |reg| {
3813 const real_offset = stack_offset + abi.stack_bias + abi.stack_reserved_area;3968 const real_offset = realStackOffset(stack_offset);
3814 const simm13 = math.cast(i13, real_offset) orelse3969 const simm13 = math.cast(i13, real_offset) orelse
3815 return self.fail("TODO larger stack offsets: {}", .{real_offset});3970 return self.fail("TODO larger stack offsets: {}", .{real_offset});
3816 return self.genStore(reg, .sp, i13, simm13, abi_size);3971 return self.genStore(reg, .sp, i13, simm13, abi_size);
...@@ -3933,6 +4088,34 @@ fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_t...@@ -3933,6 +4088,34 @@ fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_t
3933 }4088 }
3934}4089}
39354090
4091fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Register, abi_size: u64, asi: ASI) !void {
4092 switch (abi_size) {
4093 1, 2, 4, 8 => {
4094 const tag: Mir.Inst.Tag = switch (abi_size) {
4095 1 => .stba,
4096 2 => .stha,
4097 4 => .stwa,
4098 8 => .stxa,
4099 else => unreachable, // unexpected abi size
4100 };
4101
4102 _ = try self.addInst(.{
4103 .tag = tag,
4104 .data = .{
4105 .mem_asi = .{
4106 .rd = value_reg,
4107 .rs1 = addr_reg,
4108 .rs2 = off_reg,
4109 .asi = asi,
4110 },
4111 },
4112 });
4113 },
4114 3, 5, 6, 7 => return self.fail("TODO: genLoad for more abi_sizes", .{}),
4115 else => unreachable,
4116 }
4117}
4118
3936fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {4119fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
3937 const mcv: MCValue = switch (try codegen.genTypedValue(4120 const mcv: MCValue = switch (try codegen.genTypedValue(
3938 self.bin_file,4121 self.bin_file,
...@@ -4245,6 +4428,17 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {...@@ -4245,6 +4428,17 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {
4245 }4428 }
4246}4429}
42474430
4431/// Turns stack_offset MCV into a real SPARCv9 stack offset usable for asm.
4432fn realStackOffset(off: u32) u32 {
4433 return off
4434 // SPARCv9 %sp points away from the stack by some amount.
4435 + abi.stack_bias
4436 // The first couple bytes of each stack frame is reserved
4437 // for ABI and hardware purposes.
4438 + abi.stack_reserved_area;
4439 // Only after that we have the usable stack frame portion.
4440}
4441
4248/// Caller must call `CallMCValues.deinit`.4442/// Caller must call `CallMCValues.deinit`.
4249fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {4443fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
4250 const cc = fn_ty.fnCallingConvention();4444 const cc = fn_ty.fnCallingConvention();
src/arch/sparc64/Emit.zig+33
...@@ -91,6 +91,11 @@ pub fn emitMir(...@@ -91,6 +91,11 @@ pub fn emitMir(
91 .lduw => try emit.mirArithmetic3Op(inst),91 .lduw => try emit.mirArithmetic3Op(inst),
92 .ldx => try emit.mirArithmetic3Op(inst),92 .ldx => try emit.mirArithmetic3Op(inst),
9393
94 .lduba => try emit.mirMemASI(inst),
95 .lduha => try emit.mirMemASI(inst),
96 .lduwa => try emit.mirMemASI(inst),
97 .ldxa => try emit.mirMemASI(inst),
98
94 .@"and" => try emit.mirArithmetic3Op(inst),99 .@"and" => try emit.mirArithmetic3Op(inst),
95 .@"or" => try emit.mirArithmetic3Op(inst),100 .@"or" => try emit.mirArithmetic3Op(inst),
96 .xor => try emit.mirArithmetic3Op(inst),101 .xor => try emit.mirArithmetic3Op(inst),
...@@ -127,6 +132,11 @@ pub fn emitMir(...@@ -127,6 +132,11 @@ pub fn emitMir(
127 .stw => try emit.mirArithmetic3Op(inst),132 .stw => try emit.mirArithmetic3Op(inst),
128 .stx => try emit.mirArithmetic3Op(inst),133 .stx => try emit.mirArithmetic3Op(inst),
129134
135 .stba => try emit.mirMemASI(inst),
136 .stha => try emit.mirMemASI(inst),
137 .stwa => try emit.mirMemASI(inst),
138 .stxa => try emit.mirMemASI(inst),
139
130 .sub => try emit.mirArithmetic3Op(inst),140 .sub => try emit.mirArithmetic3Op(inst),
131 .subcc => try emit.mirArithmetic3Op(inst),141 .subcc => try emit.mirArithmetic3Op(inst),
132142
...@@ -368,6 +378,29 @@ fn mirConditionalMove(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -368,6 +378,29 @@ fn mirConditionalMove(emit: *Emit, inst: Mir.Inst.Index) !void {
368 }378 }
369}379}
370380
381fn mirMemASI(emit: *Emit, inst: Mir.Inst.Index) !void {
382 const tag = emit.mir.instructions.items(.tag)[inst];
383 const data = emit.mir.instructions.items(.data)[inst].mem_asi;
384
385 const rd = data.rd;
386 const rs1 = data.rs1;
387 const rs2 = data.rs2;
388 const asi = data.asi;
389
390 switch (tag) {
391 .lduba => try emit.writeInstruction(Instruction.lduba(rs1, rs2, asi, rd)),
392 .lduha => try emit.writeInstruction(Instruction.lduha(rs1, rs2, asi, rd)),
393 .lduwa => try emit.writeInstruction(Instruction.lduwa(rs1, rs2, asi, rd)),
394 .ldxa => try emit.writeInstruction(Instruction.ldxa(rs1, rs2, asi, rd)),
395
396 .stba => try emit.writeInstruction(Instruction.stba(rs1, rs2, asi, rd)),
397 .stha => try emit.writeInstruction(Instruction.stha(rs1, rs2, asi, rd)),
398 .stwa => try emit.writeInstruction(Instruction.stwa(rs1, rs2, asi, rd)),
399 .stxa => try emit.writeInstruction(Instruction.stxa(rs1, rs2, asi, rd)),
400 else => unreachable,
401 }
402}
403
371fn mirMembar(emit: *Emit, inst: Mir.Inst.Index) !void {404fn mirMembar(emit: *Emit, inst: Mir.Inst.Index) !void {
372 const tag = emit.mir.instructions.items(.tag)[inst];405 const tag = emit.mir.instructions.items(.tag)[inst];
373 const mask = emit.mir.instructions.items(.data)[inst].membar_mask;406 const mask = emit.mir.instructions.items(.data)[inst].membar_mask;
src/arch/sparc64/Mir.zig+30
...@@ -15,6 +15,7 @@ const bits = @import("bits.zig");...@@ -15,6 +15,7 @@ const bits = @import("bits.zig");
15const Air = @import("../../Air.zig");15const Air = @import("../../Air.zig");
1616
17const Instruction = bits.Instruction;17const Instruction = bits.Instruction;
18const ASI = bits.Instruction.ASI;
18const Register = bits.Register;19const Register = bits.Register;
1920
20instructions: std.MultiArrayList(Inst).Slice,21instructions: std.MultiArrayList(Inst).Slice,
...@@ -70,6 +71,16 @@ pub const Inst = struct {...@@ -70,6 +71,16 @@ pub const Inst = struct {
70 lduw,71 lduw,
71 ldx,72 ldx,
7273
74 /// A.28 Load Integer from Alternate Space
75 /// This uses the mem_asi field.
76 /// Note that the ldda variant of this instruction is deprecated, so do not emit
77 /// it unless specifically requested (e.g. by inline assembly).
78 // TODO add other operations.
79 lduba,
80 lduha,
81 lduwa,
82 ldxa,
83
73 /// A.31 Logical Operations84 /// A.31 Logical Operations
74 /// This uses the arithmetic_3op field.85 /// This uses the arithmetic_3op field.
75 // TODO add other operations.86 // TODO add other operations.
...@@ -132,6 +143,16 @@ pub const Inst = struct {...@@ -132,6 +143,16 @@ pub const Inst = struct {
132 stw,143 stw,
133 stx,144 stx,
134145
146 /// A.55 Store Integer into Alternate Space
147 /// This uses the mem_asi field.
148 /// Note that the stda variant of this instruction is deprecated, so do not emit
149 /// it unless specifically requested (e.g. by inline assembly).
150 // TODO add other operations.
151 stba,
152 stha,
153 stwa,
154 stxa,
155
135 /// A.56 Subtract156 /// A.56 Subtract
136 /// This uses the arithmetic_3op field.157 /// This uses the arithmetic_3op field.
137 // TODO add other operations.158 // TODO add other operations.
...@@ -241,6 +262,15 @@ pub const Inst = struct {...@@ -241,6 +262,15 @@ pub const Inst = struct {
241 inst: Index,262 inst: Index,
242 },263 },
243264
265 /// ASI-tagged memory operations.
266 /// Used by e.g. ldxa, stxa
267 mem_asi: struct {
268 rd: Register,
269 rs1: Register,
270 rs2: Register = .g0,
271 asi: ASI,
272 },
273
244 /// Membar mask, controls the barrier behavior274 /// Membar mask, controls the barrier behavior
245 /// Used by e.g. membar275 /// Used by e.g. membar
246 membar_mask: struct {276 membar_mask: struct {
src/arch/sparc64/bits.zig+32
...@@ -1229,6 +1229,22 @@ pub const Instruction = union(enum) {...@@ -1229,6 +1229,22 @@ pub const Instruction = union(enum) {
1229 };1229 };
1230 }1230 }
12311231
1232 pub fn lduba(rs1: Register, rs2: Register, asi: ASI, rd: Register) Instruction {
1233 return format3i(0b11, 0b01_0001, rs1, rs2, rd, asi);
1234 }
1235
1236 pub fn lduha(rs1: Register, rs2: Register, asi: ASI, rd: Register) Instruction {
1237 return format3i(0b11, 0b01_0010, rs1, rs2, rd, asi);
1238 }
1239
1240 pub fn lduwa(rs1: Register, rs2: Register, asi: ASI, rd: Register) Instruction {
1241 return format3i(0b11, 0b01_0000, rs1, rs2, rd, asi);
1242 }
1243
1244 pub fn ldxa(rs1: Register, rs2: Register, asi: ASI, rd: Register) Instruction {
1245 return format3i(0b11, 0b01_1011, rs1, rs2, rd, asi);
1246 }
1247
1232 pub fn @"and"(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {1248 pub fn @"and"(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1233 return switch (s2) {1249 return switch (s2) {
1234 Register => format3a(0b10, 0b00_0001, rs1, rs2, rd),1250 Register => format3a(0b10, 0b00_0001, rs1, rs2, rd),
...@@ -1417,6 +1433,22 @@ pub const Instruction = union(enum) {...@@ -1417,6 +1433,22 @@ pub const Instruction = union(enum) {
1417 };1433 };
1418 }1434 }
14191435
1436 pub fn stba(rs1: Register, rs2: Register, asi: ASI, rd: Register) Instruction {
1437 return format3i(0b11, 0b01_0101, rs1, rs2, rd, asi);
1438 }
1439
1440 pub fn stha(rs1: Register, rs2: Register, asi: ASI, rd: Register) Instruction {
1441 return format3i(0b11, 0b01_0110, rs1, rs2, rd, asi);
1442 }
1443
1444 pub fn stwa(rs1: Register, rs2: Register, asi: ASI, rd: Register) Instruction {
1445 return format3i(0b11, 0b01_0100, rs1, rs2, rd, asi);
1446 }
1447
1448 pub fn stxa(rs1: Register, rs2: Register, asi: ASI, rd: Register) Instruction {
1449 return format3i(0b11, 0b01_1110, rs1, rs2, rd, asi);
1450 }
1451
1420 pub fn sub(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {1452 pub fn sub(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1421 return switch (s2) {1453 return switch (s2) {
1422 Register => format3a(0b10, 0b00_0100, rs1, rs2, rd),1454 Register => format3a(0b10, 0b00_0100, rs1, rs2, rd),
test/behavior/array.zig+4
...@@ -47,6 +47,7 @@ fn getArrayLen(a: []const u32) usize {...@@ -47,6 +47,7 @@ fn getArrayLen(a: []const u32) usize {
4747
48test "array concat with undefined" {48test "array concat with undefined" {
49 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO49 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5051
51 const S = struct {52 const S = struct {
52 fn doTheTest() !void {53 fn doTheTest() !void {
...@@ -70,6 +71,7 @@ test "array concat with undefined" {...@@ -70,6 +71,7 @@ test "array concat with undefined" {
70test "array concat with tuple" {71test "array concat with tuple" {
71 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO72 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO73 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
74 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7375
74 const array: [2]u8 = .{ 1, 2 };76 const array: [2]u8 = .{ 1, 2 };
75 {77 {
...@@ -103,6 +105,7 @@ test "array init with mult" {...@@ -103,6 +105,7 @@ test "array init with mult" {
103105
104test "array literal with explicit type" {106test "array literal with explicit type" {
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 const hex_mult: [4]u16 = .{ 4096, 256, 16, 1 };110 const hex_mult: [4]u16 = .{ 4096, 256, 16, 1 };
108111
...@@ -203,6 +206,7 @@ test "nested arrays of strings" {...@@ -203,6 +206,7 @@ test "nested arrays of strings" {
203206
204test "nested arrays of integers" {207test "nested arrays of integers" {
205 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO208 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
209 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
206210
207 const array_of_numbers = [_][2]u8{211 const array_of_numbers = [_][2]u8{
208 [2]u8{ 1, 2 },212 [2]u8{ 1, 2 },
test/behavior/bugs/12051.zig+1
...@@ -6,6 +6,7 @@ test {...@@ -6,6 +6,7 @@ test {
6 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 const x = X{};10 const x = X{};
10 try std.testing.expectEqual(@as(u16, 0), x.y.a);11 try std.testing.expectEqual(@as(u16, 0), x.y.a);
11 try std.testing.expectEqual(false, x.y.b);12 try std.testing.expectEqual(false, x.y.b);
test/behavior/bugs/12450.zig+1
...@@ -13,6 +13,7 @@ test {...@@ -13,6 +13,7 @@ test {
13 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO13 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16 var f1: *align(16) Foo = @alignCast(16, @ptrCast(*align(1) Foo, &buffer[0]));17 var f1: *align(16) Foo = @alignCast(16, @ptrCast(*align(1) Foo, &buffer[0]));
17 try expect(@typeInfo(@TypeOf(f1)).Pointer.alignment == 16);18 try expect(@typeInfo(@TypeOf(f1)).Pointer.alignment == 16);
18 try expect(@ptrToInt(f1) == @ptrToInt(&f1.a));19 try expect(@ptrToInt(f1) == @ptrToInt(&f1.a));
test/behavior/comptime_memory.zig+3
...@@ -76,6 +76,7 @@ fn bigToNativeEndian(comptime T: type, v: T) T {...@@ -76,6 +76,7 @@ fn bigToNativeEndian(comptime T: type, v: T) T {
76}76}
77test "type pun endianness" {77test "type pun endianness" {
78 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
79 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7980
80 comptime {81 comptime {
81 const StructOfBytes = extern struct { x: [4]u8 };82 const StructOfBytes = extern struct { x: [4]u8 };
...@@ -376,6 +377,8 @@ test "offset field ptr by enclosing array element size" {...@@ -376,6 +377,8 @@ test "offset field ptr by enclosing array element size" {
376377
377test "accessing reinterpreted memory of parent object" {378test "accessing reinterpreted memory of parent object" {
378 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO379 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
380 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
381
379 const S = extern struct {382 const S = extern struct {
380 a: f32,383 a: f32,
381 b: [4]u8,384 b: [4]u8,
test/behavior/packed-struct.zig+3-1
...@@ -563,7 +563,7 @@ test "packed struct passed to callconv(.C) function" {...@@ -563,7 +563,7 @@ test "packed struct passed to callconv(.C) function" {
563test "overaligned pointer to packed struct" {563test "overaligned pointer to packed struct" {
564 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;564 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
565 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;565 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
566566 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
567 const S = packed struct { a: u32, b: u32 };567 const S = packed struct { a: u32, b: u32 };
568 var foo: S align(4) = .{ .a = 123, .b = 456 };568 var foo: S align(4) = .{ .a = 123, .b = 456 };
569 const ptr: *align(4) S = &foo;569 const ptr: *align(4) S = &foo;
...@@ -583,6 +583,7 @@ test "overaligned pointer to packed struct" {...@@ -583,6 +583,7 @@ test "overaligned pointer to packed struct" {
583test "packed struct initialized in bitcast" {583test "packed struct initialized in bitcast" {
584 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO584 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
585 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO585 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
586 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
586587
587 const T = packed struct { val: u8 };588 const T = packed struct { val: u8 };
588 var val: u8 = 123;589 var val: u8 = 123;
...@@ -595,6 +596,7 @@ test "pointer to container level packed struct field" {...@@ -595,6 +596,7 @@ test "pointer to container level packed struct field" {
595 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;596 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
596 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;597 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
597 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;598 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
599 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
598600
599 const S = packed struct(u32) {601 const S = packed struct(u32) {
600 test_bit: bool,602 test_bit: bool,
test/behavior/ptrcast.zig+10
...@@ -4,6 +4,8 @@ const expect = std.testing.expect;...@@ -4,6 +4,8 @@ const expect = std.testing.expect;
4const native_endian = builtin.target.cpu.arch.endian();4const native_endian = builtin.target.cpu.arch.endian();
55
6test "reinterpret bytes as integer with nonzero offset" {6test "reinterpret bytes as integer with nonzero offset" {
7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8
7 try testReinterpretBytesAsInteger();9 try testReinterpretBytesAsInteger();
8 comptime try testReinterpretBytesAsInteger();10 comptime try testReinterpretBytesAsInteger();
9}11}
...@@ -74,6 +76,8 @@ fn testReinterpretBytesAsExternStruct() !void {...@@ -74,6 +76,8 @@ fn testReinterpretBytesAsExternStruct() !void {
74}76}
7577
76test "reinterpret bytes of an extern struct (with under-aligned fields) into another" {78test "reinterpret bytes of an extern struct (with under-aligned fields) into another" {
79 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
80
77 try testReinterpretExternStructAsExternStruct();81 try testReinterpretExternStructAsExternStruct();
78 comptime try testReinterpretExternStructAsExternStruct();82 comptime try testReinterpretExternStructAsExternStruct();
79}83}
...@@ -96,6 +100,8 @@ fn testReinterpretExternStructAsExternStruct() !void {...@@ -96,6 +100,8 @@ fn testReinterpretExternStructAsExternStruct() !void {
96}100}
97101
98test "reinterpret bytes of an extern struct into another" {102test "reinterpret bytes of an extern struct into another" {
103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
104
99 try testReinterpretOverAlignedExternStructAsExternStruct();105 try testReinterpretOverAlignedExternStructAsExternStruct();
100 comptime try testReinterpretOverAlignedExternStructAsExternStruct();106 comptime try testReinterpretOverAlignedExternStructAsExternStruct();
101}107}
...@@ -191,6 +197,8 @@ const Bytes = struct {...@@ -191,6 +197,8 @@ const Bytes = struct {
191};197};
192198
193test "comptime ptrcast keeps larger alignment" {199test "comptime ptrcast keeps larger alignment" {
200 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
201
194 comptime {202 comptime {
195 const a: u32 = 1234;203 const a: u32 = 1234;
196 const p = @ptrCast([*]const u8, &a);204 const p = @ptrCast([*]const u8, &a);
...@@ -199,6 +207,8 @@ test "comptime ptrcast keeps larger alignment" {...@@ -199,6 +207,8 @@ test "comptime ptrcast keeps larger alignment" {
199}207}
200208
201test "ptrcast of const integer has the correct object size" {209test "ptrcast of const integer has the correct object size" {
210 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
211
202 const is_value = ~@intCast(isize, std.math.minInt(isize));212 const is_value = ~@intCast(isize, std.math.minInt(isize));
203 const is_bytes = @ptrCast([*]const u8, &is_value)[0..@sizeOf(isize)];213 const is_bytes = @ptrCast([*]const u8, &is_value)[0..@sizeOf(isize)];
204 if (@sizeOf(isize) == 8) {214 if (@sizeOf(isize) == 8) {
test/behavior/tuple.zig+5
...@@ -296,6 +296,7 @@ test "coerce tuple to tuple" {...@@ -296,6 +296,7 @@ test "coerce tuple to tuple" {
296test "tuple type with void field" {296test "tuple type with void field" {
297 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO297 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
298 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO298 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
299 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
299300
300 const T = std.meta.Tuple(&[_]type{void});301 const T = std.meta.Tuple(&[_]type{void});
301 const x = T{{}};302 const x = T{{}};
...@@ -341,6 +342,7 @@ test "tuple type with void field and a runtime field" {...@@ -341,6 +342,7 @@ test "tuple type with void field and a runtime field" {
341test "branching inside tuple literal" {342test "branching inside tuple literal" {
342 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO343 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
343 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO344 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
345 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
344346
345 const S = struct {347 const S = struct {
346 fn foo(a: anytype) !void {348 fn foo(a: anytype) !void {
...@@ -355,6 +357,7 @@ test "tuple initialized with a runtime known value" {...@@ -355,6 +357,7 @@ test "tuple initialized with a runtime known value" {
355 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;357 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
356 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;358 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
357 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;359 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
360 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
358361
359 const E = union(enum) { e: []const u8 };362 const E = union(enum) { e: []const u8 };
360 const W = union(enum) { w: E };363 const W = union(enum) { w: E };
...@@ -368,6 +371,7 @@ test "tuple of struct concatenation and coercion to array" {...@@ -368,6 +371,7 @@ test "tuple of struct concatenation and coercion to array" {
368 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;371 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
369 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;372 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
370 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;373 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
374 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
371375
372 const StructWithDefault = struct { value: f32 = 42 };376 const StructWithDefault = struct { value: f32 = 42 };
373 const SomeStruct = struct { array: [4]StructWithDefault };377 const SomeStruct = struct { array: [4]StructWithDefault };
...@@ -381,6 +385,7 @@ test "tuple of struct concatenation and coercion to array" {...@@ -381,6 +385,7 @@ test "tuple of struct concatenation and coercion to array" {
381test "nested runtime conditionals in tuple initializer" {385test "nested runtime conditionals in tuple initializer" {
382 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO386 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
383 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO387 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
388 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
384389
385 var data: u8 = 0;390 var data: u8 = 0;
386 const x = .{391 const x = .{
test/behavior/union.zig+1
...@@ -1495,6 +1495,7 @@ test "packed union with zero-bit field" {...@@ -1495,6 +1495,7 @@ test "packed union with zero-bit field" {
1495 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1495 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1496 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1496 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1497 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1497 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1498 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14981499
1499 const S = packed struct {1500 const S = packed struct {
1500 nested: packed union {1501 nested: packed union {
test/behavior/var_args.zig+2
...@@ -95,6 +95,7 @@ fn doNothingWithFirstArg(args: anytype) void {...@@ -95,6 +95,7 @@ fn doNothingWithFirstArg(args: anytype) void {
9595
96test "simple variadic function" {96test "simple variadic function" {
97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
98 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
98 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO99 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO100 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
100 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO101 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -143,6 +144,7 @@ test "simple variadic function" {...@@ -143,6 +144,7 @@ test "simple variadic function" {
143144
144test "variadic functions" {145test "variadic functions" {
145 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO146 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
147 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO148 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
147 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO149 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
148 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO150 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
test/behavior/vector.zig+1
...@@ -1282,6 +1282,7 @@ test "store to vector in slice" {...@@ -1282,6 +1282,7 @@ test "store to vector in slice" {
1282 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1282 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1283 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1283 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1284 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1284 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1285 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12851286
1286 var v = [_]@Vector(3, f32){1287 var v = [_]@Vector(3, f32){
1287 .{ 1, 1, 1 },1288 .{ 1, 1, 1 },