authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-18 22:23:58+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-01-18 22:23:58+01:00
loge80ebc6740d6bbe4b9b1958180a337804ff98450
tree7a4be1449a4fe3a69953d8319b82f33f376e75cc
parent305a7def136580e7a05652a95c1d2ff338541607
parent8201939d7f57d5332d209dd7fb728eafe5a8b882
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10625 from ziglang/stage2-x86_64-inline-memset

stage2: add inline memset, partial intcast and more array goodness for x86_64

7 files changed, 327 insertions(+), 71 deletions(-)

src/arch/x86_64/CodeGen.zig+206-59
...@@ -876,10 +876,26 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -876,10 +876,26 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
876 if (info_a.signedness != info_b.signedness)876 if (info_a.signedness != info_b.signedness)
877 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});877 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});
878878
879 if (info_a.bits == info_b.bits)879 const operand_abi_size = operand_ty.abiSize(self.target.*);
880 return self.finishAir(inst, operand, .{ ty_op.operand, .none, .none });880 const dest_ty = self.air.typeOfIndex(inst);
881 const dest_abi_size = dest_ty.abiSize(self.target.*);
882 const dst_mcv: MCValue = blk: {
883 if (info_a.bits == info_b.bits) {
884 break :blk operand;
885 }
886 if (operand_abi_size > 8 or dest_abi_size > 8) {
887 return self.fail("TODO implement intCast for abi sizes larger than 8", .{});
888 }
889 const reg = switch (operand) {
890 .register => |src_reg| try self.register_manager.allocReg(inst, &.{src_reg}),
891 else => try self.register_manager.allocReg(inst, &.{}),
892 };
893 try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });
894 try self.genSetReg(dest_ty, reg, operand);
895 break :blk .{ .register = registerAlias(reg, @intCast(u32, dest_abi_size)) };
896 };
881897
882 return self.fail("TODO implement intCast for {}", .{self.target.cpu.arch});898 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
883}899}
884900
885fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {901fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
...@@ -1312,59 +1328,49 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1312,59 +1328,49 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
1312 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1328 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1313}1329}
13141330
1331fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Register {
1332 const reg = try self.register_manager.allocReg(null, &.{});
1333 try self.genSetReg(index_ty, reg, index);
1334 try self.genIMulOpMir(index_ty, .{ .register = reg }, .{ .immediate = elem_size });
1335 return reg;
1336}
1337
1315fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {1338fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1316 const is_volatile = false; // TODO1339 const is_volatile = false; // TODO
1317 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1340 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1318 const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: {1341 const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: {
1319 const slice_mcv = try self.resolveInst(bin_op.lhs);1342 const slice_mcv = try self.resolveInst(bin_op.lhs);
1320 const slice_ty = self.air.typeOf(bin_op.lhs);1343 const slice_ty = self.air.typeOf(bin_op.lhs);
1321
1322 const elem_ty = slice_ty.childType();1344 const elem_ty = slice_ty.childType();
1323 const elem_size = elem_ty.abiSize(self.target.*);1345 const elem_size = elem_ty.abiSize(self.target.*);
1324
1325 var buf: Type.SlicePtrFieldTypeBuffer = undefined;1346 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1326 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);1347 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
13271348 const index_ty = self.air.typeOf(bin_op.rhs);
1328 const offset_reg = blk: {1349 const index_mcv = try self.resolveInst(bin_op.rhs);
1329 const index_ty = self.air.typeOf(bin_op.rhs);1350 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_size);
1330 const index_mcv = try self.resolveInst(bin_op.rhs);1351 const addr_reg = try self.register_manager.allocReg(null, &.{offset_reg});
1331 const offset_reg = try self.register_manager.allocReg(null, &.{});1352 switch (slice_mcv) {
1332 try self.genSetReg(index_ty, offset_reg, index_mcv);1353 .stack_offset => |off| {
1333 try self.genIMulOpMir(index_ty, .{ .register = offset_reg }, .{ .immediate = elem_size });1354 // mov reg, [rbp - 8]
1334 break :blk offset_reg;1355 _ = try self.addInst(.{
1335 };1356 .tag = .mov,
13361357 .ops = (Mir.Ops{
1337 const dst_mcv = blk: {1358 .reg1 = addr_reg.to64(),
1338 switch (slice_mcv) {1359 .reg2 = .rbp,
1339 .stack_offset => |off| {1360 .flags = 0b01,
1340 const dst_mcv = try self.allocRegOrMem(inst, false);1361 }).encode(),
1341 const addr_reg = try self.register_manager.allocReg(null, &.{offset_reg});1362 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + 16)) },
1342 // mov reg, [rbp - 8]1363 });
1343 _ = try self.addInst(.{1364 },
1344 .tag = .mov,1365 else => return self.fail("TODO implement slice_elem_val when slice is {}", .{slice_mcv}),
1345 .ops = (Mir.Ops{1366 }
1346 .reg1 = addr_reg.to64(),1367 // TODO we could allocate register here, but need to except addr register and potentially
1347 .reg2 = .rbp,1368 // offset register.
1348 .flags = 0b01,1369 const dst_mcv = try self.allocRegOrMem(inst, false);
1349 }).encode(),1370 try self.genBinMathOpMir(.add, slice_ptr_field_type, .unsigned, .{ .register = addr_reg.to64() }, .{
1350 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + 16)) },1371 .register = offset_reg.to64(),
1351 });1372 });
1352 // add addr, offset1373 try self.load(dst_mcv, .{ .register = addr_reg.to64() }, slice_ptr_field_type);
1353 _ = try self.addInst(.{
1354 .tag = .add,
1355 .ops = (Mir.Ops{
1356 .reg1 = addr_reg.to64(),
1357 .reg2 = offset_reg.to64(),
1358 }).encode(),
1359 .data = undefined,
1360 });
1361 try self.load(dst_mcv, .{ .register = addr_reg }, slice_ptr_field_type);
1362 break :blk dst_mcv;
1363 },
1364 else => return self.fail("TODO implement slice_elem_val when slice is {}", .{slice_mcv}),
1365 }
1366 };
1367
1368 break :result dst_mcv;1374 break :result dst_mcv;
1369 };1375 };
1370 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1376 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
...@@ -1382,10 +1388,43 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1382,10 +1388,43 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
13821388
1383fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {1389fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
1384 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1390 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1385 const result: MCValue = if (self.liveness.isUnused(inst))1391 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1386 .dead1392 const array_ty = self.air.typeOf(bin_op.lhs);
1387 else1393 const array = try self.resolveInst(bin_op.lhs);
1388 return self.fail("TODO implement array_elem_val for {}", .{self.target.cpu.arch});1394 const array_abi_size = array_ty.abiSize(self.target.*);
1395 const elem_ty = array_ty.childType();
1396 const elem_abi_size = elem_ty.abiSize(self.target.*);
1397 const index_ty = self.air.typeOf(bin_op.rhs);
1398 const index = try self.resolveInst(bin_op.rhs);
1399 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
1400 const addr_reg = try self.register_manager.allocReg(null, &.{offset_reg});
1401 switch (array) {
1402 .stack_offset => |off| {
1403 // lea reg, [rbp]
1404 _ = try self.addInst(.{
1405 .tag = .lea,
1406 .ops = (Mir.Ops{
1407 .reg1 = addr_reg.to64(),
1408 .reg2 = .rbp,
1409 }).encode(),
1410 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + array_abi_size)) },
1411 });
1412 },
1413 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
1414 }
1415 // TODO we could allocate register here, but need to except addr register and potentially
1416 // offset register.
1417 const dst_mcv = try self.allocRegOrMem(inst, false);
1418 try self.genBinMathOpMir(
1419 .add,
1420 array_ty,
1421 .unsigned,
1422 .{ .register = addr_reg.to64() },
1423 .{ .register = offset_reg.to64() },
1424 );
1425 try self.load(dst_mcv, .{ .register = addr_reg.to64() }, array_ty);
1426 break :result dst_mcv;
1427 };
1389 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1428 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1390}1429}
13911430
...@@ -1402,10 +1441,27 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1402,10 +1441,27 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
1402fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {1441fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
1403 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1442 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1404 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;1443 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
1405 const result: MCValue = if (self.liveness.isUnused(inst))1444 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1406 .dead1445 const ptr_ty = self.air.typeOf(extra.lhs);
1407 else1446 const ptr = try self.resolveInst(extra.lhs);
1408 return self.fail("TODO implement ptr_elem_ptr for {}", .{self.target.cpu.arch});1447 const elem_ty = ptr_ty.elemType2();
1448 const elem_abi_size = elem_ty.abiSize(self.target.*);
1449 const index_ty = self.air.typeOf(extra.rhs);
1450 const index = try self.resolveInst(extra.rhs);
1451 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
1452 const dst_mcv = blk: {
1453 switch (ptr) {
1454 .ptr_stack_offset => {
1455 const reg = try self.register_manager.allocReg(inst, &.{offset_reg});
1456 try self.genSetReg(ptr_ty, reg, ptr);
1457 break :blk .{ .register = reg };
1458 },
1459 else => return self.fail("TODO implement ptr_elem_ptr when ptr is {}", .{ptr}),
1460 }
1461 };
1462 try self.genBinMathOpMir(.add, ptr_ty, .unsigned, dst_mcv, .{ .register = offset_reg });
1463 break :result dst_mcv;
1464 };
1409 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });1465 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
1410}1466}
14111467
...@@ -3147,7 +3203,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3147,7 +3203,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3147 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),3203 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
3148 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),3204 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
3149 8 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }),3205 8 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }),
3150 else => return self.fail("TODO implement memset", .{}),3206 else => return self.genInlineMemset(ty, stack_offset, .{ .immediate = 0xaa }),
3151 }3207 }
3152 },3208 },
3153 .compare_flags_unsigned => |op| {3209 .compare_flags_unsigned => |op| {
...@@ -3397,6 +3453,97 @@ fn genInlineMemcpy(...@@ -3397,6 +3453,97 @@ fn genInlineMemcpy(
3397 try self.performReloc(loop_reloc);3453 try self.performReloc(loop_reloc);
3398}3454}
33993455
3456fn genInlineMemset(self: *Self, ty: Type, stack_offset: u32, value: MCValue) InnerError!void {
3457 try self.register_manager.getReg(.rax, null);
3458 const abi_size = ty.abiSize(self.target.*);
3459 const adj_off = stack_offset + abi_size;
3460 if (adj_off > 128) {
3461 return self.fail("TODO inline memset with large stack offset", .{});
3462 }
3463 const negative_offset = @bitCast(u32, -@intCast(i32, adj_off));
3464
3465 // We are actually counting `abi_size` bytes; however, we reuse the index register
3466 // as both the counter and offset scaler, hence we need to subtract one from `abi_size`
3467 // and count until -1.
3468 if (abi_size > math.maxInt(i32)) {
3469 // movabs rax, abi_size - 1
3470 const payload = try self.addExtra(Mir.Imm64.encode(abi_size - 1));
3471 _ = try self.addInst(.{
3472 .tag = .movabs,
3473 .ops = (Mir.Ops{
3474 .reg1 = .rax,
3475 }).encode(),
3476 .data = .{ .payload = payload },
3477 });
3478 } else {
3479 // mov rax, abi_size - 1
3480 _ = try self.addInst(.{
3481 .tag = .mov,
3482 .ops = (Mir.Ops{
3483 .reg1 = .rax,
3484 }).encode(),
3485 .data = .{ .imm = @truncate(u32, abi_size - 1) },
3486 });
3487 }
3488
3489 // loop:
3490 // cmp rax, -1
3491 const loop_start = try self.addInst(.{
3492 .tag = .cmp,
3493 .ops = (Mir.Ops{
3494 .reg1 = .rax,
3495 }).encode(),
3496 .data = .{ .imm = @bitCast(u32, @as(i32, -1)) },
3497 });
3498
3499 // je end
3500 const loop_reloc = try self.addInst(.{
3501 .tag = .cond_jmp_eq_ne,
3502 .ops = (Mir.Ops{ .flags = 0b01 }).encode(),
3503 .data = .{ .inst = undefined },
3504 });
3505
3506 switch (value) {
3507 .immediate => |x| {
3508 if (x > math.maxInt(i32)) {
3509 return self.fail("TODO inline memset for value immediate larger than 32bits", .{});
3510 }
3511 // mov byte ptr [rbp + rax + stack_offset], imm
3512 const payload = try self.addExtra(Mir.ImmPair{
3513 .dest_off = negative_offset,
3514 .operand = @truncate(u32, x),
3515 });
3516 _ = try self.addInst(.{
3517 .tag = .mov_mem_index_imm,
3518 .ops = (Mir.Ops{
3519 .reg1 = .rbp,
3520 }).encode(),
3521 .data = .{ .payload = payload },
3522 });
3523 },
3524 else => return self.fail("TODO inline memset for value of type {}", .{value}),
3525 }
3526
3527 // sub rax, 1
3528 _ = try self.addInst(.{
3529 .tag = .sub,
3530 .ops = (Mir.Ops{
3531 .reg1 = .rax,
3532 }).encode(),
3533 .data = .{ .imm = 1 },
3534 });
3535
3536 // jmp loop
3537 _ = try self.addInst(.{
3538 .tag = .jmp,
3539 .ops = (Mir.Ops{ .flags = 0b00 }).encode(),
3540 .data = .{ .inst = loop_start },
3541 });
3542
3543 // end:
3544 try self.performReloc(loop_reloc);
3545}
3546
3400fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {3547fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {
3401 switch (mcv) {3548 switch (mcv) {
3402 .dead => unreachable,3549 .dead => unreachable,
...@@ -3634,12 +3781,12 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -3634,12 +3781,12 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
3634 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3781 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3635 const ptr_ty = self.air.typeOf(ty_op.operand);3782 const ptr_ty = self.air.typeOf(ty_op.operand);
3636 const ptr = try self.resolveInst(ty_op.operand);3783 const ptr = try self.resolveInst(ty_op.operand);
3784 const array_ty = ptr_ty.childType();
3785 const array_len = array_ty.arrayLenIncludingSentinel();
3637 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {3786 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
3638 const stack_offset = try self.allocMem(inst, 16, 16);3787 const stack_offset = try self.allocMem(inst, 16, 16);
3639 const array_ty = ptr_ty.childType();3788 try self.genSetStack(ptr_ty, stack_offset + 8, ptr);
3640 const array_len = array_ty.arrayLenIncludingSentinel();3789 try self.genSetStack(Type.initTag(.u64), stack_offset, .{ .immediate = array_len });
3641 try self.genSetStack(Type.initTag(.usize), stack_offset + 8, ptr);
3642 try self.genSetStack(Type.initTag(.u64), stack_offset + 16, .{ .immediate = array_len });
3643 break :blk .{ .stack_offset = stack_offset };3790 break :blk .{ .stack_offset = stack_offset };
3644 };3791 };
3645 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3792 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
src/arch/x86_64/Emit.zig+34-1
...@@ -115,6 +115,16 @@ pub fn lowerMir(emit: *Emit) InnerError!void {...@@ -115,6 +115,16 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
115 .cmp_scale_imm => try emit.mirArithScaleImm(.cmp, inst),115 .cmp_scale_imm => try emit.mirArithScaleImm(.cmp, inst),
116 .mov_scale_imm => try emit.mirArithScaleImm(.mov, inst),116 .mov_scale_imm => try emit.mirArithScaleImm(.mov, inst),
117117
118 .adc_mem_index_imm => try emit.mirArithMemIndexImm(.adc, inst),
119 .add_mem_index_imm => try emit.mirArithMemIndexImm(.add, inst),
120 .sub_mem_index_imm => try emit.mirArithMemIndexImm(.sub, inst),
121 .xor_mem_index_imm => try emit.mirArithMemIndexImm(.xor, inst),
122 .and_mem_index_imm => try emit.mirArithMemIndexImm(.@"and", inst),
123 .or_mem_index_imm => try emit.mirArithMemIndexImm(.@"or", inst),
124 .sbb_mem_index_imm => try emit.mirArithMemIndexImm(.sbb, inst),
125 .cmp_mem_index_imm => try emit.mirArithMemIndexImm(.cmp, inst),
126 .mov_mem_index_imm => try emit.mirArithMemIndexImm(.mov, inst),
127
118 .movabs => try emit.mirMovabs(inst),128 .movabs => try emit.mirMovabs(inst),
119129
120 .lea => try emit.mirLea(inst),130 .lea => try emit.mirLea(inst),
...@@ -549,6 +559,29 @@ fn mirArithScaleImm(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void...@@ -549,6 +559,29 @@ fn mirArithScaleImm(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void
549 }), imm_pair.operand, emit.code) catch |err| emit.failWithLoweringError(err);559 }), imm_pair.operand, emit.code) catch |err| emit.failWithLoweringError(err);
550}560}
551561
562fn mirArithMemIndexImm(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
563 const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
564 assert(ops.reg2 == .none);
565 const payload = emit.mir.instructions.items(.data)[inst].payload;
566 const imm_pair = emit.mir.extraData(Mir.ImmPair, payload).data;
567 const ptr_size: Memory.PtrSize = switch (ops.flags) {
568 0b00 => .byte_ptr,
569 0b01 => .word_ptr,
570 0b10 => .dword_ptr,
571 0b11 => .qword_ptr,
572 };
573 const scale_index = ScaleIndex{
574 .scale = 0,
575 .index = .rax,
576 };
577 // OP ptr [reg1 + rax*1 + imm32], imm32
578 return lowerToMiEnc(tag, RegisterOrMemory.mem(ptr_size, .{
579 .disp = imm_pair.dest_off,
580 .base = ops.reg1,
581 .scale_index = scale_index,
582 }), imm_pair.operand, emit.code) catch |err| emit.failWithLoweringError(err);
583}
584
552fn mirMovabs(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {585fn mirMovabs(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
553 const tag = emit.mir.instructions.items(.tag)[inst];586 const tag = emit.mir.instructions.items(.tag)[inst];
554 assert(tag == .movabs);587 assert(tag == .movabs);
...@@ -1287,7 +1320,7 @@ const Memory = struct {...@@ -1287,7 +1320,7 @@ const Memory = struct {
1287 encoder.disp32(@bitCast(i32, mem_op.disp));1320 encoder.disp32(@bitCast(i32, mem_op.disp));
1288 }1321 }
1289 } else {1322 } else {
1290 if (mem_op.disp == 0) {1323 if (mem_op.disp == 0 and dst != 5) {
1291 encoder.modRm_indirectDisp0(src, dst);1324 encoder.modRm_indirectDisp0(src, dst);
1292 } else if (immOpSize(mem_op.disp) == 8) {1325 } else if (immOpSize(mem_op.disp) == 8) {
1293 encoder.modRm_indirectDisp8(src, dst);1326 encoder.modRm_indirectDisp8(src, dst);
src/arch/x86_64/Mir.zig+23
...@@ -79,6 +79,13 @@ pub const Inst = struct {...@@ -79,6 +79,13 @@ pub const Inst = struct {
79 /// * Data field `payload` points at `ImmPair`.79 /// * Data field `payload` points at `ImmPair`.
80 adc_scale_imm,80 adc_scale_imm,
8181
82 /// ops flags: form:
83 /// 0b00 byte ptr [reg1 + rax + imm32], imm8
84 /// 0b01 word ptr [reg1 + rax + imm32], imm16
85 /// 0b10 dword ptr [reg1 + rax + imm32], imm32
86 /// 0b11 qword ptr [reg1 + rax + imm32], imm32 (sign-extended to imm64)
87 adc_mem_index_imm,
88
82 // The following instructions all have the same encoding as `adc`.89 // The following instructions all have the same encoding as `adc`.
8390
84 add,91 add,
...@@ -86,81 +93,97 @@ pub const Inst = struct {...@@ -86,81 +93,97 @@ pub const Inst = struct {
86 add_scale_src,93 add_scale_src,
87 add_scale_dst,94 add_scale_dst,
88 add_scale_imm,95 add_scale_imm,
96 add_mem_index_imm,
89 sub,97 sub,
90 sub_mem_imm,98 sub_mem_imm,
91 sub_scale_src,99 sub_scale_src,
92 sub_scale_dst,100 sub_scale_dst,
93 sub_scale_imm,101 sub_scale_imm,
102 sub_mem_index_imm,
94 xor,103 xor,
95 xor_mem_imm,104 xor_mem_imm,
96 xor_scale_src,105 xor_scale_src,
97 xor_scale_dst,106 xor_scale_dst,
98 xor_scale_imm,107 xor_scale_imm,
108 xor_mem_index_imm,
99 @"and",109 @"and",
100 and_mem_imm,110 and_mem_imm,
101 and_scale_src,111 and_scale_src,
102 and_scale_dst,112 and_scale_dst,
103 and_scale_imm,113 and_scale_imm,
114 and_mem_index_imm,
104 @"or",115 @"or",
105 or_mem_imm,116 or_mem_imm,
106 or_scale_src,117 or_scale_src,
107 or_scale_dst,118 or_scale_dst,
108 or_scale_imm,119 or_scale_imm,
120 or_mem_index_imm,
109 rol,121 rol,
110 rol_mem_imm,122 rol_mem_imm,
111 rol_scale_src,123 rol_scale_src,
112 rol_scale_dst,124 rol_scale_dst,
113 rol_scale_imm,125 rol_scale_imm,
126 rol_mem_index_imm,
114 ror,127 ror,
115 ror_mem_imm,128 ror_mem_imm,
116 ror_scale_src,129 ror_scale_src,
117 ror_scale_dst,130 ror_scale_dst,
118 ror_scale_imm,131 ror_scale_imm,
132 ror_mem_index_imm,
119 rcl,133 rcl,
120 rcl_mem_imm,134 rcl_mem_imm,
121 rcl_scale_src,135 rcl_scale_src,
122 rcl_scale_dst,136 rcl_scale_dst,
123 rcl_scale_imm,137 rcl_scale_imm,
138 rcl_mem_index_imm,
124 rcr,139 rcr,
125 rcr_mem_imm,140 rcr_mem_imm,
126 rcr_scale_src,141 rcr_scale_src,
127 rcr_scale_dst,142 rcr_scale_dst,
128 rcr_scale_imm,143 rcr_scale_imm,
144 rcr_mem_index_imm,
129 shl,145 shl,
130 shl_mem_imm,146 shl_mem_imm,
131 shl_scale_src,147 shl_scale_src,
132 shl_scale_dst,148 shl_scale_dst,
133 shl_scale_imm,149 shl_scale_imm,
150 shl_mem_index_imm,
134 sal,151 sal,
135 sal_mem_imm,152 sal_mem_imm,
136 sal_scale_src,153 sal_scale_src,
137 sal_scale_dst,154 sal_scale_dst,
138 sal_scale_imm,155 sal_scale_imm,
156 sal_mem_index_imm,
139 shr,157 shr,
140 shr_mem_imm,158 shr_mem_imm,
141 shr_scale_src,159 shr_scale_src,
142 shr_scale_dst,160 shr_scale_dst,
143 shr_scale_imm,161 shr_scale_imm,
162 shr_mem_index_imm,
144 sar,163 sar,
145 sar_mem_imm,164 sar_mem_imm,
146 sar_scale_src,165 sar_scale_src,
147 sar_scale_dst,166 sar_scale_dst,
148 sar_scale_imm,167 sar_scale_imm,
168 sar_mem_index_imm,
149 sbb,169 sbb,
150 sbb_mem_imm,170 sbb_mem_imm,
151 sbb_scale_src,171 sbb_scale_src,
152 sbb_scale_dst,172 sbb_scale_dst,
153 sbb_scale_imm,173 sbb_scale_imm,
174 sbb_mem_index_imm,
154 cmp,175 cmp,
155 cmp_mem_imm,176 cmp_mem_imm,
156 cmp_scale_src,177 cmp_scale_src,
157 cmp_scale_dst,178 cmp_scale_dst,
158 cmp_scale_imm,179 cmp_scale_imm,
180 cmp_mem_index_imm,
159 mov,181 mov,
160 mov_mem_imm,182 mov_mem_imm,
161 mov_scale_src,183 mov_scale_src,
162 mov_scale_dst,184 mov_scale_dst,
163 mov_scale_imm,185 mov_scale_imm,
186 mov_mem_index_imm,
164187
165 /// ops flags: form:188 /// ops flags: form:
166 /// 0b00 reg1, [reg2 + imm32]189 /// 0b00 reg1, [reg2 + imm32]
src/arch/x86_64/PrintMir.zig+32-7
...@@ -64,6 +64,7 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap...@@ -64,6 +64,7 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap
64 .@"or" => try print.mirArith(.@"or", inst, w),64 .@"or" => try print.mirArith(.@"or", inst, w),
65 .sbb => try print.mirArith(.sbb, inst, w),65 .sbb => try print.mirArith(.sbb, inst, w),
66 .cmp => try print.mirArith(.cmp, inst, w),66 .cmp => try print.mirArith(.cmp, inst, w),
67 .mov => try print.mirArith(.mov, inst, w),
6768
68 .adc_mem_imm => try print.mirArithMemImm(.adc, inst, w),69 .adc_mem_imm => try print.mirArithMemImm(.adc, inst, w),
69 .add_mem_imm => try print.mirArithMemImm(.add, inst, w),70 .add_mem_imm => try print.mirArithMemImm(.add, inst, w),
...@@ -73,6 +74,7 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap...@@ -73,6 +74,7 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap
73 .or_mem_imm => try print.mirArithMemImm(.@"or", inst, w),74 .or_mem_imm => try print.mirArithMemImm(.@"or", inst, w),
74 .sbb_mem_imm => try print.mirArithMemImm(.sbb, inst, w),75 .sbb_mem_imm => try print.mirArithMemImm(.sbb, inst, w),
75 .cmp_mem_imm => try print.mirArithMemImm(.cmp, inst, w),76 .cmp_mem_imm => try print.mirArithMemImm(.cmp, inst, w),
77 .mov_mem_imm => try print.mirArithMemImm(.mov, inst, w),
7678
77 .adc_scale_src => try print.mirArithScaleSrc(.adc, inst, w),79 .adc_scale_src => try print.mirArithScaleSrc(.adc, inst, w),
78 .add_scale_src => try print.mirArithScaleSrc(.add, inst, w),80 .add_scale_src => try print.mirArithScaleSrc(.add, inst, w),
...@@ -82,6 +84,7 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap...@@ -82,6 +84,7 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap
82 .or_scale_src => try print.mirArithScaleSrc(.@"or", inst, w),84 .or_scale_src => try print.mirArithScaleSrc(.@"or", inst, w),
83 .sbb_scale_src => try print.mirArithScaleSrc(.sbb, inst, w),85 .sbb_scale_src => try print.mirArithScaleSrc(.sbb, inst, w),
84 .cmp_scale_src => try print.mirArithScaleSrc(.cmp, inst, w),86 .cmp_scale_src => try print.mirArithScaleSrc(.cmp, inst, w),
87 .mov_scale_src => try print.mirArithScaleSrc(.mov, inst, w),
8588
86 .adc_scale_dst => try print.mirArithScaleDst(.adc, inst, w),89 .adc_scale_dst => try print.mirArithScaleDst(.adc, inst, w),
87 .add_scale_dst => try print.mirArithScaleDst(.add, inst, w),90 .add_scale_dst => try print.mirArithScaleDst(.add, inst, w),
...@@ -91,6 +94,7 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap...@@ -91,6 +94,7 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap
91 .or_scale_dst => try print.mirArithScaleDst(.@"or", inst, w),94 .or_scale_dst => try print.mirArithScaleDst(.@"or", inst, w),
92 .sbb_scale_dst => try print.mirArithScaleDst(.sbb, inst, w),95 .sbb_scale_dst => try print.mirArithScaleDst(.sbb, inst, w),
93 .cmp_scale_dst => try print.mirArithScaleDst(.cmp, inst, w),96 .cmp_scale_dst => try print.mirArithScaleDst(.cmp, inst, w),
97 .mov_scale_dst => try print.mirArithScaleDst(.mov, inst, w),
9498
95 .adc_scale_imm => try print.mirArithScaleImm(.adc, inst, w),99 .adc_scale_imm => try print.mirArithScaleImm(.adc, inst, w),
96 .add_scale_imm => try print.mirArithScaleImm(.add, inst, w),100 .add_scale_imm => try print.mirArithScaleImm(.add, inst, w),
...@@ -100,11 +104,18 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap...@@ -100,11 +104,18 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap
100 .or_scale_imm => try print.mirArithScaleImm(.@"or", inst, w),104 .or_scale_imm => try print.mirArithScaleImm(.@"or", inst, w),
101 .sbb_scale_imm => try print.mirArithScaleImm(.sbb, inst, w),105 .sbb_scale_imm => try print.mirArithScaleImm(.sbb, inst, w),
102 .cmp_scale_imm => try print.mirArithScaleImm(.cmp, inst, w),106 .cmp_scale_imm => try print.mirArithScaleImm(.cmp, inst, w),
103
104 .mov => try print.mirArith(.mov, inst, w),
105 .mov_scale_src => try print.mirArithScaleSrc(.mov, inst, w),
106 .mov_scale_dst => try print.mirArithScaleDst(.mov, inst, w),
107 .mov_scale_imm => try print.mirArithScaleImm(.mov, inst, w),107 .mov_scale_imm => try print.mirArithScaleImm(.mov, inst, w),
108
109 .adc_mem_index_imm => try print.mirArithMemIndexImm(.adc, inst, w),
110 .add_mem_index_imm => try print.mirArithMemIndexImm(.add, inst, w),
111 .sub_mem_index_imm => try print.mirArithMemIndexImm(.sub, inst, w),
112 .xor_mem_index_imm => try print.mirArithMemIndexImm(.xor, inst, w),
113 .and_mem_index_imm => try print.mirArithMemIndexImm(.@"and", inst, w),
114 .or_mem_index_imm => try print.mirArithMemIndexImm(.@"or", inst, w),
115 .sbb_mem_index_imm => try print.mirArithMemIndexImm(.sbb, inst, w),
116 .cmp_mem_index_imm => try print.mirArithMemIndexImm(.cmp, inst, w),
117 .mov_mem_index_imm => try print.mirArithMemIndexImm(.mov, inst, w),
118
108 .movabs => try print.mirMovabs(inst, w),119 .movabs => try print.mirMovabs(inst, w),
109120
110 .lea => try print.mirLea(inst, w),121 .lea => try print.mirLea(inst, w),
...@@ -316,11 +327,11 @@ fn mirArithScaleDst(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index...@@ -316,11 +327,11 @@ fn mirArithScaleDst(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index
316327
317 if (ops.reg2 == .none) {328 if (ops.reg2 == .none) {
318 // OP [reg1 + scale*rax + 0], imm32329 // OP [reg1 + scale*rax + 0], imm32
319 try w.print("{s} [{s} + {d}*rcx + 0], {d}\n", .{ @tagName(tag), @tagName(ops.reg1), scale, imm });330 try w.print("{s} [{s} + {d}*rax + 0], {d}\n", .{ @tagName(tag), @tagName(ops.reg1), scale, imm });
320 }331 }
321332
322 // OP [reg1 + scale*rax + imm32], reg2333 // OP [reg1 + scale*rax + imm32], reg2
323 try w.print("{s} [{s} + {d}*rcx + {d}], {s}\n", .{ @tagName(tag), @tagName(ops.reg1), scale, imm, @tagName(ops.reg2) });334 try w.print("{s} [{s} + {d}*rax + {d}], {s}\n", .{ @tagName(tag), @tagName(ops.reg1), scale, imm, @tagName(ops.reg2) });
324}335}
325336
326fn mirArithScaleImm(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void {337fn mirArithScaleImm(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void {
...@@ -328,7 +339,21 @@ fn mirArithScaleImm(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index...@@ -328,7 +339,21 @@ fn mirArithScaleImm(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index
328 const scale = ops.flags;339 const scale = ops.flags;
329 const payload = print.mir.instructions.items(.data)[inst].payload;340 const payload = print.mir.instructions.items(.data)[inst].payload;
330 const imm_pair = print.mir.extraData(Mir.ImmPair, payload).data;341 const imm_pair = print.mir.extraData(Mir.ImmPair, payload).data;
331 try w.print("{s} [{s} + {d}*rcx + {d}], {d}\n", .{ @tagName(tag), @tagName(ops.reg1), scale, imm_pair.dest_off, imm_pair.operand });342 try w.print("{s} [{s} + {d}*rax + {d}], {d}\n", .{ @tagName(tag), @tagName(ops.reg1), scale, imm_pair.dest_off, imm_pair.operand });
343}
344
345fn mirArithMemIndexImm(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void {
346 const ops = Mir.Ops.decode(print.mir.instructions.items(.ops)[inst]);
347 const payload = print.mir.instructions.items(.data)[inst].payload;
348 const imm_pair = print.mir.extraData(Mir.ImmPair, payload).data;
349 try w.print("{s} ", .{@tagName(tag)});
350 switch (ops.flags) {
351 0b00 => try w.print("byte ptr ", .{}),
352 0b01 => try w.print("word ptr ", .{}),
353 0b10 => try w.print("dword ptr ", .{}),
354 0b11 => try w.print("qword ptr ", .{}),
355 }
356 try w.print("[{s} + 1*rax + {d}], {d}\n", .{ @tagName(ops.reg1), imm_pair.dest_off, imm_pair.operand });
332}357}
333358
334fn mirMovabs(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void {359fn mirMovabs(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void {
test/behavior.zig+1-1
...@@ -17,6 +17,7 @@ test {...@@ -17,6 +17,7 @@ test {
17 _ = @import("behavior/bool.zig");17 _ = @import("behavior/bool.zig");
18 _ = @import("behavior/align.zig");18 _ = @import("behavior/align.zig");
19 _ = @import("behavior/array.zig");19 _ = @import("behavior/array.zig");
20 _ = @import("behavior/cast.zig");
2021
21 if (builtin.zig_backend != .stage2_arm and builtin.zig_backend != .stage2_x86_64) {22 if (builtin.zig_backend != .stage2_arm and builtin.zig_backend != .stage2_x86_64) {
22 // Tests that pass for stage1, llvm backend, C backend, wasm backend.23 // Tests that pass for stage1, llvm backend, C backend, wasm backend.
...@@ -35,7 +36,6 @@ test {...@@ -35,7 +36,6 @@ test {
35 _ = @import("behavior/bugs/4954.zig");36 _ = @import("behavior/bugs/4954.zig");
36 _ = @import("behavior/byval_arg_var.zig");37 _ = @import("behavior/byval_arg_var.zig");
37 _ = @import("behavior/call.zig");38 _ = @import("behavior/call.zig");
38 _ = @import("behavior/cast.zig");
39 _ = @import("behavior/defer.zig");39 _ = @import("behavior/defer.zig");
40 _ = @import("behavior/enum.zig");40 _ = @import("behavior/enum.zig");
41 _ = @import("behavior/error.zig");41 _ = @import("behavior/error.zig");
test/behavior/array.zig+1-3
...@@ -75,8 +75,6 @@ test "array literal with inferred length" {...@@ -75,8 +75,6 @@ test "array literal with inferred length" {
75}75}
7676
77test "array dot len const expr" {77test "array dot len const expr" {
78 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
79
80 try expect(comptime x: {78 try expect(comptime x: {
81 break :x some_array.len == 4;79 break :x some_array.len == 4;
82 });80 });
...@@ -166,7 +164,7 @@ test "nested arrays" {...@@ -166,7 +164,7 @@ test "nested arrays" {
166}164}
167165
168test "implicit comptime in array type size" {166test "implicit comptime in array type size" {
169 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
170168
171 var arr: [plusOne(10)]bool = undefined;169 var arr: [plusOne(10)]bool = undefined;
172 try expect(arr.len == 11);170 try expect(arr.len == 11);
test/behavior/cast.zig+30
...@@ -5,6 +5,8 @@ const maxInt = std.math.maxInt;...@@ -5,6 +5,8 @@ const maxInt = std.math.maxInt;
5const builtin = @import("builtin");5const builtin = @import("builtin");
66
7test "int to ptr cast" {7test "int to ptr cast" {
8 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
9
8 const x = @as(usize, 13);10 const x = @as(usize, 13);
9 const y = @intToPtr(*u8, x);11 const y = @intToPtr(*u8, x);
10 const z = @ptrToInt(y);12 const z = @ptrToInt(y);
...@@ -12,11 +14,15 @@ test "int to ptr cast" {...@@ -12,11 +14,15 @@ test "int to ptr cast" {
12}14}
1315
14test "integer literal to pointer cast" {16test "integer literal to pointer cast" {
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
18
15 const vga_mem = @intToPtr(*u16, 0xB8000);19 const vga_mem = @intToPtr(*u16, 0xB8000);
16 try expect(@ptrToInt(vga_mem) == 0xB8000);20 try expect(@ptrToInt(vga_mem) == 0xB8000);
17}21}
1822
19test "peer type resolution: ?T and T" {23test "peer type resolution: ?T and T" {
24 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
25
20 try expect(peerTypeTAndOptionalT(true, false).? == 0);26 try expect(peerTypeTAndOptionalT(true, false).? == 0);
21 try expect(peerTypeTAndOptionalT(false, false).? == 3);27 try expect(peerTypeTAndOptionalT(false, false).? == 3);
22 comptime {28 comptime {
...@@ -33,6 +39,8 @@ fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {...@@ -33,6 +39,8 @@ fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
33}39}
3440
35test "resolve undefined with integer" {41test "resolve undefined with integer" {
42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
43
36 try testResolveUndefWithInt(true, 1234);44 try testResolveUndefWithInt(true, 1234);
37 comptime try testResolveUndefWithInt(true, 1234);45 comptime try testResolveUndefWithInt(true, 1234);
38}46}
...@@ -88,6 +96,8 @@ test "comptime_int @intToFloat" {...@@ -88,6 +96,8 @@ test "comptime_int @intToFloat" {
88}96}
8997
90test "@floatToInt" {98test "@floatToInt" {
99 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
100
91 try testFloatToInts();101 try testFloatToInts();
92 comptime try testFloatToInts();102 comptime try testFloatToInts();
93}103}
...@@ -107,6 +117,8 @@ fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {...@@ -107,6 +117,8 @@ fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
107}117}
108118
109test "implicitly cast indirect pointer to maybe-indirect pointer" {119test "implicitly cast indirect pointer to maybe-indirect pointer" {
120 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
121
110 const S = struct {122 const S = struct {
111 const Self = @This();123 const Self = @This();
112 x: u8,124 x: u8,
...@@ -163,6 +175,8 @@ test "@floatCast comptime_int and comptime_float" {...@@ -163,6 +175,8 @@ test "@floatCast comptime_int and comptime_float" {
163}175}
164176
165test "coerce undefined to optional" {177test "coerce undefined to optional" {
178 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
179
166 try expect(MakeType(void).getNull() == null);180 try expect(MakeType(void).getNull() == null);
167 try expect(MakeType(void).getNonNull() != null);181 try expect(MakeType(void).getNonNull() != null);
168}182}
...@@ -180,6 +194,8 @@ fn MakeType(comptime T: type) type {...@@ -180,6 +194,8 @@ fn MakeType(comptime T: type) type {
180}194}
181195
182test "implicit cast from *[N]T to [*c]T" {196test "implicit cast from *[N]T to [*c]T" {
197 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
198
183 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };199 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
184 var y: [*c]u16 = &x;200 var y: [*c]u16 = &x;
185201
...@@ -190,6 +206,8 @@ test "implicit cast from *[N]T to [*c]T" {...@@ -190,6 +206,8 @@ test "implicit cast from *[N]T to [*c]T" {
190}206}
191207
192test "*usize to *void" {208test "*usize to *void" {
209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
210
193 var i = @as(usize, 0);211 var i = @as(usize, 0);
194 var v = @ptrCast(*void, &i);212 var v = @ptrCast(*void, &i);
195 v.* = {};213 v.* = {};
...@@ -202,6 +220,8 @@ test "@intToEnum passed a comptime_int to an enum with one item" {...@@ -202,6 +220,8 @@ test "@intToEnum passed a comptime_int to an enum with one item" {
202}220}
203221
204test "@intCast to u0 and use the result" {222test "@intCast to u0 and use the result" {
223 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
224
205 const S = struct {225 const S = struct {
206 fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {226 fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {
207 try expect((one << @intCast(u0, bigzero)) == 1);227 try expect((one << @intCast(u0, bigzero)) == 1);
...@@ -213,6 +233,8 @@ test "@intCast to u0 and use the result" {...@@ -213,6 +233,8 @@ test "@intCast to u0 and use the result" {
213}233}
214234
215test "peer result null and comptime_int" {235test "peer result null and comptime_int" {
236 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
237
216 const S = struct {238 const S = struct {
217 fn blah(n: i32) ?i32 {239 fn blah(n: i32) ?i32 {
218 if (n == 0) {240 if (n == 0) {
...@@ -234,6 +256,8 @@ test "peer result null and comptime_int" {...@@ -234,6 +256,8 @@ test "peer result null and comptime_int" {
234}256}
235257
236test "*const ?[*]const T to [*c]const [*c]const T" {258test "*const ?[*]const T to [*c]const [*c]const T" {
259 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
260
237 var array = [_]u8{ 'o', 'k' };261 var array = [_]u8{ 'o', 'k' };
238 const opt_array_ptr: ?[*]const u8 = &array;262 const opt_array_ptr: ?[*]const u8 = &array;
239 const a: *const ?[*]const u8 = &opt_array_ptr;263 const a: *const ?[*]const u8 = &opt_array_ptr;
...@@ -243,6 +267,8 @@ test "*const ?[*]const T to [*c]const [*c]const T" {...@@ -243,6 +267,8 @@ test "*const ?[*]const T to [*c]const [*c]const T" {
243}267}
244268
245test "array coersion to undefined at runtime" {269test "array coersion to undefined at runtime" {
270 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
271
246 @setRuntimeSafety(true);272 @setRuntimeSafety(true);
247273
248 // TODO implement @setRuntimeSafety in stage2274 // TODO implement @setRuntimeSafety in stage2
...@@ -270,6 +296,8 @@ fn implicitIntLitToOptional() void {...@@ -270,6 +296,8 @@ fn implicitIntLitToOptional() void {
270}296}
271297
272test "return u8 coercing into ?u32 return type" {298test "return u8 coercing into ?u32 return type" {
299 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
300
273 const S = struct {301 const S = struct {
274 fn doTheTest() !void {302 fn doTheTest() !void {
275 try expect(foo(123).? == 123);303 try expect(foo(123).? == 123);
...@@ -288,6 +316,8 @@ test "cast from ?[*]T to ??[*]T" {...@@ -288,6 +316,8 @@ test "cast from ?[*]T to ??[*]T" {
288}316}
289317
290test "peer type unsigned int to signed" {318test "peer type unsigned int to signed" {
319 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
320
291 var w: u31 = 5;321 var w: u31 = 5;
292 var x: u8 = 7;322 var x: u8 = 7;
293 var y: i32 = -5;323 var y: i32 = -5;