Skip to content

Commit c82e1fe

Browse files
authored
Merge pull request #23355 from jacobly0/x86_64-rewrite
x86_64: start rewriting overflow operations
2 parents 9e21ba1 + 7349873 commit c82e1fe

File tree

15 files changed

+6026
-601
lines changed

15 files changed

+6026
-601
lines changed

lib/std/zig/AstGen.zig

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8854,10 +8854,10 @@ fn asmExpr(
88548854
return astgen.failNode(node, "assembly expression with no output must be marked volatile", .{});
88558855
}
88568856
}
8857-
if (full.outputs.len > 32) {
8858-
return astgen.failNode(full.outputs[32], "too many asm outputs", .{});
8857+
if (full.outputs.len >= 16) {
8858+
return astgen.failNode(full.outputs[16], "too many asm outputs", .{});
88598859
}
8860-
var outputs_buffer: [32]Zir.Inst.Asm.Output = undefined;
8860+
var outputs_buffer: [15]Zir.Inst.Asm.Output = undefined;
88618861
const outputs = outputs_buffer[0..full.outputs.len];
88628862

88638863
var output_type_bits: u32 = 0;
@@ -8893,10 +8893,10 @@ fn asmExpr(
88938893
}
88948894
}
88958895

8896-
if (full.inputs.len > 32) {
8896+
if (full.inputs.len >= 32) {
88978897
return astgen.failNode(full.inputs[32], "too many asm inputs", .{});
88988898
}
8899-
var inputs_buffer: [32]Zir.Inst.Asm.Input = undefined;
8899+
var inputs_buffer: [31]Zir.Inst.Asm.Input = undefined;
89008900
const inputs = inputs_buffer[0..full.inputs.len];
89018901

89028902
for (full.inputs, 0..) |input_node, i| {
@@ -8912,7 +8912,7 @@ fn asmExpr(
89128912
};
89138913
}
89148914

8915-
var clobbers_buffer: [32]u32 = undefined;
8915+
var clobbers_buffer: [63]u32 = undefined;
89168916
var clobber_i: usize = 0;
89178917
if (full.first_clobber) |first_clobber| clobbers: {
89188918
// asm ("foo" ::: "a", "b")
@@ -12932,14 +12932,14 @@ const GenZir = struct {
1293212932
}
1293312933
gz.astgen.extra.appendSliceAssumeCapacity(args.clobbers);
1293412934

12935-
// * 0b00000000_000XXXXX - `outputs_len`.
12936-
// * 0b000000XX_XXX00000 - `inputs_len`.
12937-
// * 0b0XXXXX00_00000000 - `clobbers_len`.
12935+
// * 0b00000000_0000XXXX - `outputs_len`.
12936+
// * 0b0000000X_XXXX0000 - `inputs_len`.
12937+
// * 0b0XXXXXX0_00000000 - `clobbers_len`.
1293812938
// * 0bX0000000_00000000 - is volatile
12939-
const small: u16 = @as(u16, @intCast(args.outputs.len)) |
12940-
@as(u16, @intCast(args.inputs.len << 5)) |
12941-
@as(u16, @intCast(args.clobbers.len << 10)) |
12942-
(@as(u16, @intFromBool(args.is_volatile)) << 15);
12939+
const small: u16 = @as(u16, @as(u4, @intCast(args.outputs.len))) << 0 |
12940+
@as(u16, @as(u5, @intCast(args.inputs.len))) << 4 |
12941+
@as(u16, @as(u6, @intCast(args.clobbers.len))) << 9 |
12942+
@as(u16, @intFromBool(args.is_volatile)) << 15;
1294312943

1294412944
const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);
1294512945
astgen.instructions.appendAssumeCapacity(.{

src/Sema.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16661,9 +16661,9 @@ fn zirAsm(
1666116661
const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand);
1666216662
const src = block.nodeOffset(extra.data.src_node);
1666316663
const ret_ty_src = block.src(.{ .node_offset_asm_ret_ty = extra.data.src_node });
16664-
const outputs_len: u5 = @truncate(extended.small);
16665-
const inputs_len: u5 = @truncate(extended.small >> 5);
16666-
const clobbers_len: u5 = @truncate(extended.small >> 10);
16664+
const outputs_len: u4 = @truncate(extended.small);
16665+
const inputs_len: u5 = @truncate(extended.small >> 4);
16666+
const clobbers_len: u6 = @truncate(extended.small >> 9);
1666716667
const is_volatile = @as(u1, @truncate(extended.small >> 15)) != 0;
1666816668
const is_global_assembly = sema.func_index == .none;
1666916669
const zir_tags = sema.code.instructions.items(.tag);

src/arch/x86_64/CodeGen.zig

Lines changed: 5570 additions & 65 deletions
Large diffs are not rendered by default.

src/arch/x86_64/Emit.zig

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,14 @@ pub fn emitMir(emit: *Emit) Error!void {
9797
op_index -= 1;
9898
const op = lowered_inst.encoding.data.ops[op_index];
9999
if (op == .none) continue;
100-
const enc_length: u4 = @intCast(
101-
std.math.divCeil(u7, @intCast(op.immBitSize()), 8) catch unreachable,
102-
);
100+
const is_mem = op.isMemory();
101+
const enc_length: u4 = if (is_mem) switch (lowered_inst.ops[op_index].mem.sib.base) {
102+
.rip_inst => 4,
103+
else => unreachable,
104+
} else @intCast(std.math.divCeil(u7, @intCast(op.immBitSize()), 8) catch unreachable);
103105
reloc_offset -= enc_length;
104-
if (op_index == lowered_relocs[0].op_index)
105-
break :reloc_offset_length .{ reloc_offset, enc_length };
106+
if (op_index == lowered_relocs[0].op_index) break :reloc_offset_length .{ reloc_offset, enc_length };
107+
std.debug.assert(!is_mem);
106108
}
107109
};
108110
try relocs.append(emit.lower.allocator, .{
@@ -434,7 +436,7 @@ pub fn emitMir(emit: *Emit) Error!void {
434436
loc_buf[0] = switch (mem.base()) {
435437
.none => .{ .constu = 0 },
436438
.reg => |reg| .{ .breg = reg.dwarfNum() },
437-
.frame, .table => unreachable,
439+
.frame, .table, .rip_inst => unreachable,
438440
.reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
439441
};
440442
break :base &loc_buf[0];

src/arch/x86_64/Encoding.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub fn findByMnemonic(
5050
else => {},
5151
} else false;
5252
const rex_extended = for (ops) |op| {
53-
if (op.isBaseExtended() or op.isIndexExtended()) break true;
53+
if (op.baseExtEnc() != 0b00 or op.indexExtEnc() != 0b00) break true;
5454
} else false;
5555

5656
if ((rex_required or rex_extended) and rex_invalid) return error.CannotEncode;

src/arch/x86_64/Lower.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ pub fn mem(lower: *Lower, op_index: InstOpIndex, payload: u32) Memory {
395395
.sib => |*sib| switch (sib.base) {
396396
else => {},
397397
.table => sib.disp = lower.reloc(op_index, .table, sib.disp).signed,
398+
.rip_inst => |inst_index| sib.disp = lower.reloc(op_index, .{ .inst = inst_index }, sib.disp).signed,
398399
},
399400
else => {},
400401
}

src/arch/x86_64/Mir.zig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1742,6 +1742,7 @@ pub const Memory = struct {
17421742
.reg => |reg| @intFromEnum(reg),
17431743
.frame => |frame_index| @intFromEnum(frame_index),
17441744
.reloc => |sym_index| sym_index,
1745+
.rip_inst => |inst_index| inst_index,
17451746
},
17461747
.off = switch (mem.mod) {
17471748
.rm => |rm| @bitCast(rm.disp),
@@ -1769,6 +1770,7 @@ pub const Memory = struct {
17691770
.frame => .{ .frame = @enumFromInt(mem.base) },
17701771
.table => .table,
17711772
.reloc => .{ .reloc = mem.base },
1773+
.rip_inst => .{ .rip_inst = mem.base },
17721774
},
17731775
.scale_index = switch (mem.info.index) {
17741776
.none => null,
@@ -1832,7 +1834,7 @@ pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffse
18321834

18331835
pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {
18341836
return switch (mem.info.base) {
1835-
.none, .reg, .table, .reloc => mem,
1837+
.none, .reg, .table, .reloc, .rip_inst => mem,
18361838
.frame => if (mir.frame_locs.len > 0) .{
18371839
.info = .{
18381840
.base = .reg,

src/arch/x86_64/abi.zig

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,8 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
266266
// separately.".
267267
const ty_size = ty.abiSize(zcu);
268268
switch (ty.containerLayout(zcu)) {
269-
.auto, .@"extern" => {},
269+
.auto => unreachable,
270+
.@"extern" => {},
270271
.@"packed" => {
271272
assert(ty_size <= 16);
272273
result[0] = .integer;
@@ -345,15 +346,17 @@ fn classifySystemVStruct(
345346
);
346347
if (zcu.typeToStruct(field_ty)) |field_loaded_struct| {
347348
switch (field_loaded_struct.layout) {
348-
.auto, .@"extern" => {
349+
.auto => unreachable,
350+
.@"extern" => {
349351
byte_offset = classifySystemVStruct(result, byte_offset, field_loaded_struct, zcu, target);
350352
continue;
351353
},
352354
.@"packed" => {},
353355
}
354356
} else if (zcu.typeToUnion(field_ty)) |field_loaded_union| {
355357
switch (field_loaded_union.flagsUnordered(ip).layout) {
356-
.auto, .@"extern" => {
358+
.auto => unreachable,
359+
.@"extern" => {
357360
byte_offset = classifySystemVUnion(result, byte_offset, field_loaded_union, zcu, target);
358361
continue;
359362
},
@@ -386,15 +389,17 @@ fn classifySystemVUnion(
386389
const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);
387390
if (zcu.typeToStruct(field_ty)) |field_loaded_struct| {
388391
switch (field_loaded_struct.layout) {
389-
.auto, .@"extern" => {
392+
.auto => unreachable,
393+
.@"extern" => {
390394
_ = classifySystemVStruct(result, starting_byte_offset, field_loaded_struct, zcu, target);
391395
continue;
392396
},
393397
.@"packed" => {},
394398
}
395399
} else if (zcu.typeToUnion(field_ty)) |field_loaded_union| {
396400
switch (field_loaded_union.flagsUnordered(ip).layout) {
397-
.auto, .@"extern" => {
401+
.auto => unreachable,
402+
.@"extern" => {
398403
_ = classifySystemVUnion(result, starting_byte_offset, field_loaded_union, zcu, target);
399404
continue;
400405
},

src/arch/x86_64/bits.zig

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const expect = std.testing.expect;
44

55
const Allocator = std.mem.Allocator;
66
const ArrayList = std.ArrayList;
7+
const Mir = @import("Mir.zig");
78

89
/// EFLAGS condition codes
910
pub const Condition = enum(u5) {
@@ -359,11 +360,20 @@ pub const Register = enum(u8) {
359360

360361
ah, ch, dh, bh,
361362

362-
ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7,
363-
ymm8, ymm9, ymm10, ymm11, ymm12, ymm13, ymm14, ymm15,
363+
zmm0, zmm1, zmm2, zmm3, zmm4, zmm5, zmm6, zmm7,
364+
zmm8, zmm9, zmm10, zmm11, zmm12, zmm13, zmm14, zmm15,
365+
zmm16, zmm17,zmm18, zmm19, zmm20, zmm21, zmm22, zmm23,
366+
zmm24, zmm25,zmm26, zmm27, zmm28, zmm29, zmm30, zmm31,
364367

365-
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
366-
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
368+
ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7,
369+
ymm8, ymm9, ymm10, ymm11, ymm12, ymm13, ymm14, ymm15,
370+
ymm16, ymm17,ymm18, ymm19, ymm20, ymm21, ymm22, ymm23,
371+
ymm24, ymm25,ymm26, ymm27, ymm28, ymm29, ymm30, ymm31,
372+
373+
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
374+
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
375+
xmm16, xmm17,xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
376+
xmm24, xmm25,xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
367377

368378
mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
369379

@@ -403,8 +413,9 @@ pub const Register = enum(u8) {
403413
@intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => .general_purpose,
404414
@intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => .gphi,
405415

406-
@intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm15) => .sse,
407-
@intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm15) => .sse,
416+
@intFromEnum(Register.zmm0) ... @intFromEnum(Register.zmm31) => .sse,
417+
@intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm31) => .sse,
418+
@intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm31) => .sse,
408419
@intFromEnum(Register.mm0) ... @intFromEnum(Register.mm7) => .mmx,
409420
@intFromEnum(Register.st0) ... @intFromEnum(Register.st7) => .x87,
410421

@@ -427,13 +438,14 @@ pub const Register = enum(u8) {
427438
@intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => @intFromEnum(Register.al),
428439
@intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => @intFromEnum(Register.ah),
429440

430-
@intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm15) => @intFromEnum(Register.ymm0) - 16,
431-
@intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm15) => @intFromEnum(Register.xmm0) - 16,
432-
@intFromEnum(Register.mm0) ... @intFromEnum(Register.mm7) => @intFromEnum(Register.mm0) - 32,
433-
@intFromEnum(Register.st0) ... @intFromEnum(Register.st7) => @intFromEnum(Register.st0) - 40,
434-
@intFromEnum(Register.es) ... @intFromEnum(Register.gs) => @intFromEnum(Register.es) - 48,
435-
@intFromEnum(Register.cr0) ... @intFromEnum(Register.cr15) => @intFromEnum(Register.cr0) - 54,
436-
@intFromEnum(Register.dr0) ... @intFromEnum(Register.dr15) => @intFromEnum(Register.dr0) - 70,
441+
@intFromEnum(Register.zmm0) ... @intFromEnum(Register.zmm31) => @intFromEnum(Register.zmm0) - 16,
442+
@intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm31) => @intFromEnum(Register.ymm0) - 16,
443+
@intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm31) => @intFromEnum(Register.xmm0) - 16,
444+
@intFromEnum(Register.mm0) ... @intFromEnum(Register.mm7) => @intFromEnum(Register.mm0) - 48,
445+
@intFromEnum(Register.st0) ... @intFromEnum(Register.st7) => @intFromEnum(Register.st0) - 56,
446+
@intFromEnum(Register.es) ... @intFromEnum(Register.gs) => @intFromEnum(Register.es) - 64,
447+
@intFromEnum(Register.cr0) ... @intFromEnum(Register.cr15) => @intFromEnum(Register.cr0) - 70,
448+
@intFromEnum(Register.dr0) ... @intFromEnum(Register.dr15) => @intFromEnum(Register.dr0) - 86,
437449

438450
else => unreachable,
439451
// zig fmt: on
@@ -450,6 +462,7 @@ pub const Register = enum(u8) {
450462
@intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => 8,
451463
@intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => 8,
452464

465+
@intFromEnum(Register.zmm0) ... @intFromEnum(Register.zmm15) => 512,
453466
@intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm15) => 256,
454467
@intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm15) => 128,
455468
@intFromEnum(Register.mm0) ... @intFromEnum(Register.mm7) => 64,
@@ -473,8 +486,9 @@ pub const Register = enum(u8) {
473486
@intFromEnum(Register.r8w) ... @intFromEnum(Register.r15w) => true,
474487
@intFromEnum(Register.r8b) ... @intFromEnum(Register.r15b) => true,
475488

476-
@intFromEnum(Register.ymm8) ... @intFromEnum(Register.ymm15) => true,
477-
@intFromEnum(Register.xmm8) ... @intFromEnum(Register.xmm15) => true,
489+
@intFromEnum(Register.zmm8) ... @intFromEnum(Register.zmm31) => true,
490+
@intFromEnum(Register.ymm8) ... @intFromEnum(Register.ymm31) => true,
491+
@intFromEnum(Register.xmm8) ... @intFromEnum(Register.xmm31) => true,
478492

479493
@intFromEnum(Register.cr8) ... @intFromEnum(Register.cr15) => true,
480494
@intFromEnum(Register.dr8) ... @intFromEnum(Register.dr15) => true,
@@ -484,7 +498,7 @@ pub const Register = enum(u8) {
484498
};
485499
}
486500

487-
pub fn enc(reg: Register) u4 {
501+
pub fn enc(reg: Register) u5 {
488502
const base = switch (@intFromEnum(reg)) {
489503
// zig fmt: off
490504
@intFromEnum(Register.rax) ... @intFromEnum(Register.r15) => @intFromEnum(Register.rax),
@@ -509,10 +523,6 @@ pub const Register = enum(u8) {
509523
return @truncate(@intFromEnum(reg) - base);
510524
}
511525

512-
pub fn lowEnc(reg: Register) u3 {
513-
return @truncate(reg.enc());
514-
}
515-
516526
pub fn toBitSize(reg: Register, bit_size: u64) Register {
517527
return switch (bit_size) {
518528
8 => reg.to8(),
@@ -557,11 +567,12 @@ pub const Register = enum(u8) {
557567
};
558568
}
559569

560-
fn sseBase(reg: Register) u7 {
570+
fn sseBase(reg: Register) u8 {
561571
assert(reg.class() == .sse);
562572
return switch (@intFromEnum(reg)) {
563-
@intFromEnum(Register.ymm0)...@intFromEnum(Register.ymm15) => @intFromEnum(Register.ymm0),
564-
@intFromEnum(Register.xmm0)...@intFromEnum(Register.xmm15) => @intFromEnum(Register.xmm0),
573+
@intFromEnum(Register.zmm0)...@intFromEnum(Register.zmm31) => @intFromEnum(Register.zmm0),
574+
@intFromEnum(Register.ymm0)...@intFromEnum(Register.ymm31) => @intFromEnum(Register.ymm0),
575+
@intFromEnum(Register.xmm0)...@intFromEnum(Register.xmm31) => @intFromEnum(Register.xmm0),
565576
else => unreachable,
566577
};
567578
}
@@ -678,15 +689,9 @@ pub const Memory = struct {
678689
frame: FrameIndex,
679690
table,
680691
reloc: u32,
692+
rip_inst: Mir.Inst.Index,
681693

682694
pub const Tag = @typeInfo(Base).@"union".tag_type.?;
683-
684-
pub fn isExtended(self: Base) bool {
685-
return switch (self) {
686-
.none, .frame, .table, .reloc => false, // rsp, rbp, and rip are not extended
687-
.reg => |reg| reg.isExtended(),
688-
};
689-
}
690695
};
691696

692697
pub const Mod = union(enum(u1)) {

0 commit comments

Comments
 (0)