mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
implement linker and c backend support for restricted type safety check
This commit is contained in:
+5
-1
@@ -12358,7 +12358,11 @@ pub fn addFieldTagValue(
|
||||
/// encoding instead of `Tag.ptr_uav_aligned` when possible.
|
||||
fn ptrsHaveSameAlignment(ip: *InternPool, a_ty: Index, a_info: Key.PtrType, b_ty: Index) bool {
|
||||
if (a_ty == b_ty) return true;
|
||||
const b_info = ip.indexToKey(b_ty).ptr_type;
|
||||
const b_info = switch (ip.indexToKey(b_ty)) {
|
||||
else => unreachable,
|
||||
.ptr_type => |ptr_type| ptr_type,
|
||||
.restricted_ptr_type => |restricted_ptr_type| ip.indexToKey(restricted_ptr_type.unrestricted_ptr_type).ptr_type,
|
||||
};
|
||||
return a_info.flags.alignment == b_info.flags.alignment and
|
||||
(a_info.child == b_info.child or a_info.flags.alignment != .none);
|
||||
}
|
||||
|
||||
+8
-4
@@ -1350,14 +1350,17 @@ pub fn unrestrictedType(ty: Type, zcu: *const Zcu) ?Type {
|
||||
};
|
||||
}
|
||||
|
||||
const RestrictedRepr = enum { double_pointer, single_pointer };
|
||||
const RestrictedRepr = enum { indirect, direct };
|
||||
pub fn restrictedRepr(ty: Type, zcu: *const Zcu) RestrictedRepr {
|
||||
return restrictedReprByZirIndex(zcu.intern_pool.indexToKey(ty.toIntern()).restricted_ptr_type.zir_index, zcu);
|
||||
return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
|
||||
.restricted_ptr_type => |restricted_ptr_type| restrictedReprByZirIndex(restricted_ptr_type.zir_index, zcu),
|
||||
else => .direct,
|
||||
};
|
||||
}
|
||||
pub fn restrictedReprByZirIndex(zir_index: InternPool.TrackedInst.Index, zcu: *const Zcu) RestrictedRepr {
|
||||
return switch (zcu.fileByIndex(zir_index.resolveFile(&zcu.intern_pool)).mod.?.optimize_mode) {
|
||||
.Debug, .ReleaseSafe => .double_pointer,
|
||||
.ReleaseFast, .ReleaseSmall => .single_pointer,
|
||||
.Debug, .ReleaseSafe => if (zcu.backendSupportsFeature(.restricted_types)) .indirect else .direct,
|
||||
.ReleaseFast, .ReleaseSmall => .direct,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2670,6 +2673,7 @@ pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Zcu.LazySrcLoc {
|
||||
const ip = &zcu.intern_pool;
|
||||
return .{
|
||||
.base_node_inst = switch (ip.indexToKey(ty.toIntern())) {
|
||||
.restricted_ptr_type => |restricted_ptr_type| restricted_ptr_type.zir_index,
|
||||
.struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) {
|
||||
.declared => |d| d.zir_index,
|
||||
.reified => |r| r.zir_index,
|
||||
|
||||
@@ -3995,6 +3995,7 @@ pub const Feature = enum {
|
||||
/// * With this feature disabled, semantic analysis, code generation, and linking all occur on the
|
||||
/// same thread, and the "emit" stage has access to AIR.
|
||||
separate_thread,
|
||||
restricted_types,
|
||||
};
|
||||
|
||||
pub fn backendSupportsFeature(zcu: *const Zcu, comptime feature: Feature) bool {
|
||||
|
||||
+241
-73
@@ -210,7 +210,7 @@ pub fn generateLazyFunction(
|
||||
debug_output: link.File.DebugInfoOutput,
|
||||
) (CodeGenError || std.Io.Writer.Error)!void {
|
||||
const zcu = pt.zcu;
|
||||
const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|
|
||||
const target = if (Type.fromInterned(lazy_sym.key).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|
|
||||
&zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.?.resolved_target.result
|
||||
else
|
||||
zcu.getTarget();
|
||||
@@ -223,13 +223,118 @@ pub fn generateLazyFunction(
|
||||
}
|
||||
}
|
||||
|
||||
const LazySymbolStructure = struct {
|
||||
parent: ?link.File.LazySymbol = null,
|
||||
modify: ?Modification = null,
|
||||
|
||||
pub const Modification = struct {
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
operation: Operation,
|
||||
|
||||
pub const Operation = enum {
|
||||
ptr_inc,
|
||||
|
||||
pub fn apply(operation: Operation, slice: []u8, endian: std.builtin.Endian) void {
|
||||
switch (operation) {
|
||||
.ptr_inc => switch (slice.len) {
|
||||
else => unreachable,
|
||||
2 => std.mem.writeInt(u16, slice[0..2], std.mem.readInt(u16, slice[0..2], endian) + 1, endian),
|
||||
4 => std.mem.writeInt(u32, slice[0..4], std.mem.readInt(u32, slice[0..4], endian) + 1, endian),
|
||||
8 => std.mem.writeInt(u64, slice[0..8], std.mem.readInt(u64, slice[0..8], endian) + 1, endian),
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
pub const LazySymbolAttributes = struct {
|
||||
header: bool = false,
|
||||
required_alignment: Alignment,
|
||||
size: ?u64 = null,
|
||||
};
|
||||
pub fn getLazySymbolInfo(
|
||||
comptime kind: enum { structure, attributes },
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
zcu: *Zcu,
|
||||
) switch (kind) {
|
||||
.structure => LazySymbolStructure,
|
||||
.attributes => LazySymbolAttributes,
|
||||
} {
|
||||
const ip = &zcu.intern_pool;
|
||||
return switch (lazy_sym.kind) {
|
||||
.code => switch (kind) {
|
||||
.structure => .{},
|
||||
.attributes => {
|
||||
const comp = zcu.comp;
|
||||
const target = &comp.root_mod.resolved_target.result;
|
||||
return .{ .required_alignment = switch (comp.root_mod.optimize_mode) {
|
||||
.Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
|
||||
.ReleaseSmall => target_util.minFunctionAlignment(target),
|
||||
} };
|
||||
},
|
||||
},
|
||||
.const_data => switch (ip.indexToKey(lazy_sym.key)) {
|
||||
else => unreachable,
|
||||
.enum_type => switch (kind) {
|
||||
.structure => .{},
|
||||
.attributes => .{ .required_alignment = .@"1" },
|
||||
},
|
||||
.restricted_ptr_type => |restricted_ptr_type| switch (kind) {
|
||||
.structure => .{},
|
||||
.attributes => {
|
||||
const restricted_ptr_ty: Type = .fromInterned(lazy_sym.key);
|
||||
const unrestricted_ptr_ty: Type =
|
||||
.fromInterned(restricted_ptr_type.unrestricted_ptr_type);
|
||||
return .{ .required_alignment = restricted_ptr_ty.abiAlignment(zcu)
|
||||
.maxStrict(unrestricted_ptr_ty.abiAlignment(zcu)) };
|
||||
},
|
||||
},
|
||||
},
|
||||
.deferred_const_data => switch (lazy_sym.key) {
|
||||
else => unreachable,
|
||||
.anyerror_type => switch (kind) {
|
||||
.structure => .{},
|
||||
.attributes => .{ .required_alignment = .@"4" },
|
||||
},
|
||||
_ => switch (ip.indexToKey(lazy_sym.key)) {
|
||||
else => unreachable,
|
||||
.ptr => |ptr| switch (ip.indexToKey(ptr.ty)) {
|
||||
else => unreachable,
|
||||
.restricted_ptr_type => |restricted_ptr_type| switch (kind) {
|
||||
.structure => .{ .parent = .{ .kind = .const_data, .key = ptr.ty }, .modify = .{
|
||||
.lazy_sym = .{ .kind = .deferred_const_data, .key = ptr.ty },
|
||||
.operation = .ptr_inc,
|
||||
} },
|
||||
.attributes => {
|
||||
const unrestricted_ptr_ty: Type =
|
||||
.fromInterned(restricted_ptr_type.unrestricted_ptr_type);
|
||||
return .{
|
||||
.required_alignment = unrestricted_ptr_ty.abiAlignment(zcu),
|
||||
.size = unrestricted_ptr_ty.abiSize(zcu),
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
.restricted_ptr_type => switch (kind) {
|
||||
.structure => .{ .parent = .{ .kind = .const_data, .key = lazy_sym.key } },
|
||||
.attributes => {
|
||||
const restricted_ptr_ty: Type = .fromInterned(lazy_sym.key);
|
||||
return .{
|
||||
.header = true,
|
||||
.required_alignment = restricted_ptr_ty.abiAlignment(zcu),
|
||||
.size = restricted_ptr_ty.abiSize(zcu),
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
pub fn generateLazySymbol(
|
||||
bin_file: *link.File,
|
||||
pt: Zcu.PerThread,
|
||||
src_loc: Zcu.LazySrcLoc,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
// TODO don't use an "out" parameter like this; put it in the result instead
|
||||
alignment: *Alignment,
|
||||
w: *std.Io.Writer,
|
||||
debug_output: link.File.DebugInfoOutput,
|
||||
reloc_parent: link.File.RelocInfo.Parent,
|
||||
@@ -243,51 +348,81 @@ pub fn generateLazySymbol(
|
||||
const target = &comp.root_mod.resolved_target.result;
|
||||
const endian = target.cpu.arch.endian();
|
||||
|
||||
log.debug("generateLazySymbol: kind = {s}, ty = {f}", .{
|
||||
log.debug("generateLazySymbol: kind = {s}, key = {f}", .{
|
||||
@tagName(lazy_sym.kind),
|
||||
Type.fromInterned(lazy_sym.ty).fmt(pt),
|
||||
Value.fromInterned(lazy_sym.key).fmtValue(pt),
|
||||
});
|
||||
|
||||
if (lazy_sym.kind == .code) {
|
||||
alignment.* = target_util.defaultFunctionAlignment(target);
|
||||
return generateLazyFunction(bin_file, pt, src_loc, lazy_sym, reloc_parent.atom_index, w, debug_output);
|
||||
switch (lazy_sym.kind) {
|
||||
.code => return generateLazyFunction(bin_file, pt, src_loc, lazy_sym, reloc_parent.atom_index, w, debug_output),
|
||||
.const_data => switch (ip.indexToKey(lazy_sym.key)) {
|
||||
.enum_type => {
|
||||
const enum_ty: Type = .fromInterned(lazy_sym.key);
|
||||
const tag_names = enum_ty.enumFields(zcu);
|
||||
for (0..tag_names.len) |tag_index| {
|
||||
const tag_name = tag_names.get(ip)[tag_index].toSlice(ip);
|
||||
try w.rebase(w.end, tag_name.len + 1);
|
||||
w.writeAll(tag_name) catch unreachable;
|
||||
w.writeByte(0) catch unreachable;
|
||||
}
|
||||
return;
|
||||
},
|
||||
.restricted_ptr_type => return,
|
||||
else => {},
|
||||
},
|
||||
.deferred_const_data => switch (lazy_sym.key) {
|
||||
.anyerror_type => {
|
||||
const err_names = ip.global_error_set.getNamesFromMainThread();
|
||||
const strings_start: u32 = @intCast(4 * (1 + err_names.len + @intFromBool(err_names.len > 0)));
|
||||
var string_index = strings_start;
|
||||
try w.rebase(w.end, string_index);
|
||||
w.writeInt(u32, @intCast(err_names.len), endian) catch unreachable;
|
||||
if (err_names.len > 0) {
|
||||
for (err_names) |err_name_nts| {
|
||||
w.writeInt(u32, string_index, endian) catch unreachable;
|
||||
string_index += @intCast(err_name_nts.toSlice(ip).len + 1);
|
||||
}
|
||||
w.writeInt(u32, string_index, endian) catch unreachable;
|
||||
try w.rebase(w.end, string_index - strings_start);
|
||||
for (err_names) |err_name_nts| {
|
||||
w.writeAll(err_name_nts.toSlice(ip)) catch unreachable;
|
||||
w.writeByte(0) catch unreachable;
|
||||
}
|
||||
}
|
||||
return;
|
||||
},
|
||||
_ => switch (ip.indexToKey(lazy_sym.key)) {
|
||||
.ptr => |ptr| switch (ip.indexToKey(ptr.ty)) {
|
||||
.restricted_ptr_type => |restricted_ptr_type| return lowerPtr(
|
||||
bin_file,
|
||||
pt,
|
||||
src_loc,
|
||||
try ip.getCoerced(
|
||||
comp.gpa,
|
||||
comp.io,
|
||||
pt.tid,
|
||||
lazy_sym.key,
|
||||
restricted_ptr_type.unrestricted_ptr_type,
|
||||
),
|
||||
w,
|
||||
reloc_parent,
|
||||
0,
|
||||
),
|
||||
else => {},
|
||||
},
|
||||
.restricted_ptr_type => return w.splatByteAll(0, @divExact(zcu.getTarget().ptrBitWidth(), 8)),
|
||||
else => {},
|
||||
},
|
||||
else => {},
|
||||
},
|
||||
}
|
||||
|
||||
if (lazy_sym.ty == .anyerror_type) {
|
||||
alignment.* = .@"4";
|
||||
const err_names = ip.global_error_set.getNamesFromMainThread();
|
||||
const strings_start: u32 = @intCast(4 * (1 + err_names.len + @intFromBool(err_names.len > 0)));
|
||||
var string_index = strings_start;
|
||||
try w.rebase(w.end, string_index);
|
||||
w.writeInt(u32, @intCast(err_names.len), endian) catch unreachable;
|
||||
if (err_names.len == 0) return;
|
||||
for (err_names) |err_name_nts| {
|
||||
w.writeInt(u32, string_index, endian) catch unreachable;
|
||||
string_index += @intCast(err_name_nts.toSlice(ip).len + 1);
|
||||
}
|
||||
w.writeInt(u32, string_index, endian) catch unreachable;
|
||||
try w.rebase(w.end, string_index - strings_start);
|
||||
for (err_names) |err_name_nts| {
|
||||
w.writeAll(err_name_nts.toSlice(ip)) catch unreachable;
|
||||
w.writeByte(0) catch unreachable;
|
||||
}
|
||||
} else if (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu) == .@"enum") {
|
||||
alignment.* = .@"1";
|
||||
const enum_ty = Type.fromInterned(lazy_sym.ty);
|
||||
const tag_names = enum_ty.enumFields(zcu);
|
||||
for (0..tag_names.len) |tag_index| {
|
||||
const tag_name = tag_names.get(ip)[tag_index].toSlice(ip);
|
||||
try w.rebase(w.end, tag_name.len + 1);
|
||||
w.writeAll(tag_name) catch unreachable;
|
||||
w.writeByte(0) catch unreachable;
|
||||
}
|
||||
} else if (Type.fromInterned(lazy_sym.ty).unrestrictedType(zcu)) |unrestricted_ptr_ty| {
|
||||
alignment.* = unrestricted_ptr_ty.abiAlignment(zcu);
|
||||
try w.splatByteAll(0, @divExact(zcu.getTarget().ptrBitWidth(), 8)); // to be filled in later
|
||||
} else {
|
||||
return zcu.codegenFailType(lazy_sym.ty, "TODO implement generateLazySymbol for {s} {f}", .{
|
||||
@tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt),
|
||||
});
|
||||
switch (ip.typeOf(lazy_sym.key)) {
|
||||
.type_type => return zcu.codegenFailType(lazy_sym.key, "TODO implement generateLazySymbol for {t} {f}", .{
|
||||
lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt),
|
||||
}),
|
||||
else => std.debug.panic("TODO implement generateLazySymbol for {t} {f}", .{
|
||||
lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,7 +576,10 @@ pub fn generateSymbol(
|
||||
128 => try w.writeInt(u128, @bitCast(f128_val), endian),
|
||||
},
|
||||
},
|
||||
.ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), w, reloc_parent, 0),
|
||||
.ptr => switch (ty.restrictedRepr(zcu)) {
|
||||
.indirect => try lowerLazySymbolRef(bin_file, pt, .{ .kind = .deferred_const_data, .key = val.toIntern() }, w, reloc_parent, 0),
|
||||
.direct => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), w, reloc_parent, 0),
|
||||
},
|
||||
.slice => |slice| {
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.ptr), w, reloc_parent);
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.len), w, reloc_parent);
|
||||
@@ -838,7 +976,7 @@ fn lowerNavRef(
|
||||
else => {},
|
||||
}
|
||||
|
||||
const vaddr = lf.getNavVAddr(pt, nav_index, .{
|
||||
const vaddr = lf.getNavVAddr(nav_index, .{
|
||||
.parent = reloc_parent,
|
||||
.offset = w.end,
|
||||
.addend = @intCast(offset),
|
||||
@@ -906,7 +1044,7 @@ pub fn genNavRef(
|
||||
.link_once => unreachable,
|
||||
}
|
||||
} else if (lf.cast(.elf2)) |elf| {
|
||||
return .{ .sym_index = @intFromEnum(elf.navSymbol(zcu, nav_index) catch |err| switch (err) {
|
||||
return .{ .sym_index = @intFromEnum(elf.navSymbol(nav_index) catch |err| switch (err) {
|
||||
error.OutOfMemory => |e| return e,
|
||||
else => |e| return .{ .fail = try ErrorMsg.create(
|
||||
zcu.gpa,
|
||||
@@ -937,13 +1075,38 @@ pub fn genNavRef(
|
||||
.link_once => unreachable,
|
||||
}
|
||||
} else if (lf.cast(.coff2)) |coff| {
|
||||
return .{ .sym_index = @intFromEnum(try coff.navSymbol(zcu, nav_index)) };
|
||||
return .{ .sym_index = @intFromEnum(try coff.navSymbol(nav_index)) };
|
||||
} else {
|
||||
const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target});
|
||||
return .{ .fail = msg };
|
||||
}
|
||||
}
|
||||
|
||||
fn lowerLazySymbolRef(
|
||||
lf: *link.File,
|
||||
pt: Zcu.PerThread,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
w: *std.Io.Writer,
|
||||
reloc_parent: link.File.RelocInfo.Parent,
|
||||
offset: u64,
|
||||
) (GenerateSymbolError || std.Io.Writer.Error)!void {
|
||||
const vaddr = lf.getLazySymbolVAddr(pt, lazy_sym, .{
|
||||
.parent = reloc_parent,
|
||||
.offset = w.end,
|
||||
.addend = @intCast(offset),
|
||||
}) catch @panic("TODO rework getNavVAddr");
|
||||
|
||||
const target = &lf.comp.root_mod.resolved_target.result;
|
||||
const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
|
||||
const endian = target.cpu.arch.endian();
|
||||
switch (ptr_width_bytes) {
|
||||
2 => try w.writeInt(u16, @intCast(vaddr), endian),
|
||||
4 => try w.writeInt(u32, @intCast(vaddr), endian),
|
||||
8 => try w.writeInt(u64, vaddr, endian),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
/// deprecated legacy type
|
||||
pub const GenResult = union(enum) {
|
||||
mcv: MCValue,
|
||||
@@ -1006,6 +1169,7 @@ pub fn genTypedValue(
|
||||
} },
|
||||
.fail => |em| .{ .fail = em },
|
||||
},
|
||||
.lea_lazy_sym => unreachable, // `Zcu.Feature.restricted_types` is not supported by this code path
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1018,6 +1182,7 @@ const LowerResult = union(enum) {
|
||||
lea_nav: InternPool.Nav.Index,
|
||||
load_uav: InternPool.Key.Ptr.BaseAddr.Uav,
|
||||
lea_uav: InternPool.Key.Ptr.BaseAddr.Uav,
|
||||
lea_lazy_sym: link.File.LazySymbol,
|
||||
};
|
||||
|
||||
pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allocator.Error!LowerResult {
|
||||
@@ -1034,38 +1199,41 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo
|
||||
.bool => return .{ .immediate = @intFromBool(val.toBool()) },
|
||||
.pointer => switch (ty.ptrSize(zcu)) {
|
||||
.slice => {},
|
||||
.one, .many, .c => {
|
||||
const ptr = ip.indexToKey(val.toIntern()).ptr;
|
||||
if (ptr.base_addr == .int) return .{ .immediate = ptr.byte_offset };
|
||||
if (ptr.byte_offset == 0) switch (ptr.base_addr) {
|
||||
.int => unreachable, // handled above
|
||||
.one, .many, .c => switch (ty.restrictedRepr(zcu)) {
|
||||
.indirect => return .{ .lea_lazy_sym = .{ .kind = .deferred_const_data, .key = val.toIntern() } },
|
||||
.direct => {
|
||||
const ptr = ip.indexToKey(val.toIntern()).ptr;
|
||||
if (ptr.base_addr == .int) return .{ .immediate = ptr.byte_offset };
|
||||
if (ptr.byte_offset == 0) switch (ptr.base_addr) {
|
||||
.int => unreachable, // handled above
|
||||
|
||||
.nav => |nav_index| {
|
||||
const nav = ip.getNav(nav_index);
|
||||
const nav_ty: Type = .fromInterned(nav.resolved.?.type);
|
||||
if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) {
|
||||
return .{ .lea_nav = nav_index };
|
||||
.nav => |nav_index| {
|
||||
const nav = ip.getNav(nav_index);
|
||||
const nav_ty: Type = .fromInterned(nav.resolved.?.type);
|
||||
if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) {
|
||||
return .{ .lea_nav = nav_index };
|
||||
} else {
|
||||
// Create the 0xaa bit pattern...
|
||||
const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3);
|
||||
// ...but align the pointer
|
||||
const alignment = zcu.navAlignment(nav_index);
|
||||
return .{ .immediate = alignment.forward(undef_ptr_bits) };
|
||||
}
|
||||
},
|
||||
|
||||
.uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).isRuntimeFnOrHasRuntimeBits(zcu)) {
|
||||
return .{ .lea_uav = uav };
|
||||
} else {
|
||||
// Create the 0xaa bit pattern...
|
||||
const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3);
|
||||
// ...but align the pointer
|
||||
const alignment = zcu.navAlignment(nav_index);
|
||||
const alignment = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu);
|
||||
return .{ .immediate = alignment.forward(undef_ptr_bits) };
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
.uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).isRuntimeFnOrHasRuntimeBits(zcu)) {
|
||||
return .{ .lea_uav = uav };
|
||||
} else {
|
||||
// Create the 0xaa bit pattern...
|
||||
const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3);
|
||||
// ...but align the pointer
|
||||
const alignment = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu);
|
||||
return .{ .immediate = alignment.forward(undef_ptr_bits) };
|
||||
},
|
||||
|
||||
else => {},
|
||||
};
|
||||
else => {},
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
.int => {
|
||||
|
||||
@@ -663,8 +663,8 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
|
||||
|
||||
maybe_noop: {
|
||||
switch (isel.air.typeOf(ty_op.operand, ip).restrictedRepr(zcu)) {
|
||||
.double_pointer => break :maybe_noop,
|
||||
.single_pointer => {},
|
||||
.indirect => break :maybe_noop,
|
||||
.direct => {},
|
||||
}
|
||||
if (true) break :maybe_noop;
|
||||
if (ty_op.operand.toIndex()) |src_air_inst_index| {
|
||||
@@ -5766,7 +5766,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
||||
const unrestricted_ty = ty_op.ty.toType();
|
||||
const restricted_ty = isel.air.typeOf(ty_op.operand, ip);
|
||||
switch (restricted_ty.restrictedRepr(zcu)) {
|
||||
.double_pointer => {
|
||||
.indirect => {
|
||||
switch (air_tag) {
|
||||
else => unreachable,
|
||||
.unwrap_restricted => {},
|
||||
@@ -5777,7 +5777,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
||||
_ = try dst_vi.value.load(isel, unrestricted_ty, ptr_mat.ra, .{});
|
||||
try ptr_mat.finish(isel);
|
||||
},
|
||||
.single_pointer => try dst_vi.value.move(isel, ty_op.operand),
|
||||
.direct => try dst_vi.value.move(isel, ty_op.operand),
|
||||
}
|
||||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
@@ -6888,12 +6888,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
||||
},
|
||||
} }));
|
||||
try isel.lazy_relocs.append(gpa, .{
|
||||
.symbol = .{ .kind = .const_data, .ty = .anyerror_type },
|
||||
.symbol = .{ .kind = .deferred_const_data, .key = .anyerror_type },
|
||||
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
|
||||
});
|
||||
try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 }));
|
||||
try isel.lazy_relocs.append(gpa, .{
|
||||
.symbol = .{ .kind = .const_data, .ty = .anyerror_type },
|
||||
.symbol = .{ .kind = .deferred_const_data, .key = .anyerror_type },
|
||||
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
|
||||
});
|
||||
try isel.emit(.adrp(ptr_ra.x(), 0));
|
||||
@@ -7231,12 +7231,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
||||
defer isel.freeReg(ptr_ra);
|
||||
try isel.emit(.subs(.wzr, error_mat.ra.w(), .{ .register = ptr_ra.w() }));
|
||||
try isel.lazy_relocs.append(gpa, .{
|
||||
.symbol = .{ .kind = .const_data, .ty = .anyerror_type },
|
||||
.symbol = .{ .kind = .deferred_const_data, .key = .anyerror_type },
|
||||
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
|
||||
});
|
||||
try isel.emit(.ldr(ptr_ra.w(), .{ .base = ptr_ra.x() }));
|
||||
try isel.lazy_relocs.append(gpa, .{
|
||||
.symbol = .{ .kind = .const_data, .ty = .anyerror_type },
|
||||
.symbol = .{ .kind = .deferred_const_data, .key = .anyerror_type },
|
||||
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
|
||||
});
|
||||
try isel.emit(.adrp(ptr_ra.x(), 0));
|
||||
|
||||
+147
-14
@@ -61,6 +61,8 @@ pub const Mir = struct {
|
||||
/// less than the natural alignment.
|
||||
need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
|
||||
ctype_deps: CType.Dependencies,
|
||||
/// Key is a restricted type or value for which we need generated supporting decls.
|
||||
need_restricted: std.array_hash_map.Auto(InternPool.Index, void),
|
||||
/// Key is an enum type for which we need a generated `@tagName` function.
|
||||
need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
|
||||
/// Key is a function Nav for which we need a generated `zig_never_tail` wrapper.
|
||||
@@ -74,6 +76,7 @@ pub const Mir = struct {
|
||||
gpa.free(mir.code);
|
||||
mir.need_uavs.deinit(gpa);
|
||||
mir.ctype_deps.deinit(gpa);
|
||||
mir.need_restricted.deinit(gpa);
|
||||
mir.need_tag_name_funcs.deinit(gpa);
|
||||
mir.need_never_tail_funcs.deinit(gpa);
|
||||
mir.need_never_inline_funcs.deinit(gpa);
|
||||
@@ -549,6 +552,25 @@ pub const Function = struct {
|
||||
try f.writeCValue(w, member, .other);
|
||||
}
|
||||
|
||||
fn writePanic(f: *Function, panic_id: Zcu.SimplePanicId, w: *std.Io.Writer) !void {
|
||||
const zcu = f.dg.pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
try renderNavName(w, switch (ip.indexToKey(zcu.builtin_decl_values.get(panic_id.toBuiltin()))) {
|
||||
inline .@"extern", .func => |func| func.owner_nav,
|
||||
.ptr => |ptr| switch (ptr.byte_offset) {
|
||||
0 => switch (ptr.base_addr) {
|
||||
.nav => |nav| nav,
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
}, ip);
|
||||
try w.writeAll("();");
|
||||
try f.newline();
|
||||
try airUnreach(f);
|
||||
}
|
||||
|
||||
fn fail(f: *Function, comptime format: []const u8, args: anytype) Error {
|
||||
return f.dg.fail(format, args);
|
||||
}
|
||||
@@ -645,6 +667,7 @@ pub const DeclGen = struct {
|
||||
/// `.none` for natural alignment. The specified alignment is never
|
||||
/// less than the natural alignment.
|
||||
uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
|
||||
need_restricted: std.array_hash_map.Auto(InternPool.Index, void),
|
||||
|
||||
fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {
|
||||
@branchHint(.cold);
|
||||
@@ -1055,11 +1078,24 @@ pub const DeclGen = struct {
|
||||
try dg.renderValue(w, .fromInterned(slice.len), initializer_type);
|
||||
try w.writeByte('}');
|
||||
},
|
||||
.ptr => {
|
||||
const derivation = try val.pointerDerivation(dg.arena, pt, null);
|
||||
try w.writeByte('(');
|
||||
try dg.renderPointer(w, derivation, location);
|
||||
try w.writeByte(')');
|
||||
.ptr => switch (ty.restrictedRepr(zcu)) {
|
||||
.indirect => {
|
||||
try dg.need_restricted.ensureUnusedCapacity(zcu.gpa, 2);
|
||||
dg.need_restricted.putAssumeCapacity(ty.toIntern(), {});
|
||||
dg.need_restricted.putAssumeCapacity(val.toIntern(), {});
|
||||
|
||||
const restricted_ty_name = ty.containerTypeName(ip).toSlice(ip);
|
||||
try w.print("&zig_restricted_{f}__{d}[zig_restricted_index_{f}__{d}]", .{
|
||||
fmtIdentUnsolo(restricted_ty_name), ty.toIntern(),
|
||||
fmtIdentUnsolo(restricted_ty_name), val.toIntern(),
|
||||
});
|
||||
},
|
||||
.direct => {
|
||||
const derivation = try val.pointerDerivation(dg.arena, pt, null);
|
||||
try w.writeByte('(');
|
||||
try dg.renderPointer(w, derivation, location);
|
||||
try w.writeByte(')');
|
||||
},
|
||||
},
|
||||
.opt => |opt| switch (CType.classifyOptional(ty, zcu)) {
|
||||
.npv_payload => unreachable, // opv optional
|
||||
@@ -2061,6 +2097,55 @@ pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn genRestricted(
|
||||
dg: *DeclGen,
|
||||
need_restricted: *const std.array_hash_map.Auto(InternPool.Index, std.array_hash_map.Auto(InternPool.Index, void)),
|
||||
w: *Writer,
|
||||
) Error!void {
|
||||
const pt = dg.pt;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
for (need_restricted.keys(), need_restricted.values()) |restricted_ty, *restricted_vals| {
|
||||
const unrestricted_ptr_type = ip.indexToKey(restricted_ty).restricted_ptr_type.unrestricted_ptr_type;
|
||||
const unrestricted_cty: CType = try .lower(.fromInterned(unrestricted_ptr_type), &dg.ctype_deps, dg.arena, zcu);
|
||||
const restricted_ty_name = Type.fromInterned(restricted_ty).containerTypeName(ip).toSlice(ip);
|
||||
try w.print(
|
||||
\\#define zig_restricted_len_{f}__{d} {d}u
|
||||
\\static {f}const zig_restricted_{f}__{d}[zig_restricted_len_{f}__{d}]{f} = {{
|
||||
\\
|
||||
, .{
|
||||
fmtIdentUnsolo(restricted_ty_name),
|
||||
restricted_ty,
|
||||
restricted_vals.count(),
|
||||
|
||||
unrestricted_cty.fmtDeclaratorPrefix(zcu),
|
||||
fmtIdentUnsolo(restricted_ty_name),
|
||||
restricted_ty,
|
||||
fmtIdentUnsolo(restricted_ty_name),
|
||||
restricted_ty,
|
||||
unrestricted_cty.fmtDeclaratorSuffix(zcu),
|
||||
});
|
||||
for (restricted_vals.keys(), 0..) |restricted_val, restricted_index| {
|
||||
try w.print(
|
||||
\\#define zig_restricted_index_{f}__{d} {d}u
|
||||
\\ [zig_restricted_index_{f}__{d}] =
|
||||
, .{
|
||||
fmtIdentUnsolo(restricted_ty_name),
|
||||
restricted_val,
|
||||
restricted_index,
|
||||
|
||||
fmtIdentUnsolo(restricted_ty_name),
|
||||
restricted_val,
|
||||
});
|
||||
try dg.renderValue(w, .fromInterned(
|
||||
try ip.getCoerced(zcu.gpa, zcu.comp.io, pt.tid, restricted_val, unrestricted_ptr_type),
|
||||
), .static_initializer);
|
||||
try w.writeAll(",\n");
|
||||
}
|
||||
try w.writeAll("};\n");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn genErrDecls(
|
||||
zcu: *const Zcu,
|
||||
w: *Writer,
|
||||
@@ -2220,6 +2305,7 @@ pub fn generate(
|
||||
.expected_block = null,
|
||||
.ctype_deps = .empty,
|
||||
.uavs = .empty,
|
||||
.need_restricted = .empty,
|
||||
},
|
||||
.code = .init(gpa),
|
||||
.indent_counter = 0,
|
||||
@@ -2231,6 +2317,7 @@ pub fn generate(
|
||||
function.code.deinit();
|
||||
function.dg.ctype_deps.deinit(gpa);
|
||||
function.dg.uavs.deinit(gpa);
|
||||
function.dg.need_restricted.deinit(gpa);
|
||||
function.deinit();
|
||||
}
|
||||
|
||||
@@ -2252,6 +2339,7 @@ pub fn generate(
|
||||
.code = &.{},
|
||||
.ctype_deps = function.dg.ctype_deps.move(),
|
||||
.need_uavs = function.dg.uavs.move(),
|
||||
.need_restricted = function.dg.need_restricted.move(),
|
||||
.need_tag_name_funcs = function.need_tag_name_funcs.move(),
|
||||
.need_never_tail_funcs = function.need_never_tail_funcs.move(),
|
||||
.need_never_inline_funcs = function.need_never_inline_funcs.move(),
|
||||
@@ -5541,8 +5629,8 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
}
|
||||
|
||||
fn airUnwrapRestricted(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
|
||||
const pt = f.dg.pt;
|
||||
const zcu = pt.zcu;
|
||||
const zcu = f.dg.pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
|
||||
|
||||
const unrestricted_ty = ty_op.ty.toType();
|
||||
@@ -5553,14 +5641,57 @@ fn airUnwrapRestricted(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue
|
||||
const w = &f.code.writer;
|
||||
const local = try f.allocLocal(inst, unrestricted_ty);
|
||||
|
||||
try f.writeCValue(w, local, .other);
|
||||
try w.writeAll(" = ");
|
||||
switch (restricted_ty.restrictedRepr(zcu)) {
|
||||
.double_pointer => {
|
||||
_ = safety; // TODO
|
||||
.indirect => {
|
||||
if (safety) {
|
||||
const target = &f.dg.mod.resolved_target.result;
|
||||
const ptr_bits = target.ptrBitWidth();
|
||||
|
||||
const int_from_ptr = try f.allocLocal(inst, .usize);
|
||||
try f.writeCValue(w, int_from_ptr, .other);
|
||||
try w.print(" = zig_subw_u{d}(({f})", .{
|
||||
ptr_bits,
|
||||
CType.fmtTypeName(.{ .int = .uintptr_t }, zcu),
|
||||
});
|
||||
try f.writeCValue(w, operand, .other);
|
||||
try w.print(", ({f})zig_restricted_{f}__{d}, {f});", .{
|
||||
CType.fmtTypeName(.{ .int = .uintptr_t }, zcu),
|
||||
fmtIdentUnsolo(restricted_ty.containerTypeName(ip).toSlice(ip)),
|
||||
restricted_ty.toIntern(),
|
||||
fmtUnsignedIntLiteralSmall(target, .uint8_t, ptr_bits, false, 10, .lower),
|
||||
});
|
||||
try f.newline();
|
||||
|
||||
const rotate_amount = std.math.log2_int(u16, @divExact(ptr_bits, 8));
|
||||
try w.print("if ((zig_shr_u{d}(", .{ptr_bits});
|
||||
try f.writeCValue(w, int_from_ptr, .other);
|
||||
try w.print(", {f}) | zig_shlw_u{d}(", .{
|
||||
fmtUnsignedIntLiteralSmall(target, .uint8_t, rotate_amount, false, 10, .lower),
|
||||
ptr_bits,
|
||||
});
|
||||
try f.writeCValue(w, int_from_ptr, .other);
|
||||
try w.print(", {f}, {f})) >= zig_restricted_len_{f}__{d}) {{", .{
|
||||
fmtUnsignedIntLiteralSmall(target, .uint8_t, ptr_bits - rotate_amount, false, 10, .lower),
|
||||
fmtUnsignedIntLiteralSmall(target, .uint8_t, ptr_bits, false, 10, .lower),
|
||||
fmtIdentUnsolo(restricted_ty.containerTypeName(ip).toSlice(ip)),
|
||||
restricted_ty.toIntern(),
|
||||
});
|
||||
f.indent();
|
||||
try f.newline();
|
||||
try f.writePanic(.corrupt_restricted_pointer, w);
|
||||
try f.outdent();
|
||||
try w.writeByte('}');
|
||||
try f.newline();
|
||||
}
|
||||
try f.writeCValue(w, local, .other);
|
||||
try w.writeAll(" = ");
|
||||
try f.writeCValueDeref(w, operand);
|
||||
},
|
||||
.single_pointer => try f.writeCValue(w, operand, .other),
|
||||
.direct => {
|
||||
try f.writeCValue(w, local, .other);
|
||||
try w.writeAll(" = ");
|
||||
try f.writeCValue(w, operand, .other);
|
||||
},
|
||||
}
|
||||
try w.writeByte(';');
|
||||
try f.newline();
|
||||
@@ -5849,7 +5980,8 @@ fn airBinBuiltinCall(
|
||||
try f.writeCValue(w, rhs, .other);
|
||||
if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
|
||||
try f.dg.renderBuiltinInfo(w, scalar_ty, info);
|
||||
try w.writeAll(");\n");
|
||||
try w.writeAll(");");
|
||||
try f.newline();
|
||||
try v.end(f, inst, w);
|
||||
|
||||
return local;
|
||||
@@ -6459,7 +6591,8 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
},
|
||||
.value => |val| try f.dg.renderValue(w, .fromInterned(val), .other),
|
||||
}
|
||||
try w.writeAll(";\n");
|
||||
try w.writeByte(';');
|
||||
try f.newline();
|
||||
}
|
||||
|
||||
return local;
|
||||
|
||||
@@ -285,7 +285,7 @@ pub const CType = union(enum) {
|
||||
.pointer => {
|
||||
const ptr = cur_ty.ptrInfo(zcu);
|
||||
if (cur_ty.unrestrictedType(zcu)) |unrestricted_ty| switch (cur_ty.restrictedRepr(zcu)) {
|
||||
.double_pointer => {
|
||||
.indirect => {
|
||||
const unrestricted_cty = try lowerInner(unrestricted_ty, true, deps, arena, zcu);
|
||||
const unrestricted_cty_buf = try arena.create(CType);
|
||||
unrestricted_cty_buf.* = unrestricted_cty;
|
||||
@@ -296,7 +296,7 @@ pub const CType = union(enum) {
|
||||
.nonstring = false,
|
||||
} };
|
||||
},
|
||||
.single_pointer => {},
|
||||
.direct => {},
|
||||
};
|
||||
switch (ptr.flags.size) {
|
||||
.slice => {
|
||||
|
||||
@@ -3261,11 +3261,13 @@ fn airUnwrapRestricted(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Alloc
|
||||
const restricted_ty = self.typeOf(ty_op.operand);
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
switch (restricted_ty.restrictedRepr(zcu)) {
|
||||
.double_pointer => {
|
||||
_ = safety; // TODO
|
||||
.indirect => {
|
||||
if (safety) {
|
||||
// TODO
|
||||
}
|
||||
return self.wip.load(.normal, .ptr, operand, unrestricted_ty.abiAlignment(zcu).toLlvm(), "restricted.unwrap");
|
||||
},
|
||||
.single_pointer => return operand,
|
||||
.direct => return operand,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1282,9 +1282,9 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
|
||||
const pt = func.pt;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
switch (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu)) {
|
||||
.@"enum" => {
|
||||
const enum_ty = Type.fromInterned(lazy_sym.ty);
|
||||
switch (ip.indexToKey(lazy_sym.key)) {
|
||||
.enum_type => {
|
||||
const enum_ty = Type.fromInterned(lazy_sym.key);
|
||||
wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(pt)});
|
||||
|
||||
const param_regs = abi.Registers.Integer.function_arg_regs;
|
||||
@@ -1301,9 +1301,9 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
|
||||
const zo = elf_file.zigObjectPtr().?;
|
||||
const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, .{
|
||||
.kind = .const_data,
|
||||
.ty = enum_ty.toIntern(),
|
||||
.key = lazy_sym.key,
|
||||
}) catch |err|
|
||||
return func.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
return func.fail("{t} creating lazy symbol", .{err});
|
||||
|
||||
try func.genSetReg(Type.u64, data_reg, .{ .lea_symbol = .{ .sym = sym_index } });
|
||||
|
||||
@@ -1367,8 +1367,8 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
|
||||
});
|
||||
},
|
||||
else => return func.fail(
|
||||
"TODO implement {s} for {f}",
|
||||
.{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },
|
||||
"TODO implement {t} for {f}",
|
||||
.{ lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt) },
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -8359,22 +8359,28 @@ fn wantSafety(func: *Func) bool {
|
||||
|
||||
fn fail(func: *const Func, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
|
||||
@branchHint(.cold);
|
||||
const zcu = func.pt.zcu;
|
||||
switch (func.owner) {
|
||||
.nav_index => |i| return zcu.codegenFail(i, format, args),
|
||||
.lazy_sym => |s| return zcu.codegenFailType(s.ty, format, args),
|
||||
}
|
||||
return error.CodegenFail;
|
||||
const pt = func.pt;
|
||||
const zcu = pt.zcu;
|
||||
return switch (func.owner) {
|
||||
.nav_index => |i| zcu.codegenFail(i, format, args),
|
||||
.lazy_sym => |s| switch (zcu.intern_pool.typeOf(s.key)) {
|
||||
.type_type => zcu.codegenFailType(s.key, format, args),
|
||||
else => std.debug.panic("{f}: " ++ format, .{Value.fromInterned(s.key).fmtValue(pt)} ++ args),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn failMsg(func: *const Func, msg: *ErrorMsg) error{ OutOfMemory, CodegenFail } {
|
||||
@branchHint(.cold);
|
||||
const zcu = func.pt.zcu;
|
||||
switch (func.owner) {
|
||||
.nav_index => |i| return zcu.codegenFailMsg(i, msg),
|
||||
.lazy_sym => |s| return zcu.codegenFailTypeMsg(s.ty, msg),
|
||||
}
|
||||
return error.CodegenFail;
|
||||
const pt = func.pt;
|
||||
const zcu = pt.zcu;
|
||||
return switch (func.owner) {
|
||||
.nav_index => |i| zcu.codegenFailMsg(i, msg),
|
||||
.lazy_sym => |s| switch (zcu.intern_pool.typeOf(s.key)) {
|
||||
.type_type => zcu.codegenFailTypeMsg(s.key, msg),
|
||||
else => std.debug.panic("{f}: {s}", .{ Value.fromInterned(s.key).fmtValue(pt), msg.msg }),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn parseRegName(name: []const u8) ?Register {
|
||||
|
||||
@@ -6730,11 +6730,11 @@ fn airUnwrapRestricted(cg: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerEr
|
||||
const unrestricted_ty = ty_op.ty.toType();
|
||||
const restricted_ty = cg.typeOf(ty_op.operand);
|
||||
const result = result: switch (restricted_ty.restrictedRepr(zcu)) {
|
||||
.double_pointer => {
|
||||
.indirect => {
|
||||
_ = safety; // TODO
|
||||
break :result try cg.load(operand, unrestricted_ty, 0);
|
||||
},
|
||||
.single_pointer => cg.reuseOperand(ty_op.operand, operand),
|
||||
.direct => cg.reuseOperand(ty_op.operand, operand),
|
||||
};
|
||||
return cg.finishAir(inst, result, &.{ty_op.operand});
|
||||
}
|
||||
|
||||
+211
-244
@@ -527,45 +527,38 @@ pub const MCValue = union(enum) {
|
||||
|
||||
pub fn format(mcv: MCValue, w: *Writer) Writer.Error!void {
|
||||
switch (mcv) {
|
||||
.none, .unreach, .dead, .undef => try w.print("({s})", .{@tagName(mcv)}),
|
||||
.none, .unreach, .dead, .undef => try w.print("({t})", .{mcv}),
|
||||
.immediate => |pl| try w.print("0x{x}", .{pl}),
|
||||
.memory => |pl| try w.print("[ds:0x{x}]", .{pl}),
|
||||
inline .eflags, .register => |pl| try w.print("{s}", .{@tagName(pl)}),
|
||||
.register_pair => |pl| try w.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),
|
||||
.register_triple => |pl| try w.print("{s}:{s}:{s}", .{
|
||||
@tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
|
||||
}),
|
||||
.register_quadruple => |pl| try w.print("{s}:{s}:{s}:{s}", .{
|
||||
@tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
|
||||
}),
|
||||
.register_offset => |pl| try w.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }),
|
||||
.register_overflow => |pl| try w.print("{s}:{s}", .{
|
||||
@tagName(pl.eflags),
|
||||
@tagName(pl.reg),
|
||||
}),
|
||||
.register_mask => |pl| try w.print("mask({s},{f}):{c}{s}", .{
|
||||
@tagName(pl.info.kind),
|
||||
inline .eflags, .register => |pl| try w.print("{t}", .{pl}),
|
||||
.register_pair => |pl| try w.print("{t}:{t}", .{ pl[1], pl[0] }),
|
||||
.register_triple => |pl| try w.print("{t}:{t}:{t}", .{ pl[2], pl[1], pl[0] }),
|
||||
.register_quadruple => |pl| try w.print("{t}:{t}:{t}:{t}", .{ pl[3], pl[2], pl[1], pl[0] }),
|
||||
.register_offset => |pl| try w.print("{t} + 0x{x}", .{ pl.reg, pl.off }),
|
||||
.register_overflow => |pl| try w.print("{t}:{t}", .{ pl.eflags, pl.reg }),
|
||||
.register_mask => |pl| try w.print("mask({t},{f}):{c}{t}", .{
|
||||
pl.info.kind,
|
||||
pl.info.scalar,
|
||||
@as(u8, if (pl.info.inverted) '!' else ' '),
|
||||
@tagName(pl.reg),
|
||||
pl.reg,
|
||||
}),
|
||||
.indirect => |pl| try w.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
|
||||
.indirect => |pl| try w.print("[{t} + 0x{x}]", .{ pl.reg, pl.off }),
|
||||
.indirect_load_frame => |pl| try w.print("[[{f} + 0x{x}]]", .{ pl.index, pl.off }),
|
||||
.load_frame => |pl| try w.print("[{f} + 0x{x}]", .{ pl.index, pl.off }),
|
||||
.lea_frame => |pl| try w.print("{f} + 0x{x}", .{ pl.index, pl.off }),
|
||||
.load_nav => |pl| try w.print("[nav:{d}]", .{@intFromEnum(pl)}),
|
||||
.lea_nav => |pl| try w.print("nav:{d}", .{@intFromEnum(pl)}),
|
||||
.load_uav => |pl| try w.print("[uav:{d}]", .{@intFromEnum(pl.val)}),
|
||||
.lea_uav => |pl| try w.print("uav:{d}", .{@intFromEnum(pl.val)}),
|
||||
.load_lazy_sym => |pl| try w.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
|
||||
.lea_lazy_sym => |pl| try w.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
|
||||
.load_extern_func => |pl| try w.print("[extern:{d}]", .{@intFromEnum(pl)}),
|
||||
.lea_extern_func => |pl| try w.print("extern:{d}", .{@intFromEnum(pl)}),
|
||||
.load_nav => |pl| try w.print("[nav:{d}]", .{pl}),
|
||||
.lea_nav => |pl| try w.print("nav:{d}", .{pl}),
|
||||
.load_uav => |pl| try w.print("[uav:{d}]", .{pl.val}),
|
||||
.lea_uav => |pl| try w.print("uav:{d}", .{pl.val}),
|
||||
.load_lazy_sym => |pl| try w.print("[lazy:{t}:{d}]", .{ pl.kind, pl.key }),
|
||||
.lea_lazy_sym => |pl| try w.print("lazy:{t}:{d}", .{ pl.kind, pl.key }),
|
||||
.load_extern_func => |pl| try w.print("[extern:{d}]", .{pl}),
|
||||
.lea_extern_func => |pl| try w.print("extern:{d}", .{pl}),
|
||||
.elementwise_args => |pl| try w.print("elementwise:{d}:[{f} + 0x{x}]", .{
|
||||
pl.regs, pl.frame_index, pl.frame_off,
|
||||
}),
|
||||
.reserved_frame => |pl| try w.print("(dead:{f})", .{pl}),
|
||||
.air_ref => |pl| try w.print("(air:0x{x})", .{@intFromEnum(pl)}),
|
||||
.air_ref => |pl| try w.print("(air:0x{x})", .{pl}),
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1138,7 +1131,7 @@ fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void {
|
||||
if (first) {
|
||||
const ip = &data.self.pt.zcu.intern_pool;
|
||||
const mir_inst = lower.mir.instructions.get(data.inst);
|
||||
try w.print(" | .{s}", .{@tagName(mir_inst.ops)});
|
||||
try w.print(" | .{t}", .{mir_inst.ops});
|
||||
switch (mir_inst.ops) {
|
||||
else => unreachable,
|
||||
.pseudo_dbg_prologue_end_none,
|
||||
@@ -2059,7 +2052,7 @@ fn gen(
|
||||
.{},
|
||||
);
|
||||
},
|
||||
else => |cc| return self.fail("{s} does not support var args", .{@tagName(cc)}),
|
||||
else => |cc| return self.fail("{t} does not support var args", .{cc}),
|
||||
};
|
||||
|
||||
if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_prologue_end_none);
|
||||
@@ -4452,8 +4445,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -4464,8 +4457,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
else => unreachable,
|
||||
.add, .add_optimized => {},
|
||||
.add_wrap => res[0].wrapInt(cg) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} wrap {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
res[0].tracking(cg),
|
||||
}),
|
||||
@@ -13029,8 +13022,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -15203,8 +15196,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -15215,8 +15208,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
else => unreachable,
|
||||
.sub, .sub_optimized => {},
|
||||
.sub_wrap => res[0].wrapInt(cg) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} wrap {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
res[0].tracking(cg),
|
||||
}),
|
||||
@@ -22050,8 +22043,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -24987,8 +24980,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty.fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -26785,8 +26778,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty.fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -26794,8 +26787,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
else => |e| return e,
|
||||
};
|
||||
res[0].wrapInt(cg) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} wrap {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
res[0].tracking(cg),
|
||||
}),
|
||||
@@ -32010,8 +32003,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ .@"0:", ._, .mov, .memad(.dst0q, .add_size, -8), .tmp3q, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -33248,8 +33241,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
assert(air_tag == .div_exact);
|
||||
res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty.fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -34705,8 +34698,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
} }) else err: {
|
||||
res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty.fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -36266,8 +36259,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
} },
|
||||
} },
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -37958,8 +37951,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} })) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty.fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -39740,8 +39733,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -43253,8 +43246,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -43367,8 +43360,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -43496,8 +43489,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -47805,8 +47798,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -52108,8 +52101,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -52957,8 +52950,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_pl.ty.toType().fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -53862,8 +53855,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_pl.ty.toType().fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -57459,8 +57452,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .@"or", .tmp2q, .tmp1q, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_pl.ty.toType().fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -60804,8 +60797,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .@"or", .tmp4q, .tmp5q, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_pl.ty.toType().fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -61199,8 +61192,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
} },
|
||||
} },
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -61762,8 +61755,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
cg.typeOf(bin_op.rhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
@@ -62124,8 +62117,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ns, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
cg.typeOf(bin_op.rhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
@@ -62136,8 +62129,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
switch (air_tag) {
|
||||
else => unreachable,
|
||||
.shl => res[0].wrapInt(cg) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} wrap {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
res[0].tracking(cg),
|
||||
}),
|
||||
@@ -62303,8 +62296,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .@"or", .dst0d, .tmp0d, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.rhs).fmt(pt),
|
||||
ops[1].tracking(cg),
|
||||
}),
|
||||
@@ -65560,8 +65553,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ .@"0:", ._, .mov, .memad(.dst0q, .add_size, -8), .tmp1q, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
lhs_ty.fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -67345,8 +67338,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_op.ty.toType().fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -70497,8 +70490,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(ty_op.operand).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -70894,8 +70887,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ .@"0:", ._, .lea, .dst0d, .leasia(.dst0, .@"8", .tmp0, .add_8_src0_size), ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(ty_op.operand).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -71782,8 +71775,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(ty_op.operand).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -72431,8 +72424,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_op.ty.toType().fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -75533,8 +75526,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_op.ty.toType().fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -76595,8 +76588,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(un_op).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -77445,8 +77438,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
} },
|
||||
} },
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(un_op).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -78996,8 +78989,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(ty_op.operand).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -80332,8 +80325,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
} },
|
||||
} },
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(un_op).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -80872,8 +80865,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(un_op).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -81352,8 +81345,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
} else err: {
|
||||
res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -81927,8 +81920,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.@"struct", .@"union" => {
|
||||
assert(ty.containerLayout(zcu) == .@"packed");
|
||||
for (&ops) |*op| op.wrapInt(cg) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} wrap {f} {f}", .{
|
||||
air_tag,
|
||||
ty.fmt(pt),
|
||||
op.tracking(cg),
|
||||
}),
|
||||
@@ -81939,8 +81932,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;
|
||||
},
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty.fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -89017,9 +89010,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
} },
|
||||
}),
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
@tagName(vector_cmp.compareOperator()),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
vector_cmp.compareOperator(),
|
||||
cg.typeOf(vector_cmp.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -91595,8 +91588,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_op.ty.toType().fmt(pt),
|
||||
cg.typeOf(ty_op.operand).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
@@ -93270,8 +93263,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_op.ty.toType().fmt(pt),
|
||||
cg.typeOf(ty_op.operand).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
@@ -98028,8 +98021,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
dst_ty.fmt(pt),
|
||||
src_ty.fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
@@ -103694,8 +103687,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_op.ty.toType().fmt(pt),
|
||||
cg.typeOf(ty_op.operand).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
@@ -103835,8 +103828,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
const restricted_ty = cg.typeOf(ty_op.operand);
|
||||
var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
|
||||
const res = res: switch (restricted_ty.restrictedRepr(zcu)) {
|
||||
.double_pointer => {
|
||||
switch (air_tag) {
|
||||
.indirect => {
|
||||
if (zcu.comp.config.use_new_linker) switch (air_tag) {
|
||||
else => unreachable,
|
||||
.unwrap_restricted => {},
|
||||
.unwrap_restricted_safe => cg.select(&.{}, &.{}, &ops, &.{ .{
|
||||
@@ -103848,7 +103841,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.call_frame = .{ .alignment = .@"32" },
|
||||
.extra_temps = .{
|
||||
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
|
||||
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .const_data, .ref = .src0 } } },
|
||||
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data, .ref = .src0 } } },
|
||||
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
|
||||
.{ .type = .usize, .kind = .{ .panic_func = .corrupt_restricted_pointer } },
|
||||
.unused,
|
||||
@@ -103878,7 +103871,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.call_frame = .{ .alignment = .@"16" },
|
||||
.extra_temps = .{
|
||||
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
|
||||
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .const_data, .ref = .src0 } } },
|
||||
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data, .ref = .src0 } } },
|
||||
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
|
||||
.{ .type = .usize, .kind = .{ .panic_func = .corrupt_restricted_pointer } },
|
||||
.unused,
|
||||
@@ -103907,7 +103900,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.call_frame = .{ .alignment = .@"8" },
|
||||
.extra_temps = .{
|
||||
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
|
||||
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .const_data, .ref = .src0 } } },
|
||||
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data, .ref = .src0 } } },
|
||||
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
|
||||
.{ .type = .usize, .kind = .{ .panic_func = .corrupt_restricted_pointer } },
|
||||
.unused,
|
||||
@@ -103929,18 +103922,18 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .call, .tmp3d, ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
unrestricted_ty.fmt(pt),
|
||||
restricted_ty.fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
else => |e| return e,
|
||||
},
|
||||
}
|
||||
};
|
||||
break :res try ops[0].load(unrestricted_ty, .{}, cg);
|
||||
},
|
||||
.single_pointer => ops[0],
|
||||
.direct => ops[0],
|
||||
};
|
||||
try res.finish(inst, &.{ty_op.operand}, &ops, cg);
|
||||
},
|
||||
@@ -115178,8 +115171,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_op.ty.toType().fmt(pt),
|
||||
cg.typeOf(ty_op.operand).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
@@ -127197,8 +127190,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_op.ty.toType().fmt(pt),
|
||||
cg.typeOf(ty_op.operand).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
@@ -161387,9 +161380,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
} },
|
||||
} },
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s}.{s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
@tagName(reduce.operation),
|
||||
error.SelectFailed => return cg.fail("failed to select {t}.{t} {f} {f}", .{
|
||||
air_tag,
|
||||
reduce.operation,
|
||||
cg.typeOf(reduce.operand).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -161398,9 +161391,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
switch (reduce.operation) {
|
||||
.And, .Or, .Xor, .Min, .Max => {},
|
||||
.Add, .Mul => if (cg.intInfo(res_ty)) |_| res[0].wrapInt(cg) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s}.{s} wrap {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
@tagName(reduce.operation),
|
||||
error.SelectFailed => return cg.fail("failed to select {t}.{t} wrap {f} {f}", .{
|
||||
air_tag,
|
||||
reduce.operation,
|
||||
res_ty.fmt(pt),
|
||||
res[0].tracking(cg),
|
||||
}),
|
||||
@@ -169101,9 +169094,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
} },
|
||||
} },
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s}.{s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
@tagName(reduce.operation),
|
||||
error.SelectFailed => return cg.fail("failed to select {t}.{t} {f} {f}", .{
|
||||
air_tag,
|
||||
reduce.operation,
|
||||
cg.typeOf(reduce.operand).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -170898,8 +170891,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_op.ty.toType().fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -170914,8 +170907,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
const bin_op = air_datas[@intFromEnum(inst)].bin_op;
|
||||
var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }) ++ .{undefined};
|
||||
ops[2] = ops[0].getByteLen(cg) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
cg.typeOf(bin_op.rhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
@@ -170955,8 +170948,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
} },
|
||||
}},
|
||||
}) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
cg.typeOf(bin_op.rhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
@@ -171136,8 +171129,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .@"test", .tmp0p, .tmp0p, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(un_op).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -171302,8 +171295,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .call, .tmp0d, ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(un_op).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -171323,7 +171316,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ .src = .{ .to_gpr, .none, .none } },
|
||||
},
|
||||
.extra_temps = .{
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
|
||||
.{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
|
||||
.unused,
|
||||
.unused,
|
||||
@@ -171352,7 +171345,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ .src = .{ .to_gpr, .none, .none } },
|
||||
},
|
||||
.extra_temps = .{
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
|
||||
.{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
|
||||
.unused,
|
||||
.unused,
|
||||
@@ -171381,7 +171374,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ .src = .{ .to_gpr, .none, .none } },
|
||||
},
|
||||
.extra_temps = .{
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
|
||||
.{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
|
||||
.unused,
|
||||
.unused,
|
||||
@@ -171404,8 +171397,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .lea, .dst1d, .leai(.dst1, .tmp1), ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(un_op).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -171422,6 +171415,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
},
|
||||
.error_set_has_value => |air_tag| {
|
||||
const ty_op = air_datas[@intFromEnum(inst)].ty_op;
|
||||
assert(ty_op.ty != .anyerror_type); // das a constant
|
||||
var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}) ++ .{try cg.tempInit(ty_op.ty.toType(), .none)};
|
||||
var res: [1]Temp = undefined;
|
||||
cg.select(&res, &.{.bool}, &ops, comptime &.{ .{
|
||||
@@ -171502,8 +171496,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .@"test", .src0d, .src0d, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
|
||||
air_tag,
|
||||
ty_op.ty.toType().fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
@@ -171575,8 +171569,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
}
|
||||
}
|
||||
},
|
||||
else => return cg.fail("failed to select {s} {f}", .{
|
||||
@tagName(air_tag),
|
||||
else => return cg.fail("failed to select {t} {f}", .{
|
||||
air_tag,
|
||||
agg_ty.fmt(pt),
|
||||
}),
|
||||
}
|
||||
@@ -173021,8 +173015,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f} {f}", .{
|
||||
air_tag,
|
||||
cg.typeOf(bin_op.lhs).fmt(pt),
|
||||
ops[0].tracking(cg),
|
||||
ops[1].tracking(cg),
|
||||
@@ -173055,7 +173049,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ .src = .{ .to_gpr, .none, .none } },
|
||||
},
|
||||
.extra_temps = .{
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
|
||||
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
|
||||
.unused,
|
||||
.unused,
|
||||
@@ -173079,7 +173073,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ .src = .{ .to_gpr, .none, .none } },
|
||||
},
|
||||
.extra_temps = .{
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
|
||||
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
|
||||
.unused,
|
||||
.unused,
|
||||
@@ -173103,7 +173097,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ .src = .{ .to_gpr, .none, .none } },
|
||||
},
|
||||
.extra_temps = .{
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
|
||||
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
|
||||
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
|
||||
.unused,
|
||||
.unused,
|
||||
@@ -173122,8 +173116,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
.{ ._, ._, .cmp, .src0d, .lea(.tmp1d), ._, ._ },
|
||||
} },
|
||||
} }) catch |err| switch (err) {
|
||||
error.SelectFailed => return cg.fail("failed to select {s} {f}", .{
|
||||
@tagName(air_tag),
|
||||
error.SelectFailed => return cg.fail("failed to select {t} {f}", .{
|
||||
air_tag,
|
||||
ops[0].tracking(cg),
|
||||
}),
|
||||
else => |e| return e,
|
||||
@@ -173856,9 +173850,9 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
|
||||
const pt = cg.pt;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
switch (ip.indexToKey(lazy_sym.ty)) {
|
||||
switch (ip.indexToKey(lazy_sym.key)) {
|
||||
.enum_type => {
|
||||
const enum_ty: Type = .fromInterned(lazy_sym.ty);
|
||||
const enum_ty: Type = .fromInterned(lazy_sym.key);
|
||||
wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(pt)});
|
||||
|
||||
const ret_regs = abi.getCAbiIntReturnRegs(.auto)[0..2].*;
|
||||
@@ -173875,12 +173869,12 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
|
||||
const data_lock = cg.register_manager.lockRegAssumeUnused(data_reg);
|
||||
defer cg.register_manager.unlockReg(data_lock);
|
||||
try cg.asmRegisterMemory(.{ ._, .lea }, data_reg.to64(), .{
|
||||
.base = .{ .lazy_sym = .{ .kind = .const_data, .ty = lazy_sym.ty } },
|
||||
.base = .{ .lazy_sym = .{ .kind = .const_data, .key = lazy_sym.key } },
|
||||
});
|
||||
|
||||
var data_off: i32 = 0;
|
||||
const reset_index = cg.next_temp_index;
|
||||
const tag_names = ip.loadEnumType(lazy_sym.ty).field_names;
|
||||
const tag_names = ip.loadEnumType(lazy_sym.key).field_names;
|
||||
for (0..tag_names.len) |tag_index| {
|
||||
var enum_temp = try cg.tempInit(enum_ty, if (enum_ty.abiSize(zcu) <= @as(u4, switch (cg.target.cpu.arch) {
|
||||
else => unreachable,
|
||||
@@ -173919,7 +173913,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
|
||||
try cg.asmOpOnly(.{ ._, .ret });
|
||||
},
|
||||
.error_set_type => |error_set_type| {
|
||||
const err_ty: Type = .fromInterned(lazy_sym.ty);
|
||||
const err_ty: Type = .fromInterned(lazy_sym.key);
|
||||
wip_mir_log.debug("{f}.@errorCast:", .{err_ty.fmt(pt)});
|
||||
|
||||
const ret_reg = abi.getCAbiIntReturnRegs(.auto)[0];
|
||||
@@ -173964,8 +173958,8 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
|
||||
try cg.asmOpOnly(.{ ._, .ret });
|
||||
},
|
||||
else => return cg.fail(
|
||||
"TODO implement {s} for {f}",
|
||||
.{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },
|
||||
"TODO implement {t} for {f}",
|
||||
.{ lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt) },
|
||||
),
|
||||
}
|
||||
try cg.resetTemps(@enumFromInt(0));
|
||||
@@ -175315,10 +175309,7 @@ fn genShiftBinOpMir(
|
||||
.mod = .{ .rm = .{
|
||||
.size = .fromSize(abi_size),
|
||||
.disp = std.math.cast(i32, @as(i64, @bitCast(addr))) orelse
|
||||
return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
|
||||
@tagName(lhs_mcv),
|
||||
@tagName(shift_mcv),
|
||||
}),
|
||||
return self.fail("TODO genShiftBinOpMir between {t} and {t}", .{ lhs_mcv, shift_mcv }),
|
||||
} },
|
||||
},
|
||||
.indirect => |reg_off| .{
|
||||
@@ -175349,10 +175340,7 @@ fn genShiftBinOpMir(
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
|
||||
@tagName(lhs_mcv),
|
||||
@tagName(shift_mcv),
|
||||
});
|
||||
return self.fail("TODO genShiftBinOpMir between {t} and {t}", .{ lhs_mcv, shift_mcv });
|
||||
}
|
||||
|
||||
fn genBinOpMir(
|
||||
@@ -175401,9 +175389,7 @@ fn genBinOpMir(
|
||||
.add => .{ ._, .adc },
|
||||
.sub, .cmp => .{ ._, .sbb },
|
||||
.@"or", .@"and", .xor => mir_tag,
|
||||
else => return self.fail("TODO genBinOpMir implement large ABI for {s}", .{
|
||||
@tagName(mir_tag[1]),
|
||||
}),
|
||||
else => return self.fail("TODO genBinOpMir implement large ABI for {t}", .{mir_tag[1]}),
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
@@ -175652,9 +175638,7 @@ fn genBinOpMir(
|
||||
.add => .{ ._, .adc },
|
||||
.sub, .cmp => .{ ._, .sbb },
|
||||
.@"or", .@"and", .xor => mir_tag,
|
||||
else => return self.fail("TODO genBinOpMir implement large ABI for {s}", .{
|
||||
@tagName(mir_tag[1]),
|
||||
}),
|
||||
else => return self.fail("TODO genBinOpMir implement large ABI for {t}", .{mir_tag[1]}),
|
||||
},
|
||||
};
|
||||
const dst_limb_mem: Memory = switch (dst_mcv) {
|
||||
@@ -176527,7 +176511,7 @@ fn genCondBrMir(self: *CodeGen, ty: Type, mcv: MCValue) !Mir.Inst.Index {
|
||||
}
|
||||
return self.fail("TODO implement condbr when condition is {f} with abi larger than 8 bytes", .{mcv});
|
||||
},
|
||||
else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(mcv)}),
|
||||
else => return self.fail("TODO implement condbr when condition is {t}", .{mcv}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177551,10 +177535,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
|
||||
label_gop.value_ptr.target = @intCast(self.mir_instructions.len);
|
||||
} else continue;
|
||||
if (mnem_str[0] == '.') {
|
||||
if (prefix != .none) return self.fail("prefixed directive: '{s} {s}'", .{
|
||||
@tagName(prefix),
|
||||
mnem_str,
|
||||
});
|
||||
if (prefix != .none) return self.fail("prefixed directive: '{t} {s}'", .{ prefix, mnem_str });
|
||||
prefix = .directive;
|
||||
}
|
||||
|
||||
@@ -177871,8 +177852,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
|
||||
inline for (@typeInfo(encoder.Instruction.Mnemonic).@"enum".fields) |mnem|
|
||||
max_mnem_len = @max(mnem.name.len, max_mnem_len);
|
||||
var intel_mnem_buf: [max_mnem_len + 1]u8 = undefined;
|
||||
const intel_mnem_str = std.fmt.bufPrint(&intel_mnem_buf, "{s}{c}", .{
|
||||
@tagName(mnem_tag),
|
||||
const intel_mnem_str = std.fmt.bufPrint(&intel_mnem_buf, "{t}{c}", .{
|
||||
mnem_tag,
|
||||
@as(u8, switch (mnem_size.size) {
|
||||
.byte => 'b',
|
||||
.word => 'w',
|
||||
@@ -177908,9 +177889,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
|
||||
) orelse continue };
|
||||
} else {
|
||||
assert(prefix != .none); // no combination of fixes produced a known mnemonic
|
||||
return self.fail("invalid prefix for mnemonic: '{s} {s}'", .{
|
||||
@tagName(prefix), mnem_name,
|
||||
});
|
||||
return self.fail("invalid prefix for mnemonic: '{t} {s}'", .{ prefix, mnem_name });
|
||||
};
|
||||
|
||||
(if (prefix == .directive) switch (mnem_tag) {
|
||||
@@ -177969,12 +177948,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
|
||||
.@".cfi_escape" => error.InvalidInstruction,
|
||||
else => unreachable,
|
||||
} else self.asmOps(mnem_fixed_tag, ops)) catch |err| switch (err) {
|
||||
error.InvalidInstruction => return self.fail("invalid instruction: '{s} {s} {s} {s} {s}'", .{
|
||||
mnem_str,
|
||||
@tagName(ops[0]),
|
||||
@tagName(ops[1]),
|
||||
@tagName(ops[2]),
|
||||
@tagName(ops[3]),
|
||||
error.InvalidInstruction => return self.fail("invalid instruction: '{s} {t} {t} {t} {t}'", .{
|
||||
mnem_str, ops[0], ops[1], ops[2], ops[3],
|
||||
}),
|
||||
else => |e| return e,
|
||||
};
|
||||
@@ -178537,9 +178512,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
|
||||
break :src_info .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
|
||||
},
|
||||
.air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref), opts),
|
||||
else => return self.fail("TODO implement genCopy for {s} of {f}", .{
|
||||
@tagName(src_mcv), ty.fmt(pt),
|
||||
}),
|
||||
else => return self.fail("TODO implement genCopy for {t} of {f}", .{ src_mcv, ty.fmt(pt) }),
|
||||
};
|
||||
defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
|
||||
|
||||
@@ -179347,9 +179320,7 @@ fn genSetMem(
|
||||
opts,
|
||||
);
|
||||
},
|
||||
else => return self.fail("TODO implement genSetMem for {s} of {f}", .{
|
||||
@tagName(src_mcv), ty.fmt(pt),
|
||||
}),
|
||||
else => return self.fail("TODO implement genSetMem for {t} of {f}", .{ src_mcv, ty.fmt(pt) }),
|
||||
},
|
||||
.register_offset => |reg_off| {
|
||||
const src_reg = self.copyToTmpRegister(ty, src_mcv) catch |err| switch (err) {
|
||||
@@ -179705,7 +179676,7 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void {
|
||||
};
|
||||
switch (ptr_mem.mod) {
|
||||
.rm => {},
|
||||
.off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}),
|
||||
.off => return self.fail("TODO airCmpxchg with {t}", .{ptr_mcv}),
|
||||
}
|
||||
const ptr_lock = switch (ptr_mem.base) {
|
||||
.none, .frame, .nav, .uav => null,
|
||||
@@ -179788,7 +179759,7 @@ fn atomicOp(
|
||||
};
|
||||
switch (ptr_mem.mod) {
|
||||
.rm => {},
|
||||
.off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}),
|
||||
.off => return self.fail("TODO airCmpxchg with {t}", .{ptr_mcv}),
|
||||
}
|
||||
const mem_lock = switch (ptr_mem.base) {
|
||||
.none, .frame, .nav, .uav => null,
|
||||
@@ -179883,8 +179854,8 @@ fn atomicOp(
|
||||
else => null,
|
||||
},
|
||||
else => unreachable,
|
||||
}) orelse return self.fail("TODO implement atomicOp of {s} for {f}", .{
|
||||
@tagName(op), val_ty.fmt(pt),
|
||||
}) orelse return self.fail("TODO implement atomicOp of {t} for {f}", .{
|
||||
op, val_ty.fmt(pt),
|
||||
});
|
||||
try self.genSetReg(sse_reg, val_ty, .{ .register = .rax }, .{});
|
||||
switch (mir_tag[0]) {
|
||||
@@ -180952,7 +180923,7 @@ fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void {
|
||||
);
|
||||
break :result .{ .load_frame = .{ .index = dst_fi } };
|
||||
},
|
||||
else => |cc| return self.fail("{s} does not support var args", .{@tagName(cc)}),
|
||||
else => |cc| return self.fail("{t} does not support var args", .{cc}),
|
||||
};
|
||||
return self.finishAir(inst, result, .{ .none, .none, .none });
|
||||
}
|
||||
@@ -181139,7 +181110,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
|
||||
try self.convertFloatVarArg(inst, ty, promote_ty, promote_mcv);
|
||||
break :result promote_mcv;
|
||||
},
|
||||
else => |cc| return self.fail("{s} does not support var args", .{@tagName(cc)}),
|
||||
else => |cc| return self.fail("{t} does not support var args", .{cc}),
|
||||
};
|
||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||
}
|
||||
@@ -181236,6 +181207,7 @@ fn lowerValue(cg: *CodeGen, val: Value) Allocator.Error!MCValue {
|
||||
.lea_nav => |nav| .{ .lea_nav = nav },
|
||||
.lea_uav => |uav| .{ .lea_uav = uav },
|
||||
.load_uav => |uav| .{ .load_uav = uav },
|
||||
.lea_lazy_sym => |lazy_sym| .{ .lea_lazy_sym = lazy_sym },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -181630,10 +181602,14 @@ fn resolveCallingConventionValues(
|
||||
|
||||
fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
|
||||
@branchHint(.cold);
|
||||
const zcu = cg.pt.zcu;
|
||||
const pt = cg.pt;
|
||||
const zcu = pt.zcu;
|
||||
return switch (cg.owner) {
|
||||
.nav_index => |i| zcu.codegenFail(i, format, args),
|
||||
.lazy_sym => |s| zcu.codegenFailType(s.ty, format, args),
|
||||
.lazy_sym => |s| switch (zcu.intern_pool.typeOf(s.key)) {
|
||||
.type_type => zcu.codegenFailType(s.key, format, args),
|
||||
else => std.debug.panic("{f}: " ++ format, .{Value.fromInterned(s.key).fmtValue(pt)} ++ args),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -187899,14 +187875,14 @@ const Select = struct {
|
||||
error.InvalidInstruction => {
|
||||
const fixes = @tagName(mir_tag[0]);
|
||||
const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
|
||||
return s.cg.fail("invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'", .{
|
||||
return s.cg.fail("invalid instruction: '{s}{t}{s} {t} {t} {t} {t}'", .{
|
||||
fixes[0..fixes_blank],
|
||||
@tagName(mir_tag[1]),
|
||||
mir_tag[1],
|
||||
fixes[fixes_blank + 1 ..],
|
||||
@tagName(mir_ops[0]),
|
||||
@tagName(mir_ops[1]),
|
||||
@tagName(mir_ops[2]),
|
||||
@tagName(mir_ops[3]),
|
||||
mir_ops[0],
|
||||
mir_ops[1],
|
||||
mir_ops[2],
|
||||
mir_ops[3],
|
||||
});
|
||||
},
|
||||
else => |e| return e,
|
||||
@@ -187976,16 +187952,7 @@ const Select = struct {
|
||||
},
|
||||
.f_p => switch (mir_tag[1]) {
|
||||
.add, .com, .comi, .div, .divr, .mul, .st, .sub, .subr, .ucom, .ucomi => s.top +%= 1,
|
||||
else => {
|
||||
const fixes = @tagName(mir_tag[0]);
|
||||
const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
|
||||
std.debug.panic("{s}: {s}{s}{s}\n", .{
|
||||
@src().fn_name,
|
||||
fixes[0..fixes_blank],
|
||||
@tagName(mir_tag[1]),
|
||||
fixes[fixes_blank + 1 ..],
|
||||
});
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
.f_pp => switch (mir_tag[1]) {
|
||||
.com, .ucom => s.top +%= 2,
|
||||
@@ -189095,7 +189062,7 @@ const Select = struct {
|
||||
const ty = if (lazy_symbol_spec.ref == .none) spec.type else lazy_symbol_spec.ref.typeOf(s);
|
||||
return .{ try cg.tempInit(.usize, .{ .lea_lazy_sym = .{
|
||||
.kind = lazy_symbol_spec.kind,
|
||||
.ty = switch (ip.indexToKey(ty.toIntern())) {
|
||||
.key = switch (ip.indexToKey(ty.toIntern())) {
|
||||
.inferred_error_set_type => |func_index| switch (ip.funcIesResolvedUnordered(func_index)) {
|
||||
.none => unreachable,
|
||||
else => |ty_index| ty_index,
|
||||
|
||||
@@ -163,8 +163,8 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
else if (emit.bin_file.cast(.macho)) |macho_file|
|
||||
macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err|
|
||||
return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
|
||||
else if (emit.bin_file.cast(.coff2)) |elf|
|
||||
@intFromEnum(try elf.lazySymbol(lazy_sym))
|
||||
else if (emit.bin_file.cast(.coff2)) |coff|
|
||||
@intFromEnum(try coff.lazySymbol(lazy_sym))
|
||||
else
|
||||
return emit.fail("lazy symbols unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
|
||||
.is_extern = false,
|
||||
|
||||
@@ -1867,7 +1867,7 @@ pub const Memory = struct {
|
||||
size: bits.Memory.Size,
|
||||
index: Register,
|
||||
scale: bits.Memory.Scale,
|
||||
_: u13 = undefined,
|
||||
unused: u13 = 0,
|
||||
};
|
||||
|
||||
pub fn encode(mem: bits.Memory) Memory {
|
||||
@@ -1895,7 +1895,7 @@ pub const Memory = struct {
|
||||
.rip_inst => |inst_index| inst_index,
|
||||
.nav => |nav| @intFromEnum(nav),
|
||||
.uav => |uav| @intFromEnum(uav.val),
|
||||
.lazy_sym => |lazy_sym| @intFromEnum(lazy_sym.ty),
|
||||
.lazy_sym => |lazy_sym| @intFromEnum(lazy_sym.key),
|
||||
.extern_func => |extern_func| @intFromEnum(extern_func),
|
||||
},
|
||||
.off = switch (mem.mod) {
|
||||
@@ -1933,7 +1933,10 @@ pub const Memory = struct {
|
||||
.rip_inst => .{ .rip_inst = mem.base },
|
||||
.nav => .{ .nav = @enumFromInt(mem.base) },
|
||||
.uav => .{ .uav = .{ .val = @enumFromInt(mem.base), .orig_ty = @enumFromInt(mem.extra) } },
|
||||
.lazy_sym => .{ .lazy_sym = .{ .kind = @enumFromInt(mem.extra), .ty = @enumFromInt(mem.base) } },
|
||||
.lazy_sym => .{ .lazy_sym = .{
|
||||
.kind = @enumFromInt(mem.extra),
|
||||
.key = @enumFromInt(mem.base),
|
||||
} },
|
||||
.extern_func => .{ .extern_func = @enumFromInt(mem.base) },
|
||||
},
|
||||
.scale_index = switch (mem.info.index) {
|
||||
@@ -2061,10 +2064,28 @@ pub fn emitLazy(
|
||||
.table_relocs = .empty,
|
||||
};
|
||||
defer e.deinit();
|
||||
e.emitMir() catch |err| switch (err) {
|
||||
error.LowerFail, error.EmitFail => return zcu.codegenFailTypeMsg(lazy_sym.ty, e.lower.err_msg.?),
|
||||
error.InvalidInstruction, error.CannotEncode => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}),
|
||||
else => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s}", .{@errorName(err)}),
|
||||
e.emitMir() catch |err| switch (zcu.intern_pool.typeOf(lazy_sym.key)) {
|
||||
.type_type => switch (err) {
|
||||
error.LowerFail, error.EmitFail => return zcu.codegenFailTypeMsg(lazy_sym.key, e.lower.err_msg.?),
|
||||
error.InvalidInstruction, error.CannotEncode => return zcu.codegenFailType(
|
||||
lazy_sym.key,
|
||||
"emit MIR failed: {t} (Zig compiler bug)",
|
||||
.{err},
|
||||
),
|
||||
else => return zcu.codegenFailType(lazy_sym.key, "emit MIR failed: {t}", .{err}),
|
||||
},
|
||||
else => switch (err) {
|
||||
error.LowerFail, error.EmitFail => std.debug.panic("{f}: {s}", .{
|
||||
@import("../../Value.zig").fromInterned(lazy_sym.key).fmtValue(pt), e.lower.err_msg.?.msg,
|
||||
}),
|
||||
error.InvalidInstruction, error.CannotEncode => std.debug.panic(
|
||||
"{f}: emit MIR failed: {t} (Zig compiler bug)",
|
||||
.{ @import("../../Value.zig").fromInterned(lazy_sym.key).fmtValue(pt), err },
|
||||
),
|
||||
else => std.debug.panic("{f}: emit MIR failed: {t}", .{
|
||||
@import("../../Value.zig").fromInterned(lazy_sym.key).fmtValue(pt), err,
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ pub const Instruction = struct {
|
||||
try w.print("{f} ", .{sib.ptr_size});
|
||||
|
||||
if (mem.isSegmentRegister()) {
|
||||
return w.print("{s}:0x{x}", .{ @tagName(sib.base.reg), sib.disp });
|
||||
return w.print("{t}:0x{x}", .{ sib.base.reg, sib.disp });
|
||||
}
|
||||
|
||||
try w.writeByte('[');
|
||||
@@ -246,21 +246,18 @@ pub const Instruction = struct {
|
||||
var any = true;
|
||||
switch (sib.base) {
|
||||
.none => any = false,
|
||||
.reg => |reg| try w.print("{s}", .{@tagName(reg)}),
|
||||
.reg => |reg| try w.print("{t}", .{reg}),
|
||||
.frame => |frame_index| try w.print("{f}", .{frame_index}),
|
||||
.table => try w.print("Table", .{}),
|
||||
.rip_inst => |inst_index| try w.print("RipInst({d})", .{inst_index}),
|
||||
.nav => |nav| try w.print("Nav({d})", .{@intFromEnum(nav)}),
|
||||
.uav => |uav| try w.print("Uav({d})", .{@intFromEnum(uav.val)}),
|
||||
.lazy_sym => |lazy_sym| try w.print("LazySym({s}, {d})", .{
|
||||
@tagName(lazy_sym.kind),
|
||||
@intFromEnum(lazy_sym.ty),
|
||||
}),
|
||||
.extern_func => |extern_func| try w.print("ExternFunc({d})", .{@intFromEnum(extern_func)}),
|
||||
.nav => |nav| try w.print("Nav({d})", .{nav}),
|
||||
.uav => |uav| try w.print("Uav({d})", .{uav.val}),
|
||||
.lazy_sym => |lazy_sym| try w.print("LazySym({t}, {d})", .{ lazy_sym.kind, lazy_sym.key }),
|
||||
.extern_func => |extern_func| try w.print("ExternFunc({d})", .{extern_func}),
|
||||
}
|
||||
if (mem.scaleIndex()) |si| {
|
||||
if (any) try w.writeAll(" + ");
|
||||
try w.print("{s} * {d}", .{ @tagName(si.index), si.scale });
|
||||
try w.print("{t} * {d}", .{ si.index, si.scale });
|
||||
any = true;
|
||||
}
|
||||
if (sib.disp != 0 or !any) {
|
||||
@@ -274,10 +271,7 @@ pub const Instruction = struct {
|
||||
|
||||
try w.writeByte(']');
|
||||
},
|
||||
.moffs => |moffs| try w.print("{s}:0x{x}", .{
|
||||
@tagName(moffs.seg),
|
||||
moffs.offset,
|
||||
}),
|
||||
.moffs => |moffs| try w.print("{t}:0x{x}", .{ moffs.seg, moffs.offset }),
|
||||
},
|
||||
.imm => |imm| if (enc_op.isSigned()) {
|
||||
const imms = imm.asSigned(enc_op.immBitSize());
|
||||
@@ -344,9 +338,9 @@ pub const Instruction = struct {
|
||||
pub fn format(inst: Instruction, w: *Writer) Writer.Error!void {
|
||||
switch (inst.prefix) {
|
||||
.none, .directive => {},
|
||||
else => try w.print("{s} ", .{@tagName(inst.prefix)}),
|
||||
else => try w.print("{t} ", .{inst.prefix}),
|
||||
}
|
||||
try w.print("{s}", .{@tagName(inst.encoding.mnemonic)});
|
||||
try w.print("{t}", .{inst.encoding.mnemonic});
|
||||
for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| {
|
||||
if (op == .none) break;
|
||||
if (i > 0) try w.writeByte(',');
|
||||
|
||||
+18
-4
@@ -1019,7 +1019,7 @@ pub const File = struct {
|
||||
/// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate
|
||||
/// the block/atom.
|
||||
/// Never called when LLVM is codegenning the ZCU.
|
||||
pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 {
|
||||
pub fn getNavVAddr(base: *File, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 {
|
||||
assert(base.comp.zcu.?.llvm_object == null);
|
||||
switch (base.tag) {
|
||||
.lld => unreachable,
|
||||
@@ -1029,7 +1029,7 @@ pub const File = struct {
|
||||
.plan9 => unreachable,
|
||||
inline else => |tag| {
|
||||
dev.check(tag.devFeature());
|
||||
return @as(*tag.Type(), @fieldParentPtr("base", base)).getNavVAddr(pt, nav_index, reloc_info);
|
||||
return @as(*tag.Type(), @fieldParentPtr("base", base)).getNavVAddr(nav_index, reloc_info);
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1290,11 +1290,25 @@ pub const File = struct {
|
||||
};
|
||||
|
||||
pub const LazySymbol = struct {
|
||||
pub const Kind = enum { code, const_data };
|
||||
pub const Kind = enum(u2) { code, const_data, deferred_const_data };
|
||||
|
||||
kind: Kind,
|
||||
ty: InternPool.Index,
|
||||
key: InternPool.Index,
|
||||
};
|
||||
pub fn getLazySymbolVAddr(base: *File, pt: Zcu.PerThread, lazy_symbol: LazySymbol, reloc_info: RelocInfo) !u64 {
|
||||
assert(base.comp.zcu.?.llvm_object == null);
|
||||
switch (base.tag) {
|
||||
.lld => unreachable,
|
||||
.c => unreachable,
|
||||
.spirv => unreachable,
|
||||
.wasm => unreachable,
|
||||
.plan9 => unreachable,
|
||||
inline else => |tag| {
|
||||
dev.check(tag.devFeature());
|
||||
return @as(*tag.Type(), @fieldParentPtr("base", base)).getLazySymbolVAddr(pt, lazy_symbol, reloc_info);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn determinePermissions(
|
||||
output_mode: std.builtin.OutputMode,
|
||||
|
||||
+50
-3
@@ -134,6 +134,7 @@ const RenderedDecl = struct {
|
||||
code: String,
|
||||
ctype_deps: CTypeDependencies,
|
||||
need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
|
||||
need_restricted: std.array_hash_map.Auto(InternPool.Index, void),
|
||||
need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
|
||||
need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
|
||||
need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
|
||||
@@ -143,6 +144,7 @@ const RenderedDecl = struct {
|
||||
.code = .empty,
|
||||
.ctype_deps = .empty,
|
||||
.need_uavs = .empty,
|
||||
.need_restricted = .empty,
|
||||
.need_tag_name_funcs = .empty,
|
||||
.need_never_tail_funcs = .empty,
|
||||
.need_never_inline_funcs = .empty,
|
||||
@@ -150,6 +152,7 @@ const RenderedDecl = struct {
|
||||
|
||||
fn deinit(rd: *RenderedDecl, gpa: Allocator) void {
|
||||
rd.need_uavs.deinit(gpa);
|
||||
rd.need_restricted.deinit(gpa);
|
||||
rd.need_tag_name_funcs.deinit(gpa);
|
||||
rd.need_never_tail_funcs.deinit(gpa);
|
||||
rd.need_never_inline_funcs.deinit(gpa);
|
||||
@@ -162,6 +165,7 @@ const RenderedDecl = struct {
|
||||
fn clearRetainingCapacity(rd: *RenderedDecl) void {
|
||||
rd.fwd_decl = undefined;
|
||||
rd.code = undefined;
|
||||
rd.need_restricted.clearRetainingCapacity();
|
||||
rd.need_uavs.clearRetainingCapacity();
|
||||
rd.need_tag_name_funcs.clearRetainingCapacity();
|
||||
rd.need_never_tail_funcs.clearRetainingCapacity();
|
||||
@@ -501,6 +505,7 @@ pub fn updateFunc(
|
||||
.code = try c.addString(&.{ mir.c.code_header, mir.c.code }),
|
||||
.ctype_deps = try c.addCTypeDependencies(pt, &mir.c.ctype_deps),
|
||||
.need_uavs = mir.c.need_uavs.move(),
|
||||
.need_restricted = mir.c.need_restricted.move(),
|
||||
.need_tag_name_funcs = mir.c.need_tag_name_funcs.move(),
|
||||
.need_never_tail_funcs = mir.c.need_never_tail_funcs.move(),
|
||||
.need_never_inline_funcs = mir.c.need_never_inline_funcs.move(),
|
||||
@@ -576,11 +581,13 @@ pub fn updateNav(
|
||||
.expected_block = null,
|
||||
.ctype_deps = .empty,
|
||||
.uavs = rendered_decl.need_uavs.move(),
|
||||
.need_restricted = .empty,
|
||||
};
|
||||
|
||||
defer {
|
||||
rendered_decl.need_uavs = dg.uavs.move();
|
||||
dg.ctype_deps.deinit(gpa);
|
||||
dg.need_restricted.deinit(gpa);
|
||||
}
|
||||
|
||||
rendered_decl.fwd_decl = fwd_decl: {
|
||||
@@ -618,6 +625,7 @@ pub fn updateNav(
|
||||
};
|
||||
|
||||
rendered_decl.ctype_deps = try c.addCTypeDependencies(pt, &dg.ctype_deps);
|
||||
rendered_decl.need_restricted = dg.need_restricted.move();
|
||||
}
|
||||
|
||||
const old_uavs_len = c.uavs.count();
|
||||
@@ -667,10 +675,12 @@ fn updateUav(
|
||||
.expected_block = null,
|
||||
.ctype_deps = .empty,
|
||||
.uavs = .empty,
|
||||
.need_restricted = .empty,
|
||||
};
|
||||
defer {
|
||||
rendered_decl.need_uavs = dg.uavs.move();
|
||||
dg.ctype_deps.deinit(gpa);
|
||||
dg.need_restricted.deinit(gpa);
|
||||
}
|
||||
|
||||
rendered_decl.fwd_decl = fwd_decl: {
|
||||
@@ -716,6 +726,7 @@ fn updateUav(
|
||||
};
|
||||
|
||||
rendered_decl.ctype_deps = try c.addCTypeDependencies(pt, &dg.ctype_deps);
|
||||
rendered_decl.need_restricted = dg.need_restricted.move();
|
||||
}
|
||||
|
||||
pub fn updateLineNumber(c: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) error{}!void {
|
||||
@@ -795,6 +806,10 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
|
||||
var need_aligned_types: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, u64) = .empty;
|
||||
defer need_aligned_types.deinit(gpa);
|
||||
|
||||
var need_restricted: std.array_hash_map.Auto(InternPool.Index, std.array_hash_map.Auto(InternPool.Index, void)) = .empty;
|
||||
defer need_restricted.deinit(gpa);
|
||||
defer for (need_restricted.values()) |*values| values.deinit(gpa);
|
||||
|
||||
var need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty;
|
||||
defer need_tag_name_funcs.deinit(gpa);
|
||||
|
||||
@@ -816,7 +831,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
|
||||
if (!gop.found_existing) gop.value_ptr.* = .none;
|
||||
}
|
||||
|
||||
// For every referenced NAV, some UAVs, C types, and lazy functions may be referenced.
|
||||
// For every referenced NAV, some UAVs, restricted types, C types, and lazy functions may be referenced.
|
||||
for (need_navs.keys()) |nav| {
|
||||
const rendered = c.navs.getPtr(nav).?;
|
||||
try mergeNeededCTypes(
|
||||
@@ -827,6 +842,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
|
||||
&rendered.ctype_deps,
|
||||
);
|
||||
try mergeNeededUavs(zcu, &need_uavs, &rendered.need_uavs);
|
||||
try mergeNeededRestricted(zcu, &need_restricted, &rendered.need_restricted);
|
||||
|
||||
try need_tag_name_funcs.ensureUnusedCapacity(gpa, rendered.need_tag_name_funcs.count());
|
||||
for (rendered.need_tag_name_funcs.keys()) |enum_type| {
|
||||
@@ -844,7 +860,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
|
||||
}
|
||||
}
|
||||
|
||||
// UAVs may reference other UAVs or C types.
|
||||
// UAVs may reference other UAVs, restricted types, or C types.
|
||||
{
|
||||
var index: usize = 0;
|
||||
while (need_uavs.count() > index) : (index += 1) {
|
||||
@@ -858,6 +874,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
|
||||
&rendered.ctype_deps,
|
||||
);
|
||||
try mergeNeededUavs(zcu, &need_uavs, &rendered.need_uavs);
|
||||
try mergeNeededRestricted(zcu, &need_restricted, &rendered.need_restricted);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -962,7 +979,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
|
||||
// * NAV exports
|
||||
// * UAV forward declarations
|
||||
// * NAV forward declarations
|
||||
// * Lazy declarations (error names; @tagName functions; never_tail/never_inline wrappers)
|
||||
// * Lazy declarations (restricted decls; error names; @tagName functions; never_tail/never_inline wrappers)
|
||||
// * UAV definitions
|
||||
// * NAV definitions
|
||||
//
|
||||
@@ -1115,11 +1132,18 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
|
||||
.error_msg = null,
|
||||
.ctype_deps = .empty,
|
||||
.uavs = .empty,
|
||||
.need_restricted = .empty,
|
||||
};
|
||||
defer {
|
||||
assert(lazy_dg.uavs.count() == 0);
|
||||
lazy_dg.ctype_deps.deinit(gpa);
|
||||
assert(lazy_dg.need_restricted.count() == 0);
|
||||
}
|
||||
codegen.genRestricted(&lazy_dg, &need_restricted, &lazy_decls_aw.writer) catch |err| switch (err) {
|
||||
error.WriteFailed => return error.OutOfMemory,
|
||||
error.OutOfMemory => |e| return e,
|
||||
error.AnalysisFail => unreachable,
|
||||
};
|
||||
const slice_const_u8_sentinel_0_cty: codegen.CType = try .lower(
|
||||
.slice_const_u8_sentinel_0,
|
||||
&lazy_dg.ctype_deps,
|
||||
@@ -1259,10 +1283,12 @@ pub fn updateExports(
|
||||
.error_msg = null,
|
||||
.ctype_deps = .empty,
|
||||
.uavs = .empty,
|
||||
.need_restricted = .empty,
|
||||
};
|
||||
defer {
|
||||
assert(dg.uavs.count() == 0);
|
||||
dg.ctype_deps.deinit(gpa);
|
||||
assert(dg.need_restricted.count() == 0);
|
||||
}
|
||||
|
||||
const code: String = code: {
|
||||
@@ -1347,6 +1373,27 @@ fn mergeNeededUavs(
|
||||
}
|
||||
}
|
||||
|
||||
fn mergeNeededRestricted(
|
||||
zcu: *const Zcu,
|
||||
global: *std.array_hash_map.Auto(InternPool.Index, std.array_hash_map.Auto(InternPool.Index, void)),
|
||||
new: *const std.array_hash_map.Auto(InternPool.Index, void),
|
||||
) Allocator.Error!void {
|
||||
const gpa = zcu.comp.gpa;
|
||||
const ip = &zcu.intern_pool;
|
||||
|
||||
try global.ensureUnusedCapacity(gpa, new.count());
|
||||
for (new.keys()) |restricted_key| {
|
||||
const restricted_ty = switch (ip.indexToKey(restricted_key)) {
|
||||
else => unreachable,
|
||||
.restricted_ptr_type => restricted_key,
|
||||
.ptr => |ptr| ptr.ty,
|
||||
};
|
||||
const gop = global.getOrPutAssumeCapacity(restricted_ty);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .empty;
|
||||
if (restricted_ty != restricted_key) try gop.value_ptr.put(gpa, restricted_key, {});
|
||||
}
|
||||
}
|
||||
|
||||
fn addCTypeDependencies(
|
||||
c: *C,
|
||||
pt: Zcu.PerThread,
|
||||
|
||||
+77
-36
@@ -138,6 +138,7 @@ pub const Node = union(enum) {
|
||||
uav: UavMapIndex,
|
||||
lazy_code: LazyMapRef.Index(.code),
|
||||
lazy_const_data: LazyMapRef.Index(.const_data),
|
||||
lazy_deferred_const_data: LazyMapRef.Index(.deferred_const_data),
|
||||
|
||||
pub const PseudoSectionMapIndex = enum(u32) {
|
||||
_,
|
||||
@@ -222,7 +223,7 @@ pub const Node = union(enum) {
|
||||
}
|
||||
|
||||
pub fn lazySymbol(lmr: LazyMapRef, coff: *const Coff) link.File.LazySymbol {
|
||||
return .{ .kind = lmr.kind, .ty = coff.lazy.getPtrConst(lmr.kind).map.keys()[lmr.index] };
|
||||
return .{ .kind = lmr.kind, .key = coff.lazy.getPtrConst(lmr.kind).map.keys()[lmr.index] };
|
||||
}
|
||||
|
||||
pub fn symbol(lmr: LazyMapRef, coff: *const Coff) Symbol.Index {
|
||||
@@ -1053,6 +1054,7 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 {
|
||||
.uav,
|
||||
.lazy_code,
|
||||
.lazy_const_data,
|
||||
.lazy_deferred_const_data,
|
||||
=> |mi| mi.symbol(coff),
|
||||
};
|
||||
break :parent_rva parent_si.get(coff).rva;
|
||||
@@ -1259,7 +1261,8 @@ fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.Na
|
||||
if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();
|
||||
return @enumFromInt(sym_gop.index);
|
||||
}
|
||||
pub fn navSymbol(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {
|
||||
pub fn navSymbol(coff: *Coff, nav_index: InternPool.Nav.Index) !Symbol.Index {
|
||||
const zcu = coff.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(nav_index);
|
||||
if (nav.getExtern(ip)) |@"extern"| return coff.globalSymbol(
|
||||
@@ -1282,24 +1285,38 @@ pub fn uavSymbol(coff: *Coff, uav_val: InternPool.Index) !Symbol.Index {
|
||||
return umi.symbol(coff);
|
||||
}
|
||||
|
||||
pub fn lazySymbol(coff: *Coff, lazy: link.File.LazySymbol) !Symbol.Index {
|
||||
const gpa = coff.base.comp.gpa;
|
||||
try coff.symbol_table.ensureUnusedCapacity(gpa, 1);
|
||||
const sym_gop = try coff.lazy.getPtr(lazy.kind).map.getOrPut(gpa, lazy.ty);
|
||||
if (!sym_gop.found_existing) {
|
||||
sym_gop.value_ptr.* = try coff.initSymbolAssumeCapacity();
|
||||
coff.synth_prog_node.increaseEstimatedTotalItems(1);
|
||||
}
|
||||
return sym_gop.value_ptr.*;
|
||||
fn lazySymbolIfExists(coff: *Coff, lazy_sym: link.File.LazySymbol) ?Symbol.Index {
|
||||
return coff.lazy.getPtr(lazy_sym.kind).map.get(lazy_sym.key);
|
||||
}
|
||||
fn lazySymbolAssumeCapacity(coff: *Coff, lazy_sym: link.File.LazySymbol) !struct { Symbol.Index, usize } {
|
||||
const gop = try coff.lazy.getPtr(lazy_sym.kind).map.getOrPut(coff.base.comp.gpa, lazy_sym.key);
|
||||
if (gop.found_existing) return .{ gop.value_ptr.*, gop.index };
|
||||
const si = try coff.initSymbolAssumeCapacity();
|
||||
gop.value_ptr.* = si;
|
||||
coff.synth_prog_node.increaseEstimatedTotalItems(1);
|
||||
return .{ si, gop.index };
|
||||
}
|
||||
pub fn lazySymbol(coff: *Coff, lazy_sym: link.File.LazySymbol) !Symbol.Index {
|
||||
// optimize for future lookups, at the cost of an extra initial key lookup
|
||||
if (coff.lazySymbolIfExists(lazy_sym)) |si| return si;
|
||||
const comp = coff.base.comp;
|
||||
const structure = codegen.getLazySymbolInfo(.structure, lazy_sym, comp.zcu.?);
|
||||
try coff.symbol_table.ensureUnusedCapacity(
|
||||
comp.gpa,
|
||||
@as(usize, @intFromBool(structure.parent != null)) + 1,
|
||||
);
|
||||
if (structure.parent) |parent_lazy_sym| _ = try coff.lazySymbolAssumeCapacity(parent_lazy_sym);
|
||||
if (structure.modify) |modification| _ = try coff.lazySymbolAssumeCapacity(modification.lazy_sym);
|
||||
const si, _ = try coff.lazySymbolAssumeCapacity(lazy_sym);
|
||||
return si;
|
||||
}
|
||||
|
||||
pub fn getNavVAddr(
|
||||
coff: *Coff,
|
||||
pt: Zcu.PerThread,
|
||||
nav: InternPool.Nav.Index,
|
||||
reloc_info: link.File.RelocInfo,
|
||||
) !u64 {
|
||||
return coff.getVAddr(reloc_info, try coff.navSymbol(pt.zcu, nav));
|
||||
return coff.getVAddr(reloc_info, try coff.navSymbol(nav));
|
||||
}
|
||||
|
||||
pub fn getUavVAddr(
|
||||
@@ -1310,6 +1327,15 @@ pub fn getUavVAddr(
|
||||
return coff.getVAddr(reloc_info, try coff.uavSymbol(uav));
|
||||
}
|
||||
|
||||
pub fn getLazySymbolVAddr(
|
||||
coff: *Coff,
|
||||
_: Zcu.PerThread,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
reloc_info: link.File.RelocInfo,
|
||||
) !u64 {
|
||||
return coff.getVAddr(reloc_info, try coff.lazySymbol(lazy_sym));
|
||||
}
|
||||
|
||||
pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol.Index) !u64 {
|
||||
try coff.addReloc(
|
||||
@enumFromInt(reloc_info.parent.atom_index),
|
||||
@@ -1713,7 +1739,7 @@ fn updateFuncInner(
|
||||
|
||||
pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void {
|
||||
coff.flushLazy(pt, .{
|
||||
.kind = .const_data,
|
||||
.kind = .deferred_const_data,
|
||||
.index = @intCast(coff.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),
|
||||
}) catch |err| switch (err) {
|
||||
error.OutOfMemory => |e| return e,
|
||||
@@ -1798,13 +1824,13 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
|
||||
lazy.value.pending_index += 1;
|
||||
const kind = switch (lmr.kind) {
|
||||
.code => "code",
|
||||
.const_data => "data",
|
||||
.const_data, .deferred_const_data => "data",
|
||||
};
|
||||
var name: [std.Progress.Node.max_name_len]u8 = undefined;
|
||||
const sub_prog_node = coff.synth_prog_node.start(
|
||||
std.fmt.bufPrint(&name, "lazy {s} for {f}", .{
|
||||
kind,
|
||||
Type.fromInterned(lmr.lazySymbol(coff).ty).fmt(pt),
|
||||
Value.fromInterned(lmr.lazySymbol(coff).key).fmtValue(pt),
|
||||
}) catch &name,
|
||||
0,
|
||||
);
|
||||
@@ -2092,24 +2118,36 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
const lazy = lmr.lazySymbol(coff);
|
||||
const lazy_sym = lmr.lazySymbol(coff);
|
||||
const si = lmr.symbol(coff);
|
||||
const structure = codegen.getLazySymbolInfo(.structure, lazy_sym, zcu);
|
||||
const ni = ni: {
|
||||
const sym = si.get(coff);
|
||||
switch (sym.ni) {
|
||||
.none => {
|
||||
try coff.nodes.ensureUnusedCapacity(gpa, 1);
|
||||
const sec_si: Symbol.Index = switch (lazy.kind) {
|
||||
const attrs = codegen.getLazySymbolInfo(.attributes, lazy_sym, zcu);
|
||||
const parent_si: Symbol.Index = if (structure.parent) |parent_lazy_sym|
|
||||
coff.lazySymbolIfExists(parent_lazy_sym).?
|
||||
else switch (lazy_sym.kind) {
|
||||
.code => .text,
|
||||
.const_data => .rdata,
|
||||
.const_data, .deferred_const_data => .rdata,
|
||||
};
|
||||
const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{ .moved = true });
|
||||
coff.nodes.appendAssumeCapacity(switch (lazy.kind) {
|
||||
const addChildNode =
|
||||
if (attrs.header) &MappedFile.addOnlyChildNode else &MappedFile.addLastChildNode;
|
||||
const ni = try addChildNode(&coff.mf, coff.base.comp.gpa, parent_si.node(coff), .{
|
||||
.size = attrs.size orelse 0,
|
||||
.alignment = attrs.required_alignment.toStdMem(),
|
||||
.fixed = attrs.header,
|
||||
.moved = true,
|
||||
});
|
||||
coff.nodes.appendAssumeCapacity(switch (lazy_sym.kind) {
|
||||
.code => .{ .lazy_code = @enumFromInt(lmr.index) },
|
||||
.const_data => .{ .lazy_const_data = @enumFromInt(lmr.index) },
|
||||
.deferred_const_data => .{ .lazy_deferred_const_data = @enumFromInt(lmr.index) },
|
||||
});
|
||||
sym.ni = ni;
|
||||
sym.section_number = sec_si.get(coff).section_number;
|
||||
sym.section_number = parent_si.get(coff).section_number;
|
||||
},
|
||||
else => si.deleteLocationRelocs(coff),
|
||||
}
|
||||
@@ -2118,22 +2156,25 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
|
||||
break :ni sym.ni;
|
||||
};
|
||||
|
||||
var required_alignment: InternPool.Alignment = .none;
|
||||
var nw: MappedFile.Node.Writer = undefined;
|
||||
ni.writer(&coff.mf, gpa, &nw);
|
||||
defer nw.deinit();
|
||||
try codegen.generateLazySymbol(
|
||||
&coff.base,
|
||||
pt,
|
||||
Type.fromInterned(lazy.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
|
||||
lazy,
|
||||
&required_alignment,
|
||||
Type.fromInterned(lazy_sym.key).srcLocOrNull(pt.zcu) orelse .unneeded,
|
||||
lazy_sym,
|
||||
&nw.interface,
|
||||
.none,
|
||||
.{ .atom_index = @intFromEnum(si) },
|
||||
);
|
||||
si.get(coff).size = @intCast(nw.interface.end);
|
||||
si.applyLocationRelocs(coff);
|
||||
|
||||
if (structure.modify) |modification| modification.operation.apply(
|
||||
coff.lazySymbolIfExists(modification.lazy_sym).?.node(coff).slice(&coff.mf),
|
||||
coff.targetEndian(),
|
||||
);
|
||||
}
|
||||
|
||||
fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
|
||||
@@ -2219,6 +2260,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
|
||||
.uav,
|
||||
.lazy_code,
|
||||
.lazy_const_data,
|
||||
.lazy_deferred_const_data,
|
||||
=> |mi| mi.symbol(coff).flushMoved(coff),
|
||||
}
|
||||
try ni.childrenMoved(coff.base.comp.gpa, &coff.mf);
|
||||
@@ -2269,7 +2311,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {
|
||||
inline .pseudo_section,
|
||||
.object_section,
|
||||
=> |smi| smi.symbol(coff).get(coff).size = @intCast(size),
|
||||
.global, .nav, .uav, .lazy_code, .lazy_const_data => {},
|
||||
.global, .nav, .uav, .lazy_code, .lazy_const_data, .lazy_deferred_const_data => {},
|
||||
}
|
||||
}
|
||||
fn virtualSlide(coff: *Coff, start_section_index: usize, start_rva: u32) !void {
|
||||
@@ -2322,7 +2364,7 @@ fn updateExportsInner(
|
||||
}
|
||||
try coff.symbol_table.ensureUnusedCapacity(gpa, export_indices.len);
|
||||
const exported_si: Symbol.Index = switch (exported) {
|
||||
.nav => |nav| try coff.navSymbol(zcu, nav),
|
||||
.nav => |nav| try coff.navSymbol(nav),
|
||||
.uav => |uav| @enumFromInt(switch (try coff.lowerUav(
|
||||
pt,
|
||||
uav,
|
||||
@@ -2365,7 +2407,7 @@ pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTe
|
||||
_ = name;
|
||||
}
|
||||
|
||||
pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) Io.Cancelable!void {
|
||||
pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) !void {
|
||||
const comp = coff.base.comp;
|
||||
const io = comp.io;
|
||||
var buffer: [512]u8 = undefined;
|
||||
@@ -2373,7 +2415,7 @@ pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) Io.Cancelable!void {
|
||||
defer io.unlockStderr();
|
||||
const w = &stderr.file_writer.interface;
|
||||
coff.printNode(tid, w, .root, 0) catch |err| switch (err) {
|
||||
error.WriteFailed => return stderr.err.?,
|
||||
error.WriteFailed => return stderr.file_writer.err.?,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2412,7 +2454,7 @@ pub fn printNode(
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(nmi.navIndex(coff));
|
||||
try w.print("({f}, {f})", .{
|
||||
Type.fromInterned(nav.typeOf(ip)).fmt(.{ .zcu = zcu, .tid = tid }),
|
||||
Type.fromInterned(nav.resolved.?.type).fmt(.{ .zcu = zcu, .tid = tid }),
|
||||
nav.fqn.fmt(ip),
|
||||
});
|
||||
},
|
||||
@@ -2425,10 +2467,9 @@ pub fn printNode(
|
||||
});
|
||||
},
|
||||
inline .lazy_code, .lazy_const_data => |lmi| try w.print("({f})", .{
|
||||
Type.fromInterned(lmi.lazySymbol(coff).ty).fmt(.{
|
||||
.zcu = coff.base.comp.zcu.?,
|
||||
.tid = tid,
|
||||
}),
|
||||
Value.fromInterned(lmi.lazySymbol(coff).key).fmtValue(
|
||||
.{ .zcu = coff.base.comp.zcu.?, .tid = tid },
|
||||
),
|
||||
}),
|
||||
}
|
||||
{
|
||||
@@ -2458,7 +2499,7 @@ pub fn printNode(
|
||||
const line_len = 0x10;
|
||||
var line_it = std.mem.window(
|
||||
u8,
|
||||
coff.mf.contents[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)],
|
||||
coff.mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)],
|
||||
line_len,
|
||||
line_len,
|
||||
);
|
||||
|
||||
+2
-2
@@ -3631,11 +3631,11 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
|
||||
},
|
||||
},
|
||||
.restricted_ptr_type => |restricted_ptr_type| switch (Type.restrictedReprByZirIndex(restricted_ptr_type.zir_index, zcu)) {
|
||||
.double_pointer => continue :key .{ .ptr_type = .{
|
||||
.indirect => continue :key .{ .ptr_type = .{
|
||||
.child = restricted_ptr_type.unrestricted_ptr_type,
|
||||
.flags = .{ .is_const = true },
|
||||
} },
|
||||
.single_pointer => continue :key .{ .ptr_type = ip.indexToKey(restricted_ptr_type.unrestricted_ptr_type).ptr_type },
|
||||
.direct => continue :key .{ .ptr_type = ip.indexToKey(restricted_ptr_type.unrestricted_ptr_type).ptr_type },
|
||||
},
|
||||
.array_type => |array_type| {
|
||||
const array_child_type: Type = .fromInterned(array_type.child);
|
||||
|
||||
+6
-2
@@ -467,8 +467,8 @@ pub fn deinit(self: *Elf) void {
|
||||
self.dump_argv_list.deinit(gpa);
|
||||
}
|
||||
|
||||
pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
|
||||
return self.zigObjectPtr().?.getNavVAddr(self, pt, nav_index, reloc_info);
|
||||
pub fn getNavVAddr(self: *Elf, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
|
||||
return self.zigObjectPtr().?.getNavVAddr(self, nav_index, reloc_info);
|
||||
}
|
||||
|
||||
pub fn lowerUav(
|
||||
@@ -485,6 +485,10 @@ pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.Relo
|
||||
return self.zigObjectPtr().?.getUavVAddr(self, uav, reloc_info);
|
||||
}
|
||||
|
||||
pub fn getLazySymbolVAddr(self: *Elf, pt: Zcu.PerThread, lazy_sym: link.File.LazySymbol, reloc_info: link.File.RelocInfo) !u64 {
|
||||
return self.zigObjectPtr().?.getLazySymbolVAddr(self, pt, lazy_sym, reloc_info);
|
||||
}
|
||||
|
||||
/// Returns end pos of collision, if any.
|
||||
fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {
|
||||
const comp = self.base.comp;
|
||||
|
||||
+87
-53
@@ -31,16 +31,17 @@ dwarf: ?Dwarf = null,
|
||||
|
||||
/// Table of tracked LazySymbols.
|
||||
lazy_syms: LazySymbolTable = .{},
|
||||
/// Table of tracked LazySymbols that are deferred until flush.
|
||||
deferred_lazy_syms: LazySymbolTable = .{},
|
||||
|
||||
/// Table of tracked `Nav`s.
|
||||
navs: NavTable = .{},
|
||||
/// Table of tracked `Uav`s.
|
||||
uavs: UavTable = .{},
|
||||
|
||||
/// TLS variables indexed by Atom.Index.
|
||||
tls_variables: TlsTable = .{},
|
||||
|
||||
/// Table of tracked `Uav`s.
|
||||
uavs: UavTable = .{},
|
||||
|
||||
debug_info_section_dirty: bool = false,
|
||||
debug_abbrev_section_dirty: bool = false,
|
||||
debug_aranges_section_dirty: bool = false,
|
||||
@@ -246,13 +247,14 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
|
||||
}
|
||||
self.relocs.deinit(allocator);
|
||||
|
||||
self.lazy_syms.deinit(allocator);
|
||||
self.deferred_lazy_syms.deinit(allocator);
|
||||
|
||||
for (self.navs.values()) |*meta| {
|
||||
meta.exports.deinit(allocator);
|
||||
}
|
||||
self.navs.deinit(allocator);
|
||||
|
||||
self.lazy_syms.deinit(allocator);
|
||||
|
||||
for (self.uavs.values()) |*meta| {
|
||||
meta.exports.deinit(allocator);
|
||||
}
|
||||
@@ -266,30 +268,22 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
|
||||
|
||||
pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
|
||||
// Handle any lazy symbols that were emitted by incremental compilation.
|
||||
if (self.lazy_syms.getPtr(.anyerror_type)) |metadata| {
|
||||
{
|
||||
const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);
|
||||
defer pt.deactivate();
|
||||
|
||||
// Most lazy symbols can be updated on first use, but
|
||||
// anyerror needs to wait for everything to be flushed.
|
||||
if (metadata.text_state != .unused) self.updateLazySymbol(
|
||||
elf_file,
|
||||
pt,
|
||||
.{ .kind = .code, .ty = .anyerror_type },
|
||||
metadata.text_symbol_index,
|
||||
) catch |err| switch (err) {
|
||||
error.CodegenFail => return error.LinkFailure,
|
||||
else => |e| return e,
|
||||
};
|
||||
if (metadata.rodata_state != .unused) self.updateLazySymbol(
|
||||
elf_file,
|
||||
pt,
|
||||
.{ .kind = .const_data, .ty = .anyerror_type },
|
||||
metadata.rodata_symbol_index,
|
||||
) catch |err| switch (err) {
|
||||
error.CodegenFail => return error.LinkFailure,
|
||||
else => |e| return e,
|
||||
};
|
||||
for (self.deferred_lazy_syms.values(), self.deferred_lazy_syms.keys()) |*metadata, key| {
|
||||
assert(metadata.text_state == .unused);
|
||||
if (metadata.rodata_state != .unused) self.updateLazySymbol(
|
||||
elf_file,
|
||||
pt,
|
||||
.{ .kind = .deferred_const_data, .key = key },
|
||||
metadata.rodata_symbol_index,
|
||||
) catch |err| switch (err) {
|
||||
error.CodegenFail => return error.LinkFailure,
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
}
|
||||
for (self.lazy_syms.values()) |*metadata| {
|
||||
if (metadata.text_state != .unused) metadata.text_state = .flushed;
|
||||
@@ -923,11 +917,10 @@ pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8
|
||||
pub fn getNavVAddr(
|
||||
self: *ZigObject,
|
||||
elf_file: *Elf,
|
||||
pt: Zcu.PerThread,
|
||||
nav_index: InternPool.Nav.Index,
|
||||
reloc_info: link.File.RelocInfo,
|
||||
) !u64 {
|
||||
const zcu = pt.zcu;
|
||||
const zcu = elf_file.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(nav_index);
|
||||
log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
|
||||
@@ -993,6 +986,44 @@ pub fn getUavVAddr(
|
||||
return @intCast(vaddr);
|
||||
}
|
||||
|
||||
pub fn getLazySymbolVAddr(
|
||||
self: *ZigObject,
|
||||
elf_file: *Elf,
|
||||
pt: Zcu.PerThread,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
reloc_info: link.File.RelocInfo,
|
||||
) !u64 {
|
||||
log.debug("getLazySymbolVAddr {t} {f}({d})", .{
|
||||
lazy_sym.kind,
|
||||
Value.fromInterned(lazy_sym.key).fmtValue(pt),
|
||||
lazy_sym.key,
|
||||
});
|
||||
const this_sym_index = try self.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym);
|
||||
const this_sym = self.symbol(this_sym_index);
|
||||
const vaddr = this_sym.address(.{}, elf_file);
|
||||
switch (reloc_info.parent) {
|
||||
.none => unreachable,
|
||||
.atom_index => |atom_index| {
|
||||
const parent_atom = self.symbol(atom_index).atom(elf_file).?;
|
||||
const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);
|
||||
try parent_atom.addReloc(elf_file.base.comp.gpa, .{
|
||||
.r_offset = reloc_info.offset,
|
||||
.r_info = (@as(u64, @intCast(this_sym_index)) << 32) | r_type,
|
||||
.r_addend = reloc_info.addend,
|
||||
}, self);
|
||||
},
|
||||
.debug_output => |debug_output| switch (debug_output) {
|
||||
.dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{
|
||||
.source_off = @intCast(reloc_info.offset),
|
||||
.target_sym = this_sym_index,
|
||||
.target_off = reloc_info.addend,
|
||||
}),
|
||||
.none => unreachable,
|
||||
},
|
||||
}
|
||||
return @bitCast(vaddr);
|
||||
}
|
||||
|
||||
pub fn lowerUav(
|
||||
self: *ZigObject,
|
||||
elf_file: *Elf,
|
||||
@@ -1063,12 +1094,16 @@ pub fn getOrCreateMetadataForLazySymbol(
|
||||
pt: Zcu.PerThread,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
) !Symbol.Index {
|
||||
const gop = try self.lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.ty);
|
||||
errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
|
||||
const lazy_syms = switch (lazy_sym.kind) {
|
||||
.code, .const_data => &self.lazy_syms,
|
||||
.deferred_const_data => &self.deferred_lazy_syms,
|
||||
};
|
||||
const gop = try lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.key);
|
||||
errdefer _ = if (!gop.found_existing) lazy_syms.pop();
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
const symbol_index_ptr, const state_ptr = switch (lazy_sym.kind) {
|
||||
.code => .{ &gop.value_ptr.text_symbol_index, &gop.value_ptr.text_state },
|
||||
.const_data => .{ &gop.value_ptr.rodata_symbol_index, &gop.value_ptr.rodata_state },
|
||||
.const_data, .deferred_const_data => .{ &gop.value_ptr.rodata_symbol_index, &gop.value_ptr.rodata_state },
|
||||
};
|
||||
switch (state_ptr.*) {
|
||||
.unused => symbol_index_ptr.* = try self.newSymbolWithAtom(pt.zcu.gpa, 0),
|
||||
@@ -1077,8 +1112,10 @@ pub fn getOrCreateMetadataForLazySymbol(
|
||||
}
|
||||
state_ptr.* = .pending_flush;
|
||||
const symbol_index = symbol_index_ptr.*;
|
||||
// anyerror needs to be deferred until flush
|
||||
if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(elf_file, pt, lazy_sym, symbol_index);
|
||||
switch (lazy_sym.kind) {
|
||||
.code, .const_data => try self.updateLazySymbol(elf_file, pt, lazy_sym, symbol_index),
|
||||
.deferred_const_data => {},
|
||||
}
|
||||
return symbol_index;
|
||||
}
|
||||
|
||||
@@ -1726,20 +1763,18 @@ fn updateLazySymbol(
|
||||
self: *ZigObject,
|
||||
elf_file: *Elf,
|
||||
pt: Zcu.PerThread,
|
||||
sym: link.File.LazySymbol,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
symbol_index: Symbol.Index,
|
||||
) !void {
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
var required_alignment: InternPool.Alignment = .none;
|
||||
var aw: std.Io.Writer.Allocating = .init(gpa);
|
||||
defer aw.deinit();
|
||||
|
||||
const name_str_index = blk: {
|
||||
const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
|
||||
@tagName(sym.kind),
|
||||
Type.fromInterned(sym.ty).fmt(pt),
|
||||
const name = try std.fmt.allocPrint(gpa, "__lazy_{t}_{f}", .{
|
||||
lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt),
|
||||
});
|
||||
defer gpa.free(name);
|
||||
break :blk try self.strtab.insert(gpa, name);
|
||||
@@ -1748,9 +1783,8 @@ fn updateLazySymbol(
|
||||
codegen.generateLazySymbol(
|
||||
&elf_file.base,
|
||||
pt,
|
||||
Type.fromInterned(sym.ty).srcLocOrNull(zcu) orelse .unneeded,
|
||||
sym,
|
||||
&required_alignment,
|
||||
Type.fromInterned(lazy_sym.key).srcLocOrNull(zcu) orelse .unneeded,
|
||||
lazy_sym,
|
||||
&aw.writer,
|
||||
.none,
|
||||
.{ .atom_index = symbol_index },
|
||||
@@ -1760,7 +1794,7 @@ fn updateLazySymbol(
|
||||
};
|
||||
const code = aw.written();
|
||||
|
||||
const output_section_index = switch (sym.kind) {
|
||||
const output_section_index = switch (lazy_sym.kind) {
|
||||
.code => if (self.text_index) |sym_index|
|
||||
self.symbol(sym_index).outputShndx(elf_file).?
|
||||
else osec: {
|
||||
@@ -1773,7 +1807,7 @@ fn updateLazySymbol(
|
||||
self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec);
|
||||
break :osec osec;
|
||||
},
|
||||
.const_data => if (self.rodata_index) |sym_index|
|
||||
.const_data, .deferred_const_data => if (self.rodata_index) |sym_index|
|
||||
self.symbol(sym_index).outputShndx(elf_file).?
|
||||
else osec: {
|
||||
const osec = try elf_file.addSection(.{
|
||||
@@ -1786,24 +1820,24 @@ fn updateLazySymbol(
|
||||
break :osec osec;
|
||||
},
|
||||
};
|
||||
const local_sym = self.symbol(symbol_index);
|
||||
local_sym.name_offset = name_str_index;
|
||||
const local_esym = &self.symtab.items(.elf_sym)[local_sym.esym_index];
|
||||
local_esym.st_name = name_str_index;
|
||||
local_esym.st_info |= elf.STT_OBJECT;
|
||||
local_esym.st_size = code.len;
|
||||
const atom_ptr = local_sym.atom(elf_file).?;
|
||||
const sym = self.symbol(symbol_index);
|
||||
sym.name_offset = name_str_index;
|
||||
const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
|
||||
esym.st_name = name_str_index;
|
||||
esym.st_info |= elf.STT_OBJECT;
|
||||
esym.st_size = code.len;
|
||||
const atom_ptr = sym.atom(elf_file).?;
|
||||
atom_ptr.alive = true;
|
||||
atom_ptr.name_offset = name_str_index;
|
||||
atom_ptr.alignment = required_alignment;
|
||||
atom_ptr.alignment = codegen.getLazySymbolInfo(.attributes, lazy_sym, zcu).required_alignment;
|
||||
atom_ptr.size = code.len;
|
||||
atom_ptr.output_section_index = output_section_index;
|
||||
|
||||
try self.allocateAtom(atom_ptr, true, elf_file);
|
||||
errdefer self.freeNavMetadata(elf_file, symbol_index);
|
||||
|
||||
local_sym.value = 0;
|
||||
local_esym.st_value = 0;
|
||||
sym.value = 0;
|
||||
esym.st_value = 0;
|
||||
|
||||
try elf_file.pwriteAll(code, atom_ptr.offset(elf_file));
|
||||
}
|
||||
|
||||
+92
-46
@@ -75,6 +75,7 @@ pub const Node = union(enum) {
|
||||
uav: UavMapIndex,
|
||||
lazy_code: LazyMapRef.Index(.code),
|
||||
lazy_const_data: LazyMapRef.Index(.const_data),
|
||||
lazy_deferred_const_data: LazyMapRef.Index(.deferred_const_data),
|
||||
|
||||
pub const InputIndex = enum(u32) {
|
||||
_,
|
||||
@@ -163,7 +164,7 @@ pub const Node = union(enum) {
|
||||
}
|
||||
|
||||
pub fn lazySymbol(lmr: LazyMapRef, elf: *const Elf) link.File.LazySymbol {
|
||||
return .{ .kind = lmr.kind, .ty = elf.lazy.getPtrConst(lmr.kind).map.keys()[lmr.index] };
|
||||
return .{ .kind = lmr.kind, .key = elf.lazy.getPtrConst(lmr.kind).map.keys()[lmr.index] };
|
||||
}
|
||||
|
||||
pub fn symbol(lmr: LazyMapRef, elf: *const Elf) Symbol.Index {
|
||||
@@ -1680,7 +1681,12 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
|
||||
},
|
||||
.section => |si| si,
|
||||
.input_section => unreachable,
|
||||
inline .nav, .uav, .lazy_code, .lazy_const_data => |mi| mi.symbol(elf),
|
||||
inline .nav,
|
||||
.uav,
|
||||
.lazy_code,
|
||||
.lazy_const_data,
|
||||
.lazy_deferred_const_data,
|
||||
=> |mi| mi.symbol(elf),
|
||||
};
|
||||
break :parent_vaddr if (parent_si == elf.si.tdata) 0 else switch (elf.symPtr(parent_si)) {
|
||||
inline else => |sym| elf.targetLoad(&sym.value),
|
||||
@@ -1927,7 +1933,8 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavM
|
||||
});
|
||||
return @enumFromInt(nav_gop.index);
|
||||
}
|
||||
pub fn navSymbol(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {
|
||||
pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) !Symbol.Index {
|
||||
const zcu = elf.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(nav_index);
|
||||
if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{
|
||||
@@ -1963,20 +1970,35 @@ pub fn uavSymbol(elf: *Elf, uav_val: InternPool.Index) !Symbol.Index {
|
||||
return umi.symbol(elf);
|
||||
}
|
||||
|
||||
pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !Symbol.Index {
|
||||
const gpa = elf.base.comp.gpa;
|
||||
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
||||
const lazy_gop = try elf.lazy.getPtr(lazy.kind).map.getOrPut(gpa, lazy.ty);
|
||||
if (!lazy_gop.found_existing) {
|
||||
lazy_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{
|
||||
.type = switch (lazy.kind) {
|
||||
.code => .FUNC,
|
||||
.const_data => .OBJECT,
|
||||
},
|
||||
});
|
||||
elf.synth_prog_node.increaseEstimatedTotalItems(1);
|
||||
}
|
||||
return lazy_gop.value_ptr.*;
|
||||
fn lazySymbolIfExists(elf: *Elf, lazy_sym: link.File.LazySymbol) ?Symbol.Index {
|
||||
return elf.lazy.getPtr(lazy_sym.kind).map.get(lazy_sym.key);
|
||||
}
|
||||
fn lazySymbolAssumeCapacity(elf: *Elf, lazy_sym: link.File.LazySymbol) !struct { Symbol.Index, usize } {
|
||||
const gop = try elf.lazy.getPtr(lazy_sym.kind).map.getOrPut(elf.base.comp.gpa, lazy_sym.key);
|
||||
if (gop.found_existing) return .{ gop.value_ptr.*, gop.index };
|
||||
const si = try elf.initSymbolAssumeCapacity(.{
|
||||
.type = switch (lazy_sym.kind) {
|
||||
.code => .FUNC,
|
||||
.const_data, .deferred_const_data => .OBJECT,
|
||||
},
|
||||
});
|
||||
gop.value_ptr.* = si;
|
||||
elf.synth_prog_node.increaseEstimatedTotalItems(1);
|
||||
return .{ si, gop.index };
|
||||
}
|
||||
pub fn lazySymbol(elf: *Elf, lazy_sym: link.File.LazySymbol) !Symbol.Index {
|
||||
// optimize for future lookups, at the cost of an extra initial key lookup
|
||||
if (elf.lazySymbolIfExists(lazy_sym)) |si| return si;
|
||||
const comp = elf.base.comp;
|
||||
const structure = codegen.getLazySymbolInfo(.structure, lazy_sym, comp.zcu.?);
|
||||
try elf.symtab.ensureUnusedCapacity(
|
||||
comp.gpa,
|
||||
@as(usize, @intFromBool(structure.parent != null)) + @intFromBool(structure.modify != null) + 1,
|
||||
);
|
||||
if (structure.parent) |parent_lazy_sym| _ = try elf.lazySymbolAssumeCapacity(parent_lazy_sym);
|
||||
if (structure.modify) |modification| _ = try elf.lazySymbolAssumeCapacity(modification.lazy_sym);
|
||||
const si, _ = try elf.lazySymbolAssumeCapacity(lazy_sym);
|
||||
return si;
|
||||
}
|
||||
|
||||
pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError ||
|
||||
@@ -2531,11 +2553,10 @@ fn prelinkInner(elf: *Elf) !void {
|
||||
|
||||
pub fn getNavVAddr(
|
||||
elf: *Elf,
|
||||
pt: Zcu.PerThread,
|
||||
nav: InternPool.Nav.Index,
|
||||
reloc_info: link.File.RelocInfo,
|
||||
) !u64 {
|
||||
return elf.getVAddr(reloc_info, try elf.navSymbol(pt.zcu, nav));
|
||||
return elf.getVAddr(reloc_info, try elf.navSymbol(nav));
|
||||
}
|
||||
|
||||
pub fn getUavVAddr(
|
||||
@@ -2546,6 +2567,15 @@ pub fn getUavVAddr(
|
||||
return elf.getVAddr(reloc_info, try elf.uavSymbol(uav));
|
||||
}
|
||||
|
||||
pub fn getLazySymbolVAddr(
|
||||
elf: *Elf,
|
||||
_: Zcu.PerThread,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
reloc_info: link.File.RelocInfo,
|
||||
) !u64 {
|
||||
return elf.getVAddr(reloc_info, try elf.lazySymbol(lazy_sym));
|
||||
}
|
||||
|
||||
pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target_si: Symbol.Index) !u64 {
|
||||
try elf.addReloc(
|
||||
@enumFromInt(reloc_info.parent.atom_index),
|
||||
@@ -3106,13 +3136,13 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {
|
||||
lazy.value.pending_index += 1;
|
||||
const kind = switch (lmr.kind) {
|
||||
.code => "code",
|
||||
.const_data => "data",
|
||||
.const_data, .deferred_const_data => "data",
|
||||
};
|
||||
var name: [std.Progress.Node.max_name_len]u8 = undefined;
|
||||
const sub_prog_node = elf.synth_prog_node.start(
|
||||
std.fmt.bufPrint(&name, "lazy {s} for {f}", .{
|
||||
kind,
|
||||
Type.fromInterned(lmr.lazySymbol(elf).ty).fmt(pt),
|
||||
Value.fromInterned(lmr.lazySymbol(elf).key).fmtValue(pt),
|
||||
}) catch &name,
|
||||
0,
|
||||
);
|
||||
@@ -3259,26 +3289,38 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
const lazy = lmr.lazySymbol(elf);
|
||||
const lazy_sym = lmr.lazySymbol(elf);
|
||||
const si = lmr.symbol(elf);
|
||||
const structure = codegen.getLazySymbolInfo(.structure, lazy_sym, zcu);
|
||||
const ni = ni: {
|
||||
const sym = si.get(elf);
|
||||
switch (sym.ni) {
|
||||
.none => {
|
||||
try elf.nodes.ensureUnusedCapacity(gpa, 1);
|
||||
const sec_si: Symbol.Index = switch (lazy.kind) {
|
||||
const attrs = codegen.getLazySymbolInfo(.attributes, lazy_sym, zcu);
|
||||
const parent_si: Symbol.Index = if (structure.parent) |parent_lazy_sym|
|
||||
elf.lazySymbolIfExists(parent_lazy_sym).?
|
||||
else switch (lazy_sym.kind) {
|
||||
.code => .text,
|
||||
.const_data => .rodata,
|
||||
.const_data, .deferred_const_data => .rodata,
|
||||
};
|
||||
const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{ .moved = true });
|
||||
elf.nodes.appendAssumeCapacity(switch (lazy.kind) {
|
||||
const addChildNode =
|
||||
if (attrs.header) &MappedFile.addOnlyChildNode else &MappedFile.addLastChildNode;
|
||||
const ni = try addChildNode(&elf.mf, elf.base.comp.gpa, parent_si.node(elf), .{
|
||||
.size = attrs.size orelse 0,
|
||||
.alignment = attrs.required_alignment.toStdMem(),
|
||||
.fixed = attrs.header,
|
||||
.moved = true,
|
||||
});
|
||||
elf.nodes.appendAssumeCapacity(switch (lazy_sym.kind) {
|
||||
.code => .{ .lazy_code = @enumFromInt(lmr.index) },
|
||||
.const_data => .{ .lazy_const_data = @enumFromInt(lmr.index) },
|
||||
.deferred_const_data => .{ .lazy_deferred_const_data = @enumFromInt(lmr.index) },
|
||||
});
|
||||
sym.ni = ni;
|
||||
switch (elf.symPtr(si)) {
|
||||
inline else => |sym_ptr, class| sym_ptr.shndx =
|
||||
@field(elf.symPtr(sec_si), @tagName(class)).shndx,
|
||||
@field(elf.symPtr(parent_si), @tagName(class)).shndx,
|
||||
}
|
||||
},
|
||||
else => si.deleteLocationRelocs(elf),
|
||||
@@ -3288,16 +3330,14 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
|
||||
break :ni sym.ni;
|
||||
};
|
||||
|
||||
var required_alignment: InternPool.Alignment = .none;
|
||||
var nw: MappedFile.Node.Writer = undefined;
|
||||
ni.writer(&elf.mf, gpa, &nw);
|
||||
defer nw.deinit();
|
||||
try codegen.generateLazySymbol(
|
||||
&elf.base,
|
||||
pt,
|
||||
Type.fromInterned(lazy.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
|
||||
lazy,
|
||||
&required_alignment,
|
||||
Type.fromInterned(lazy_sym.key).srcLocOrNull(pt.zcu) orelse .unneeded,
|
||||
lazy_sym,
|
||||
&nw.interface,
|
||||
.none,
|
||||
.{ .atom_index = @intFromEnum(si) },
|
||||
@@ -3306,6 +3346,11 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
|
||||
inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
|
||||
}
|
||||
si.applyLocationRelocs(elf);
|
||||
|
||||
if (structure.modify) |modification| modification.operation.apply(
|
||||
elf.lazySymbolIfExists(modification.lazy_sym).?.node(elf).slice(&elf.mf),
|
||||
elf.targetEndian(),
|
||||
);
|
||||
}
|
||||
|
||||
fn flushInputSection(elf: *Elf, isi: Node.InputSectionIndex) !void {
|
||||
@@ -3501,10 +3546,12 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
||||
} - old_addr + new_addr);
|
||||
}
|
||||
},
|
||||
inline .nav, .uav, .lazy_code, .lazy_const_data => |mi| mi.symbol(elf).flushMoved(
|
||||
elf,
|
||||
elf.computeNodeVAddr(ni),
|
||||
),
|
||||
inline .nav,
|
||||
.uav,
|
||||
.lazy_code,
|
||||
.lazy_const_data,
|
||||
.lazy_deferred_const_data,
|
||||
=> |mi| mi.symbol(elf).flushMoved(elf, elf.computeNodeVAddr(ni)),
|
||||
}
|
||||
try ni.childrenMoved(elf.base.comp.gpa, &elf.mf);
|
||||
}
|
||||
@@ -3614,7 +3661,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
||||
elf.targetStore(&shdr.size, @intCast(size));
|
||||
},
|
||||
},
|
||||
.input_section, .nav, .uav, .lazy_code, .lazy_const_data => {},
|
||||
.input_section, .nav, .uav, .lazy_code, .lazy_const_data, .lazy_deferred_const_data => {},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3655,7 +3702,7 @@ fn updateExportsInner(
|
||||
try elf.symtab.ensureUnusedCapacity(gpa, export_indices.len);
|
||||
const exported_si: Symbol.Index, const @"type": std.elf.STT = switch (exported) {
|
||||
.nav => |nav| .{
|
||||
try elf.navSymbol(zcu, nav),
|
||||
try elf.navSymbol(nav),
|
||||
navType(ip, ip.getNav(nav).resolved.?, elf.base.comp.config.any_non_single_threaded),
|
||||
},
|
||||
.uav => |uav| .{ @enumFromInt(switch (try elf.lowerUav(
|
||||
@@ -3715,15 +3762,15 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm
|
||||
_ = name;
|
||||
}
|
||||
|
||||
pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void {
|
||||
pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) !void {
|
||||
const comp = elf.base.comp;
|
||||
const io = comp.io;
|
||||
var buffer: [512]u8 = undefined;
|
||||
const stderr = try io.lockStderr(&buffer, null);
|
||||
defer io.lockStderr();
|
||||
defer io.unlockStderr();
|
||||
const w = &stderr.file_writer.interface;
|
||||
elf.printNode(tid, w, .root, 0) catch |err| switch (err) {
|
||||
error.WriteFailed => return stderr.err.?,
|
||||
error.WriteFailed => return stderr.file_writer.err.?,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3773,7 +3820,7 @@ pub fn printNode(
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(nmi.navIndex(elf));
|
||||
try w.print("({f}, {f})", .{
|
||||
Type.fromInterned(nav.typeOf(ip)).fmt(.{ .zcu = zcu, .tid = tid }),
|
||||
Type.fromInterned(nav.resolved.?.type).fmt(.{ .zcu = zcu, .tid = tid }),
|
||||
nav.fqn.fmt(ip),
|
||||
});
|
||||
},
|
||||
@@ -3786,17 +3833,16 @@ pub fn printNode(
|
||||
});
|
||||
},
|
||||
inline .lazy_code, .lazy_const_data => |lmi| try w.print("({f})", .{
|
||||
Type.fromInterned(lmi.lazySymbol(elf).ty).fmt(.{
|
||||
.zcu = elf.base.comp.zcu.?,
|
||||
.tid = tid,
|
||||
}),
|
||||
Value.fromInterned(lmi.lazySymbol(elf).key).fmtValue(
|
||||
.{ .zcu = elf.base.comp.zcu.?, .tid = tid },
|
||||
),
|
||||
}),
|
||||
}
|
||||
{
|
||||
const mf_node = &elf.mf.nodes.items[@intFromEnum(ni)];
|
||||
const off, const size = mf_node.location().resolve(&elf.mf);
|
||||
try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x}{s}{s}{s}{s}\n", .{
|
||||
@intFromEnum(ni),
|
||||
ni,
|
||||
off,
|
||||
size,
|
||||
mf_node.flags.alignment.toByteUnits(),
|
||||
|
||||
+6
-2
@@ -3116,8 +3116,8 @@ pub fn freeNav(self: *MachO, nav: InternPool.Nav.Index) void {
|
||||
return self.getZigObject().?.freeNav(nav);
|
||||
}
|
||||
|
||||
pub fn getNavVAddr(self: *MachO, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
|
||||
return self.getZigObject().?.getNavVAddr(self, pt, nav_index, reloc_info);
|
||||
pub fn getNavVAddr(self: *MachO, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
|
||||
return self.getZigObject().?.getNavVAddr(self, nav_index, reloc_info);
|
||||
}
|
||||
|
||||
pub fn lowerUav(
|
||||
@@ -3134,6 +3134,10 @@ pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.Re
|
||||
return self.getZigObject().?.getUavVAddr(self, uav, reloc_info);
|
||||
}
|
||||
|
||||
pub fn getLazySymbolVAddr(self: *MachO, pt: Zcu.PerThread, lazy_sym: link.File.LazySymbol, reloc_info: link.File.RelocInfo) !u64 {
|
||||
return self.getZigObject().?.getLazySymbolVAddr(self, pt, lazy_sym, reloc_info);
|
||||
}
|
||||
|
||||
pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u32 {
|
||||
return self.getZigObject().?.getGlobalSymbol(self, name, lib_name);
|
||||
}
|
||||
|
||||
@@ -18,10 +18,11 @@ atoms_extra: std.ArrayList(u32) = .empty,
|
||||
|
||||
/// Table of tracked LazySymbols.
|
||||
lazy_syms: LazySymbolTable = .{},
|
||||
/// Table of tracked LazySymbols that are deferred until flush.
|
||||
deferred_lazy_syms: LazySymbolTable = .{},
|
||||
|
||||
/// Table of tracked Navs.
|
||||
navs: NavTable = .{},
|
||||
|
||||
/// Table of tracked Uavs.
|
||||
uavs: UavTable = .{},
|
||||
|
||||
@@ -78,13 +79,14 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
|
||||
self.atoms_indexes.deinit(allocator);
|
||||
self.atoms_extra.deinit(allocator);
|
||||
|
||||
self.lazy_syms.deinit(allocator);
|
||||
self.deferred_lazy_syms.deinit(allocator);
|
||||
|
||||
for (self.navs.values()) |*meta| {
|
||||
meta.exports.deinit(allocator);
|
||||
}
|
||||
self.navs.deinit(allocator);
|
||||
|
||||
self.lazy_syms.deinit(allocator);
|
||||
|
||||
for (self.uavs.values()) |*meta| {
|
||||
meta.exports.deinit(allocator);
|
||||
}
|
||||
@@ -559,30 +561,23 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.F
|
||||
const diags = &macho_file.base.comp.link_diags;
|
||||
|
||||
// Handle any lazy symbols that were emitted by incremental compilation.
|
||||
if (self.lazy_syms.getPtr(.anyerror_type)) |metadata| {
|
||||
{
|
||||
const pt: Zcu.PerThread = .activate(macho_file.base.comp.zcu.?, tid);
|
||||
defer pt.deactivate();
|
||||
|
||||
// Most lazy symbols can be updated on first use, but
|
||||
// anyerror needs to wait for everything to be flushed.
|
||||
if (metadata.text_state != .unused) self.updateLazySymbol(
|
||||
macho_file,
|
||||
pt,
|
||||
.{ .kind = .code, .ty = .anyerror_type },
|
||||
metadata.text_symbol_index,
|
||||
) catch |err| switch (err) {
|
||||
error.OutOfMemory, error.LinkFailure => |e| return e,
|
||||
else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
|
||||
};
|
||||
if (metadata.const_state != .unused) self.updateLazySymbol(
|
||||
macho_file,
|
||||
pt,
|
||||
.{ .kind = .const_data, .ty = .anyerror_type },
|
||||
metadata.const_symbol_index,
|
||||
) catch |err| switch (err) {
|
||||
error.OutOfMemory, error.LinkFailure => |e| return e,
|
||||
else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
|
||||
};
|
||||
for (self.deferred_lazy_syms.values(), self.deferred_lazy_syms.keys()) |*metadata, key| {
|
||||
assert(metadata.text_state == .unused);
|
||||
if (metadata.const_state != .unused) self.updateLazySymbol(
|
||||
macho_file,
|
||||
pt,
|
||||
.{ .kind = .deferred_const_data, .key = key },
|
||||
metadata.const_symbol_index,
|
||||
) catch |err| switch (err) {
|
||||
error.LinkFailure, error.CodegenFail => return error.LinkFailure,
|
||||
error.OutOfMemory => |e| return e,
|
||||
else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
|
||||
};
|
||||
}
|
||||
}
|
||||
for (self.lazy_syms.values()) |*metadata| {
|
||||
if (metadata.text_state != .unused) metadata.text_state = .flushed;
|
||||
@@ -614,11 +609,10 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.F
|
||||
pub fn getNavVAddr(
|
||||
self: *ZigObject,
|
||||
macho_file: *MachO,
|
||||
pt: Zcu.PerThread,
|
||||
nav_index: InternPool.Nav.Index,
|
||||
reloc_info: link.File.RelocInfo,
|
||||
) !u64 {
|
||||
const zcu = pt.zcu;
|
||||
const zcu = macho_file.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(nav_index);
|
||||
log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
|
||||
@@ -698,6 +692,51 @@ pub fn getUavVAddr(
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
pub fn getLazySymbolVAddr(
|
||||
self: *ZigObject,
|
||||
macho_file: *MachO,
|
||||
pt: Zcu.PerThread,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
reloc_info: link.File.RelocInfo,
|
||||
) !u64 {
|
||||
log.debug("getLazySymbolVAddr {t} {f}({d})", .{
|
||||
lazy_sym.kind,
|
||||
Value.fromInterned(lazy_sym.key).fmtValue(pt),
|
||||
lazy_sym.key,
|
||||
});
|
||||
const sym_index = try self.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym);
|
||||
const sym = self.symbols.items[sym_index];
|
||||
const vaddr = sym.getAddress(.{}, macho_file);
|
||||
switch (reloc_info.parent) {
|
||||
.none => unreachable,
|
||||
.atom_index => |atom_index| {
|
||||
const parent_atom = self.symbols.items[atom_index].getAtom(macho_file).?;
|
||||
try parent_atom.addReloc(macho_file, .{
|
||||
.tag = .@"extern",
|
||||
.offset = @intCast(reloc_info.offset),
|
||||
.target = sym_index,
|
||||
.addend = reloc_info.addend,
|
||||
.type = .unsigned,
|
||||
.meta = .{
|
||||
.pcrel = false,
|
||||
.has_subtractor = false,
|
||||
.length = 3,
|
||||
.symbolnum = @intCast(sym.nlist_idx),
|
||||
},
|
||||
});
|
||||
},
|
||||
.debug_output => |debug_output| switch (debug_output) {
|
||||
.dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{
|
||||
.source_off = @intCast(reloc_info.offset),
|
||||
.target_sym = sym_index,
|
||||
.target_off = reloc_info.addend,
|
||||
}),
|
||||
.none => unreachable,
|
||||
},
|
||||
}
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
pub fn lowerUav(
|
||||
self: *ZigObject,
|
||||
macho_file: *MachO,
|
||||
@@ -1355,35 +1394,34 @@ fn updateLazySymbol(
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
var required_alignment: Atom.Alignment = .none;
|
||||
var aw: std.Io.Writer.Allocating = .init(gpa);
|
||||
defer aw.deinit();
|
||||
|
||||
const name_str = blk: {
|
||||
const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
|
||||
@tagName(lazy_sym.kind),
|
||||
Type.fromInterned(lazy_sym.ty).fmt(pt),
|
||||
const name = try std.fmt.allocPrint(gpa, "__lazy_{t}_{f}", .{
|
||||
lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt),
|
||||
});
|
||||
defer gpa.free(name);
|
||||
break :blk try self.addString(gpa, name);
|
||||
};
|
||||
|
||||
const src = Type.fromInterned(lazy_sym.ty).srcLocOrNull(zcu) orelse Zcu.LazySrcLoc.unneeded;
|
||||
try codegen.generateLazySymbol(
|
||||
codegen.generateLazySymbol(
|
||||
&macho_file.base,
|
||||
pt,
|
||||
src,
|
||||
Type.fromInterned(lazy_sym.key).srcLocOrNull(zcu) orelse Zcu.LazySrcLoc.unneeded,
|
||||
lazy_sym,
|
||||
&required_alignment,
|
||||
&aw.writer,
|
||||
.none,
|
||||
.{ .atom_index = symbol_index },
|
||||
);
|
||||
) catch |err| switch (err) {
|
||||
error.WriteFailed => return error.OutOfMemory,
|
||||
else => |e| return e,
|
||||
};
|
||||
const code = aw.written();
|
||||
|
||||
const output_section_index = switch (lazy_sym.kind) {
|
||||
.code => macho_file.zig_text_sect_index.?,
|
||||
.const_data => macho_file.zig_const_sect_index.?,
|
||||
.const_data, .deferred_const_data => macho_file.zig_const_sect_index.?,
|
||||
};
|
||||
const sym = &self.symbols.items[symbol_index];
|
||||
sym.name = name_str;
|
||||
@@ -1398,7 +1436,7 @@ fn updateLazySymbol(
|
||||
const atom = sym.getAtom(macho_file).?;
|
||||
atom.setAlive(true);
|
||||
atom.name = name_str;
|
||||
atom.alignment = required_alignment;
|
||||
atom.alignment = codegen.getLazySymbolInfo(.attributes, lazy_sym, zcu).required_alignment;
|
||||
atom.size = code.len;
|
||||
atom.out_n_sect = output_section_index;
|
||||
|
||||
@@ -1516,12 +1554,16 @@ pub fn getOrCreateMetadataForLazySymbol(
|
||||
pt: Zcu.PerThread,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
) !Symbol.Index {
|
||||
const gop = try self.lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.ty);
|
||||
errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
|
||||
const lazy_syms = switch (lazy_sym.kind) {
|
||||
.code, .const_data => &self.lazy_syms,
|
||||
.deferred_const_data => &self.deferred_lazy_syms,
|
||||
};
|
||||
const gop = try lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.key);
|
||||
errdefer _ = if (!gop.found_existing) lazy_syms.pop();
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
const symbol_index_ptr, const state_ptr = switch (lazy_sym.kind) {
|
||||
.code => .{ &gop.value_ptr.text_symbol_index, &gop.value_ptr.text_state },
|
||||
.const_data => .{ &gop.value_ptr.const_symbol_index, &gop.value_ptr.const_state },
|
||||
.const_data, .deferred_const_data => .{ &gop.value_ptr.const_symbol_index, &gop.value_ptr.const_state },
|
||||
};
|
||||
switch (state_ptr.*) {
|
||||
.unused => symbol_index_ptr.* = try self.newSymbolWithAtom(pt.zcu.gpa, .{}, macho_file),
|
||||
@@ -1530,8 +1572,10 @@ pub fn getOrCreateMetadataForLazySymbol(
|
||||
}
|
||||
state_ptr.* = .pending_flush;
|
||||
const symbol_index = symbol_index_ptr.*;
|
||||
// anyerror needs to be deferred until flush
|
||||
if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(macho_file, pt, lazy_sym, symbol_index);
|
||||
switch (lazy_sym.kind) {
|
||||
.code, .const_data => try self.updateLazySymbol(macho_file, pt, lazy_sym, symbol_index),
|
||||
.deferred_const_data => {},
|
||||
}
|
||||
return symbol_index;
|
||||
}
|
||||
|
||||
|
||||
@@ -948,5 +948,9 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
|
||||
// being run in a separate thread from now on.
|
||||
else => true,
|
||||
},
|
||||
.restricted_types => switch (backend) {
|
||||
.stage2_c, .stage2_x86_64 => true,
|
||||
else => false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user