mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
type checking for synthetic functions
This commit is contained in:
parent
a4895f3c42
commit
5b18af85cb
19
src/link.zig
19
src/link.zig
@ -214,22 +214,35 @@ pub const Diags = struct {
|
||||
return error.LinkFailure;
|
||||
}
|
||||
|
||||
pub fn failSourceLocation(diags: *Diags, sl: SourceLocation, comptime format: []const u8, args: anytype) error{LinkFailure} {
|
||||
@branchHint(.cold);
|
||||
addErrorSourceLocation(diags, sl, format, args);
|
||||
return error.LinkFailure;
|
||||
}
|
||||
|
||||
pub fn addError(diags: *Diags, comptime format: []const u8, args: anytype) void {
|
||||
return addErrorSourceLocation(diags, .none, format, args);
|
||||
}
|
||||
|
||||
pub fn addErrorSourceLocation(diags: *Diags, sl: SourceLocation, comptime format: []const u8, args: anytype) void {
|
||||
@branchHint(.cold);
|
||||
const gpa = diags.gpa;
|
||||
const eu_main_msg = std.fmt.allocPrint(gpa, format, args);
|
||||
diags.mutex.lock();
|
||||
defer diags.mutex.unlock();
|
||||
addErrorLockedFallible(diags, eu_main_msg) catch |err| switch (err) {
|
||||
addErrorLockedFallible(diags, sl, eu_main_msg) catch |err| switch (err) {
|
||||
error.OutOfMemory => diags.setAllocFailureLocked(),
|
||||
};
|
||||
}
|
||||
|
||||
fn addErrorLockedFallible(diags: *Diags, eu_main_msg: Allocator.Error![]u8) Allocator.Error!void {
|
||||
fn addErrorLockedFallible(diags: *Diags, sl: SourceLocation, eu_main_msg: Allocator.Error![]u8) Allocator.Error!void {
|
||||
const gpa = diags.gpa;
|
||||
const main_msg = try eu_main_msg;
|
||||
errdefer gpa.free(main_msg);
|
||||
try diags.msgs.append(gpa, .{ .msg = main_msg });
|
||||
try diags.msgs.append(gpa, .{
|
||||
.msg = main_msg,
|
||||
.source_location = sl,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn addErrorWithNotes(diags: *Diags, note_count: usize) error{OutOfMemory}!ErrorWithNotes {
|
||||
|
||||
@ -474,6 +474,10 @@ pub const SourceLocation = enum(u32) {
|
||||
err_msg.notes[err.note_slot - 1].source_location = .{ .wasm = sl };
|
||||
}
|
||||
|
||||
pub fn fail(sl: SourceLocation, diags: *link.Diags, comptime format: []const u8, args: anytype) error{LinkFailure} {
|
||||
return diags.failSourceLocation(.{ .wasm = sl }, format, args);
|
||||
}
|
||||
|
||||
pub fn string(
|
||||
sl: SourceLocation,
|
||||
msg: []const u8,
|
||||
@ -881,12 +885,11 @@ pub const FunctionImport = extern struct {
|
||||
__wasm_call_ctors,
|
||||
__wasm_init_memory,
|
||||
__wasm_init_tls,
|
||||
__zig_error_names,
|
||||
// Next, index into `object_functions`.
|
||||
// Next, index into `zcu_funcs`.
|
||||
_,
|
||||
|
||||
const first_object_function = @intFromEnum(Resolution.__zig_error_names) + 1;
|
||||
const first_object_function = @intFromEnum(Resolution.__wasm_init_tls) + 1;
|
||||
|
||||
pub const Unpacked = union(enum) {
|
||||
unresolved,
|
||||
@ -894,7 +897,6 @@ pub const FunctionImport = extern struct {
|
||||
__wasm_call_ctors,
|
||||
__wasm_init_memory,
|
||||
__wasm_init_tls,
|
||||
__zig_error_names,
|
||||
object_function: ObjectFunctionIndex,
|
||||
zcu_func: ZcuFunc.Index,
|
||||
};
|
||||
@ -906,7 +908,6 @@ pub const FunctionImport = extern struct {
|
||||
.__wasm_call_ctors => .__wasm_call_ctors,
|
||||
.__wasm_init_memory => .__wasm_init_memory,
|
||||
.__wasm_init_tls => .__wasm_init_tls,
|
||||
.__zig_error_names => .__zig_error_names,
|
||||
_ => {
|
||||
const object_function_index = @intFromEnum(r) - first_object_function;
|
||||
|
||||
@ -927,7 +928,6 @@ pub const FunctionImport = extern struct {
|
||||
.__wasm_call_ctors => .__wasm_call_ctors,
|
||||
.__wasm_init_memory => .__wasm_init_memory,
|
||||
.__wasm_init_tls => .__wasm_init_tls,
|
||||
.__zig_error_names => .__zig_error_names,
|
||||
.object_function => |i| @enumFromInt(first_object_function + @intFromEnum(i)),
|
||||
.zcu_func => |i| @enumFromInt(first_object_function + wasm.object_functions.items.len + @intFromEnum(i)),
|
||||
};
|
||||
@ -957,11 +957,11 @@ pub const FunctionImport = extern struct {
|
||||
pub fn typeIndex(r: Resolution, wasm: *Wasm) FunctionType.Index {
|
||||
return switch (unpack(r, wasm)) {
|
||||
.unresolved => unreachable,
|
||||
.__wasm_apply_global_tls_relocs => @panic("TODO"),
|
||||
.__wasm_call_ctors => @panic("TODO"),
|
||||
.__wasm_init_memory => @panic("TODO"),
|
||||
.__wasm_init_tls => @panic("TODO"),
|
||||
.__zig_error_names => @panic("TODO"),
|
||||
.__wasm_apply_global_tls_relocs,
|
||||
.__wasm_call_ctors,
|
||||
.__wasm_init_memory,
|
||||
=> getExistingFuncType2(wasm, &.{}, &.{}),
|
||||
.__wasm_init_tls => getExistingFuncType2(wasm, &.{.i32}, &.{}),
|
||||
.object_function => |i| i.ptr(wasm).type_index,
|
||||
.zcu_func => |i| i.typeIndex(wasm).?,
|
||||
};
|
||||
@ -974,7 +974,6 @@ pub const FunctionImport = extern struct {
|
||||
.__wasm_call_ctors => @tagName(Unpacked.__wasm_call_ctors),
|
||||
.__wasm_init_memory => @tagName(Unpacked.__wasm_init_memory),
|
||||
.__wasm_init_tls => @tagName(Unpacked.__wasm_init_tls),
|
||||
.__zig_error_names => @tagName(Unpacked.__zig_error_names),
|
||||
.object_function => |i| i.ptr(wasm).name.slice(wasm),
|
||||
.zcu_func => |i| i.name(wasm),
|
||||
};
|
||||
@ -2991,7 +2990,7 @@ fn markFunctionImport(
|
||||
name: String,
|
||||
import: *FunctionImport,
|
||||
func_index: FunctionImport.Index,
|
||||
) Allocator.Error!void {
|
||||
) link.File.FlushError!void {
|
||||
if (import.flags.alive) return;
|
||||
import.flags.alive = true;
|
||||
|
||||
@ -3002,17 +3001,13 @@ fn markFunctionImport(
|
||||
|
||||
if (import.resolution == .unresolved) {
|
||||
if (name == wasm.preloaded_strings.__wasm_init_memory) {
|
||||
import.resolution = .__wasm_init_memory;
|
||||
wasm.functions.putAssumeCapacity(.__wasm_init_memory, {});
|
||||
try wasm.resolveFunctionSynthetic(import, .__wasm_init_memory, &.{}, &.{});
|
||||
} else if (name == wasm.preloaded_strings.__wasm_apply_global_tls_relocs) {
|
||||
import.resolution = .__wasm_apply_global_tls_relocs;
|
||||
wasm.functions.putAssumeCapacity(.__wasm_apply_global_tls_relocs, {});
|
||||
try wasm.resolveFunctionSynthetic(import, .__wasm_apply_global_tls_relocs, &.{}, &.{});
|
||||
} else if (name == wasm.preloaded_strings.__wasm_call_ctors) {
|
||||
import.resolution = .__wasm_call_ctors;
|
||||
wasm.functions.putAssumeCapacity(.__wasm_call_ctors, {});
|
||||
try wasm.resolveFunctionSynthetic(import, .__wasm_call_ctors, &.{}, &.{});
|
||||
} else if (name == wasm.preloaded_strings.__wasm_init_tls) {
|
||||
import.resolution = .__wasm_init_tls;
|
||||
wasm.functions.putAssumeCapacity(.__wasm_init_tls, {});
|
||||
try wasm.resolveFunctionSynthetic(import, .__wasm_init_tls, &.{.i32}, &.{});
|
||||
} else {
|
||||
try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm));
|
||||
}
|
||||
@ -3022,7 +3017,7 @@ fn markFunctionImport(
|
||||
}
|
||||
|
||||
/// Recursively mark alive everything referenced by the function.
|
||||
fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex) Allocator.Error!void {
|
||||
fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex) link.File.FlushError!void {
|
||||
const comp = wasm.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const gop = try wasm.functions.getOrPut(gpa, .fromObjectFunction(wasm, i));
|
||||
@ -3046,7 +3041,7 @@ fn markGlobalImport(
|
||||
name: String,
|
||||
import: *GlobalImport,
|
||||
global_index: GlobalImport.Index,
|
||||
) !void {
|
||||
) link.File.FlushError!void {
|
||||
if (import.flags.alive) return;
|
||||
import.flags.alive = true;
|
||||
|
||||
@ -3082,7 +3077,7 @@ fn markGlobalImport(
|
||||
}
|
||||
}
|
||||
|
||||
fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex) Allocator.Error!void {
|
||||
fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex) link.File.FlushError!void {
|
||||
const comp = wasm.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const gop = try wasm.globals.getOrPut(gpa, .fromObjectGlobal(wasm, i));
|
||||
@ -3105,7 +3100,7 @@ fn markTableImport(
|
||||
name: String,
|
||||
import: *TableImport,
|
||||
table_index: TableImport.Index,
|
||||
) !void {
|
||||
) link.File.FlushError!void {
|
||||
if (import.flags.alive) return;
|
||||
import.flags.alive = true;
|
||||
|
||||
@ -3127,7 +3122,7 @@ fn markTableImport(
|
||||
}
|
||||
}
|
||||
|
||||
fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) Allocator.Error!void {
|
||||
fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) link.File.FlushError!void {
|
||||
const segment = segment_index.ptr(wasm);
|
||||
if (segment.flags.alive) return;
|
||||
segment.flags.alive = true;
|
||||
@ -3135,7 +3130,7 @@ fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) Allocato
|
||||
try wasm.markRelocations(segment.relocations(wasm));
|
||||
}
|
||||
|
||||
fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) Allocator.Error!void {
|
||||
fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.File.FlushError!void {
|
||||
for (relocs.slice.tags(wasm), relocs.slice.pointees(wasm), relocs.slice.offsets(wasm)) |tag, *pointee, offset| {
|
||||
if (offset >= relocs.end) break;
|
||||
switch (tag) {
|
||||
@ -3751,7 +3746,7 @@ pub fn internValtypeList(wasm: *Wasm, valtype_list: []const std.wasm.Valtype) Al
|
||||
return .fromString(try internString(wasm, @ptrCast(valtype_list)));
|
||||
}
|
||||
|
||||
pub fn getExistingValtypeList(wasm: *Wasm, valtype_list: []const std.wasm.Valtype) ?ValtypeList {
|
||||
pub fn getExistingValtypeList(wasm: *const Wasm, valtype_list: []const std.wasm.Valtype) ?ValtypeList {
|
||||
return .fromString(getExistingString(wasm, @ptrCast(valtype_list)) orelse return null);
|
||||
}
|
||||
|
||||
@ -3766,6 +3761,13 @@ pub fn getExistingFuncType(wasm: *const Wasm, ft: FunctionType) ?FunctionType.In
|
||||
return @enumFromInt(index);
|
||||
}
|
||||
|
||||
pub fn getExistingFuncType2(wasm: *const Wasm, params: []const std.wasm.Valtype, returns: []const std.wasm.Valtype) FunctionType.Index {
|
||||
return getExistingFuncType(wasm, .{
|
||||
.params = getExistingValtypeList(wasm, params).?,
|
||||
.returns = getExistingValtypeList(wasm, returns).?,
|
||||
}).?;
|
||||
}
|
||||
|
||||
pub fn internFunctionType(
|
||||
wasm: *Wasm,
|
||||
cc: std.builtin.CallingConvention,
|
||||
@ -4080,3 +4082,26 @@ fn addZcuImportReserved(wasm: *Wasm, nav_index: InternPool.Nav.Index) ZcuImportI
|
||||
gop.value_ptr.* = {};
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn resolveFunctionSynthetic(
|
||||
wasm: *Wasm,
|
||||
import: *FunctionImport,
|
||||
res: FunctionImport.Resolution,
|
||||
params: []const std.wasm.Valtype,
|
||||
returns: []const std.wasm.Valtype,
|
||||
) link.File.FlushError!void {
|
||||
import.resolution = res;
|
||||
wasm.functions.putAssumeCapacity(res, {});
|
||||
// This is not only used for type-checking but also ensures the function
|
||||
// type index is interned so that it is guaranteed to exist during `flush`.
|
||||
const correct_func_type = try addFuncType(wasm, .{
|
||||
.params = try internValtypeList(wasm, params),
|
||||
.returns = try internValtypeList(wasm, returns),
|
||||
});
|
||||
if (import.type != correct_func_type) {
|
||||
const diags = &wasm.base.comp.link_diags;
|
||||
return import.source_location.fail(diags, "synthetic function {s} {} imported with incorrect signature {}", .{
|
||||
@tagName(res), correct_func_type.fmt(wasm), import.type.fmt(wasm),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -682,7 +682,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
|
||||
.__wasm_call_ctors => @panic("TODO lower __wasm_call_ctors"),
|
||||
.__wasm_init_memory => @panic("TODO lower __wasm_init_memory "),
|
||||
.__wasm_init_tls => @panic("TODO lower __wasm_init_tls "),
|
||||
.__zig_error_names => @panic("TODO lower __zig_error_names "),
|
||||
.object_function => |i| {
|
||||
_ = i;
|
||||
@panic("TODO lower object function code and apply relocations");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user