Merge pull request #22876 from jacobly0/x86_64-rewrite

x86_64: implement error set and enum safety
This commit is contained in:
Andrew Kelley 2025-02-15 12:33:09 -08:00 committed by GitHub
commit e5174c7441
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
172 changed files with 11211 additions and 5445 deletions

View File

@ -230,6 +230,7 @@ comptime {
_ = @import("compiler_rt/trunc.zig");
// BigInt. Alphabetically sorted.
_ = @import("compiler_rt/divmodei4.zig");
_ = @import("compiler_rt/udivmodei4.zig");
_ = @import("compiler_rt/udivmodti4.zig");

View File

@ -0,0 +1,50 @@
const std = @import("std");
const builtin = @import("builtin");
const common = @import("common.zig");
const udivmod = @import("udivmodei4.zig").divmod;
comptime {
@export(&__divei4, .{ .name = "__divei4", .linkage = common.linkage, .visibility = common.visibility });
@export(&__modei4, .{ .name = "__modei4", .linkage = common.linkage, .visibility = common.visibility });
}
const endian = builtin.cpu.arch.endian();
inline fn limb(x: []u32, i: usize) *u32 {
return if (endian == .little) &x[i] else &x[x.len - 1 - i];
}
inline fn neg(x: []u32) void {
var ov: u1 = 1;
for (0..x.len) |limb_index| {
const l = limb(x, limb_index);
l.*, ov = @addWithOverflow(~l.*, ov);
}
}
/// Mutates the arguments!
fn divmod(q: ?[]u32, r: ?[]u32, u: []u32, v: []u32) !void {
const u_sign: i32 = @bitCast(u[u.len - 1]);
const v_sign: i32 = @bitCast(v[v.len - 1]);
if (u_sign < 0) neg(u);
if (v_sign < 0) neg(v);
try @call(.always_inline, udivmod, .{ q, r, u, v });
if (q) |x| if (u_sign ^ v_sign < 0) neg(x);
if (r) |x| if (u_sign < 0) neg(x);
}
pub fn __divei4(r_q: [*]u32, u_p: [*]u32, v_p: [*]u32, bits: usize) callconv(.C) void {
@setRuntimeSafety(builtin.is_test);
const u = u_p[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
const v = v_p[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
const q = r_q[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
@call(.always_inline, divmod, .{ q, null, u, v }) catch unreachable;
}
pub fn __modei4(r_p: [*]u32, u_p: [*]u32, v_p: [*]u32, bits: usize) callconv(.C) void {
@setRuntimeSafety(builtin.is_test);
const u = u_p[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
const v = v_p[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
const r = r_p[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
@call(.always_inline, divmod, .{ null, r, u, v }) catch unreachable;
}

View File

@ -27,8 +27,8 @@ inline fn limb_set(x: []u32, i: usize, v: u32) void {
}
}
// Uses Knuth's Algorithm D, 4.3.1, p. 272.
fn divmod(q: ?[]u32, r: ?[]u32, u: []const u32, v: []const u32) !void {
/// Uses Knuth's Algorithm D, 4.3.1, p. 272.
pub fn divmod(q: ?[]u32, r: ?[]u32, u: []const u32, v: []const u32) !void {
if (q) |q_| @memset(q_[0..], 0);
if (r) |r_| @memset(r_[0..], 0);

View File

@ -8850,7 +8850,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
// Use `intCast`, since it'll set up the Sema-emitted safety checks for us!
const int_val = try sema.intCast(block, src, int_tag_ty, src, operand, src, true, true);
const result = try block.addBitCast(dest_ty, int_val);
if (zcu.backendSupportsFeature(.is_named_enum_value)) {
if (!dest_ty.isNonexhaustiveEnum(zcu) and zcu.backendSupportsFeature(.is_named_enum_value)) {
const ok = try block.addUnOp(.is_named_enum_value, result);
try sema.addSafetyCheck(block, src, ok, .invalid_enum_value);
}

View File

@ -4190,11 +4190,11 @@ pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type };
pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type };
pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type };
pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type };
pub const single_const_pointer_to_comptime_int: Type = .{
.ip_index = .single_const_pointer_to_comptime_int_type,
};
pub const manyptr_const_u8: Type = .{ .ip_index = .manyptr_const_u8_type };
pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type };
pub const single_const_pointer_to_comptime_int: Type = .{ .ip_index = .single_const_pointer_to_comptime_int_type };
pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };
pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type };

File diff suppressed because it is too large Load Diff

View File

@ -88,13 +88,32 @@ pub fn emitMir(emit: *Emit) Error!void {
lowered_relocs[0].lowered_inst_index == lowered_index) : ({
lowered_relocs = lowered_relocs[1..];
}) switch (lowered_relocs[0].target) {
.inst => |target| try relocs.append(emit.lower.allocator, .{
.source = start_offset,
.source_offset = end_offset - 4,
.target = target,
.target_offset = lowered_relocs[0].off,
.length = @intCast(end_offset - start_offset),
}),
.inst => |target| {
const inst_length: u4 = @intCast(end_offset - start_offset);
const reloc_offset, const reloc_length = reloc_offset_length: {
var reloc_offset = inst_length;
var op_index: usize = lowered_inst.ops.len;
while (true) {
op_index -= 1;
const op = lowered_inst.encoding.data.ops[op_index];
if (op == .none) continue;
const enc_length: u4 = @intCast(
std.math.divCeil(u7, @intCast(op.immBitSize()), 8) catch unreachable,
);
reloc_offset -= enc_length;
if (op_index == lowered_relocs[0].op_index)
break :reloc_offset_length .{ reloc_offset, enc_length };
}
};
try relocs.append(emit.lower.allocator, .{
.inst_offset = start_offset,
.inst_length = inst_length,
.source_offset = reloc_offset,
.source_length = reloc_length,
.target = target,
.target_offset = lowered_relocs[0].off,
});
},
.table => try table_relocs.append(emit.lower.allocator, .{
.source_offset = end_offset - 4,
.target_offset = lowered_relocs[0].off,
@ -409,7 +428,7 @@ pub fn emitMir(emit: *Emit) Error!void {
} } };
},
.pseudo_dbg_local_am => loc: {
const mem = emit.lower.mem(mir_inst.data.ax.payload);
const mem = emit.lower.mem(undefined, mir_inst.data.ax.payload);
break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
base: {
loc_buf[0] = switch (mem.base()) {
@ -466,15 +485,18 @@ pub fn emitMir(emit: *Emit) Error!void {
}
}
}
{
// TODO this function currently assumes all relocs via JMP/CALL instructions are 32bit in size.
// This should be reversed like it is done in aarch64 MIR emit code: start with the smallest
// possible resolution, i.e., 8bit, and iteratively converge on the minimum required resolution
// until the entire decl is correctly emitted with all JMP/CALL instructions within range.
for (relocs.items) |reloc| {
const target = code_offset_mapping[reloc.target];
const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length)) + reloc.target_offset;
std.mem.writeInt(i32, emit.code.items[reloc.source_offset..][0..4], @intCast(disp), .little);
for (relocs.items) |reloc| {
const target = code_offset_mapping[reloc.target];
const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.inst_offset + reloc.inst_length)) + reloc.target_offset;
const inst_bytes = emit.code.items[reloc.inst_offset..][0..reloc.inst_length];
switch (reloc.source_length) {
else => unreachable,
inline 1, 4 => |source_length| std.mem.writeInt(
@Type(.{ .int = .{ .signedness = .signed, .bits = @as(u16, 8) * source_length } }),
inst_bytes[reloc.source_offset..][0..source_length],
@intCast(disp),
.little,
),
}
}
if (emit.lower.mir.table.len > 0) {
@ -511,15 +533,17 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
const Reloc = struct {
/// Offset of the instruction.
source: u32,
inst_offset: u32,
/// Length of the instruction.
inst_length: u4,
/// Offset of the relocation within the instruction.
source_offset: u32,
source_offset: u4,
/// Length of the relocation.
source_length: u4,
/// Target of the relocation.
target: Mir.Inst.Index,
/// Offset from the target instruction.
/// Offset from the target.
target_offset: i32,
/// Length of the instruction.
length: u5,
};
const TableReloc = struct {

View File

@ -304,20 +304,20 @@ pub const Mnemonic = enum {
jnc, jne, jng, jnge, jnl, jnle, jno, jnp, jns, jnz, jo, jp, jpe, jpo, jrcxz, js, jz,
lahf, lar, lea, leave, lfence, lgdt, lidt, lldt, lmsw, loop, loope, loopne,
lods, lodsb, lodsd, lodsq, lodsw,
lsl, ltr, lzcnt,
lsl, ltr,
mfence, mov, movbe,
movs, movsb, movsd, movsq, movsw,
movsx, movsxd, movzx, mul,
neg, nop, not,
@"or", out, outs, outsb, outsd, outsw,
pause, pop, popcnt, popf, popfd, popfq, push, pushfq,
pause, pop, popf, popfd, popfq, push, pushfq,
rcl, rcr,
rdfsbase, rdgsbase, rdmsr, rdpid, rdpkru, rdpmc, rdrand, rdseed, rdssd, rdssq, rdtsc, rdtscp,
ret, rol, ror, rorx, rsm,
sahf, sal, sar, sarx, sbb,
ret, rol, ror, rsm,
sahf, sal, sar, sbb,
scas, scasb, scasd, scasq, scasw,
senduipi, serialize,
shl, shld, shlx, shr, shrd, shrx,
shl, shld, shr, shrd,
stac, stc, std, sti, str, stui,
sub, swapgs, syscall, sysenter, sysexit, sysret,
seta, setae, setb, setbe, setc, sete, setg, setge, setl, setle, setna, setnae,
@ -433,6 +433,8 @@ pub const Mnemonic = enum {
roundpd, roundps, roundsd, roundss,
// SSE4.2
crc32, pcmpgtq,
// ABM
lzcnt, popcnt,
// PCLMUL
pclmulqdq,
// AES
@ -440,7 +442,6 @@ pub const Mnemonic = enum {
// SHA
sha1rnds4, sha1nexte, sha1msg1, sha1msg2, sha256msg1, sha256msg2, sha256rnds2,
// AVX
andn, bextr, blsi, blsmsk, blsr, bzhi, tzcnt,
vaddpd, vaddps, vaddsd, vaddss, vaddsubpd, vaddsubps,
vaesdec, vaesdeclast, vaesenc, vaesenclast, vaesimc, vaeskeygenassist,
vandnpd, vandnps, vandpd, vandps,
@ -506,6 +507,10 @@ pub const Mnemonic = enum {
vtestpd, vtestps,
vucomisd, vucomiss, vunpckhpd, vunpckhps, vunpcklpd, vunpcklps,
vxorpd, vxorps,
// BMI
andn, bextr, blsi, blsmsk, blsr, tzcnt,
// BMI2
bzhi, mulx, pdep, pext, rorx, sarx, shlx, shrx,
// F16C
vcvtph2ps, vcvtps2ph,
// FMA

View File

@ -10,32 +10,38 @@ mir: Mir,
cc: std.builtin.CallingConvention,
err_msg: ?*Zcu.ErrorMsg = null,
src_loc: Zcu.LazySrcLoc,
result_insts_len: u8 = undefined,
result_relocs_len: u8 = undefined,
result_insts: [
@max(
1, // non-pseudo instructions
3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
2, // cmovcc: cmovcc \ cmovcc
3, // setcc: setcc \ setcc \ logicop
2, // jcc: jcc \ jcc
pseudo_probe_align_insts,
pseudo_probe_adjust_unrolled_max_insts,
pseudo_probe_adjust_setup_insts,
pseudo_probe_adjust_loop_insts,
abi.Win64.callee_preserved_regs.len * 2, // push_regs/pop_regs
abi.SysV.callee_preserved_regs.len * 2, // push_regs/pop_regs
)
]Instruction = undefined,
result_relocs: [
@max(
1, // jmp/jcc/call/mov/lea: jmp/jcc/call/mov/lea
2, // jcc: jcc \ jcc
2, // test \ jcc \ probe \ sub \ jmp
1, // probe \ sub \ jcc
3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
)
]Reloc = undefined,
result_insts_len: ResultInstIndex = undefined,
result_insts: [max_result_insts]Instruction = undefined,
result_relocs_len: ResultRelocIndex = undefined,
result_relocs: [max_result_relocs]Reloc = undefined,
const max_result_insts = @max(
1, // non-pseudo instructions
3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
2, // cmovcc: cmovcc \ cmovcc
3, // setcc: setcc \ setcc \ logicop
2, // jcc: jcc \ jcc
pseudo_probe_align_insts,
pseudo_probe_adjust_unrolled_max_insts,
pseudo_probe_adjust_setup_insts,
pseudo_probe_adjust_loop_insts,
abi.Win64.callee_preserved_regs.len * 2, // push_regs/pop_regs
abi.SysV.callee_preserved_regs.len * 2, // push_regs/pop_regs
);
const max_result_relocs = @max(
1, // jmp/jcc/call/mov/lea: jmp/jcc/call/mov/lea
2, // jcc: jcc \ jcc
2, // test \ jcc \ probe \ sub \ jmp
1, // probe \ sub \ jcc
3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
);
const ResultInstIndex = std.math.IntFittingRange(0, max_result_insts - 1);
const ResultRelocIndex = std.math.IntFittingRange(0, max_result_relocs - 1);
const InstOpIndex = std.math.IntFittingRange(
0,
@typeInfo(@FieldType(Instruction, "ops")).array.len - 1,
);
pub const pseudo_probe_align_insts = 5; // test \ jcc \ probe \ sub \ jmp
pub const pseudo_probe_adjust_unrolled_max_insts =
@ -51,7 +57,8 @@ pub const Error = error{
};
pub const Reloc = struct {
lowered_inst_index: u8,
lowered_inst_index: ResultInstIndex,
op_index: InstOpIndex,
target: Target,
off: i32,
@ -114,11 +121,11 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
assert(inst.data.rx.fixes == ._);
try lower.emit(.none, .cmovnz, &.{
.{ .reg = inst.data.rx.r1 },
.{ .mem = lower.mem(inst.data.rx.payload) },
.{ .mem = lower.mem(1, inst.data.rx.payload) },
});
try lower.emit(.none, .cmovp, &.{
.{ .reg = inst.data.rx.r1 },
.{ .mem = lower.mem(inst.data.rx.payload) },
.{ .mem = lower.mem(1, inst.data.rx.payload) },
});
},
.pseudo_set_z_and_np_r => {
@ -137,13 +144,13 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.pseudo_set_z_and_np_m => {
assert(inst.data.rx.fixes == ._);
try lower.emit(.none, .setz, &.{
.{ .mem = lower.mem(inst.data.rx.payload) },
.{ .mem = lower.mem(0, inst.data.rx.payload) },
});
try lower.emit(.none, .setnp, &.{
.{ .reg = inst.data.rx.r1 },
});
try lower.emit(.none, .@"and", &.{
.{ .mem = lower.mem(inst.data.rx.payload) },
.{ .mem = lower.mem(0, inst.data.rx.payload) },
.{ .reg = inst.data.rx.r1 },
});
},
@ -163,32 +170,32 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.pseudo_set_nz_or_p_m => {
assert(inst.data.rx.fixes == ._);
try lower.emit(.none, .setnz, &.{
.{ .mem = lower.mem(inst.data.rx.payload) },
.{ .mem = lower.mem(0, inst.data.rx.payload) },
});
try lower.emit(.none, .setp, &.{
.{ .reg = inst.data.rx.r1 },
});
try lower.emit(.none, .@"or", &.{
.{ .mem = lower.mem(inst.data.rx.payload) },
.{ .mem = lower.mem(0, inst.data.rx.payload) },
.{ .reg = inst.data.rx.r1 },
});
},
.pseudo_j_z_and_np_inst => {
assert(inst.data.inst.fixes == ._);
try lower.emit(.none, .jnz, &.{
.{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
.{ .imm = lower.reloc(0, .{ .inst = index + 1 }, 0) },
});
try lower.emit(.none, .jnp, &.{
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
.{ .imm = lower.reloc(0, .{ .inst = inst.data.inst.inst }, 0) },
});
},
.pseudo_j_nz_or_p_inst => {
assert(inst.data.inst.fixes == ._);
try lower.emit(.none, .jnz, &.{
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
.{ .imm = lower.reloc(0, .{ .inst = inst.data.inst.inst }, 0) },
});
try lower.emit(.none, .jp, &.{
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
.{ .imm = lower.reloc(0, .{ .inst = inst.data.inst.inst }, 0) },
});
},
@ -198,7 +205,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.{ .imm = .s(@bitCast(inst.data.ri.i)) },
});
try lower.emit(.none, .jz, &.{
.{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
.{ .imm = lower.reloc(0, .{ .inst = index + 1 }, 0) },
});
try lower.emit(.none, .lea, &.{
.{ .reg = inst.data.ri.r1 },
@ -214,7 +221,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.{ .reg = inst.data.ri.r1.to32() },
});
try lower.emit(.none, .jmp, &.{
.{ .imm = lower.reloc(.{ .inst = index }, 0) },
.{ .imm = lower.reloc(0, .{ .inst = index }, 0) },
});
assert(lower.result_insts_len == pseudo_probe_align_insts);
},
@ -260,7 +267,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.{ .imm = .s(page_size) },
});
try lower.emit(.none, .jae, &.{
.{ .imm = lower.reloc(.{ .inst = index }, 0) },
.{ .imm = lower.reloc(0, .{ .inst = index }, 0) },
});
assert(lower.result_insts_len == pseudo_probe_adjust_loop_insts);
},
@ -382,21 +389,22 @@ pub fn imm(lower: *const Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
};
}
pub fn mem(lower: *Lower, payload: u32) Memory {
pub fn mem(lower: *Lower, op_index: InstOpIndex, payload: u32) Memory {
var m = lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();
switch (m) {
.sib => |*sib| switch (sib.base) {
else => {},
.table => sib.disp = lower.reloc(.table, sib.disp).signed,
.table => sib.disp = lower.reloc(op_index, .table, sib.disp).signed,
},
else => {},
}
return m;
}
fn reloc(lower: *Lower, target: Reloc.Target, off: i32) Immediate {
fn reloc(lower: *Lower, op_index: InstOpIndex, target: Reloc.Target, off: i32) Immediate {
lower.result_relocs[lower.result_relocs_len] = .{
.lowered_inst_index = lower.result_insts_len,
.op_index = op_index,
.target = target,
.off = off,
};
@ -409,7 +417,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
var emit_mnemonic = mnemonic;
var emit_ops_storage: [4]Operand = undefined;
const emit_ops = emit_ops_storage[0..ops.len];
for (emit_ops, ops) |*emit_op, op| {
for (emit_ops, ops, 0..) |*emit_op, op, op_index| {
emit_op.* = switch (op) {
else => op,
.mem => |mem_op| switch (mem_op.base()) {
@ -428,22 +436,22 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
if (lower.pic) {
// Here, we currently assume local dynamic TLS vars, and so
// we emit LD model.
_ = lower.reloc(.{ .linker_tlsld = sym_index }, 0);
_ = lower.reloc(1, .{ .linker_tlsld = sym_index }, 0);
lower.result_insts[lower.result_insts_len] = try .new(.none, .lea, &.{
.{ .reg = .rdi },
.{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) },
.{ .mem = Memory.initRip(.none, 0) },
}, lower.target);
lower.result_insts_len += 1;
_ = lower.reloc(.{
_ = lower.reloc(0, .{
.linker_extern_fn = try elf_file.getGlobalSymbol("__tls_get_addr", null),
}, 0);
lower.result_insts[lower.result_insts_len] = try .new(.none, .call, &.{
.{ .imm = .s(0) },
}, lower.target);
lower.result_insts_len += 1;
_ = lower.reloc(.{ .linker_dtpoff = sym_index }, 0);
_ = lower.reloc(@intCast(op_index), .{ .linker_dtpoff = sym_index }, 0);
emit_mnemonic = .lea;
break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{
break :op .{ .mem = Memory.initSib(.none, .{
.base = .{ .reg = .rax },
.disp = std.math.minInt(i32),
}) };
@ -454,24 +462,26 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
.{ .mem = Memory.initSib(.qword, .{ .base = .{ .reg = .fs } }) },
}, lower.target);
lower.result_insts_len += 1;
_ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
_ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
emit_mnemonic = .lea;
break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{
break :op .{ .mem = Memory.initSib(.none, .{
.base = .{ .reg = .rax },
.disp = std.math.minInt(i32),
}) };
}
}
_ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
if (lower.pic) switch (mnemonic) {
.lea => {
if (elf_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
break :op .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) };
_ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
if (!elf_sym.flags.is_extern_ptr) break :op .{ .mem = Memory.initRip(.none, 0) };
emit_mnemonic = .mov;
break :op .{ .mem = Memory.initRip(.ptr, 0) };
},
.mov => {
if (elf_sym.flags.is_extern_ptr) {
const reg = ops[0].reg;
_ = lower.reloc(1, .{ .linker_reloc = sym_index }, 0);
lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
.{ .reg = reg.to64() },
.{ .mem = Memory.initRip(.qword, 0) },
@ -481,10 +491,13 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
.reg = reg.to64(),
} }) };
}
_ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
break :op .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) };
},
else => unreachable,
} else switch (mnemonic) {
};
_ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
switch (mnemonic) {
.call => break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{
.base = .{ .reg = .ds },
}) },
@ -502,10 +515,10 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
const macho_sym = zo.symbols.items[sym_index];
if (macho_sym.flags.tlv) {
_ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
_ = lower.reloc(1, .{ .linker_reloc = sym_index }, 0);
lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
.{ .reg = .rdi },
.{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) },
.{ .mem = Memory.initRip(.ptr, 0) },
}, lower.target);
lower.result_insts_len += 1;
lower.result_insts[lower.result_insts_len] = try .new(.none, .call, &.{
@ -516,15 +529,17 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
break :op .{ .reg = .rax };
}
_ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
break :op switch (mnemonic) {
.lea => {
if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
break :op .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) };
_ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
if (!macho_sym.flags.is_extern_ptr) break :op .{ .mem = Memory.initRip(.none, 0) };
emit_mnemonic = .mov;
break :op .{ .mem = Memory.initRip(.ptr, 0) };
},
.mov => {
if (macho_sym.flags.is_extern_ptr) {
const reg = ops[0].reg;
_ = lower.reloc(1, .{ .linker_reloc = sym_index }, 0);
lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
.{ .reg = reg.to64() },
.{ .mem = Memory.initRip(.qword, 0) },
@ -534,6 +549,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
.reg = reg.to64(),
} }) };
}
_ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
break :op .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) };
},
else => unreachable,
@ -550,7 +566,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
}
fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
@setEvalBranchQuota(2_400);
@setEvalBranchQuota(2_500);
const fixes = switch (inst.ops) {
.none => inst.data.none.fixes,
.inst => inst.data.inst.fixes,
@ -595,7 +611,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
}, switch (inst.ops) {
.none => &.{},
.inst => &.{
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
.{ .imm = lower.reloc(0, .{ .inst = inst.data.inst.inst }, 0) },
},
.i_s, .i_u => &.{
.{ .imm = lower.imm(inst.ops, inst.data.i.i) },
@ -642,10 +658,10 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
.{ .imm = lower.imm(inst.ops, inst.data.rri.i) },
},
.m => &.{
.{ .mem = lower.mem(inst.data.x.payload) },
.{ .mem = lower.mem(0, inst.data.x.payload) },
},
.mi_s, .mi_u => &.{
.{ .mem = lower.mem(inst.data.x.payload + 1) },
.{ .mem = lower.mem(0, inst.data.x.payload + 1) },
.{ .imm = lower.imm(
inst.ops,
lower.mir.extraData(Mir.Imm32, inst.data.x.payload).data.imm,
@ -653,64 +669,64 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
},
.rm => &.{
.{ .reg = inst.data.rx.r1 },
.{ .mem = lower.mem(inst.data.rx.payload) },
.{ .mem = lower.mem(1, inst.data.rx.payload) },
},
.rmr => &.{
.{ .reg = inst.data.rrx.r1 },
.{ .mem = lower.mem(inst.data.rrx.payload) },
.{ .mem = lower.mem(1, inst.data.rrx.payload) },
.{ .reg = inst.data.rrx.r2 },
},
.rmi => &.{
.{ .reg = inst.data.rix.r1 },
.{ .mem = lower.mem(inst.data.rix.payload) },
.{ .mem = lower.mem(1, inst.data.rix.payload) },
.{ .imm = lower.imm(inst.ops, inst.data.rix.i) },
},
.rmi_s, .rmi_u => &.{
.{ .reg = inst.data.rx.r1 },
.{ .mem = lower.mem(inst.data.rx.payload + 1) },
.{ .mem = lower.mem(1, inst.data.rx.payload + 1) },
.{ .imm = lower.imm(
inst.ops,
lower.mir.extraData(Mir.Imm32, inst.data.rx.payload).data.imm,
) },
},
.mr => &.{
.{ .mem = lower.mem(inst.data.rx.payload) },
.{ .mem = lower.mem(0, inst.data.rx.payload) },
.{ .reg = inst.data.rx.r1 },
},
.mrr => &.{
.{ .mem = lower.mem(inst.data.rrx.payload) },
.{ .mem = lower.mem(0, inst.data.rrx.payload) },
.{ .reg = inst.data.rrx.r1 },
.{ .reg = inst.data.rrx.r2 },
},
.mri => &.{
.{ .mem = lower.mem(inst.data.rix.payload) },
.{ .mem = lower.mem(0, inst.data.rix.payload) },
.{ .reg = inst.data.rix.r1 },
.{ .imm = lower.imm(inst.ops, inst.data.rix.i) },
},
.rrm => &.{
.{ .reg = inst.data.rrx.r1 },
.{ .reg = inst.data.rrx.r2 },
.{ .mem = lower.mem(inst.data.rrx.payload) },
.{ .mem = lower.mem(2, inst.data.rrx.payload) },
},
.rrmr => &.{
.{ .reg = inst.data.rrrx.r1 },
.{ .reg = inst.data.rrrx.r2 },
.{ .mem = lower.mem(inst.data.rrrx.payload) },
.{ .mem = lower.mem(2, inst.data.rrrx.payload) },
.{ .reg = inst.data.rrrx.r3 },
},
.rrmi => &.{
.{ .reg = inst.data.rrix.r1 },
.{ .reg = inst.data.rrix.r2 },
.{ .mem = lower.mem(inst.data.rrix.payload) },
.{ .mem = lower.mem(2, inst.data.rrix.payload) },
.{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },
},
.extern_fn_reloc, .rel => &.{
.{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc.sym_index }, inst.data.reloc.off) },
.{ .imm = lower.reloc(0, .{ .linker_extern_fn = inst.data.reloc.sym_index }, inst.data.reloc.off) },
},
.got_reloc, .direct_reloc, .import_reloc => ops: {
const reg = inst.data.rx.r1;
const extra = lower.mir.extraData(bits.SymbolOffset, inst.data.rx.payload).data;
_ = lower.reloc(switch (inst.ops) {
_ = lower.reloc(1, switch (inst.ops) {
.got_reloc => .{ .linker_got = extra.sym_index },
.direct_reloc => .{ .linker_direct = extra.sym_index },
.import_reloc => .{ .linker_import = extra.sym_index },

View File

@ -100,6 +100,8 @@ pub const Inst = struct {
/// ___ Division
_d,
/// ___ Without Affecting Flags
_x,
/// ___ Left
_l,
/// ___ Left Double
@ -483,6 +485,7 @@ pub const Inst = struct {
/// ASCII adjust al after subtraction
aa,
/// Add with carry
/// Unsigned integer addition of two operands with carry flag
adc,
/// Add
/// Add packed integers
@ -1162,10 +1165,8 @@ pub const Inst = struct {
fmadd231,
// ADX
/// Unsigned integer addition of two operands with carry flag
adcx,
/// Unsigned integer addition of two operands with overflow flag
adox,
ado,
// AESKLE
/// Encode 128-bit key with key locker

View File

@ -405,9 +405,9 @@ pub const table = [_]Entry{
.{ .jb, .d, &.{ .rel32 }, &.{ 0x0f, 0x82 }, 0, .none, .none },
.{ .jbe, .d, &.{ .rel32 }, &.{ 0x0f, 0x86 }, 0, .none, .none },
.{ .jc, .d, &.{ .rel32 }, &.{ 0x0f, 0x82 }, 0, .none, .none },
.{ .jcxz, .d, &.{ .rel32 }, &.{ 0xe3 }, 0, .short, .@"32bit" },
.{ .jecxz, .d, &.{ .rel32 }, &.{ 0xe3 }, 0, .none, .@"32bit" },
.{ .jrcxz, .d, &.{ .rel32 }, &.{ 0xe3 }, 0, .none, .@"64bit" },
.{ .jcxz, .d, &.{ .rel8 }, &.{ 0xe3 }, 0, .short, .@"32bit" },
.{ .jecxz, .d, &.{ .rel8 }, &.{ 0xe3 }, 0, .none, .@"32bit" },
.{ .jrcxz, .d, &.{ .rel8 }, &.{ 0xe3 }, 0, .none, .@"64bit" },
.{ .je, .d, &.{ .rel32 }, &.{ 0x0f, 0x84 }, 0, .none, .none },
.{ .jg, .d, &.{ .rel32 }, &.{ 0x0f, 0x8f }, 0, .none, .none },
.{ .jge, .d, &.{ .rel32 }, &.{ 0x0f, 0x8d }, 0, .none, .none },
@ -477,10 +477,6 @@ pub const table = [_]Entry{
.{ .ltr, .m, &.{ .rm16 }, &.{ 0x0f, 0x00 }, 3, .none, .none },
.{ .lzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .short, .lzcnt },
.{ .lzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none, .lzcnt },
.{ .lzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .long, .lzcnt },
.{ .mfence, .z, &.{}, &.{ 0x0f, 0xae, 0xf0 }, 0, .none, .none },
.{ .mov, .mr, &.{ .rm8, .r8 }, &.{ 0x88 }, 0, .none, .none },
@ -630,10 +626,6 @@ pub const table = [_]Entry{
.{ .pop, .m, &.{ .rm16 }, &.{ 0x8f }, 0, .short, .none },
.{ .pop, .m, &.{ .rm64 }, &.{ 0x8f }, 0, .none, .none },
.{ .popcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .short, .popcnt },
.{ .popcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none, .popcnt },
.{ .popcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long, .popcnt },
.{ .popf, .z, &.{}, &.{ 0x9d }, 0, .short, .none },
.{ .popfd, .z, &.{}, &.{ 0x9d }, 0, .none, .@"32bit" },
.{ .popfq, .z, &.{}, &.{ 0x9d }, 0, .none, .@"64bit" },
@ -1738,6 +1730,15 @@ pub const table = [_]Entry{
.{ .pcmpgtq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x37 }, 0, .none, .sse4_2 },
// ABM
.{ .lzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .short, .lzcnt },
.{ .lzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none, .lzcnt },
.{ .lzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .long, .lzcnt },
.{ .popcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .short, .popcnt },
.{ .popcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none, .popcnt },
.{ .popcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long, .popcnt },
// PCLMUL
.{ .pclmulqdq, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x44 }, 0, .none, .pclmul },
@ -1771,38 +1772,6 @@ pub const table = [_]Entry{
.{ .sha256msg2, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x38, 0xcd }, 0, .none, .sha },
// AVX
.{ .andn, .rvm, &.{ .r32, .r32, .rm32 }, &.{ 0x0f, 0x38, 0xf2 }, 0, .vex_lz_w0, .bmi },
.{ .andn, .rvm, &.{ .r64, .r64, .rm64 }, &.{ 0x0f, 0x38, 0xf2 }, 0, .vex_lz_w1, .bmi },
.{ .bextr, .rmv, &.{ .r32, .rm32, .r32 }, &.{ 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w0, .bmi },
.{ .bextr, .rmv, &.{ .r64, .rm64, .r64 }, &.{ 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w1, .bmi },
.{ .blsi, .vm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x38, 0xf3 }, 3, .vex_lz_w0, .bmi },
.{ .blsi, .vm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x38, 0xf3 }, 3, .vex_lz_w1, .bmi },
.{ .blsmsk, .vm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x38, 0xf3 }, 2, .vex_lz_w0, .bmi },
.{ .blsmsk, .vm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x38, 0xf3 }, 2, .vex_lz_w1, .bmi },
.{ .blsr, .vm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x38, 0xf3 }, 1, .vex_lz_w0, .bmi },
.{ .blsr, .vm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x38, 0xf3 }, 1, .vex_lz_w1, .bmi },
.{ .bzhi, .rmv, &.{ .r32, .rm32, .r32 }, &.{ 0x0f, 0x38, 0xf5 }, 0, .vex_lz_w0, .bmi2 },
.{ .bzhi, .rmv, &.{ .r64, .rm64, .r64 }, &.{ 0x0f, 0x38, 0xf5 }, 0, .vex_lz_w1, .bmi2 },
.{ .rorx, .rmi, &.{ .r32, .rm32, .imm8 }, &.{ 0xf2, 0x0f, 0x3a }, 0, .vex_lz_w0, .bmi2 },
.{ .rorx, .rmi, &.{ .r64, .rm64, .imm8 }, &.{ 0xf2, 0x0f, 0x3a }, 0, .vex_lz_w1, .bmi2 },
.{ .sarx, .rmv, &.{ .r32, .rm32, .r32 }, &.{ 0xf3, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w0, .bmi2 },
.{ .shlx, .rmv, &.{ .r32, .rm32, .r32 }, &.{ 0x66, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w0, .bmi2 },
.{ .shrx, .rmv, &.{ .r32, .rm32, .r32 }, &.{ 0xf2, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w0, .bmi2 },
.{ .sarx, .rmv, &.{ .r64, .rm64, .r64 }, &.{ 0xf3, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w1, .bmi2 },
.{ .shlx, .rmv, &.{ .r64, .rm64, .r64 }, &.{ 0x66, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w1, .bmi2 },
.{ .shrx, .rmv, &.{ .r64, .rm64, .r64 }, &.{ 0xf2, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w1, .bmi2 },
.{ .tzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .short, .bmi },
.{ .tzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none, .bmi },
.{ .tzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .long, .bmi },
.{ .vaddpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x58 }, 0, .vex_128_wig, .avx },
.{ .vaddpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x58 }, 0, .vex_256_wig, .avx },
@ -2307,6 +2276,49 @@ pub const table = [_]Entry{
.{ .vxorps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x57 }, 0, .vex_128_wig, .avx },
.{ .vxorps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x57 }, 0, .vex_256_wig, .avx },
// BMI
.{ .andn, .rvm, &.{ .r32, .r32, .rm32 }, &.{ 0x0f, 0x38, 0xf2 }, 0, .vex_lz_w0, .bmi },
.{ .andn, .rvm, &.{ .r64, .r64, .rm64 }, &.{ 0x0f, 0x38, 0xf2 }, 0, .vex_lz_w1, .bmi },
.{ .bextr, .rmv, &.{ .r32, .rm32, .r32 }, &.{ 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w0, .bmi },
.{ .bextr, .rmv, &.{ .r64, .rm64, .r64 }, &.{ 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w1, .bmi },
.{ .blsi, .vm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x38, 0xf3 }, 3, .vex_lz_w0, .bmi },
.{ .blsi, .vm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x38, 0xf3 }, 3, .vex_lz_w1, .bmi },
.{ .blsmsk, .vm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x38, 0xf3 }, 2, .vex_lz_w0, .bmi },
.{ .blsmsk, .vm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x38, 0xf3 }, 2, .vex_lz_w1, .bmi },
.{ .blsr, .vm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x38, 0xf3 }, 1, .vex_lz_w0, .bmi },
.{ .blsr, .vm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x38, 0xf3 }, 1, .vex_lz_w1, .bmi },
.{ .tzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .short, .bmi },
.{ .tzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none, .bmi },
.{ .tzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .long, .bmi },
// BMI2
.{ .bzhi, .rmv, &.{ .r32, .rm32, .r32 }, &.{ 0x0f, 0x38, 0xf5 }, 0, .vex_lz_w0, .bmi2 },
.{ .bzhi, .rmv, &.{ .r64, .rm64, .r64 }, &.{ 0x0f, 0x38, 0xf5 }, 0, .vex_lz_w1, .bmi2 },
.{ .mulx, .rvm, &.{ .r32, .r32, .rm32 }, &.{ 0xf2, 0x0f, 0x38, 0xf6 }, 0, .vex_lz_w0, .bmi2 },
.{ .mulx, .rvm, &.{ .r64, .r64, .rm64 }, &.{ 0xf2, 0x0f, 0x38, 0xf6 }, 0, .vex_lz_w1, .bmi2 },
.{ .pdep, .rvm, &.{ .r32, .r32, .rm32 }, &.{ 0xf2, 0x0f, 0x38, 0xf5 }, 0, .vex_lz_w0, .bmi2 },
.{ .pdep, .rvm, &.{ .r64, .r64, .rm64 }, &.{ 0xf2, 0x0f, 0x38, 0xf5 }, 0, .vex_lz_w1, .bmi2 },
.{ .pext, .rvm, &.{ .r32, .r32, .rm32 }, &.{ 0xf3, 0x0f, 0x38, 0xf5 }, 0, .vex_lz_w0, .bmi2 },
.{ .pext, .rvm, &.{ .r64, .r64, .rm64 }, &.{ 0xf3, 0x0f, 0x38, 0xf5 }, 0, .vex_lz_w1, .bmi2 },
.{ .rorx, .rmi, &.{ .r32, .rm32, .imm8 }, &.{ 0xf2, 0x0f, 0x3a }, 0, .vex_lz_w0, .bmi2 },
.{ .rorx, .rmi, &.{ .r64, .rm64, .imm8 }, &.{ 0xf2, 0x0f, 0x3a }, 0, .vex_lz_w1, .bmi2 },
.{ .sarx, .rmv, &.{ .r32, .rm32, .r32 }, &.{ 0xf3, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w0, .bmi2 },
.{ .shlx, .rmv, &.{ .r32, .rm32, .r32 }, &.{ 0x66, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w0, .bmi2 },
.{ .shrx, .rmv, &.{ .r32, .rm32, .r32 }, &.{ 0xf2, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w0, .bmi2 },
.{ .sarx, .rmv, &.{ .r64, .rm64, .r64 }, &.{ 0xf3, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w1, .bmi2 },
.{ .shlx, .rmv, &.{ .r64, .rm64, .r64 }, &.{ 0x66, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w1, .bmi2 },
.{ .shrx, .rmv, &.{ .r64, .rm64, .r64 }, &.{ 0xf2, 0x0f, 0x38, 0xf7 }, 0, .vex_lz_w1, .bmi2 },
// F16C
.{ .vcvtph2ps, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x66, 0x0f, 0x38, 0x13 }, 0, .vex_128_w0, .f16c },
.{ .vcvtph2ps, .rm, &.{ .ymm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x13 }, 0, .vex_256_w0, .f16c },

View File

@ -83,8 +83,10 @@ pub fn generateLazyFunction(
debug_output: link.File.DebugInfoOutput,
) CodeGenError!void {
const zcu = pt.zcu;
const file = Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(&zcu.intern_pool);
const target = zcu.fileByIndex(file).mod.resolved_target.result;
const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|
zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.resolved_target.result
else
zcu.getTarget();
switch (target_util.zigBackend(target, false)) {
else => unreachable,
inline .stage2_x86_64, .stage2_riscv64 => |backend| {

View File

@ -39,10 +39,7 @@ test {
_ = Package;
}
const thread_stack_size = switch (builtin.zig_backend) {
else => std.Thread.SpawnConfig.default_stack_size,
.stage2_x86_64 => 32 << 20,
};
const thread_stack_size = 32 << 20;
pub const std_options: std.Options = .{
.wasiCwd = wasi_cwd,

View File

@ -726,11 +726,11 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
else => false,
},
.is_named_enum_value => switch (backend) {
.stage2_llvm => true,
.stage2_llvm, .stage2_x86_64 => true,
else => false,
},
.error_set_has_value => switch (backend) {
.stage2_llvm, .stage2_wasm => true,
.stage2_llvm, .stage2_wasm, .stage2_x86_64 => true,
else => false,
},
.field_reordering => switch (backend) {

View File

@ -527,7 +527,7 @@ fn testIntDivision() !void {
try expect(mod(i64, -14, 12) == 10);
try expect(mod(i16, -2, 12) == 10);
try expect(mod(i16, -118, 12) == 2);
try expect(mod(i8, -2, 12) == 10); // TODO: fails in x86_64
try expect(mod(i8, -2, 12) == 10);
try expect(rem(i64, -118, 12) == -10);
try expect(rem(i32, 10, 12) == 10);

View File

@ -93,6 +93,11 @@ pub fn build(b: *std.Build) void {
.cpu_arch = .x86_64,
.cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v3 },
},
.{
.cpu_arch = .x86_64,
.cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v3 },
.cpu_features_add = std.Target.x86.featureSet(&.{.adx}),
},
.{
.cpu_arch = .x86_64,
.cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v4 },

View File

@ -33,6 +33,28 @@ fn Scalar(comptime Type: type) type {
.vector => |info| info.child,
};
}
fn AddOneBit(comptime Type: type) type {
const ResultScalar = switch (@typeInfo(Scalar(Type))) {
.int => |int| @Type(.{ .int = .{ .signedness = int.signedness, .bits = 1 + int.bits } }),
.float => Scalar(Type),
else => @compileError(@typeName(Type)),
};
return switch (@typeInfo(Type)) {
else => ResultScalar,
.vector => |vector| @Vector(vector.len, ResultScalar),
};
}
fn DoubleBits(comptime Type: type) type {
const ResultScalar = switch (@typeInfo(Scalar(Type))) {
.int => |int| @Type(.{ .int = .{ .signedness = int.signedness, .bits = int.bits * 2 } }),
.float => Scalar(Type),
else => @compileError(@typeName(Type)),
};
return switch (@typeInfo(Type)) {
else => ResultScalar,
.vector => |vector| @Vector(vector.len, ResultScalar),
};
}
// inline to avoid a runtime `@splat`
inline fn splat(comptime Type: type, scalar: Scalar(Type)) Type {
return switch (@typeInfo(Type)) {
@ -16205,6 +16227,8 @@ fn binary(comptime op: anytype, comptime opts: struct { compare: Compare = .rela
);
}
fn testInts() !void {
try testArgs(i4, 0x3, 0x2);
try testArgs(u4, 0xe, 0x6);
try testArgs(i8, 0x48, 0x6c);
try testArgs(u8, 0xbb, 0x43);
try testArgs(i16, -0x0fdf, 0x302e);
@ -17967,8 +17991,8 @@ fn binary(comptime op: anytype, comptime opts: struct { compare: Compare = .rela
-0x12, -0x1e, 0x18, 0x6e, 0x31, 0x53, -0x6a, -0x34, 0x13, 0x4d, 0x30, -0x7d, -0x31, 0x1e, -0x24, 0x32,
-0x1e, -0x01, 0x55, 0x33, -0x75, -0x44, -0x57, 0x2b, -0x66, 0x19, 0x7f, -0x28, -0x3f, -0x7e, -0x5d, -0x06,
}, .{
0x05, -0x23, 0x43, -0x54, -0x41, 0x7f, -0x6a, -0x31, 0x04, 0x15, -0x7a, -0x37, 0x6d, 0x16, 0x00, 0x4a,
0x15, 0x55, -0x4a, 0x16, -0x73, -0x0c, 0x1c, -0x26, -0x14, 0x00, 0x55, 0x7b, 0x16, -0x2e, -0x5f, -0x67,
0x05, -0x23, 0x43, -0x54, -0x41, 0x7f, -0x6a, -0x31, 0x04, 0x15, -0x7a, -0x37, 0x6d, 0x16, 0x01, 0x4a,
0x15, 0x55, -0x4a, 0x16, -0x73, -0x0c, 0x1c, -0x26, -0x14, -0x01, 0x55, 0x7b, 0x16, -0x2e, -0x5f, -0x67,
});
try testArgs(@Vector(64, i8), .{
-0x05, 0x76, 0x4e, -0x5c, 0x7b, -0x1a, -0x38, -0x2e, 0x3d, 0x36, 0x01, 0x30, -0x02, -0x71, -0x24, 0x24,
@ -17997,7 +18021,7 @@ fn binary(comptime op: anytype, comptime opts: struct { compare: Compare = .rela
0x23, 0x3b, 0x0a, 0x7a, 0x19, 0x14, 0x65, -0x1d, 0x2b, 0x65, 0x33, 0x2a, 0x52, -0x63, 0x57, 0x10,
-0x1b, 0x26, -0x46, -0x7e, -0x25, 0x79, -0x01, -0x0d, -0x49, -0x4d, 0x74, 0x03, 0x77, 0x16, 0x03, -0x3d,
0x1c, 0x25, 0x5a, -0x2f, -0x16, -0x5f, -0x36, -0x55, -0x44, -0x0c, -0x0f, 0x7b, -0x15, -0x1d, 0x32, 0x31,
0x6e, -0x44, -0x4a, -0x64, 0x67, 0x04, 0x47, 0x00, 0x3c, -0x0a, -0x79, 0x3d, 0x48, 0x5a, 0x61, -0x2c,
0x6e, -0x44, -0x4a, -0x64, 0x67, 0x04, 0x47, -0x02, 0x3c, -0x0a, -0x79, 0x3d, 0x48, 0x5a, 0x61, -0x2c,
0x6d, -0x68, -0x71, -0x6b, -0x11, 0x44, -0x75, -0x55, -0x67, -0x52, 0x64, -0x3d, -0x05, -0x76, -0x6d, -0x44,
});
@ -18024,7 +18048,7 @@ fn binary(comptime op: anytype, comptime opts: struct { compare: Compare = .rela
try testArgs(@Vector(16, u8), .{
0xea, 0x80, 0xbb, 0xe8, 0x74, 0x81, 0xc8, 0x66, 0x7b, 0x41, 0x90, 0xcb, 0x30, 0x70, 0x4b, 0x0f,
}, .{
0x61, 0x26, 0xbe, 0x47, 0x00, 0x9c, 0x55, 0xa5, 0x59, 0xf0, 0xb2, 0x20, 0x30, 0xaf, 0x82, 0x3e,
0x61, 0x26, 0xbe, 0x47, 0x02, 0x9c, 0x55, 0xa5, 0x59, 0xf0, 0xb2, 0x20, 0x30, 0xaf, 0x82, 0x3e,
});
try testArgs(@Vector(32, u8), .{
0xa1, 0x88, 0xc4, 0xf4, 0x77, 0x0b, 0xf5, 0xbb, 0x09, 0x03, 0xbf, 0xf5, 0xcc, 0x7f, 0x6b, 0x2a,
@ -18950,22 +18974,45 @@ fn binary(comptime op: anytype, comptime opts: struct { compare: Compare = .rela
};
}
inline fn add(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs + rhs) {
return lhs + rhs;
inline fn addUnsafe(comptime Type: type, lhs: Type, rhs: Type) AddOneBit(Type) {
@setRuntimeSafety(false);
return @as(AddOneBit(Type), lhs) + rhs;
}
test add {
const test_add = binary(add, .{});
try test_add.testFloats();
try test_add.testFloatVectors();
test addUnsafe {
const test_add_unsafe = binary(addUnsafe, .{});
try test_add_unsafe.testInts();
try test_add_unsafe.testIntVectors();
try test_add_unsafe.testFloats();
try test_add_unsafe.testFloatVectors();
}
inline fn subtract(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs - rhs) {
return lhs - rhs;
inline fn subUnsafe(comptime Type: type, lhs: Type, rhs: Type) AddOneBit(Type) {
@setRuntimeSafety(false);
switch (@typeInfo(Scalar(Type))) {
else => @compileError(@typeName(Type)),
.int => |int| switch (int.signedness) {
.signed => {},
.unsigned => return @as(AddOneBit(Type), @max(lhs, rhs)) - @min(lhs, rhs),
},
.float => {},
}
return @as(AddOneBit(Type), lhs) - rhs;
}
test subtract {
const test_subtract = binary(subtract, .{});
try test_subtract.testFloats();
try test_subtract.testFloatVectors();
test subUnsafe {
const test_sub_unsafe = binary(subUnsafe, .{});
try test_sub_unsafe.testInts();
try test_sub_unsafe.testIntVectors();
try test_sub_unsafe.testFloats();
try test_sub_unsafe.testFloatVectors();
}
inline fn mulUnsafe(comptime Type: type, lhs: Type, rhs: Type) DoubleBits(Type) {
@setRuntimeSafety(false);
return @as(DoubleBits(Type), lhs) * rhs;
}
test mulUnsafe {
const test_mul_unsafe = binary(mulUnsafe, .{});
try test_mul_unsafe.testInts();
}
inline fn multiply(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs * rhs) {
@ -18999,42 +19046,51 @@ test divide {
try test_divide.testFloatVectors();
}
// workaround https://github.com/ziglang/zig/issues/22748
// TODO: @TypeOf(@divTrunc(lhs, rhs))
inline fn divTrunc(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs / rhs) {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
return @trunc(lhs / rhs);
inline fn divTrunc(comptime Type: type, lhs: Type, rhs: Type) Type {
switch (@typeInfo(Scalar(Type))) {
else => @compileError(@typeName(Type)),
.int => return @divTrunc(lhs, rhs),
.float => {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
return @trunc(lhs / rhs);
}
// workaround https://github.com/ziglang/zig/issues/22748
// workaround https://github.com/ziglang/zig/issues/22749
// TODO: return @divTrunc(lhs, rhs);
var rt_lhs = lhs;
var rt_rhs = rhs;
_ = .{ &rt_lhs, &rt_rhs };
return @divTrunc(rt_lhs, rt_rhs);
},
}
// workaround https://github.com/ziglang/zig/issues/22748
// workaround https://github.com/ziglang/zig/issues/22749
// TODO: return @divTrunc(lhs, rhs);
var rt_lhs = lhs;
var rt_rhs = rhs;
_ = .{ &rt_lhs, &rt_rhs };
return @divTrunc(rt_lhs, rt_rhs);
}
test divTrunc {
const test_div_trunc = binary(divTrunc, .{ .compare = .approx_int });
try test_div_trunc.testInts();
try test_div_trunc.testIntVectors();
try test_div_trunc.testFloats();
try test_div_trunc.testFloatVectors();
}
// workaround https://github.com/ziglang/zig/issues/22748
// TODO: @TypeOf(@divFloor(lhs, rhs))
inline fn divFloor(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs / rhs) {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
return @floor(lhs / rhs);
inline fn divFloor(comptime Type: type, lhs: Type, rhs: Type) Type {
switch (@typeInfo(Scalar(Type))) {
else => @compileError(@typeName(Type)),
.int => return @divFloor(lhs, rhs),
.float => {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
return @floor(lhs / rhs);
}
// workaround https://github.com/ziglang/zig/issues/22748
// workaround https://github.com/ziglang/zig/issues/22749
// TODO: return @divFloor(lhs, rhs);
var rt_lhs = lhs;
var rt_rhs = rhs;
_ = .{ &rt_lhs, &rt_rhs };
return @divFloor(rt_lhs, rt_rhs);
},
}
// workaround https://github.com/ziglang/zig/issues/22748
// workaround https://github.com/ziglang/zig/issues/22749
// TODO: return @divFloor(lhs, rhs);
var rt_lhs = lhs;
var rt_rhs = rhs;
_ = &rt_lhs;
_ = &rt_rhs;
return @divFloor(rt_lhs, rt_rhs);
}
test divFloor {
const test_div_floor = binary(divFloor, .{ .compare = .approx_int });
@ -19045,25 +19101,33 @@ test divFloor {
// workaround https://github.com/ziglang/zig/issues/22748
// TODO: @TypeOf(@rem(lhs, rhs))
inline fn rem(comptime Type: type, lhs: Type, rhs: Type) Type {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
switch (@typeInfo(Type)) {
else => return if (rhs != 0) @rem(lhs, rhs) else nan(Type),
.vector => |info| {
var res: Type = undefined;
inline for (0..info.len) |i| res[i] = if (rhs[i] != 0) @rem(lhs[i], rhs[i]) else nan(Scalar(Type));
return res;
},
}
switch (@typeInfo(Scalar(Type))) {
else => @compileError(@typeName(Type)),
.int => return @rem(lhs, rhs),
.float => {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
switch (@typeInfo(Type)) {
else => return if (rhs != 0) @rem(lhs, rhs) else nan(Type),
.vector => |info| {
var res: Type = undefined;
inline for (0..info.len) |i| res[i] = if (rhs[i] != 0) @rem(lhs[i], rhs[i]) else nan(Scalar(Type));
return res;
},
}
}
// workaround https://github.com/ziglang/zig/issues/22748
// TODO: return @rem(lhs, rhs);
var rt_rhs = rhs;
_ = &rt_rhs;
return @rem(lhs, rt_rhs);
},
}
// workaround https://github.com/ziglang/zig/issues/22748
// TODO: return @rem(lhs, rhs);
var rt_rhs = rhs;
_ = &rt_rhs;
return @rem(lhs, rt_rhs);
}
test rem {
const test_rem = binary(rem, .{});
try test_rem.testInts();
try test_rem.testIntVectors();
try test_rem.testFloats();
try test_rem.testFloatVectors();
}

View File

@ -1,4 +1,4 @@
fn access(comptime array: anytype) !void {
fn accessSlice(comptime array: anytype) !void {
var slice: []const @typeInfo(@TypeOf(array)).array.child = undefined;
slice = &array;
inline for (0.., &array) |ct_index, *elem| {
@ -20,18 +20,153 @@ fn access(comptime array: anytype) !void {
if (slice[rt_index] != elem.*) return error.Unexpected;
}
}
test access {
try access([3]u8{ 0xdb, 0xef, 0xbd });
try access([3]u16{ 0x340e, 0x3654, 0x88d7 });
try access([3]u32{ 0xd424c2c0, 0x2d6ac466, 0x5a0cfaba });
try access([3]u64{
test accessSlice {
try accessSlice([3]u8{ 0xdb, 0xef, 0xbd });
try accessSlice([3]u16{ 0x340e, 0x3654, 0x88d7 });
try accessSlice([3]u32{ 0xd424c2c0, 0x2d6ac466, 0x5a0cfaba });
try accessSlice([3]u64{
0x9327a4f5221666a6,
0x5c34d3ddd84a8b12,
0xbae087f39f649260,
});
try access([3]u128{
try accessSlice([3]u128{
0x601cf010065444d4d42d5536dd9b95db,
0xa03f592fcaa22d40af23a0c735531e3c,
0x5da44907b31602b95c2d93f0b582ceab,
});
}
fn accessVector(comptime init: anytype) !void {
const Vector = @TypeOf(init);
var vector: Vector = undefined;
vector = init;
inline for (0..@typeInfo(Vector).vector.len) |ct_index| {
var rt_index: usize = undefined;
rt_index = ct_index;
if (&vector[rt_index] != &vector[ct_index]) return error.Unexpected;
if (vector[rt_index] != vector[ct_index]) return error.Unexpected;
}
}
test accessVector {
try accessVector(@Vector(1, bool){
false,
});
try accessVector(@Vector(2, bool){
false, true,
});
try accessVector(@Vector(3, bool){
true, true, false,
});
try accessVector(@Vector(5, bool){
true, false, true, false, true,
});
try accessVector(@Vector(7, bool){
true, false, true, true, true, false, true,
});
try accessVector(@Vector(8, bool){
false, true, false, true, false, false, false, true,
});
try accessVector(@Vector(9, bool){
true, true, false, true, false, false, false, false,
true,
});
try accessVector(@Vector(15, bool){
false, true, true, true, false, true, false, false,
true, true, false, false, true, false, false,
});
try accessVector(@Vector(16, bool){
true, true, false, true, false, false, false, false,
false, true, true, false, false, false, true, true,
});
try accessVector(@Vector(17, bool){
true, false, true, true, false, true, false, true,
true, true, true, false, false, false, true, true,
false,
});
try accessVector(@Vector(31, bool){
true, false, true, true, false, true, true, true,
false, true, false, true, false, true, true, true,
false, false, true, false, false, false, false, true,
true, true, true, false, false, false, false,
});
try accessVector(@Vector(32, bool){
true, true, false, false, false, true, true, true,
false, true, true, true, false, true, false, true,
false, true, false, true, false, true, true, false,
false, false, false, false, false, true, true, true,
});
try accessVector(@Vector(33, bool){
true, false, false, false, false, true, true, true,
false, false, true, false, true, true, false, true,
true, true, false, true, true, false, false, false,
false, true, false, false, false, true, true, false,
false,
});
try accessVector(@Vector(63, bool){
false, false, true, true, true, false, true, true,
true, false, true, true, true, false, true, false,
true, true, false, true, false, true, true, true,
false, false, true, false, false, false, false, true,
true, true, true, true, false, true, false, true,
true, true, false, false, true, false, false, true,
false, true, false, false, false, false, true, true,
false, true, false, false, true, true, true,
});
try accessVector(@Vector(64, bool){
false, false, true, true, true, false, true, true,
true, false, true, true, false, true, true, false,
false, false, false, false, true, true, false, true,
true, true, true, true, false, false, false, true,
true, false, true, true, false, false, true, false,
false, true, true, false, true, true, false, false,
true, true, false, true, false, true, true, true,
false, true, true, false, false, false, false, false,
});
try accessVector(@Vector(65, bool){
false, false, true, true, true, true, true, true,
true, false, false, false, false, true, true, false,
true, false, true, true, true, false, false, false,
true, false, true, true, false, true, true, true,
true, true, false, true, true, false, true, false,
false, true, false, true, false, false, true, false,
true, false, true, true, true, false, true, true,
false, false, true, true, true, true, false, false,
true,
});
try accessVector(@Vector(8, u8){
0x60, 0xf7, 0xf4, 0xb0, 0x05, 0xd3, 0x06, 0x78,
});
try accessVector(@Vector(8, u16){
0x9c91, 0xfb8b, 0x7f80, 0x8304, 0x6e52, 0xd8ef, 0x37fc, 0x7851,
});
try accessVector(@Vector(8, u32){
0x688b88e2, 0x68e2b7a2, 0x87574680, 0xab4f0769,
0x75472bb5, 0xa791f2ae, 0xeb2ed416, 0x5f05ce82,
});
try accessVector(@Vector(8, u64){
0xdefd1ddffaedf818, 0x91c78a29d3d59890,
0x842aaf8fd3c7b785, 0x970a07b8f9f4a6b3,
0x21b2425d1a428246, 0xea50e41174a7977b,
0x08d0f1c4f5978b74, 0x8dc88a7fd85e0e67,
});
try accessVector(@Vector(8, u128){
0x6f2cbde1fb219b1e73d7f774d10f0d94,
0x7c1412616cda20436d7106691d8ba4cc,
0x4ee940b50e97675b3b35d7872a35b5ad,
0x6d994fb8caa1b2fac48acbb68fa2d2f1,
0xdee698c7ec8de9b5940903e3fc665b63,
0x0751491a509e4a1ce8cfa6d62fe9e74c,
0x3d880f0a927ce3bfc2682b72070fcd50,
0x82f0eec62881598699eeb93fbb456e95,
});
try accessVector(@Vector(8, u256){
0x6ee4f35fe624d365952f73960791238ac781bfba782abc7866a691063e43ce48,
0xb006491f54a9c9292458a5835b7d5f4cfa18136f175eef0a13bb8adf5c3dc061,
0xd6e25ca1bc5685fc52609e261b9065bc05a8662e9291660033dd7f6d98e562b3,
0x992c5e54e0e6331dac258996be7dae9b2a2eff323a39043ba8d2721420dc5f5c,
0x257313f45fb3556d0fc323d5f38c953e9a093fe2278655312b6a5b64aab9d901,
0x6c8ad2182b9a3b2b19c2c9b152956b383d0fee2e3fbd5b02ed72227446a7b221,
0xd80cafc2252b289793799675e43f97ba4a5448c7b57e1544a464687b435efc7b,
0xfcb480f2d70afd53c4689dd3f5db7638c24302f2a6a15f738167db090d91fb28,
});
}

View File

@ -18,5 +18,5 @@ pub fn main() !void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -8,7 +8,7 @@ export fn entry() usize {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :4:29: error: invalid operands to binary expression: 'struct' and 'struct'

View File

@ -11,7 +11,7 @@ fn doSomeAsm() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :6:5: error: unable to evaluate comptime expression

View File

@ -8,7 +8,7 @@ export fn foo() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :4:5: error: asm cannot output to const local 'f'

View File

@ -17,7 +17,7 @@ export fn comptimeBuiltinCall() callconv(.Naked) void {
fn f() void {}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:6: error: runtime call not allowed in naked function

View File

@ -4,7 +4,7 @@ export fn entry() void {
fn foo() callconv(.naked) void {}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:5: error: unable to call function with calling convention 'naked'

View File

@ -10,7 +10,7 @@ export fn entry1() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:36: error: type 'u32' cannot represent integer value '-1'

View File

@ -5,7 +5,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :4:12: error: operator == not allowed for type '?[3]i32'

View File

@ -13,7 +13,7 @@ export fn baz() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :6:5: error: found compile log statement

View File

@ -10,7 +10,7 @@ fn inner(comptime n: usize) void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :8:9: error: found compile log statement

View File

@ -8,7 +8,7 @@ export fn entry() usize {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:16: error: division by zero here causes undefined behavior

View File

@ -5,7 +5,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:32: error: null pointer casted to type '*i32'

View File

@ -6,7 +6,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:32: error: use of undefined value here causes undefined behavior

View File

@ -6,7 +6,7 @@ export fn foo() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:9: error: expected type 'u16', found '*const [5:0]u8'

View File

@ -15,7 +15,7 @@ fn foo(x: i32) !void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :5:9: error: duplicate switch value

View File

@ -15,7 +15,7 @@ pub export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :9:48: error: caught unexpected error 'InvalidVersion'

View File

@ -13,7 +13,7 @@ fn foo(x: i32) !void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:26: error: switch must handle all possibilities

View File

@ -24,7 +24,7 @@ pub fn main() Error!void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :23:29: error: expected type 'error{InvalidCharacter}', found '@typeInfo(@typeInfo(@TypeOf(tmp.fooey)).@"fn".return_type.?).error_union.error_set'

View File

@ -4,7 +4,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: exact division produced remainder

View File

@ -8,7 +8,7 @@ export fn entry2() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: primitive integer type 'u65536' exceeds maximum bit width of 65535

View File

@ -4,7 +4,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:25: error: exported symbol name cannot be empty

View File

@ -4,7 +4,7 @@ export fn foo(a: *i32) Foo {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:12: error: expected pointer type, found 'i32'

View File

@ -4,7 +4,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: exact division produced remainder

View File

@ -7,7 +7,7 @@ fn concat() [16]f32 {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:17: error: expected type '[4]f32', found '[16]f32'

View File

@ -4,7 +4,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :1:1: error: non-extern function has no body

View File

@ -19,7 +19,7 @@ pub export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :18:43: error: value of type 'type' ignored

View File

@ -36,7 +36,7 @@ pub fn is(comptime id: std.builtin.TypeId) TraitFn {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :8:48: error: expected type 'type', found 'bool'

View File

@ -7,7 +7,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :6:9: error: array literal requires address-of operator (&) to coerce to slice type '[]i32'

View File

@ -11,7 +11,7 @@ export fn entry2() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:14: error: expected type 'f32', found 'f64'

View File

@ -13,7 +13,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :11:21: error: 'error.B' not a member of error set 'error{A,C}'

View File

@ -24,7 +24,7 @@ export fn incompatiblePointers4() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :5:9: error: incompatible types: '?@Vector(10, i32)' and '@Vector(11, i32)'

View File

@ -4,7 +4,7 @@ fn main() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:23: error: trailing digit separator

View File

@ -16,7 +16,7 @@ export fn entry4() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: primitive integer type 'u000123' has leading zero

View File

@ -11,7 +11,7 @@ fn loadv(ptr: anytype) i31 {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :10:15: error: unable to determine vector element index of type '*align(16:0:4:?) i31'

View File

@ -24,7 +24,7 @@ export fn foo() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :23:6: error: no field or member function named 'init' in 'tmp.List'

View File

@ -12,7 +12,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :4:26: error: array literal requires address-of operator (&) to coerce to slice type '[][2]f32'

View File

@ -1,5 +1,5 @@
// error
// backend=llvm
// backend=stage2
// target=x86_64-linux
// output_mode=Exe
//

View File

@ -11,7 +11,7 @@ fn foo() ?OtherError!i32 {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :5:34: error: expected type '?error{NextError}!i32', found '?error{OutOfMemory}!i32'

View File

@ -16,7 +16,7 @@ pub export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :15:28: error: expected type '*const fn (type, u8, u8) u32', found '*const fn (void, u8, u8) u32'

View File

@ -43,7 +43,7 @@ export fn entry7() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:31: error: backing integer type 'u32' has bit size 32 but the struct fields have a total bit size of 29

View File

@ -78,7 +78,7 @@ export fn entry14() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:12: error: packed structs cannot contain fields of type 'anyerror'

View File

@ -1,7 +1,7 @@
fn main() void {}
// error
// backend=llvm
// backend=stage2
// target=x86_64-linux
// output_mode=Exe
//

View File

@ -3,7 +3,7 @@ export fn entry(a: *i32) usize {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:12: error: expected pointer type, found 'usize'

View File

@ -13,7 +13,7 @@ fn foo(x: i32) !void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:34: error: ranges not allowed when switching on type '@typeInfo(@typeInfo(@TypeOf(tmp.foo)).@"fn".return_type.?).error_union.error_set'

View File

@ -6,7 +6,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:5: error: cannot assign to constant

View File

@ -6,7 +6,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:5: error: cannot assign to constant

View File

@ -7,7 +7,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:5: error: cannot return from naked function

View File

@ -4,7 +4,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: operation caused overflow

View File

@ -4,7 +4,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: exact shift shifted out 1 bits

View File

@ -3,7 +3,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :?:?: error: 10 unused arguments in '{d} {d} {d} {d} {d}'

View File

@ -11,7 +11,7 @@ fn storev(ptr: anytype, val: i31) void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :10:8: error: unable to determine vector element index of type '*align(16:0:4:?) i31'

View File

@ -8,7 +8,7 @@ fn foo() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :6:9: error: cannot suspend inside suspend block

View File

@ -20,7 +20,7 @@ export fn entry() usize {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :14:14: error: unreachable else prong; all cases already handled

View File

@ -7,7 +7,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:11: error: unable to evaluate comptime expression

View File

@ -21,7 +21,7 @@ pub export fn simple() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :7:14: error: unreachable else prong; all cases already handled

View File

@ -19,7 +19,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:5: error: runtime safety check not allowed in naked function

View File

@ -23,7 +23,7 @@ pub export fn entry2() void {
}
// error
// backend=llvm
// backend=stage2,llvm
// target=native
//
// :6:20: error: cannot @bitCast to '[]i32'

View File

@ -7,7 +7,7 @@ pub fn main() void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux-gnu
// link_libc=true
//

View File

@ -14,5 +14,5 @@ fn foo(comptime info: std.builtin.Type) !void {
// run
// is_test=true
// backend=llvm
// backend=stage2,llvm
//

View File

@ -36,5 +36,5 @@ fn assert(ok: bool) void {
// TODO: enable this for native backend
// run
// backend=llvm
// backend=stage2,llvm
// target=aarch64-linux,aarch64-macos

View File

@ -7,6 +7,6 @@ pub fn main() void {
// compile
// output_mode=Exe
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
//

View File

@ -8,6 +8,6 @@ pub fn main() void {
// compile
// output_mode=Exe
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
//

View File

@ -11,6 +11,6 @@ pub fn main() void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
//

View File

@ -5,7 +5,7 @@ pub fn main() void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
// link_libc=true
//

View File

@ -4,6 +4,6 @@ pub fn main() void {
}
// compile
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
//

View File

@ -44,6 +44,6 @@ pub fn main() void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
//

View File

@ -18,5 +18,5 @@ pub fn main() !void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -7,5 +7,5 @@ pub fn main() void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -21,5 +21,5 @@ fn foo(bytes: []u8) u32 {
return int_slice[0];
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -22,5 +22,5 @@ fn bar(a: u2) Foo {
fn baz(_: Foo) void {}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -19,5 +19,5 @@ pub fn main() u8 {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -19,5 +19,5 @@ pub fn main() u8 {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -17,5 +17,5 @@ fn foo(set1: Set1) Set2 {
return @errorCast(set1);
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -16,5 +16,5 @@ fn foo() anyerror!i32 {
return error.Bar;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -18,5 +18,5 @@ fn bar(one: u1, not_zero: i32) void {
_ = x;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -16,5 +16,5 @@ fn bar(a: f32) i8 {
}
fn baz(_: i8) void {}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -16,5 +16,5 @@ fn bar(a: f32) u8 {
}
fn baz(_: u8) void {}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -16,5 +16,5 @@ fn bar(a: f32) u8 {
}
fn baz(_: u8) void {}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -15,5 +15,5 @@ pub fn main() !void {
return error.TestFailed;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -15,5 +15,5 @@ pub fn main() !void {
return error.TestFailed;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -15,5 +15,5 @@ pub fn main() !void {
return error.TestFailed;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View File

@ -22,5 +22,5 @@ pub fn main() !void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

Some files were not shown because too many files have changed in this diff Show More