rework error handling in the backends
This commit is contained in:
169
src/codegen.zig
169
src/codegen.zig
@@ -24,13 +24,6 @@ const Zir = std.zig.Zir;
|
||||
const Alignment = InternPool.Alignment;
|
||||
const dev = @import("dev.zig");
|
||||
|
||||
pub const Result = union(enum) {
|
||||
/// The `code` parameter passed to `generateSymbol` has the value.
|
||||
ok,
|
||||
/// There was a codegen error.
|
||||
fail: *ErrorMsg,
|
||||
};
|
||||
|
||||
pub const CodeGenError = error{
|
||||
OutOfMemory,
|
||||
/// Compiler was asked to operate on a number larger than supported.
|
||||
@@ -64,7 +57,7 @@ pub fn generateFunction(
|
||||
liveness: Liveness,
|
||||
code: *std.ArrayList(u8),
|
||||
debug_output: link.File.DebugInfoOutput,
|
||||
) CodeGenError!Result {
|
||||
) CodeGenError!void {
|
||||
const zcu = pt.zcu;
|
||||
const func = zcu.funcInfo(func_index);
|
||||
const target = zcu.navFileScope(func.owner_nav).mod.resolved_target.result;
|
||||
@@ -89,7 +82,7 @@ pub fn generateLazyFunction(
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
code: *std.ArrayList(u8),
|
||||
debug_output: link.File.DebugInfoOutput,
|
||||
) CodeGenError!Result {
|
||||
) CodeGenError!void {
|
||||
const zcu = pt.zcu;
|
||||
const file = Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(&zcu.intern_pool);
|
||||
const target = zcu.fileByIndex(file).mod.resolved_target.result;
|
||||
@@ -120,17 +113,17 @@ pub fn generateLazySymbol(
|
||||
code: *std.ArrayList(u8),
|
||||
debug_output: link.File.DebugInfoOutput,
|
||||
reloc_parent: link.File.RelocInfo.Parent,
|
||||
) CodeGenError!Result {
|
||||
) CodeGenError!void {
|
||||
_ = reloc_parent;
|
||||
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const comp = bin_file.comp;
|
||||
const ip = &pt.zcu.intern_pool;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const endian = target.cpu.arch.endian();
|
||||
const gpa = comp.gpa;
|
||||
|
||||
log.debug("generateLazySymbol: kind = {s}, ty = {}", .{
|
||||
@tagName(lazy_sym.kind),
|
||||
@@ -161,26 +154,29 @@ pub fn generateLazySymbol(
|
||||
string_index += @intCast(err_name.len + 1);
|
||||
}
|
||||
mem.writeInt(u32, code.items[offset_index..][0..4], string_index, endian);
|
||||
return .ok;
|
||||
} else if (Type.fromInterned(lazy_sym.ty).zigTypeTag(pt.zcu) == .@"enum") {
|
||||
} 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(pt.zcu);
|
||||
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 code.ensureUnusedCapacity(tag_name.len + 1);
|
||||
code.appendSliceAssumeCapacity(tag_name);
|
||||
code.appendAssumeCapacity(0);
|
||||
}
|
||||
return .ok;
|
||||
} else return .{ .fail = try .create(
|
||||
gpa,
|
||||
src_loc,
|
||||
"TODO implement generateLazySymbol for {s} {}",
|
||||
.{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },
|
||||
) };
|
||||
} else {
|
||||
return zcu.codegenFailType(lazy_sym.ty, "TODO implement generateLazySymbol for {s} {}", .{
|
||||
@tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub const GenerateSymbolError = error{
|
||||
OutOfMemory,
|
||||
/// Compiler was asked to operate on a number larger than supported.
|
||||
Overflow,
|
||||
};
|
||||
|
||||
pub fn generateSymbol(
|
||||
bin_file: *link.File,
|
||||
pt: Zcu.PerThread,
|
||||
@@ -188,7 +184,7 @@ pub fn generateSymbol(
|
||||
val: Value,
|
||||
code: *std.ArrayList(u8),
|
||||
reloc_parent: link.File.RelocInfo.Parent,
|
||||
) CodeGenError!Result {
|
||||
) GenerateSymbolError!void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@@ -204,7 +200,7 @@ pub fn generateSymbol(
|
||||
if (val.isUndefDeep(zcu)) {
|
||||
const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
|
||||
try code.appendNTimes(0xaa, abi_size);
|
||||
return .ok;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ip.indexToKey(val.toIntern())) {
|
||||
@@ -266,7 +262,7 @@ pub fn generateSymbol(
|
||||
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
|
||||
try code.writer().writeInt(u16, err_val, endian);
|
||||
return .ok;
|
||||
return;
|
||||
}
|
||||
|
||||
const payload_align = payload_ty.abiAlignment(zcu);
|
||||
@@ -281,13 +277,10 @@ pub fn generateSymbol(
|
||||
// emit payload part of the error union
|
||||
{
|
||||
const begin = code.items.len;
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (error_union.val) {
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (error_union.val) {
|
||||
.err_name => try pt.intern(.{ .undef = payload_ty.toIntern() }),
|
||||
.payload => |payload| payload,
|
||||
}), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return .{ .fail = em },
|
||||
}
|
||||
}), code, reloc_parent);
|
||||
const unpadded_end = code.items.len - begin;
|
||||
const padded_end = abi_align.forward(unpadded_end);
|
||||
const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
|
||||
@@ -312,10 +305,7 @@ pub fn generateSymbol(
|
||||
},
|
||||
.enum_tag => |enum_tag| {
|
||||
const int_tag_ty = ty.intTagType(zcu);
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, try pt.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return .{ .fail = em },
|
||||
}
|
||||
try generateSymbol(bin_file, pt, src_loc, try pt.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), code, reloc_parent);
|
||||
},
|
||||
.float => |float| switch (float.storage) {
|
||||
.f16 => |f16_val| writeFloat(f16, f16_val, target, endian, try code.addManyAsArray(2)),
|
||||
@@ -328,19 +318,10 @@ pub fn generateSymbol(
|
||||
},
|
||||
.f128 => |f128_val| writeFloat(f128, f128_val, target, endian, try code.addManyAsArray(16)),
|
||||
},
|
||||
.ptr => switch (try lowerPtr(bin_file, pt, src_loc, val.toIntern(), code, reloc_parent, 0)) {
|
||||
.ok => {},
|
||||
.fail => |em| return .{ .fail = em },
|
||||
},
|
||||
.ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), code, reloc_parent, 0),
|
||||
.slice => |slice| {
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.ptr), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return .{ .fail = em },
|
||||
}
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.len), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return .{ .fail = em },
|
||||
}
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.ptr), code, reloc_parent);
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.len), code, reloc_parent);
|
||||
},
|
||||
.opt => {
|
||||
const payload_type = ty.optionalChild(zcu);
|
||||
@@ -349,10 +330,7 @@ pub fn generateSymbol(
|
||||
|
||||
if (ty.optionalReprIsPayload(zcu)) {
|
||||
if (payload_val) |value| {
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, value, code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return Result{ .fail = em },
|
||||
}
|
||||
try generateSymbol(bin_file, pt, src_loc, value, code, reloc_parent);
|
||||
} else {
|
||||
try code.appendNTimes(0, abi_size);
|
||||
}
|
||||
@@ -362,10 +340,7 @@ pub fn generateSymbol(
|
||||
const value = payload_val orelse Value.fromInterned(try pt.intern(.{
|
||||
.undef = payload_type.toIntern(),
|
||||
}));
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, value, code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return Result{ .fail = em },
|
||||
}
|
||||
try generateSymbol(bin_file, pt, src_loc, value, code, reloc_parent);
|
||||
}
|
||||
try code.writer().writeByte(@intFromBool(payload_val != null));
|
||||
try code.appendNTimes(0, padding);
|
||||
@@ -377,17 +352,14 @@ pub fn generateSymbol(
|
||||
.elems, .repeated_elem => {
|
||||
var index: u64 = 0;
|
||||
while (index < array_type.lenIncludingSentinel()) : (index += 1) {
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {
|
||||
.bytes => unreachable,
|
||||
.elems => |elems| elems[@intCast(index)],
|
||||
.repeated_elem => |elem| if (index < array_type.len)
|
||||
elem
|
||||
else
|
||||
array_type.sentinel,
|
||||
}), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return .{ .fail = em },
|
||||
}
|
||||
}), code, reloc_parent);
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -437,16 +409,13 @@ pub fn generateSymbol(
|
||||
.elems, .repeated_elem => {
|
||||
var index: u64 = 0;
|
||||
while (index < vector_type.len) : (index += 1) {
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {
|
||||
.bytes => unreachable,
|
||||
.elems => |elems| elems[
|
||||
math.cast(usize, index) orelse return error.Overflow
|
||||
],
|
||||
.repeated_elem => |elem| elem,
|
||||
}), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return .{ .fail = em },
|
||||
}
|
||||
}), code, reloc_parent);
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -476,10 +445,7 @@ pub fn generateSymbol(
|
||||
.repeated_elem => |elem| elem,
|
||||
};
|
||||
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return Result{ .fail = em },
|
||||
}
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent);
|
||||
const unpadded_field_end = code.items.len - struct_begin;
|
||||
|
||||
// Pad struct members if required
|
||||
@@ -518,10 +484,8 @@ pub fn generateSymbol(
|
||||
return error.Overflow;
|
||||
var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size);
|
||||
defer tmp_list.deinit();
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), &tmp_list, reloc_parent)) {
|
||||
.ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),
|
||||
.fail => |em| return Result{ .fail = em },
|
||||
}
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), &tmp_list, reloc_parent);
|
||||
@memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items);
|
||||
} else {
|
||||
Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), pt, code.items[current_pos..], bits) catch unreachable;
|
||||
}
|
||||
@@ -553,10 +517,7 @@ pub fn generateSymbol(
|
||||
) orelse return error.Overflow;
|
||||
if (padding > 0) try code.appendNTimes(0, padding);
|
||||
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return Result{ .fail = em },
|
||||
}
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent);
|
||||
}
|
||||
|
||||
const size = struct_type.sizeUnordered(ip);
|
||||
@@ -582,10 +543,7 @@ pub fn generateSymbol(
|
||||
|
||||
// Check if we should store the tag first.
|
||||
if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) {
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return Result{ .fail = em },
|
||||
}
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent);
|
||||
}
|
||||
|
||||
const union_obj = zcu.typeToUnion(ty).?;
|
||||
@@ -595,10 +553,7 @@ pub fn generateSymbol(
|
||||
if (!field_ty.hasRuntimeBits(zcu)) {
|
||||
try code.appendNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);
|
||||
} else {
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return Result{ .fail = em },
|
||||
}
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), code, reloc_parent);
|
||||
|
||||
const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(zcu)) orelse return error.Overflow;
|
||||
if (padding > 0) {
|
||||
@@ -606,17 +561,11 @@ pub fn generateSymbol(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return Result{ .fail = em },
|
||||
}
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), code, reloc_parent);
|
||||
}
|
||||
|
||||
if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) {
|
||||
switch (try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent)) {
|
||||
.ok => {},
|
||||
.fail => |em| return Result{ .fail = em },
|
||||
}
|
||||
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent);
|
||||
|
||||
if (layout.padding > 0) {
|
||||
try code.appendNTimes(0, layout.padding);
|
||||
@@ -625,7 +574,6 @@ pub fn generateSymbol(
|
||||
},
|
||||
.memoized_call => unreachable,
|
||||
}
|
||||
return .ok;
|
||||
}
|
||||
|
||||
fn lowerPtr(
|
||||
@@ -636,7 +584,7 @@ fn lowerPtr(
|
||||
code: *std.ArrayList(u8),
|
||||
reloc_parent: link.File.RelocInfo.Parent,
|
||||
prev_offset: u64,
|
||||
) CodeGenError!Result {
|
||||
) GenerateSymbolError!void {
|
||||
const zcu = pt.zcu;
|
||||
const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
|
||||
const offset: u64 = prev_offset + ptr.byte_offset;
|
||||
@@ -689,7 +637,7 @@ fn lowerUavRef(
|
||||
code: *std.ArrayList(u8),
|
||||
reloc_parent: link.File.RelocInfo.Parent,
|
||||
offset: u64,
|
||||
) CodeGenError!Result {
|
||||
) GenerateSymbolError!void {
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
const ip = &zcu.intern_pool;
|
||||
@@ -702,14 +650,7 @@ fn lowerUavRef(
|
||||
const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn";
|
||||
if (!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) {
|
||||
try code.appendNTimes(0xaa, ptr_width_bytes);
|
||||
return .ok;
|
||||
}
|
||||
|
||||
const uav_align = ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment;
|
||||
const res = try lf.lowerUav(pt, uav_val, uav_align, src_loc);
|
||||
switch (res) {
|
||||
.mcv => {},
|
||||
.fail => |em| return .{ .fail = em },
|
||||
return;
|
||||
}
|
||||
|
||||
switch (lf.tag) {
|
||||
@@ -727,11 +668,17 @@ fn lowerUavRef(
|
||||
.pointee = .{ .uav_index = uav.val },
|
||||
});
|
||||
try code.appendNTimes(0, ptr_width_bytes);
|
||||
return .ok;
|
||||
return;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
const uav_align = ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment;
|
||||
switch (try lf.lowerUav(pt, uav_val, uav_align, src_loc)) {
|
||||
.mcv => {},
|
||||
.fail => |em| std.debug.panic("TODO rework lowerUav. internal error: {s}", .{em.msg}),
|
||||
}
|
||||
|
||||
const vaddr = try lf.getUavVAddr(uav_val, .{
|
||||
.parent = reloc_parent,
|
||||
.offset = code.items.len,
|
||||
@@ -744,8 +691,6 @@ fn lowerUavRef(
|
||||
8 => mem.writeInt(u64, try code.addManyAsArray(8), vaddr, endian),
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
return Result.ok;
|
||||
}
|
||||
|
||||
fn lowerNavRef(
|
||||
@@ -756,7 +701,7 @@ fn lowerNavRef(
|
||||
code: *std.ArrayList(u8),
|
||||
reloc_parent: link.File.RelocInfo.Parent,
|
||||
offset: u64,
|
||||
) CodeGenError!Result {
|
||||
) GenerateSymbolError!void {
|
||||
_ = src_loc;
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
@@ -768,7 +713,7 @@ fn lowerNavRef(
|
||||
const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn";
|
||||
if (!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) {
|
||||
try code.appendNTimes(0xaa, ptr_width_bytes);
|
||||
return Result.ok;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (lf.tag) {
|
||||
@@ -786,16 +731,16 @@ fn lowerNavRef(
|
||||
.pointee = .{ .nav_index = nav_index },
|
||||
});
|
||||
try code.appendNTimes(0, ptr_width_bytes);
|
||||
return .ok;
|
||||
return;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
const vaddr = try lf.getNavVAddr(pt, nav_index, .{
|
||||
const vaddr = lf.getNavVAddr(pt, nav_index, .{
|
||||
.parent = reloc_parent,
|
||||
.offset = code.items.len,
|
||||
.addend = @intCast(offset),
|
||||
});
|
||||
}) catch @panic("TODO rework getNavVAddr");
|
||||
const endian = target.cpu.arch.endian();
|
||||
switch (ptr_width_bytes) {
|
||||
2 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(vaddr), endian),
|
||||
@@ -803,8 +748,6 @@ fn lowerNavRef(
|
||||
8 => mem.writeInt(u64, try code.addManyAsArray(8), vaddr, endian),
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
return .ok;
|
||||
}
|
||||
|
||||
/// Helper struct to denote that the value is in memory but requires a linker relocation fixup:
|
||||
|
||||
Reference in New Issue
Block a user