mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 00:08:56 +00:00
Merge pull request #16318 from ziglang/rework-generics
rework generic function calls
This commit is contained in:
commit
0aacb6369f
@ -1669,8 +1669,9 @@ pub fn ArrayHashMapUnmanaged(
|
||||
|
||||
inline fn checkedHash(ctx: anytype, key: anytype) u32 {
|
||||
comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(key), K, u32, true);
|
||||
// If you get a compile error on the next line, it means that
|
||||
const hash = ctx.hash(key); // your generic hash function doesn't accept your key
|
||||
// If you get a compile error on the next line, it means that your
|
||||
// generic hash function doesn't accept your key.
|
||||
const hash = ctx.hash(key);
|
||||
if (@TypeOf(hash) != u32) {
|
||||
@compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic hash function that returns the wrong type!\n" ++
|
||||
@typeName(u32) ++ " was expected, but found " ++ @typeName(@TypeOf(hash)));
|
||||
@ -1679,8 +1680,9 @@ pub fn ArrayHashMapUnmanaged(
|
||||
}
|
||||
inline fn checkedEql(ctx: anytype, a: anytype, b: K, b_index: usize) bool {
|
||||
comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(a), K, u32, true);
|
||||
// If you get a compile error on the next line, it means that
|
||||
const eql = ctx.eql(a, b, b_index); // your generic eql function doesn't accept (self, adapt key, K, index)
|
||||
// If you get a compile error on the next line, it means that your
|
||||
// generic eql function doesn't accept (self, adapt key, K, index).
|
||||
const eql = ctx.eql(a, b, b_index);
|
||||
if (@TypeOf(eql) != bool) {
|
||||
@compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic eql function that returns the wrong type!\n" ++
|
||||
@typeName(bool) ++ " was expected, but found " ++ @typeName(@TypeOf(eql)));
|
||||
|
||||
@ -946,6 +946,7 @@ pub const Inst = struct {
|
||||
slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
|
||||
optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type),
|
||||
anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),
|
||||
adhoc_inferred_error_set_type = @intFromEnum(InternPool.Index.adhoc_inferred_error_set_type),
|
||||
generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),
|
||||
empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),
|
||||
undef = @intFromEnum(InternPool.Index.undef),
|
||||
@ -1003,7 +1004,7 @@ pub const Inst = struct {
|
||||
},
|
||||
ty_fn: struct {
|
||||
ty: Ref,
|
||||
func: Module.Fn.Index,
|
||||
func: InternPool.Index,
|
||||
},
|
||||
br: struct {
|
||||
block_inst: Index,
|
||||
@ -1436,7 +1437,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
|
||||
|
||||
.call, .call_always_tail, .call_never_tail, .call_never_inline => {
|
||||
const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);
|
||||
return ip.funcReturnType(callee_ty.toIntern()).toType();
|
||||
return ip.funcTypeReturnType(callee_ty.toIntern()).toType();
|
||||
},
|
||||
|
||||
.slice_elem_val, .ptr_elem_val, .array_elem_val => {
|
||||
|
||||
@ -12095,7 +12095,10 @@ const GenZir = struct {
|
||||
return gz.addAsIndex(.{
|
||||
.tag = .save_err_ret_index,
|
||||
.data = .{ .save_err_ret_index = .{
|
||||
.operand = if (cond == .if_of_error_type) cond.if_of_error_type else .none,
|
||||
.operand = switch (cond) {
|
||||
.if_of_error_type => |x| x,
|
||||
else => .none,
|
||||
},
|
||||
} },
|
||||
});
|
||||
}
|
||||
|
||||
@ -281,6 +281,7 @@ pub fn generateZirData(self: *Autodoc) !void {
|
||||
// Poison and special tag
|
||||
.generic_poison_type,
|
||||
.var_args_param_type,
|
||||
.adhoc_inferred_error_set_type,
|
||||
=> .{
|
||||
.Type = .{ .name = try tmpbuf.toOwnedSlice() },
|
||||
},
|
||||
|
||||
@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig");
|
||||
const fatal = @import("main.zig").fatal;
|
||||
const clangMain = @import("main.zig").clangMain;
|
||||
const Module = @import("Module.zig");
|
||||
const InternPool = @import("InternPool.zig");
|
||||
const BuildId = std.Build.CompileStep.BuildId;
|
||||
const Cache = std.Build.Cache;
|
||||
const translate_c = @import("translate_c.zig");
|
||||
@ -227,7 +228,8 @@ const Job = union(enum) {
|
||||
/// Write the constant value for a Decl to the output file.
|
||||
codegen_decl: Module.Decl.Index,
|
||||
/// Write the machine code for a function to the output file.
|
||||
codegen_func: Module.Fn.Index,
|
||||
/// This will either be a non-generic `func_decl` or a `func_instance`.
|
||||
codegen_func: InternPool.Index,
|
||||
/// Render the .h file snippet for the Decl.
|
||||
emit_h_decl: Module.Decl.Index,
|
||||
/// The Decl needs to be analyzed and possibly export itself.
|
||||
@ -2053,15 +2055,9 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
|
||||
const decl = module.declPtr(decl_index);
|
||||
assert(decl.deletion_flag);
|
||||
assert(decl.dependants.count() == 0);
|
||||
const is_anon = if (decl.zir_decl_index == 0) blk: {
|
||||
break :blk module.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index);
|
||||
} else false;
|
||||
assert(decl.zir_decl_index != 0);
|
||||
|
||||
try module.clearDecl(decl_index, null);
|
||||
|
||||
if (is_anon) {
|
||||
module.destroyDecl(decl_index);
|
||||
}
|
||||
}
|
||||
|
||||
try module.processExports();
|
||||
@ -3216,8 +3212,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
|
||||
// Tests are always emitted in test binaries. The decl_refs are created by
|
||||
// Module.populateTestFunctions, but this will not queue body analysis, so do
|
||||
// that now.
|
||||
const func_index = module.intern_pool.indexToFunc(decl.val.ip_index).unwrap().?;
|
||||
try module.ensureFuncBodyAnalysisQueued(func_index);
|
||||
try module.ensureFuncBodyAnalysisQueued(decl.val.toIntern());
|
||||
}
|
||||
},
|
||||
.update_embed_file => |embed_file| {
|
||||
|
||||
2099
src/InternPool.zig
2099
src/InternPool.zig
File diff suppressed because it is too large
Load Diff
875
src/Module.zig
875
src/Module.zig
File diff suppressed because it is too large
Load Diff
2755
src/Sema.zig
2755
src/Sema.zig
File diff suppressed because it is too large
Load Diff
@ -205,7 +205,7 @@ pub fn print(
|
||||
mod.declPtr(extern_func.decl).name.fmt(ip),
|
||||
}),
|
||||
.func => |func| return writer.print("(function '{}')", .{
|
||||
mod.declPtr(mod.funcPtr(func.index).owner_decl).name.fmt(ip),
|
||||
mod.declPtr(func.owner_decl).name.fmt(ip),
|
||||
}),
|
||||
.int => |int| switch (int.storage) {
|
||||
inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
|
||||
|
||||
24
src/Zir.zig
24
src/Zir.zig
@ -65,9 +65,13 @@ pub const ExtraIndex = enum(u32) {
|
||||
_,
|
||||
};
|
||||
|
||||
fn ExtraData(comptime T: type) type {
|
||||
return struct { data: T, end: usize };
|
||||
}
|
||||
|
||||
/// Returns the requested data, as well as the new index which is at the start of the
|
||||
/// trailers for the object.
|
||||
pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, end: usize } {
|
||||
pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
|
||||
const fields = @typeInfo(T).Struct.fields;
|
||||
var i: usize = index;
|
||||
var result: T = undefined;
|
||||
@ -90,13 +94,24 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en
|
||||
};
|
||||
}
|
||||
|
||||
/// Given an index into `string_bytes` returns the null-terminated string found there.
|
||||
/// TODO migrate to use this for type safety
|
||||
pub const NullTerminatedString = enum(u32) {
|
||||
_,
|
||||
};
|
||||
|
||||
/// TODO: migrate to nullTerminatedString2 for type safety
|
||||
pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 {
|
||||
var end: usize = index;
|
||||
return nullTerminatedString2(code, @enumFromInt(index));
|
||||
}
|
||||
|
||||
/// Given an index into `string_bytes` returns the null-terminated string found there.
|
||||
pub fn nullTerminatedString2(code: Zir, index: NullTerminatedString) [:0]const u8 {
|
||||
const start = @intFromEnum(index);
|
||||
var end: u32 = start;
|
||||
while (code.string_bytes[end] != 0) {
|
||||
end += 1;
|
||||
}
|
||||
return code.string_bytes[index..end :0];
|
||||
return code.string_bytes[start..end :0];
|
||||
}
|
||||
|
||||
pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {
|
||||
@ -2076,6 +2091,7 @@ pub const Inst = struct {
|
||||
slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
|
||||
optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type),
|
||||
anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),
|
||||
adhoc_inferred_error_set_type = @intFromEnum(InternPool.Index.adhoc_inferred_error_set_type),
|
||||
generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),
|
||||
empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),
|
||||
undef = @intFromEnum(InternPool.Index.undef),
|
||||
|
||||
@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
|
||||
const TypedValue = @import("../../TypedValue.zig");
|
||||
const link = @import("../../link.zig");
|
||||
const Module = @import("../../Module.zig");
|
||||
const InternPool = @import("../../InternPool.zig");
|
||||
const Compilation = @import("../../Compilation.zig");
|
||||
const ErrorMsg = Module.ErrorMsg;
|
||||
const Target = std.Target;
|
||||
@ -49,7 +50,8 @@ liveness: Liveness,
|
||||
bin_file: *link.File,
|
||||
debug_output: DebugInfoOutput,
|
||||
target: *const std.Target,
|
||||
mod_fn: *const Module.Fn,
|
||||
func_index: InternPool.Index,
|
||||
owner_decl: Module.Decl.Index,
|
||||
err_msg: ?*ErrorMsg,
|
||||
args: []MCValue,
|
||||
ret_mcv: MCValue,
|
||||
@ -199,7 +201,7 @@ const DbgInfoReloc = struct {
|
||||
else => unreachable, // not a possible argument
|
||||
|
||||
};
|
||||
try dw.genArgDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, loc);
|
||||
try dw.genArgDbgInfo(reloc.name, reloc.ty, function.owner_decl, loc);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
@ -245,7 +247,7 @@ const DbgInfoReloc = struct {
|
||||
break :blk .nop;
|
||||
},
|
||||
};
|
||||
try dw.genVarDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, is_ptr, loc);
|
||||
try dw.genVarDbgInfo(reloc.name, reloc.ty, function.owner_decl, is_ptr, loc);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
@ -328,7 +330,7 @@ const Self = @This();
|
||||
pub fn generate(
|
||||
bin_file: *link.File,
|
||||
src_loc: Module.SrcLoc,
|
||||
module_fn_index: Module.Fn.Index,
|
||||
func_index: InternPool.Index,
|
||||
air: Air,
|
||||
liveness: Liveness,
|
||||
code: *std.ArrayList(u8),
|
||||
@ -339,8 +341,8 @@ pub fn generate(
|
||||
}
|
||||
|
||||
const mod = bin_file.options.module.?;
|
||||
const module_fn = mod.funcPtr(module_fn_index);
|
||||
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
|
||||
const func = mod.funcInfo(func_index);
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
assert(fn_owner_decl.has_tv);
|
||||
const fn_type = fn_owner_decl.ty;
|
||||
|
||||
@ -359,7 +361,8 @@ pub fn generate(
|
||||
.debug_output = debug_output,
|
||||
.target = &bin_file.options.target,
|
||||
.bin_file = bin_file,
|
||||
.mod_fn = module_fn,
|
||||
.func_index = func_index,
|
||||
.owner_decl = func.owner_decl,
|
||||
.err_msg = null,
|
||||
.args = undefined, // populated after `resolveCallingConventionValues`
|
||||
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
|
||||
@ -368,8 +371,8 @@ pub fn generate(
|
||||
.branch_stack = &branch_stack,
|
||||
.src_loc = src_loc,
|
||||
.stack_align = undefined,
|
||||
.end_di_line = module_fn.rbrace_line,
|
||||
.end_di_column = module_fn.rbrace_column,
|
||||
.end_di_line = func.rbrace_line,
|
||||
.end_di_column = func.rbrace_column,
|
||||
};
|
||||
defer function.stack.deinit(bin_file.allocator);
|
||||
defer function.blocks.deinit(bin_file.allocator);
|
||||
@ -416,8 +419,8 @@ pub fn generate(
|
||||
.src_loc = src_loc,
|
||||
.code = code,
|
||||
.prev_di_pc = 0,
|
||||
.prev_di_line = module_fn.lbrace_line,
|
||||
.prev_di_column = module_fn.lbrace_column,
|
||||
.prev_di_line = func.lbrace_line,
|
||||
.prev_di_column = func.lbrace_column,
|
||||
.stack_size = function.max_end_stack,
|
||||
.saved_regs_stack_space = function.saved_regs_stack_space,
|
||||
};
|
||||
@ -4011,12 +4014,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
|
||||
const atom_index = switch (self.bin_file.tag) {
|
||||
.macho => blk: {
|
||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
|
||||
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
.coff => blk: {
|
||||
const coff_file = self.bin_file.cast(link.File.Coff).?;
|
||||
const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
|
||||
break :blk coff_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
else => unreachable, // unsupported target format
|
||||
@ -4190,10 +4193,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
|
||||
while (self.args[arg_index] == .none) arg_index += 1;
|
||||
self.arg_index = arg_index + 1;
|
||||
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const ty = self.typeOfIndex(inst);
|
||||
const tag = self.air.instructions.items(.tag)[inst];
|
||||
const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
|
||||
const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
|
||||
const name = mod.getParamName(self.func_index, src_index);
|
||||
|
||||
try self.dbg_info_relocs.append(self.gpa, .{
|
||||
.tag = tag,
|
||||
@ -4348,7 +4352,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
|
||||
if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
|
||||
const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call_extern,
|
||||
@ -4617,9 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const function = mod.funcPtr(ty_fn.func);
|
||||
const func = mod.funcInfo(ty_fn.func);
|
||||
// TODO emit debug info for function change
|
||||
_ = function;
|
||||
_ = func;
|
||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
||||
}
|
||||
|
||||
@ -5529,12 +5533,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
|
||||
const atom_index = switch (self.bin_file.tag) {
|
||||
.macho => blk: {
|
||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
|
||||
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
.coff => blk: {
|
||||
const coff_file = self.bin_file.cast(link.File.Coff).?;
|
||||
const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
|
||||
break :blk coff_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
else => unreachable, // unsupported target format
|
||||
@ -5650,12 +5654,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
||||
const atom_index = switch (self.bin_file.tag) {
|
||||
.macho => blk: {
|
||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
|
||||
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
.coff => blk: {
|
||||
const coff_file = self.bin_file.cast(link.File.Coff).?;
|
||||
const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
|
||||
break :blk coff_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
else => unreachable, // unsupported target format
|
||||
@ -5847,12 +5851,12 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
|
||||
const atom_index = switch (self.bin_file.tag) {
|
||||
.macho => blk: {
|
||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
|
||||
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
.coff => blk: {
|
||||
const coff_file = self.bin_file.cast(link.File.Coff).?;
|
||||
const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
|
||||
break :blk coff_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
else => unreachable, // unsupported target format
|
||||
@ -6164,7 +6168,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
|
||||
self.bin_file,
|
||||
self.src_loc,
|
||||
arg_tv,
|
||||
self.mod_fn.owner_decl,
|
||||
self.owner_decl,
|
||||
)) {
|
||||
.mcv => |mcv| switch (mcv) {
|
||||
.none => .none,
|
||||
@ -6198,6 +6202,7 @@ const CallMCValues = struct {
|
||||
/// Caller must call `CallMCValues.deinit`.
|
||||
fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const ip = &mod.intern_pool;
|
||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||
const cc = fn_info.cc;
|
||||
var result: CallMCValues = .{
|
||||
@ -6240,10 +6245,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
}
|
||||
}
|
||||
|
||||
for (fn_info.param_types, 0..) |ty, i| {
|
||||
for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
|
||||
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||
if (param_size == 0) {
|
||||
result.args[i] = .{ .none = {} };
|
||||
result_arg.* = .{ .none = {} };
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -6256,7 +6261,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
|
||||
if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
|
||||
if (param_size <= 8) {
|
||||
result.args[i] = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) };
|
||||
result_arg.* = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) };
|
||||
ncrn += 1;
|
||||
} else {
|
||||
return self.fail("TODO MCValues with multiple registers", .{});
|
||||
@ -6273,7 +6278,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
}
|
||||
}
|
||||
|
||||
result.args[i] = .{ .stack_argument_offset = nsaa };
|
||||
result_arg.* = .{ .stack_argument_offset = nsaa };
|
||||
nsaa += param_size;
|
||||
}
|
||||
}
|
||||
@ -6305,16 +6310,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
|
||||
var stack_offset: u32 = 0;
|
||||
|
||||
for (fn_info.param_types, 0..) |ty, i| {
|
||||
for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
|
||||
if (ty.toType().abiSize(mod) > 0) {
|
||||
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||
const param_alignment = ty.toType().abiAlignment(mod);
|
||||
|
||||
stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);
|
||||
result.args[i] = .{ .stack_argument_offset = stack_offset };
|
||||
result_arg.* = .{ .stack_argument_offset = stack_offset };
|
||||
stack_offset += param_size;
|
||||
} else {
|
||||
result.args[i] = .{ .none = {} };
|
||||
result_arg.* = .{ .none = {} };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
|
||||
const TypedValue = @import("../../TypedValue.zig");
|
||||
const link = @import("../../link.zig");
|
||||
const Module = @import("../../Module.zig");
|
||||
const InternPool = @import("../../InternPool.zig");
|
||||
const Compilation = @import("../../Compilation.zig");
|
||||
const ErrorMsg = Module.ErrorMsg;
|
||||
const Target = std.Target;
|
||||
@ -50,7 +51,7 @@ liveness: Liveness,
|
||||
bin_file: *link.File,
|
||||
debug_output: DebugInfoOutput,
|
||||
target: *const std.Target,
|
||||
mod_fn: *const Module.Fn,
|
||||
func_index: InternPool.Index,
|
||||
err_msg: ?*ErrorMsg,
|
||||
args: []MCValue,
|
||||
ret_mcv: MCValue,
|
||||
@ -258,6 +259,7 @@ const DbgInfoReloc = struct {
|
||||
}
|
||||
|
||||
fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {
|
||||
const mod = function.bin_file.options.module.?;
|
||||
switch (function.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) {
|
||||
@ -278,7 +280,7 @@ const DbgInfoReloc = struct {
|
||||
else => unreachable, // not a possible argument
|
||||
};
|
||||
|
||||
try dw.genArgDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, loc);
|
||||
try dw.genArgDbgInfo(reloc.name, reloc.ty, mod.funcOwnerDeclIndex(function.func_index), loc);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
@ -286,6 +288,7 @@ const DbgInfoReloc = struct {
|
||||
}
|
||||
|
||||
fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
|
||||
const mod = function.bin_file.options.module.?;
|
||||
const is_ptr = switch (reloc.tag) {
|
||||
.dbg_var_ptr => true,
|
||||
.dbg_var_val => false,
|
||||
@ -321,7 +324,7 @@ const DbgInfoReloc = struct {
|
||||
break :blk .nop;
|
||||
},
|
||||
};
|
||||
try dw.genVarDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, is_ptr, loc);
|
||||
try dw.genVarDbgInfo(reloc.name, reloc.ty, mod.funcOwnerDeclIndex(function.func_index), is_ptr, loc);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
@ -334,7 +337,7 @@ const Self = @This();
|
||||
pub fn generate(
|
||||
bin_file: *link.File,
|
||||
src_loc: Module.SrcLoc,
|
||||
module_fn_index: Module.Fn.Index,
|
||||
func_index: InternPool.Index,
|
||||
air: Air,
|
||||
liveness: Liveness,
|
||||
code: *std.ArrayList(u8),
|
||||
@ -345,8 +348,8 @@ pub fn generate(
|
||||
}
|
||||
|
||||
const mod = bin_file.options.module.?;
|
||||
const module_fn = mod.funcPtr(module_fn_index);
|
||||
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
|
||||
const func = mod.funcInfo(func_index);
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
assert(fn_owner_decl.has_tv);
|
||||
const fn_type = fn_owner_decl.ty;
|
||||
|
||||
@ -365,7 +368,7 @@ pub fn generate(
|
||||
.target = &bin_file.options.target,
|
||||
.bin_file = bin_file,
|
||||
.debug_output = debug_output,
|
||||
.mod_fn = module_fn,
|
||||
.func_index = func_index,
|
||||
.err_msg = null,
|
||||
.args = undefined, // populated after `resolveCallingConventionValues`
|
||||
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
|
||||
@ -374,8 +377,8 @@ pub fn generate(
|
||||
.branch_stack = &branch_stack,
|
||||
.src_loc = src_loc,
|
||||
.stack_align = undefined,
|
||||
.end_di_line = module_fn.rbrace_line,
|
||||
.end_di_column = module_fn.rbrace_column,
|
||||
.end_di_line = func.rbrace_line,
|
||||
.end_di_column = func.rbrace_column,
|
||||
};
|
||||
defer function.stack.deinit(bin_file.allocator);
|
||||
defer function.blocks.deinit(bin_file.allocator);
|
||||
@ -422,8 +425,8 @@ pub fn generate(
|
||||
.src_loc = src_loc,
|
||||
.code = code,
|
||||
.prev_di_pc = 0,
|
||||
.prev_di_line = module_fn.lbrace_line,
|
||||
.prev_di_column = module_fn.lbrace_column,
|
||||
.prev_di_line = func.lbrace_line,
|
||||
.prev_di_column = func.lbrace_column,
|
||||
.stack_size = function.max_end_stack,
|
||||
.saved_regs_stack_space = function.saved_regs_stack_space,
|
||||
};
|
||||
@ -4163,10 +4166,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
|
||||
while (self.args[arg_index] == .none) arg_index += 1;
|
||||
self.arg_index = arg_index + 1;
|
||||
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const ty = self.typeOfIndex(inst);
|
||||
const tag = self.air.instructions.items(.tag)[inst];
|
||||
const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
|
||||
const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
|
||||
const name = mod.getParamName(self.func_index, src_index);
|
||||
|
||||
try self.dbg_info_relocs.append(self.gpa, .{
|
||||
.tag = tag,
|
||||
@ -4569,9 +4573,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const function = mod.funcPtr(ty_fn.func);
|
||||
const func = mod.funcInfo(ty_fn.func);
|
||||
// TODO emit debug info for function change
|
||||
_ = function;
|
||||
_ = func;
|
||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
||||
}
|
||||
|
||||
@ -6113,11 +6117,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
|
||||
}
|
||||
|
||||
fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const mcv: MCValue = switch (try codegen.genTypedValue(
|
||||
self.bin_file,
|
||||
self.src_loc,
|
||||
arg_tv,
|
||||
self.mod_fn.owner_decl,
|
||||
mod.funcOwnerDeclIndex(self.func_index),
|
||||
)) {
|
||||
.mcv => |mcv| switch (mcv) {
|
||||
.none => .none,
|
||||
@ -6149,6 +6154,7 @@ const CallMCValues = struct {
|
||||
/// Caller must call `CallMCValues.deinit`.
|
||||
fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const ip = &mod.intern_pool;
|
||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||
const cc = fn_info.cc;
|
||||
var result: CallMCValues = .{
|
||||
@ -6194,14 +6200,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
}
|
||||
}
|
||||
|
||||
for (fn_info.param_types, 0..) |ty, i| {
|
||||
for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
|
||||
if (ty.toType().abiAlignment(mod) == 8)
|
||||
ncrn = std.mem.alignForward(usize, ncrn, 2);
|
||||
|
||||
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||
if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
|
||||
if (param_size <= 4) {
|
||||
result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };
|
||||
result_arg.* = .{ .register = c_abi_int_param_regs[ncrn] };
|
||||
ncrn += 1;
|
||||
} else {
|
||||
return self.fail("TODO MCValues with multiple registers", .{});
|
||||
@ -6213,7 +6219,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
if (ty.toType().abiAlignment(mod) == 8)
|
||||
nsaa = std.mem.alignForward(u32, nsaa, 8);
|
||||
|
||||
result.args[i] = .{ .stack_argument_offset = nsaa };
|
||||
result_arg.* = .{ .stack_argument_offset = nsaa };
|
||||
nsaa += param_size;
|
||||
}
|
||||
}
|
||||
@ -6244,16 +6250,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
|
||||
var stack_offset: u32 = 0;
|
||||
|
||||
for (fn_info.param_types, 0..) |ty, i| {
|
||||
for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
|
||||
if (ty.toType().abiSize(mod) > 0) {
|
||||
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||
const param_alignment = ty.toType().abiAlignment(mod);
|
||||
|
||||
stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);
|
||||
result.args[i] = .{ .stack_argument_offset = stack_offset };
|
||||
result_arg.* = .{ .stack_argument_offset = stack_offset };
|
||||
stack_offset += param_size;
|
||||
} else {
|
||||
result.args[i] = .{ .none = {} };
|
||||
result_arg.* = .{ .none = {} };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ const Value = @import("../../value.zig").Value;
|
||||
const TypedValue = @import("../../TypedValue.zig");
|
||||
const link = @import("../../link.zig");
|
||||
const Module = @import("../../Module.zig");
|
||||
const InternPool = @import("../../InternPool.zig");
|
||||
const Compilation = @import("../../Compilation.zig");
|
||||
const ErrorMsg = Module.ErrorMsg;
|
||||
const Target = std.Target;
|
||||
@ -43,7 +44,7 @@ air: Air,
|
||||
liveness: Liveness,
|
||||
bin_file: *link.File,
|
||||
target: *const std.Target,
|
||||
mod_fn: *const Module.Fn,
|
||||
func_index: InternPool.Index,
|
||||
code: *std.ArrayList(u8),
|
||||
debug_output: DebugInfoOutput,
|
||||
err_msg: ?*ErrorMsg,
|
||||
@ -217,7 +218,7 @@ const Self = @This();
|
||||
pub fn generate(
|
||||
bin_file: *link.File,
|
||||
src_loc: Module.SrcLoc,
|
||||
module_fn_index: Module.Fn.Index,
|
||||
func_index: InternPool.Index,
|
||||
air: Air,
|
||||
liveness: Liveness,
|
||||
code: *std.ArrayList(u8),
|
||||
@ -228,8 +229,8 @@ pub fn generate(
|
||||
}
|
||||
|
||||
const mod = bin_file.options.module.?;
|
||||
const module_fn = mod.funcPtr(module_fn_index);
|
||||
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
|
||||
const func = mod.funcInfo(func_index);
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
assert(fn_owner_decl.has_tv);
|
||||
const fn_type = fn_owner_decl.ty;
|
||||
|
||||
@ -247,7 +248,7 @@ pub fn generate(
|
||||
.liveness = liveness,
|
||||
.target = &bin_file.options.target,
|
||||
.bin_file = bin_file,
|
||||
.mod_fn = module_fn,
|
||||
.func_index = func_index,
|
||||
.code = code,
|
||||
.debug_output = debug_output,
|
||||
.err_msg = null,
|
||||
@ -258,8 +259,8 @@ pub fn generate(
|
||||
.branch_stack = &branch_stack,
|
||||
.src_loc = src_loc,
|
||||
.stack_align = undefined,
|
||||
.end_di_line = module_fn.rbrace_line,
|
||||
.end_di_column = module_fn.rbrace_column,
|
||||
.end_di_line = func.rbrace_line,
|
||||
.end_di_column = func.rbrace_column,
|
||||
};
|
||||
defer function.stack.deinit(bin_file.allocator);
|
||||
defer function.blocks.deinit(bin_file.allocator);
|
||||
@ -301,8 +302,8 @@ pub fn generate(
|
||||
.src_loc = src_loc,
|
||||
.code = code,
|
||||
.prev_di_pc = 0,
|
||||
.prev_di_line = module_fn.lbrace_line,
|
||||
.prev_di_column = module_fn.lbrace_column,
|
||||
.prev_di_line = func.lbrace_line,
|
||||
.prev_di_column = func.lbrace_column,
|
||||
};
|
||||
defer emit.deinit();
|
||||
|
||||
@ -1627,13 +1628,15 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
}
|
||||
|
||||
fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const arg = self.air.instructions.items(.data)[inst].arg;
|
||||
const ty = self.air.getRefType(arg.ty);
|
||||
const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);
|
||||
const owner_decl = mod.funcOwnerDeclIndex(self.func_index);
|
||||
const name = mod.getParamName(self.func_index, arg.src_index);
|
||||
|
||||
switch (self.debug_output) {
|
||||
.dwarf => |dw| switch (mcv) {
|
||||
.register => |reg| try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, .{
|
||||
.register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{
|
||||
.register = reg.dwarfLocOp(),
|
||||
}),
|
||||
.stack_offset => {},
|
||||
@ -1742,24 +1745,28 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
}
|
||||
|
||||
if (try self.air.value(callee, mod)) |func_value| {
|
||||
if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
|
||||
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
||||
const atom = elf_file.getAtom(atom_index);
|
||||
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
|
||||
const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
|
||||
try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });
|
||||
_ = try self.addInst(.{
|
||||
.tag = .jalr,
|
||||
.data = .{ .i_type = .{
|
||||
.rd = .ra,
|
||||
.rs1 = .ra,
|
||||
.imm12 = 0,
|
||||
} },
|
||||
});
|
||||
} else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
|
||||
return self.fail("TODO implement calling extern functions", .{});
|
||||
} else {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
|
||||
.func => |func| {
|
||||
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
||||
const atom = elf_file.getAtom(atom_index);
|
||||
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
|
||||
const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
|
||||
try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });
|
||||
_ = try self.addInst(.{
|
||||
.tag = .jalr,
|
||||
.data = .{ .i_type = .{
|
||||
.rd = .ra,
|
||||
.rs1 = .ra,
|
||||
.imm12 = 0,
|
||||
} },
|
||||
});
|
||||
},
|
||||
.extern_func => {
|
||||
return self.fail("TODO implement calling extern functions", .{});
|
||||
},
|
||||
else => {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
},
|
||||
}
|
||||
} else {
|
||||
return self.fail("TODO implement calling runtime-known function pointer", .{});
|
||||
@ -1876,9 +1883,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const function = mod.funcPtr(ty_fn.func);
|
||||
const func = mod.funcInfo(ty_fn.func);
|
||||
// TODO emit debug info for function change
|
||||
_ = function;
|
||||
_ = func;
|
||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
||||
}
|
||||
|
||||
@ -2569,11 +2576,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
|
||||
}
|
||||
|
||||
fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const mcv: MCValue = switch (try codegen.genTypedValue(
|
||||
self.bin_file,
|
||||
self.src_loc,
|
||||
typed_value,
|
||||
self.mod_fn.owner_decl,
|
||||
mod.funcOwnerDeclIndex(self.func_index),
|
||||
)) {
|
||||
.mcv => |mcv| switch (mcv) {
|
||||
.none => .none,
|
||||
@ -2605,6 +2613,7 @@ const CallMCValues = struct {
|
||||
/// Caller must call `CallMCValues.deinit`.
|
||||
fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const ip = &mod.intern_pool;
|
||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||
const cc = fn_info.cc;
|
||||
var result: CallMCValues = .{
|
||||
@ -2636,14 +2645,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
var next_stack_offset: u32 = 0;
|
||||
const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };
|
||||
|
||||
for (fn_info.param_types, 0..) |ty, i| {
|
||||
for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
|
||||
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||
if (param_size <= 8) {
|
||||
if (next_register < argument_registers.len) {
|
||||
result.args[i] = .{ .register = argument_registers[next_register] };
|
||||
result_arg.* = .{ .register = argument_registers[next_register] };
|
||||
next_register += 1;
|
||||
} else {
|
||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
||||
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||
next_register += next_stack_offset;
|
||||
}
|
||||
} else if (param_size <= 16) {
|
||||
@ -2652,11 +2661,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||
} else if (next_register < argument_registers.len) {
|
||||
return self.fail("TODO MCValues split register + stack", .{});
|
||||
} else {
|
||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
||||
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||
next_register += next_stack_offset;
|
||||
}
|
||||
} else {
|
||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
||||
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||
next_register += next_stack_offset;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ const Allocator = mem.Allocator;
|
||||
const builtin = @import("builtin");
|
||||
const link = @import("../../link.zig");
|
||||
const Module = @import("../../Module.zig");
|
||||
const InternPool = @import("../../InternPool.zig");
|
||||
const TypedValue = @import("../../TypedValue.zig");
|
||||
const ErrorMsg = Module.ErrorMsg;
|
||||
const codegen = @import("../../codegen.zig");
|
||||
@ -52,7 +53,7 @@ air: Air,
|
||||
liveness: Liveness,
|
||||
bin_file: *link.File,
|
||||
target: *const std.Target,
|
||||
mod_fn: *const Module.Fn,
|
||||
func_index: InternPool.Index,
|
||||
code: *std.ArrayList(u8),
|
||||
debug_output: DebugInfoOutput,
|
||||
err_msg: ?*ErrorMsg,
|
||||
@ -260,7 +261,7 @@ const BigTomb = struct {
|
||||
pub fn generate(
|
||||
bin_file: *link.File,
|
||||
src_loc: Module.SrcLoc,
|
||||
module_fn_index: Module.Fn.Index,
|
||||
func_index: InternPool.Index,
|
||||
air: Air,
|
||||
liveness: Liveness,
|
||||
code: *std.ArrayList(u8),
|
||||
@ -271,8 +272,8 @@ pub fn generate(
|
||||
}
|
||||
|
||||
const mod = bin_file.options.module.?;
|
||||
const module_fn = mod.funcPtr(module_fn_index);
|
||||
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
|
||||
const func = mod.funcInfo(func_index);
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
assert(fn_owner_decl.has_tv);
|
||||
const fn_type = fn_owner_decl.ty;
|
||||
|
||||
@ -289,8 +290,8 @@ pub fn generate(
|
||||
.air = air,
|
||||
.liveness = liveness,
|
||||
.target = &bin_file.options.target,
|
||||
.func_index = func_index,
|
||||
.bin_file = bin_file,
|
||||
.mod_fn = module_fn,
|
||||
.code = code,
|
||||
.debug_output = debug_output,
|
||||
.err_msg = null,
|
||||
@ -301,8 +302,8 @@ pub fn generate(
|
||||
.branch_stack = &branch_stack,
|
||||
.src_loc = src_loc,
|
||||
.stack_align = undefined,
|
||||
.end_di_line = module_fn.rbrace_line,
|
||||
.end_di_column = module_fn.rbrace_column,
|
||||
.end_di_line = func.rbrace_line,
|
||||
.end_di_column = func.rbrace_column,
|
||||
};
|
||||
defer function.stack.deinit(bin_file.allocator);
|
||||
defer function.blocks.deinit(bin_file.allocator);
|
||||
@ -344,8 +345,8 @@ pub fn generate(
|
||||
.src_loc = src_loc,
|
||||
.code = code,
|
||||
.prev_di_pc = 0,
|
||||
.prev_di_line = module_fn.lbrace_line,
|
||||
.prev_di_column = module_fn.lbrace_column,
|
||||
.prev_di_line = func.lbrace_line,
|
||||
.prev_di_column = func.lbrace_column,
|
||||
};
|
||||
defer emit.deinit();
|
||||
|
||||
@ -1345,37 +1346,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
// on linking.
|
||||
if (try self.air.value(callee, mod)) |func_value| {
|
||||
if (self.bin_file.tag == link.File.Elf.base_tag) {
|
||||
if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
|
||||
const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
|
||||
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
||||
const atom = elf_file.getAtom(atom_index);
|
||||
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
|
||||
break :blk @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
|
||||
} else unreachable;
|
||||
switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
|
||||
.func => |func| {
|
||||
const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
|
||||
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
||||
const atom = elf_file.getAtom(atom_index);
|
||||
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
|
||||
break :blk @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
|
||||
} else unreachable;
|
||||
|
||||
try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr });
|
||||
try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr });
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .jmpl,
|
||||
.data = .{
|
||||
.arithmetic_3op = .{
|
||||
.is_imm = false,
|
||||
.rd = .o7,
|
||||
.rs1 = .o7,
|
||||
.rs2_or_imm = .{ .rs2 = .g0 },
|
||||
_ = try self.addInst(.{
|
||||
.tag = .jmpl,
|
||||
.data = .{
|
||||
.arithmetic_3op = .{
|
||||
.is_imm = false,
|
||||
.rd = .o7,
|
||||
.rs1 = .o7,
|
||||
.rs2_or_imm = .{ .rs2 = .g0 },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// TODO Find a way to fill this delay slot
|
||||
_ = try self.addInst(.{
|
||||
.tag = .nop,
|
||||
.data = .{ .nop = {} },
|
||||
});
|
||||
} else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
|
||||
return self.fail("TODO implement calling extern functions", .{});
|
||||
} else {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
// TODO Find a way to fill this delay slot
|
||||
_ = try self.addInst(.{
|
||||
.tag = .nop,
|
||||
.data = .{ .nop = {} },
|
||||
});
|
||||
},
|
||||
.extern_func => {
|
||||
return self.fail("TODO implement calling extern functions", .{});
|
||||
},
|
||||
else => {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
},
|
||||
}
|
||||
} else @panic("TODO SPARCv9 currently does not support non-ELF binaries");
|
||||
} else {
|
||||
@ -1660,9 +1665,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const function = mod.funcPtr(ty_fn.func);
|
||||
const func = mod.funcInfo(ty_fn.func);
|
||||
// TODO emit debug info for function change
|
||||
_ = function;
|
||||
_ = func;
|
||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
||||
}
|
||||
|
||||
@ -3595,13 +3600,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
|
||||
}
|
||||
|
||||
fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const arg = self.air.instructions.items(.data)[inst].arg;
|
||||
const ty = self.air.getRefType(arg.ty);
|
||||
const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);
|
||||
const owner_decl = mod.funcOwnerDeclIndex(self.func_index);
|
||||
const name = mod.getParamName(self.func_index, arg.src_index);
|
||||
|
||||
switch (self.debug_output) {
|
||||
.dwarf => |dw| switch (mcv) {
|
||||
.register => |reg| try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, .{
|
||||
.register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{
|
||||
.register = reg.dwarfLocOp(),
|
||||
}),
|
||||
else => {},
|
||||
@ -4127,11 +4134,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re
|
||||
}
|
||||
|
||||
fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const mcv: MCValue = switch (try codegen.genTypedValue(
|
||||
self.bin_file,
|
||||
self.src_loc,
|
||||
typed_value,
|
||||
self.mod_fn.owner_decl,
|
||||
mod.funcOwnerDeclIndex(self.func_index),
|
||||
)) {
|
||||
.mcv => |mcv| switch (mcv) {
|
||||
.none => .none,
|
||||
@ -4452,6 +4460,7 @@ fn realStackOffset(off: u32) u32 {
|
||||
/// Caller must call `CallMCValues.deinit`.
|
||||
fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const ip = &mod.intern_pool;
|
||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||
const cc = fn_info.cc;
|
||||
var result: CallMCValues = .{
|
||||
@ -4486,14 +4495,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
|
||||
.callee => abi.c_abi_int_param_regs_callee_view,
|
||||
};
|
||||
|
||||
for (fn_info.param_types, 0..) |ty, i| {
|
||||
for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
|
||||
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||
if (param_size <= 8) {
|
||||
if (next_register < argument_registers.len) {
|
||||
result.args[i] = .{ .register = argument_registers[next_register] };
|
||||
result_arg.* = .{ .register = argument_registers[next_register] };
|
||||
next_register += 1;
|
||||
} else {
|
||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
||||
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||
next_register += next_stack_offset;
|
||||
}
|
||||
} else if (param_size <= 16) {
|
||||
@ -4502,11 +4511,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
|
||||
} else if (next_register < argument_registers.len) {
|
||||
return self.fail("TODO MCValues split register + stack", .{});
|
||||
} else {
|
||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
||||
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||
next_register += next_stack_offset;
|
||||
}
|
||||
} else {
|
||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
||||
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||
next_register += next_stack_offset;
|
||||
}
|
||||
}
|
||||
|
||||
@ -650,7 +650,7 @@ air: Air,
|
||||
liveness: Liveness,
|
||||
gpa: mem.Allocator,
|
||||
debug_output: codegen.DebugInfoOutput,
|
||||
mod_fn: *const Module.Fn,
|
||||
func_index: InternPool.Index,
|
||||
/// Contains a list of current branches.
|
||||
/// When we return from a branch, the branch will be popped from this list,
|
||||
/// which means branches can only contain references from within its own branch,
|
||||
@ -1202,7 +1202,7 @@ fn genFunctype(
|
||||
pub fn generate(
|
||||
bin_file: *link.File,
|
||||
src_loc: Module.SrcLoc,
|
||||
func_index: Module.Fn.Index,
|
||||
func_index: InternPool.Index,
|
||||
air: Air,
|
||||
liveness: Liveness,
|
||||
code: *std.ArrayList(u8),
|
||||
@ -1210,7 +1210,7 @@ pub fn generate(
|
||||
) codegen.CodeGenError!codegen.Result {
|
||||
_ = src_loc;
|
||||
const mod = bin_file.options.module.?;
|
||||
const func = mod.funcPtr(func_index);
|
||||
const func = mod.funcInfo(func_index);
|
||||
var code_gen: CodeGen = .{
|
||||
.gpa = bin_file.allocator,
|
||||
.air = air,
|
||||
@ -1223,7 +1223,7 @@ pub fn generate(
|
||||
.target = bin_file.options.target,
|
||||
.bin_file = bin_file.cast(link.File.Wasm).?,
|
||||
.debug_output = debug_output,
|
||||
.mod_fn = func,
|
||||
.func_index = func_index,
|
||||
};
|
||||
defer code_gen.deinit();
|
||||
|
||||
@ -1237,8 +1237,9 @@ pub fn generate(
|
||||
|
||||
fn genFunc(func: *CodeGen) InnerError!void {
|
||||
const mod = func.bin_file.base.options.module.?;
|
||||
const ip = &mod.intern_pool;
|
||||
const fn_info = mod.typeToFunc(func.decl.ty).?;
|
||||
var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);
|
||||
var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), fn_info.return_type.toType(), mod);
|
||||
defer func_type.deinit(func.gpa);
|
||||
_ = try func.bin_file.storeDeclType(func.decl_index, func_type);
|
||||
|
||||
@ -1347,6 +1348,7 @@ const CallWValues = struct {
|
||||
|
||||
fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {
|
||||
const mod = func.bin_file.base.options.module.?;
|
||||
const ip = &mod.intern_pool;
|
||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||
const cc = fn_info.cc;
|
||||
var result: CallWValues = .{
|
||||
@ -1369,7 +1371,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
|
||||
|
||||
switch (cc) {
|
||||
.Unspecified => {
|
||||
for (fn_info.param_types) |ty| {
|
||||
for (fn_info.param_types.get(ip)) |ty| {
|
||||
if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
continue;
|
||||
}
|
||||
@ -1379,7 +1381,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
|
||||
}
|
||||
},
|
||||
.C => {
|
||||
for (fn_info.param_types) |ty| {
|
||||
for (fn_info.param_types.get(ip)) |ty| {
|
||||
const ty_classes = abi.classifyType(ty.toType(), mod);
|
||||
for (ty_classes) |class| {
|
||||
if (class == .none) continue;
|
||||
@ -2185,6 +2187,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
|
||||
const ty = func.typeOf(pl_op.operand);
|
||||
|
||||
const mod = func.bin_file.base.options.module.?;
|
||||
const ip = &mod.intern_pool;
|
||||
const fn_ty = switch (ty.zigTypeTag(mod)) {
|
||||
.Fn => ty,
|
||||
.Pointer => ty.childType(mod),
|
||||
@ -2203,7 +2206,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
|
||||
} else if (func_val.getExternFunc(mod)) |extern_func| {
|
||||
const ext_decl = mod.declPtr(extern_func.decl);
|
||||
const ext_info = mod.typeToFunc(ext_decl.ty).?;
|
||||
var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod);
|
||||
var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types.get(ip), ext_info.return_type.toType(), mod);
|
||||
defer func_type.deinit(func.gpa);
|
||||
const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);
|
||||
const atom = func.bin_file.getAtomPtr(atom_index);
|
||||
@ -2253,7 +2256,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
|
||||
const operand = try func.resolveInst(pl_op.operand);
|
||||
try func.emitWValue(operand);
|
||||
|
||||
var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);
|
||||
var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), fn_info.return_type.toType(), mod);
|
||||
defer fn_type.deinit(func.gpa);
|
||||
|
||||
const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type);
|
||||
@ -2564,8 +2567,8 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
switch (func.debug_output) {
|
||||
.dwarf => |dwarf| {
|
||||
const src_index = func.air.instructions.items(.data)[inst].arg.src_index;
|
||||
const name = func.mod_fn.getParamName(func.bin_file.base.options.module.?, src_index);
|
||||
try dwarf.genArgDbgInfo(name, arg_ty, func.mod_fn.owner_decl, .{
|
||||
const name = mod.getParamName(func.func_index, src_index);
|
||||
try dwarf.genArgDbgInfo(name, arg_ty, mod.funcOwnerDeclIndex(func.func_index), .{
|
||||
.wasm_local = arg.local.value,
|
||||
});
|
||||
},
|
||||
@ -6198,6 +6201,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
|
||||
if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
|
||||
|
||||
const mod = func.bin_file.base.options.module.?;
|
||||
const pl_op = func.air.instructions.items(.data)[inst].pl_op;
|
||||
const ty = func.typeOf(pl_op.operand);
|
||||
const operand = try func.resolveInst(pl_op.operand);
|
||||
@ -6214,7 +6218,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
|
||||
break :blk .nop;
|
||||
},
|
||||
};
|
||||
try func.debug_output.dwarf.genVarDbgInfo(name, ty, func.mod_fn.owner_decl, is_ptr, loc);
|
||||
try func.debug_output.dwarf.genVarDbgInfo(name, ty, mod.funcOwnerDeclIndex(func.func_index), is_ptr, loc);
|
||||
|
||||
func.finishAir(inst, .none, &.{});
|
||||
}
|
||||
|
||||
@ -110,20 +110,21 @@ const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
|
||||
const RegisterOffset = struct { reg: Register, off: i32 = 0 };
|
||||
|
||||
const Owner = union(enum) {
|
||||
mod_fn: *const Module.Fn,
|
||||
func_index: InternPool.Index,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
|
||||
fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index {
|
||||
return switch (owner) {
|
||||
.mod_fn => |mod_fn| mod_fn.owner_decl,
|
||||
.func_index => |func_index| mod.funcOwnerDeclIndex(func_index),
|
||||
.lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(mod),
|
||||
};
|
||||
}
|
||||
|
||||
fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 {
|
||||
switch (owner) {
|
||||
.mod_fn => |mod_fn| {
|
||||
const decl_index = mod_fn.owner_decl;
|
||||
.func_index => |func_index| {
|
||||
const mod = ctx.bin_file.options.module.?;
|
||||
const decl_index = mod.funcOwnerDeclIndex(func_index);
|
||||
if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
|
||||
return macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
@ -638,7 +639,7 @@ const Self = @This();
|
||||
pub fn generate(
|
||||
bin_file: *link.File,
|
||||
src_loc: Module.SrcLoc,
|
||||
module_fn_index: Module.Fn.Index,
|
||||
func_index: InternPool.Index,
|
||||
air: Air,
|
||||
liveness: Liveness,
|
||||
code: *std.ArrayList(u8),
|
||||
@ -649,8 +650,8 @@ pub fn generate(
|
||||
}
|
||||
|
||||
const mod = bin_file.options.module.?;
|
||||
const module_fn = mod.funcPtr(module_fn_index);
|
||||
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
|
||||
const func = mod.funcInfo(func_index);
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
assert(fn_owner_decl.has_tv);
|
||||
const fn_type = fn_owner_decl.ty;
|
||||
|
||||
@ -662,15 +663,15 @@ pub fn generate(
|
||||
.target = &bin_file.options.target,
|
||||
.bin_file = bin_file,
|
||||
.debug_output = debug_output,
|
||||
.owner = .{ .mod_fn = module_fn },
|
||||
.owner = .{ .func_index = func_index },
|
||||
.err_msg = null,
|
||||
.args = undefined, // populated after `resolveCallingConventionValues`
|
||||
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
|
||||
.fn_type = fn_type,
|
||||
.arg_index = 0,
|
||||
.src_loc = src_loc,
|
||||
.end_di_line = module_fn.rbrace_line,
|
||||
.end_di_column = module_fn.rbrace_column,
|
||||
.end_di_line = func.rbrace_line,
|
||||
.end_di_column = func.rbrace_column,
|
||||
};
|
||||
defer {
|
||||
function.frame_allocs.deinit(gpa);
|
||||
@ -687,17 +688,16 @@ pub fn generate(
|
||||
if (builtin.mode == .Debug) function.mir_to_air_map.deinit(gpa);
|
||||
}
|
||||
|
||||
wip_mir_log.debug("{}:", .{function.fmtDecl(module_fn.owner_decl)});
|
||||
wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)});
|
||||
|
||||
const ip = &mod.intern_pool;
|
||||
|
||||
try function.frame_allocs.resize(gpa, FrameIndex.named_count);
|
||||
function.frame_allocs.set(
|
||||
@intFromEnum(FrameIndex.stack_frame),
|
||||
FrameAlloc.init(.{
|
||||
.size = 0,
|
||||
.alignment = if (mod.align_stack_fns.get(module_fn_index)) |set_align_stack|
|
||||
@intCast(set_align_stack.alignment.toByteUnitsOptional().?)
|
||||
else
|
||||
1,
|
||||
.alignment = @intCast(func.analysis(ip).stack_alignment.toByteUnitsOptional() orelse 1),
|
||||
}),
|
||||
);
|
||||
function.frame_allocs.set(
|
||||
@ -761,8 +761,8 @@ pub fn generate(
|
||||
.debug_output = debug_output,
|
||||
.code = code,
|
||||
.prev_di_pc = 0,
|
||||
.prev_di_line = module_fn.lbrace_line,
|
||||
.prev_di_column = module_fn.lbrace_column,
|
||||
.prev_di_line = func.lbrace_line,
|
||||
.prev_di_column = func.lbrace_column,
|
||||
};
|
||||
defer emit.deinit();
|
||||
emit.emitMir() catch |err| switch (err) {
|
||||
@ -7942,7 +7942,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
|
||||
|
||||
const ty = self.typeOfIndex(inst);
|
||||
const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
|
||||
const name = self.owner.mod_fn.getParamName(mod, src_index);
|
||||
const name = mod.getParamName(self.owner.func_index, src_index);
|
||||
try self.genArgDbgInfo(ty, name, dst_mcv);
|
||||
|
||||
break :result dst_mcv;
|
||||
@ -8139,7 +8139,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
if (try self.air.value(callee, mod)) |func_value| {
|
||||
const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
|
||||
if (switch (func_key) {
|
||||
.func => |func| mod.funcPtr(func.index).owner_decl,
|
||||
.func => |func| func.owner_decl,
|
||||
.ptr => |ptr| switch (ptr.addr) {
|
||||
.decl => |decl| decl,
|
||||
else => null,
|
||||
@ -8582,9 +8582,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const function = mod.funcPtr(ty_fn.func);
|
||||
const func = mod.funcInfo(ty_fn.func);
|
||||
// TODO emit debug info for function change
|
||||
_ = function;
|
||||
_ = func;
|
||||
return self.finishAir(inst, .unreach, .{ .none, .none, .none });
|
||||
}
|
||||
|
||||
@ -11719,11 +11719,12 @@ fn resolveCallingConventionValues(
|
||||
stack_frame_base: FrameIndex,
|
||||
) !CallMCValues {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const ip = &mod.intern_pool;
|
||||
const cc = fn_info.cc;
|
||||
const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
|
||||
defer self.gpa.free(param_types);
|
||||
|
||||
for (param_types[0..fn_info.param_types.len], fn_info.param_types) |*dest, src| {
|
||||
for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src| {
|
||||
dest.* = src.toType();
|
||||
}
|
||||
// TODO: promote var arg types
|
||||
|
||||
@ -67,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {
|
||||
pub fn generateFunction(
|
||||
bin_file: *link.File,
|
||||
src_loc: Module.SrcLoc,
|
||||
func_index: Module.Fn.Index,
|
||||
func_index: InternPool.Index,
|
||||
air: Air,
|
||||
liveness: Liveness,
|
||||
code: *std.ArrayList(u8),
|
||||
|
||||
@ -257,7 +257,8 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
|
||||
return .{ .data = ident };
|
||||
}
|
||||
|
||||
/// This data is available when outputting .c code for a `Module.Fn.Index`.
|
||||
/// This data is available when outputting .c code for a `InternPool.Index`
|
||||
/// that corresponds to `func`.
|
||||
/// It is not available when generating .h file.
|
||||
pub const Function = struct {
|
||||
air: Air,
|
||||
@ -268,7 +269,7 @@ pub const Function = struct {
|
||||
next_block_index: usize = 0,
|
||||
object: Object,
|
||||
lazy_fns: LazyFnMap,
|
||||
func_index: Module.Fn.Index,
|
||||
func_index: InternPool.Index,
|
||||
/// All the locals, to be emitted at the top of the function.
|
||||
locals: std.ArrayListUnmanaged(Local) = .{},
|
||||
/// Which locals are available for reuse, based on Type.
|
||||
@ -1487,6 +1488,7 @@ pub const DeclGen = struct {
|
||||
) !void {
|
||||
const store = &dg.ctypes.set;
|
||||
const mod = dg.module;
|
||||
const ip = &mod.intern_pool;
|
||||
|
||||
const fn_decl = mod.declPtr(fn_decl_index);
|
||||
const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);
|
||||
@ -1499,7 +1501,7 @@ pub const DeclGen = struct {
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
if (fn_decl.val.getFunction(mod)) |func| if (func.is_cold) try w.writeAll("zig_cold ");
|
||||
if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold) try w.writeAll("zig_cold ");
|
||||
if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
|
||||
|
||||
const trailing = try renderTypePrefix(
|
||||
@ -1744,7 +1746,7 @@ pub const DeclGen = struct {
|
||||
return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
|
||||
.variable => |variable| mod.decl_exports.contains(variable.decl),
|
||||
.extern_func => true,
|
||||
.func => |func| mod.decl_exports.contains(mod.funcPtr(func.index).owner_decl),
|
||||
.func => |func| mod.decl_exports.contains(func.owner_decl),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
@ -1800,7 +1802,12 @@ pub const DeclGen = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn writeCValueMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
|
||||
fn writeCValueMember(
|
||||
dg: *DeclGen,
|
||||
writer: anytype,
|
||||
c_value: CValue,
|
||||
member: CValue,
|
||||
) error{ OutOfMemory, AnalysisFail }!void {
|
||||
try dg.writeCValue(writer, c_value);
|
||||
try writer.writeByte('.');
|
||||
try dg.writeCValue(writer, member);
|
||||
@ -4161,7 +4168,7 @@ fn airCall(
|
||||
const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
|
||||
break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
|
||||
.extern_func => |extern_func| extern_func.decl,
|
||||
.func => |func| mod.funcPtr(func.index).owner_decl,
|
||||
.func => |func| func.owner_decl,
|
||||
.ptr => |ptr| switch (ptr.addr) {
|
||||
.decl => |decl| decl,
|
||||
else => break :known,
|
||||
@ -4238,9 +4245,9 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const ty_fn = f.air.instructions.items(.data)[inst].ty_fn;
|
||||
const mod = f.object.dg.module;
|
||||
const writer = f.object.writer();
|
||||
const function = mod.funcPtr(ty_fn.func);
|
||||
const owner_decl = mod.funcOwnerDeclPtr(ty_fn.func);
|
||||
try writer.print("/* dbg func:{s} */\n", .{
|
||||
mod.intern_pool.stringToSlice(mod.declPtr(function.owner_decl).name),
|
||||
mod.intern_pool.stringToSlice(owner_decl.name),
|
||||
});
|
||||
return .none;
|
||||
}
|
||||
|
||||
@ -1722,6 +1722,7 @@ pub const CType = extern union {
|
||||
|
||||
.Fn => {
|
||||
const info = mod.typeToFunc(ty).?;
|
||||
const ip = &mod.intern_pool;
|
||||
if (!info.is_generic) {
|
||||
if (lookup.isMutable()) {
|
||||
const param_kind: Kind = switch (kind) {
|
||||
@ -1730,7 +1731,7 @@ pub const CType = extern union {
|
||||
.payload => unreachable,
|
||||
};
|
||||
_ = try lookup.typeToIndex(info.return_type.toType(), param_kind);
|
||||
for (info.param_types) |param_type| {
|
||||
for (info.param_types.get(ip)) |param_type| {
|
||||
if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||
_ = try lookup.typeToIndex(param_type.toType(), param_kind);
|
||||
}
|
||||
@ -2014,6 +2015,7 @@ pub const CType = extern union {
|
||||
.function,
|
||||
.varargs_function,
|
||||
=> {
|
||||
const ip = &mod.intern_pool;
|
||||
const info = mod.typeToFunc(ty).?;
|
||||
assert(!info.is_generic);
|
||||
const param_kind: Kind = switch (kind) {
|
||||
@ -2023,14 +2025,14 @@ pub const CType = extern union {
|
||||
};
|
||||
|
||||
var c_params_len: usize = 0;
|
||||
for (info.param_types) |param_type| {
|
||||
for (info.param_types.get(ip)) |param_type| {
|
||||
if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||
c_params_len += 1;
|
||||
}
|
||||
|
||||
const params_pl = try arena.alloc(Index, c_params_len);
|
||||
var c_param_i: usize = 0;
|
||||
for (info.param_types) |param_type| {
|
||||
for (info.param_types.get(ip)) |param_type| {
|
||||
if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||
params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;
|
||||
c_param_i += 1;
|
||||
@ -2147,6 +2149,7 @@ pub const CType = extern union {
|
||||
=> {
|
||||
if (ty.zigTypeTag(mod) != .Fn) return false;
|
||||
|
||||
const ip = &mod.intern_pool;
|
||||
const info = mod.typeToFunc(ty).?;
|
||||
assert(!info.is_generic);
|
||||
const data = cty.cast(Payload.Function).?.data;
|
||||
@ -2160,7 +2163,7 @@ pub const CType = extern union {
|
||||
return false;
|
||||
|
||||
var c_param_i: usize = 0;
|
||||
for (info.param_types) |param_type| {
|
||||
for (info.param_types.get(ip)) |param_type| {
|
||||
if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||
|
||||
if (c_param_i >= data.param_types.len) return false;
|
||||
@ -2202,6 +2205,7 @@ pub const CType = extern union {
|
||||
autoHash(hasher, t);
|
||||
|
||||
const mod = self.lookup.getModule();
|
||||
const ip = &mod.intern_pool;
|
||||
switch (t) {
|
||||
.fwd_anon_struct,
|
||||
.fwd_anon_union,
|
||||
@ -2270,7 +2274,7 @@ pub const CType = extern union {
|
||||
};
|
||||
|
||||
self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind);
|
||||
for (info.param_types) |param_type| {
|
||||
for (info.param_types.get(ip)) |param_type| {
|
||||
if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||
self.updateHasherRecurse(hasher, param_type.toType(), param_kind);
|
||||
}
|
||||
|
||||
@ -867,14 +867,15 @@ pub const Object = struct {
|
||||
pub fn updateFunc(
|
||||
o: *Object,
|
||||
mod: *Module,
|
||||
func_index: Module.Fn.Index,
|
||||
func_index: InternPool.Index,
|
||||
air: Air,
|
||||
liveness: Liveness,
|
||||
) !void {
|
||||
const func = mod.funcPtr(func_index);
|
||||
const func = mod.funcInfo(func_index);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const target = mod.getTarget();
|
||||
const ip = &mod.intern_pool;
|
||||
|
||||
var dg: DeclGen = .{
|
||||
.object = o,
|
||||
@ -885,26 +886,25 @@ pub const Object = struct {
|
||||
|
||||
const llvm_func = try o.resolveLlvmFunction(decl_index);
|
||||
|
||||
if (mod.align_stack_fns.get(func_index)) |align_info| {
|
||||
o.addFnAttrInt(llvm_func, "alignstack", align_info.alignment.toByteUnitsOptional().?);
|
||||
o.addFnAttr(llvm_func, "noinline");
|
||||
} else {
|
||||
Object.removeFnAttr(llvm_func, "alignstack");
|
||||
if (!func.is_noinline) Object.removeFnAttr(llvm_func, "noinline");
|
||||
}
|
||||
|
||||
if (func.is_cold) {
|
||||
o.addFnAttr(llvm_func, "cold");
|
||||
} else {
|
||||
Object.removeFnAttr(llvm_func, "cold");
|
||||
}
|
||||
|
||||
if (func.is_noinline) {
|
||||
if (func.analysis(ip).is_noinline) {
|
||||
o.addFnAttr(llvm_func, "noinline");
|
||||
} else {
|
||||
Object.removeFnAttr(llvm_func, "noinline");
|
||||
}
|
||||
|
||||
if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| {
|
||||
o.addFnAttrInt(llvm_func, "alignstack", alignment);
|
||||
o.addFnAttr(llvm_func, "noinline");
|
||||
} else {
|
||||
Object.removeFnAttr(llvm_func, "alignstack");
|
||||
}
|
||||
|
||||
if (func.analysis(ip).is_cold) {
|
||||
o.addFnAttr(llvm_func, "cold");
|
||||
} else {
|
||||
Object.removeFnAttr(llvm_func, "cold");
|
||||
}
|
||||
|
||||
// TODO: disable this if safety is off for the function scope
|
||||
const ssp_buf_size = mod.comp.bin_file.options.stack_protector;
|
||||
if (ssp_buf_size != 0) {
|
||||
@ -921,7 +921,7 @@ pub const Object = struct {
|
||||
o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
|
||||
}
|
||||
|
||||
if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
|
||||
if (ip.stringToSliceUnwrap(decl.@"linksection")) |section|
|
||||
llvm_func.setSection(section);
|
||||
|
||||
// Remove all the basic blocks of a function in order to start over, generating
|
||||
@ -968,7 +968,7 @@ pub const Object = struct {
|
||||
.byval => {
|
||||
assert(!it.byval_attr);
|
||||
const param_index = it.zig_index - 1;
|
||||
const param_ty = fn_info.param_types[param_index].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[param_index].toType();
|
||||
const param = llvm_func.getParam(llvm_arg_i);
|
||||
try args.ensureUnusedCapacity(1);
|
||||
|
||||
@ -987,7 +987,7 @@ pub const Object = struct {
|
||||
llvm_arg_i += 1;
|
||||
},
|
||||
.byref => {
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
const param_llvm_ty = try o.lowerType(param_ty);
|
||||
const param = llvm_func.getParam(llvm_arg_i);
|
||||
const alignment = param_ty.abiAlignment(mod);
|
||||
@ -1006,7 +1006,7 @@ pub const Object = struct {
|
||||
}
|
||||
},
|
||||
.byref_mut => {
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
const param_llvm_ty = try o.lowerType(param_ty);
|
||||
const param = llvm_func.getParam(llvm_arg_i);
|
||||
const alignment = param_ty.abiAlignment(mod);
|
||||
@ -1026,7 +1026,7 @@ pub const Object = struct {
|
||||
},
|
||||
.abi_sized_int => {
|
||||
assert(!it.byval_attr);
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
const param = llvm_func.getParam(llvm_arg_i);
|
||||
llvm_arg_i += 1;
|
||||
|
||||
@ -1053,7 +1053,7 @@ pub const Object = struct {
|
||||
},
|
||||
.slice => {
|
||||
assert(!it.byval_attr);
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
const ptr_info = param_ty.ptrInfo(mod);
|
||||
|
||||
if (math.cast(u5, it.zig_index - 1)) |i| {
|
||||
@ -1083,7 +1083,7 @@ pub const Object = struct {
|
||||
.multiple_llvm_types => {
|
||||
assert(!it.byval_attr);
|
||||
const field_types = it.llvm_types_buffer[0..it.llvm_types_len];
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
const param_llvm_ty = try o.lowerType(param_ty);
|
||||
const param_alignment = param_ty.abiAlignment(mod);
|
||||
const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);
|
||||
@ -1114,7 +1114,7 @@ pub const Object = struct {
|
||||
args.appendAssumeCapacity(casted);
|
||||
},
|
||||
.float_array => {
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
const param_llvm_ty = try o.lowerType(param_ty);
|
||||
const param = llvm_func.getParam(llvm_arg_i);
|
||||
llvm_arg_i += 1;
|
||||
@ -1132,7 +1132,7 @@ pub const Object = struct {
|
||||
}
|
||||
},
|
||||
.i32_array, .i64_array => {
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
const param_llvm_ty = try o.lowerType(param_ty);
|
||||
const param = llvm_func.getParam(llvm_arg_i);
|
||||
llvm_arg_i += 1;
|
||||
@ -1168,7 +1168,7 @@ pub const Object = struct {
|
||||
const decl_di_ty = try o.lowerDebugType(decl.ty, .full);
|
||||
const subprogram = dib.createFunction(
|
||||
di_file.?.toScope(),
|
||||
mod.intern_pool.stringToSlice(decl.name),
|
||||
ip.stringToSlice(decl.name),
|
||||
llvm_func.getValueName(),
|
||||
di_file.?,
|
||||
line_number,
|
||||
@ -1460,6 +1460,7 @@ pub const Object = struct {
|
||||
const target = o.target;
|
||||
const dib = o.di_builder.?;
|
||||
const mod = o.module;
|
||||
const ip = &mod.intern_pool;
|
||||
switch (ty.zigTypeTag(mod)) {
|
||||
.Void, .NoReturn => {
|
||||
const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
|
||||
@ -1492,7 +1493,6 @@ pub const Object = struct {
|
||||
return enum_di_ty;
|
||||
}
|
||||
|
||||
const ip = &mod.intern_pool;
|
||||
const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
|
||||
|
||||
const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);
|
||||
@ -1518,7 +1518,7 @@ pub const Object = struct {
|
||||
if (@sizeOf(usize) == @sizeOf(u64)) {
|
||||
enumerators[i] = dib.createEnumerator2(
|
||||
field_name_z,
|
||||
@as(c_uint, @intCast(bigint.limbs.len)),
|
||||
@intCast(bigint.limbs.len),
|
||||
bigint.limbs.ptr,
|
||||
int_info.bits,
|
||||
int_info.signedness == .unsigned,
|
||||
@ -2320,8 +2320,8 @@ pub const Object = struct {
|
||||
try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
|
||||
}
|
||||
|
||||
for (0..mod.typeToFunc(ty).?.param_types.len) |i| {
|
||||
const param_ty = mod.typeToFunc(ty).?.param_types[i].toType();
|
||||
for (0..fn_info.param_types.len) |i| {
|
||||
const param_ty = fn_info.param_types.get(ip)[i].toType();
|
||||
if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||
|
||||
if (isByRef(param_ty, mod)) {
|
||||
@ -2475,9 +2475,10 @@ pub const Object = struct {
|
||||
const fn_type = try o.lowerType(zig_fn_type);
|
||||
|
||||
const fqn = try decl.getFullyQualifiedName(mod);
|
||||
const ip = &mod.intern_pool;
|
||||
|
||||
const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
|
||||
const llvm_fn = o.llvm_module.addFunctionInAddressSpace(mod.intern_pool.stringToSlice(fqn), fn_type, llvm_addrspace);
|
||||
const llvm_fn = o.llvm_module.addFunctionInAddressSpace(ip.stringToSlice(fqn), fn_type, llvm_addrspace);
|
||||
gop.value_ptr.* = llvm_fn;
|
||||
|
||||
const is_extern = decl.isExtern(mod);
|
||||
@ -2486,8 +2487,8 @@ pub const Object = struct {
|
||||
llvm_fn.setUnnamedAddr(.True);
|
||||
} else {
|
||||
if (target.isWasm()) {
|
||||
o.addFnAttrString(llvm_fn, "wasm-import-name", mod.intern_pool.stringToSlice(decl.name));
|
||||
if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
|
||||
o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name));
|
||||
if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
|
||||
if (!std.mem.eql(u8, lib_name, "c")) {
|
||||
o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
|
||||
}
|
||||
@ -2546,13 +2547,13 @@ pub const Object = struct {
|
||||
while (it.next()) |lowering| switch (lowering) {
|
||||
.byval => {
|
||||
const param_index = it.zig_index - 1;
|
||||
const param_ty = fn_info.param_types[param_index].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[param_index].toType();
|
||||
if (!isByRef(param_ty, mod)) {
|
||||
o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
|
||||
}
|
||||
},
|
||||
.byref => {
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1];
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1];
|
||||
const param_llvm_ty = try o.lowerType(param_ty.toType());
|
||||
const alignment = param_ty.toType().abiAlignment(mod);
|
||||
o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
|
||||
@ -3031,6 +3032,7 @@ pub const Object = struct {
|
||||
|
||||
fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type {
|
||||
const mod = o.module;
|
||||
const ip = &mod.intern_pool;
|
||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||
const llvm_ret_ty = try lowerFnRetTy(o, fn_info);
|
||||
|
||||
@ -3052,19 +3054,19 @@ pub const Object = struct {
|
||||
while (it.next()) |lowering| switch (lowering) {
|
||||
.no_bits => continue,
|
||||
.byval => {
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
try llvm_params.append(try o.lowerType(param_ty));
|
||||
},
|
||||
.byref, .byref_mut => {
|
||||
try llvm_params.append(o.context.pointerType(0));
|
||||
},
|
||||
.abi_sized_int => {
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));
|
||||
try llvm_params.append(o.context.intType(abi_size * 8));
|
||||
},
|
||||
.slice => {
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)
|
||||
param_ty.optionalChild(mod).slicePtrFieldType(mod)
|
||||
else
|
||||
@ -3083,7 +3085,7 @@ pub const Object = struct {
|
||||
try llvm_params.append(o.context.intType(16));
|
||||
},
|
||||
.float_array => |count| {
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
|
||||
const field_count = @as(c_uint, @intCast(count));
|
||||
const arr_ty = float_ty.arrayType(field_count);
|
||||
@ -3137,8 +3139,7 @@ pub const Object = struct {
|
||||
return llvm_type.getUndef();
|
||||
}
|
||||
|
||||
const val_key = mod.intern_pool.indexToKey(tv.val.toIntern());
|
||||
switch (val_key) {
|
||||
switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
|
||||
.int_type,
|
||||
.ptr_type,
|
||||
.array_type,
|
||||
@ -3175,12 +3176,14 @@ pub const Object = struct {
|
||||
.enum_literal,
|
||||
.empty_enum_value,
|
||||
=> unreachable, // non-runtime values
|
||||
.extern_func, .func => {
|
||||
const fn_decl_index = switch (val_key) {
|
||||
.extern_func => |extern_func| extern_func.decl,
|
||||
.func => |func| mod.funcPtr(func.index).owner_decl,
|
||||
else => unreachable,
|
||||
};
|
||||
.extern_func => |extern_func| {
|
||||
const fn_decl_index = extern_func.decl;
|
||||
const fn_decl = mod.declPtr(fn_decl_index);
|
||||
try mod.markDeclAlive(fn_decl);
|
||||
return o.resolveLlvmFunction(fn_decl_index);
|
||||
},
|
||||
.func => |func| {
|
||||
const fn_decl_index = func.owner_decl;
|
||||
const fn_decl = mod.declPtr(fn_decl_index);
|
||||
try mod.markDeclAlive(fn_decl);
|
||||
return o.resolveLlvmFunction(fn_decl_index);
|
||||
@ -4598,6 +4601,7 @@ pub const FuncGen = struct {
|
||||
const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]));
|
||||
const o = self.dg.object;
|
||||
const mod = o.module;
|
||||
const ip = &mod.intern_pool;
|
||||
const callee_ty = self.typeOf(pl_op.operand);
|
||||
const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
|
||||
.Fn => callee_ty,
|
||||
@ -4801,14 +4805,14 @@ pub const FuncGen = struct {
|
||||
while (it.next()) |lowering| switch (lowering) {
|
||||
.byval => {
|
||||
const param_index = it.zig_index - 1;
|
||||
const param_ty = fn_info.param_types[param_index].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[param_index].toType();
|
||||
if (!isByRef(param_ty, mod)) {
|
||||
o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
|
||||
}
|
||||
},
|
||||
.byref => {
|
||||
const param_index = it.zig_index - 1;
|
||||
const param_ty = fn_info.param_types[param_index].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[param_index].toType();
|
||||
const param_llvm_ty = try o.lowerType(param_ty);
|
||||
const alignment = param_ty.abiAlignment(mod);
|
||||
o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
|
||||
@ -4828,7 +4832,7 @@ pub const FuncGen = struct {
|
||||
|
||||
.slice => {
|
||||
assert(!it.byval_attr);
|
||||
const param_ty = fn_info.param_types[it.zig_index - 1].toType();
|
||||
const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
|
||||
const ptr_info = param_ty.ptrInfo(mod);
|
||||
const llvm_arg_i = it.llvm_index - 2;
|
||||
|
||||
@ -4930,7 +4934,7 @@ pub const FuncGen = struct {
|
||||
fg.context.pointerType(0).constNull(),
|
||||
null_opt_addr_global,
|
||||
};
|
||||
const panic_func = mod.funcPtrUnwrap(mod.panic_func_index).?;
|
||||
const panic_func = mod.funcInfo(mod.panic_func_index);
|
||||
const panic_decl = mod.declPtr(panic_func.owner_decl);
|
||||
const fn_info = mod.typeToFunc(panic_decl.ty).?;
|
||||
const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl);
|
||||
@ -6030,7 +6034,7 @@ pub const FuncGen = struct {
|
||||
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||
|
||||
const mod = o.module;
|
||||
const func = mod.funcPtr(ty_fn.func);
|
||||
const func = mod.funcInfo(ty_fn.func);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
|
||||
@ -6039,7 +6043,7 @@ pub const FuncGen = struct {
|
||||
const cur_debug_location = self.builder.getCurrentDebugLocation2();
|
||||
|
||||
try self.dbg_inlined.append(self.gpa, .{
|
||||
.loc = @as(*llvm.DILocation, @ptrCast(cur_debug_location)),
|
||||
.loc = @ptrCast(cur_debug_location),
|
||||
.scope = self.di_scope.?,
|
||||
.base_line = self.base_line,
|
||||
});
|
||||
@ -6057,8 +6061,6 @@ pub const FuncGen = struct {
|
||||
.is_var_args = false,
|
||||
.is_generic = false,
|
||||
.is_noinline = false,
|
||||
.align_is_generic = false,
|
||||
.cc_is_generic = false,
|
||||
.section_is_generic = false,
|
||||
.addrspace_is_generic = false,
|
||||
});
|
||||
@ -6090,8 +6092,7 @@ pub const FuncGen = struct {
|
||||
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||
|
||||
const mod = o.module;
|
||||
const func = mod.funcPtr(ty_fn.func);
|
||||
const decl = mod.declPtr(func.owner_decl);
|
||||
const decl = mod.funcOwnerDeclPtr(ty_fn.func);
|
||||
const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
|
||||
self.di_file = di_file;
|
||||
const old = self.dbg_inlined.pop();
|
||||
@ -8137,12 +8138,13 @@ pub const FuncGen = struct {
|
||||
}
|
||||
|
||||
const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
|
||||
const func = self.dg.decl.getOwnedFunction(mod).?;
|
||||
const func_index = self.dg.decl.getOwnedFunctionIndex();
|
||||
const func = mod.funcInfo(func_index);
|
||||
const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
|
||||
const lbrace_col = func.lbrace_column + 1;
|
||||
const di_local_var = dib.createParameterVariable(
|
||||
self.di_scope.?,
|
||||
func.getParamName(mod, src_index).ptr, // TODO test 0 bit args
|
||||
mod.getParamName(func_index, src_index).ptr, // TODO test 0 bit args
|
||||
self.di_file.?,
|
||||
lbrace_line,
|
||||
try o.lowerDebugType(inst_ty, .full),
|
||||
@ -10653,30 +10655,31 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {
|
||||
}
|
||||
|
||||
fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool {
|
||||
if (!fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) return false;
|
||||
const return_type = fn_info.return_type.toType();
|
||||
if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) return false;
|
||||
|
||||
const target = mod.getTarget();
|
||||
switch (fn_info.cc) {
|
||||
.Unspecified, .Inline => return isByRef(fn_info.return_type.toType(), mod),
|
||||
.Unspecified, .Inline => return isByRef(return_type, mod),
|
||||
.C => switch (target.cpu.arch) {
|
||||
.mips, .mipsel => return false,
|
||||
.x86_64 => switch (target.os.tag) {
|
||||
.windows => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
|
||||
else => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
|
||||
.windows => return x86_64_abi.classifyWindows(return_type, mod) == .memory,
|
||||
else => return firstParamSRetSystemV(return_type, mod),
|
||||
},
|
||||
.wasm32 => return wasm_c_abi.classifyType(fn_info.return_type.toType(), mod)[0] == .indirect,
|
||||
.aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory,
|
||||
.arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type.toType(), mod, .ret)) {
|
||||
.wasm32 => return wasm_c_abi.classifyType(return_type, mod)[0] == .indirect,
|
||||
.aarch64, .aarch64_be => return aarch64_c_abi.classifyType(return_type, mod) == .memory,
|
||||
.arm, .armeb => switch (arm_c_abi.classifyType(return_type, mod, .ret)) {
|
||||
.memory, .i64_array => return true,
|
||||
.i32_array => |size| return size != 1,
|
||||
.byval => return false,
|
||||
},
|
||||
.riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory,
|
||||
.riscv32, .riscv64 => return riscv_c_abi.classifyType(return_type, mod) == .memory,
|
||||
else => return false, // TODO investigate C ABI for other architectures
|
||||
},
|
||||
.SysV => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
|
||||
.Win64 => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
|
||||
.Stdcall => return !isScalar(mod, fn_info.return_type.toType()),
|
||||
.SysV => return firstParamSRetSystemV(return_type, mod),
|
||||
.Win64 => return x86_64_abi.classifyWindows(return_type, mod) == .memory,
|
||||
.Stdcall => return !isScalar(mod, return_type),
|
||||
else => return false,
|
||||
}
|
||||
}
|
||||
@ -10888,13 +10891,17 @@ const ParamTypeIterator = struct {
|
||||
|
||||
pub fn next(it: *ParamTypeIterator) ?Lowering {
|
||||
if (it.zig_index >= it.fn_info.param_types.len) return null;
|
||||
const ty = it.fn_info.param_types[it.zig_index];
|
||||
const mod = it.object.module;
|
||||
const ip = &mod.intern_pool;
|
||||
const ty = it.fn_info.param_types.get(ip)[it.zig_index];
|
||||
it.byval_attr = false;
|
||||
return nextInner(it, ty.toType());
|
||||
}
|
||||
|
||||
/// `airCall` uses this instead of `next` so that it can take into account variadic functions.
|
||||
pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) ?Lowering {
|
||||
const mod = it.object.module;
|
||||
const ip = &mod.intern_pool;
|
||||
if (it.zig_index >= it.fn_info.param_types.len) {
|
||||
if (it.zig_index >= args.len) {
|
||||
return null;
|
||||
@ -10902,7 +10909,7 @@ const ParamTypeIterator = struct {
|
||||
return nextInner(it, fg.typeOf(args[it.zig_index]));
|
||||
}
|
||||
} else {
|
||||
return nextInner(it, it.fn_info.param_types[it.zig_index].toType());
|
||||
return nextInner(it, it.fn_info.param_types.get(ip)[it.zig_index].toType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -238,7 +238,7 @@ pub const DeclGen = struct {
|
||||
if (ty.zigTypeTag(mod) == .Fn) {
|
||||
const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
|
||||
.extern_func => |extern_func| extern_func.decl,
|
||||
.func => |func| mod.funcPtr(func.index).owner_decl,
|
||||
.func => |func| func.owner_decl,
|
||||
else => unreachable,
|
||||
};
|
||||
const spv_decl_index = try self.resolveDecl(fn_decl_index);
|
||||
@ -255,13 +255,14 @@ pub const DeclGen = struct {
|
||||
/// Fetch or allocate a result id for decl index. This function also marks the decl as alive.
|
||||
/// Note: Function does not actually generate the decl.
|
||||
fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {
|
||||
const decl = self.module.declPtr(decl_index);
|
||||
try self.module.markDeclAlive(decl);
|
||||
const mod = self.module;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
try mod.markDeclAlive(decl);
|
||||
|
||||
const entry = try self.decl_link.getOrPut(decl_index);
|
||||
if (!entry.found_existing) {
|
||||
// TODO: Extern fn?
|
||||
const kind: SpvModule.DeclKind = if (decl.val.getFunctionIndex(self.module) != .none)
|
||||
const kind: SpvModule.DeclKind = if (decl.val.isFuncBody(mod))
|
||||
.func
|
||||
else
|
||||
.global;
|
||||
@ -1268,6 +1269,7 @@ pub const DeclGen = struct {
|
||||
},
|
||||
.Fn => switch (repr) {
|
||||
.direct => {
|
||||
const ip = &mod.intern_pool;
|
||||
const fn_info = mod.typeToFunc(ty).?;
|
||||
// TODO: Put this somewhere in Sema.zig
|
||||
if (fn_info.is_var_args)
|
||||
@ -1275,8 +1277,8 @@ pub const DeclGen = struct {
|
||||
|
||||
const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len);
|
||||
defer self.gpa.free(param_ty_refs);
|
||||
for (param_ty_refs, 0..) |*param_type, i| {
|
||||
param_type.* = try self.resolveType(fn_info.param_types[i].toType(), .direct);
|
||||
for (param_ty_refs, fn_info.param_types.get(ip)) |*param_type, fn_param_type| {
|
||||
param_type.* = try self.resolveType(fn_param_type.toType(), .direct);
|
||||
}
|
||||
const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct);
|
||||
|
||||
@ -1576,6 +1578,7 @@ pub const DeclGen = struct {
|
||||
|
||||
fn genDecl(self: *DeclGen) !void {
|
||||
const mod = self.module;
|
||||
const ip = &mod.intern_pool;
|
||||
const decl = mod.declPtr(self.decl_index);
|
||||
const spv_decl_index = try self.resolveDecl(self.decl_index);
|
||||
|
||||
@ -1594,7 +1597,8 @@ pub const DeclGen = struct {
|
||||
const fn_info = mod.typeToFunc(decl.ty).?;
|
||||
|
||||
try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);
|
||||
for (fn_info.param_types) |param_type| {
|
||||
for (0..fn_info.param_types.len) |i| {
|
||||
const param_type = fn_info.param_types.get(ip)[i];
|
||||
const param_type_id = try self.resolveTypeId(param_type.toType());
|
||||
const arg_result_id = self.spv.allocId();
|
||||
try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
|
||||
@ -1621,7 +1625,7 @@ pub const DeclGen = struct {
|
||||
try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
|
||||
try self.spv.addFunction(spv_decl_index, self.func);
|
||||
|
||||
const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(self.module));
|
||||
const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module));
|
||||
|
||||
try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{
|
||||
.target = decl_id,
|
||||
|
||||
@ -16,6 +16,7 @@ const Compilation = @import("Compilation.zig");
|
||||
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
|
||||
const Liveness = @import("Liveness.zig");
|
||||
const Module = @import("Module.zig");
|
||||
const InternPool = @import("InternPool.zig");
|
||||
const Package = @import("Package.zig");
|
||||
const Type = @import("type.zig").Type;
|
||||
const TypedValue = @import("TypedValue.zig");
|
||||
@ -562,7 +563,7 @@ pub const File = struct {
|
||||
}
|
||||
|
||||
/// May be called before or after updateDeclExports for any given Decl.
|
||||
pub fn updateFunc(base: *File, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) UpdateDeclError!void {
|
||||
pub fn updateFunc(base: *File, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) UpdateDeclError!void {
|
||||
if (build_options.only_c) {
|
||||
assert(base.tag == .c);
|
||||
return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness);
|
||||
|
||||
@ -88,13 +88,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn updateFunc(self: *C, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
|
||||
pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const gpa = self.base.allocator;
|
||||
|
||||
const func = module.funcPtr(func_index);
|
||||
const func = module.funcInfo(func_index);
|
||||
const decl_index = func.owner_decl;
|
||||
const gop = try self.decl_table.getOrPut(gpa, decl_index);
|
||||
if (!gop.found_existing) {
|
||||
|
||||
@ -1032,7 +1032,7 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {
|
||||
self.getAtomPtr(atom_index).sym_index = 0;
|
||||
}
|
||||
|
||||
pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
|
||||
pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
|
||||
if (build_options.skip_non_native and builtin.object_format != .coff) {
|
||||
@panic("Attempted to compile for object format that was disabled by build configuration");
|
||||
}
|
||||
@ -1044,7 +1044,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: A
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const func = mod.funcPtr(func_index);
|
||||
const func = mod.funcInfo(func_index);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
|
||||
@ -1424,7 +1424,7 @@ pub fn updateDeclExports(
|
||||
// detect the default subsystem.
|
||||
for (exports) |exp| {
|
||||
const exported_decl = mod.declPtr(exp.exported_decl);
|
||||
if (exported_decl.getOwnedFunctionIndex(mod) == .none) continue;
|
||||
if (exported_decl.getOwnedFunction(mod) == null) continue;
|
||||
const winapi_cc = switch (self.base.options.target.cpu.arch) {
|
||||
.x86 => std.builtin.CallingConvention.Stdcall,
|
||||
else => std.builtin.CallingConvention.C,
|
||||
|
||||
@ -1043,6 +1043,7 @@ pub fn commitDeclState(
|
||||
var dbg_line_buffer = &decl_state.dbg_line;
|
||||
var dbg_info_buffer = &decl_state.dbg_info;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const ip = &mod.intern_pool;
|
||||
|
||||
const target_endian = self.target.cpu.arch.endian();
|
||||
|
||||
@ -1241,20 +1242,9 @@ pub fn commitDeclState(
|
||||
while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) {
|
||||
const symbol = &decl_state.abbrev_table.items[sym_index];
|
||||
const ty = symbol.type;
|
||||
const deferred: bool = blk: {
|
||||
if (ty.isAnyError(mod)) break :blk true;
|
||||
switch (mod.intern_pool.indexToKey(ty.ip_index)) {
|
||||
.inferred_error_set_type => |ies_index| {
|
||||
const ies = mod.inferredErrorSetPtr(ies_index);
|
||||
if (!ies.is_resolved) break :blk true;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
break :blk false;
|
||||
};
|
||||
if (deferred) continue;
|
||||
if (ip.isErrorSetType(ty.toIntern())) continue;
|
||||
|
||||
symbol.offset = @as(u32, @intCast(dbg_info_buffer.items.len));
|
||||
symbol.offset = @intCast(dbg_info_buffer.items.len);
|
||||
try decl_state.addDbgInfoType(mod, di_atom_index, ty);
|
||||
}
|
||||
}
|
||||
@ -1265,18 +1255,7 @@ pub fn commitDeclState(
|
||||
if (reloc.target) |target| {
|
||||
const symbol = decl_state.abbrev_table.items[target];
|
||||
const ty = symbol.type;
|
||||
const deferred: bool = blk: {
|
||||
if (ty.isAnyError(mod)) break :blk true;
|
||||
switch (mod.intern_pool.indexToKey(ty.ip_index)) {
|
||||
.inferred_error_set_type => |ies_index| {
|
||||
const ies = mod.inferredErrorSetPtr(ies_index);
|
||||
if (!ies.is_resolved) break :blk true;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
break :blk false;
|
||||
};
|
||||
if (deferred) {
|
||||
if (ip.isErrorSetType(ty.toIntern())) {
|
||||
log.debug("resolving %{d} deferred until flush", .{target});
|
||||
try self.global_abbrev_relocs.append(gpa, .{
|
||||
.target = null,
|
||||
@ -2505,18 +2484,18 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
|
||||
defer arena_alloc.deinit();
|
||||
const arena = arena_alloc.allocator();
|
||||
|
||||
// TODO: don't create a zig type for this, just make the dwarf info
|
||||
// without touching the zig type system.
|
||||
const names = try arena.dupe(InternPool.NullTerminatedString, module.global_error_set.keys());
|
||||
std.mem.sort(InternPool.NullTerminatedString, names, {}, InternPool.NullTerminatedString.indexLessThan);
|
||||
|
||||
const error_ty = try module.intern(.{ .error_set_type = .{ .names = names } });
|
||||
var dbg_info_buffer = std.ArrayList(u8).init(arena);
|
||||
try addDbgInfoErrorSet(module, error_ty.toType(), self.target, &dbg_info_buffer);
|
||||
try addDbgInfoErrorSetNames(
|
||||
module,
|
||||
Type.anyerror,
|
||||
module.global_error_set.keys(),
|
||||
self.target,
|
||||
&dbg_info_buffer,
|
||||
);
|
||||
|
||||
const di_atom_index = try self.createAtom(.di_atom);
|
||||
log.debug("updateDeclDebugInfoAllocation in flushModule", .{});
|
||||
try self.updateDeclDebugInfoAllocation(di_atom_index, @as(u32, @intCast(dbg_info_buffer.items.len)));
|
||||
try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(dbg_info_buffer.items.len));
|
||||
log.debug("writeDeclDebugInfo in flushModule", .{});
|
||||
try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items);
|
||||
|
||||
@ -2633,6 +2612,17 @@ fn addDbgInfoErrorSet(
|
||||
ty: Type,
|
||||
target: std.Target,
|
||||
dbg_info_buffer: *std.ArrayList(u8),
|
||||
) !void {
|
||||
return addDbgInfoErrorSetNames(mod, ty, ty.errorSetNames(mod), target, dbg_info_buffer);
|
||||
}
|
||||
|
||||
fn addDbgInfoErrorSetNames(
|
||||
mod: *Module,
|
||||
/// Used for printing the type name only.
|
||||
ty: Type,
|
||||
error_names: []const InternPool.NullTerminatedString,
|
||||
target: std.Target,
|
||||
dbg_info_buffer: *std.ArrayList(u8),
|
||||
) !void {
|
||||
const target_endian = target.cpu.arch.endian();
|
||||
|
||||
@ -2655,7 +2645,6 @@ fn addDbgInfoErrorSet(
|
||||
// DW.AT.const_value, DW.FORM.data8
|
||||
mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
|
||||
|
||||
const error_names = ty.errorSetNames(mod);
|
||||
for (error_names) |error_name_ip| {
|
||||
const int = try mod.getErrorValue(error_name_ip);
|
||||
const error_name = mod.intern_pool.stringToSlice(error_name_ip);
|
||||
|
||||
@ -2575,7 +2575,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
|
||||
return local_sym;
|
||||
}
|
||||
|
||||
pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
|
||||
pub fn updateFunc(self: *Elf, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
|
||||
if (build_options.skip_non_native and builtin.object_format != .elf) {
|
||||
@panic("Attempted to compile for object format that was disabled by build configuration");
|
||||
}
|
||||
@ -2586,7 +2586,7 @@ pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Ai
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const func = mod.funcPtr(func_index);
|
||||
const func = mod.funcInfo(func_index);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
|
||||
|
||||
@ -1845,7 +1845,7 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
|
||||
self.markRelocsDirtyByTarget(target);
|
||||
}
|
||||
|
||||
pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
|
||||
pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
|
||||
if (build_options.skip_non_native and builtin.object_format != .macho) {
|
||||
@panic("Attempted to compile for object format that was disabled by build configuration");
|
||||
}
|
||||
@ -1855,7 +1855,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air:
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const func = mod.funcPtr(func_index);
|
||||
const func = mod.funcInfo(func_index);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ const assert = std.debug.assert;
|
||||
const log = std.log.scoped(.link);
|
||||
|
||||
const Module = @import("../Module.zig");
|
||||
const InternPool = @import("../InternPool.zig");
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const link = @import("../link.zig");
|
||||
const trace = @import("../tracy.zig").trace;
|
||||
@ -68,7 +69,7 @@ pub fn deinit(self: *NvPtx) void {
|
||||
self.base.allocator.free(self.ptx_file_name);
|
||||
}
|
||||
|
||||
pub fn updateFunc(self: *NvPtx, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
|
||||
pub fn updateFunc(self: *NvPtx, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
|
||||
if (!build_options.have_llvm) return;
|
||||
try self.llvm_object.updateFunc(module, func_index, air, liveness);
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
const Plan9 = @This();
|
||||
const link = @import("../link.zig");
|
||||
const Module = @import("../Module.zig");
|
||||
const InternPool = @import("../InternPool.zig");
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const aout = @import("Plan9/aout.zig");
|
||||
const codegen = @import("../codegen.zig");
|
||||
@ -344,12 +345,12 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi
|
||||
}
|
||||
}
|
||||
|
||||
pub fn updateFunc(self: *Plan9, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
|
||||
pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
|
||||
if (build_options.skip_non_native and builtin.object_format != .plan9) {
|
||||
@panic("Attempted to compile for object format that was disabled by build configuration");
|
||||
}
|
||||
|
||||
const func = mod.funcPtr(func_index);
|
||||
const func = mod.funcInfo(func_index);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
self.freeUnnamedConsts(decl_index);
|
||||
@ -908,7 +909,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
|
||||
// in the deleteUnusedDecl function.
|
||||
const mod = self.base.options.module.?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const is_fn = decl.val.getFunctionIndex(mod) != .none;
|
||||
const is_fn = decl.val.isFuncBody(mod);
|
||||
if (is_fn) {
|
||||
var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;
|
||||
var submap = symidx_and_submap.functions;
|
||||
|
||||
@ -29,6 +29,7 @@ const assert = std.debug.assert;
|
||||
const log = std.log.scoped(.link);
|
||||
|
||||
const Module = @import("../Module.zig");
|
||||
const InternPool = @import("../InternPool.zig");
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const link = @import("../link.zig");
|
||||
const codegen = @import("../codegen/spirv.zig");
|
||||
@ -103,12 +104,12 @@ pub fn deinit(self: *SpirV) void {
|
||||
self.decl_link.deinit();
|
||||
}
|
||||
|
||||
pub fn updateFunc(self: *SpirV, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
|
||||
pub fn updateFunc(self: *SpirV, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
|
||||
if (build_options.skip_non_native) {
|
||||
@panic("Attempted to compile for architecture that was disabled by build configuration");
|
||||
}
|
||||
|
||||
const func = module.funcPtr(func_index);
|
||||
const func = module.funcInfo(func_index);
|
||||
|
||||
var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
|
||||
defer decl_gen.deinit();
|
||||
@ -138,7 +139,7 @@ pub fn updateDeclExports(
|
||||
exports: []const *Module.Export,
|
||||
) !void {
|
||||
const decl = mod.declPtr(decl_index);
|
||||
if (decl.val.getFunctionIndex(mod) != .none and decl.ty.fnCallingConvention(mod) == .Kernel) {
|
||||
if (decl.val.isFuncBody(mod) and decl.ty.fnCallingConvention(mod) == .Kernel) {
|
||||
// TODO: Unify with resolveDecl in spirv.zig.
|
||||
const entry = try self.decl_link.getOrPut(decl_index);
|
||||
if (!entry.found_existing) {
|
||||
|
||||
@ -12,6 +12,7 @@ const log = std.log.scoped(.link);
|
||||
pub const Atom = @import("Wasm/Atom.zig");
|
||||
const Dwarf = @import("Dwarf.zig");
|
||||
const Module = @import("../Module.zig");
|
||||
const InternPool = @import("../InternPool.zig");
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const CodeGen = @import("../arch/wasm/CodeGen.zig");
|
||||
const codegen = @import("../codegen.zig");
|
||||
@ -1338,7 +1339,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
|
||||
pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
|
||||
if (build_options.skip_non_native and builtin.object_format != .wasm) {
|
||||
@panic("Attempted to compile for object format that was disabled by build configuration");
|
||||
}
|
||||
@ -1349,7 +1350,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: A
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const func = mod.funcPtr(func_index);
|
||||
const func = mod.funcInfo(func_index);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
|
||||
|
||||
@ -665,7 +665,7 @@ const Writer = struct {
|
||||
fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
const ty_fn = w.air.instructions.items(.data)[inst].ty_fn;
|
||||
const func_index = ty_fn.func;
|
||||
const owner_decl = w.module.declPtr(w.module.funcPtr(func_index).owner_decl);
|
||||
const owner_decl = w.module.funcOwnerDeclPtr(func_index);
|
||||
try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)});
|
||||
}
|
||||
|
||||
|
||||
96
src/type.zig
96
src/type.zig
@ -250,21 +250,19 @@ pub const Type = struct {
|
||||
try print(error_union_type.payload_type.toType(), writer, mod);
|
||||
return;
|
||||
},
|
||||
.inferred_error_set_type => |index| {
|
||||
const ies = mod.inferredErrorSetPtr(index);
|
||||
const func = ies.func;
|
||||
|
||||
.inferred_error_set_type => |func_index| {
|
||||
try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
|
||||
const owner_decl = mod.declPtr(mod.funcPtr(func).owner_decl);
|
||||
const owner_decl = mod.funcOwnerDeclPtr(func_index);
|
||||
try owner_decl.renderFullyQualifiedName(mod, writer);
|
||||
try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
|
||||
},
|
||||
.error_set_type => |error_set_type| {
|
||||
const ip = &mod.intern_pool;
|
||||
const names = error_set_type.names;
|
||||
try writer.writeAll("error{");
|
||||
for (names, 0..) |name, i| {
|
||||
for (names.get(ip), 0..) |name, i| {
|
||||
if (i != 0) try writer.writeByte(',');
|
||||
try writer.print("{}", .{name.fmt(&mod.intern_pool)});
|
||||
try writer.print("{}", .{name.fmt(ip)});
|
||||
}
|
||||
try writer.writeAll("}");
|
||||
},
|
||||
@ -294,6 +292,7 @@ pub const Type = struct {
|
||||
.comptime_int,
|
||||
.comptime_float,
|
||||
.noreturn,
|
||||
.adhoc_inferred_error_set,
|
||||
=> return writer.writeAll(@tagName(s)),
|
||||
|
||||
.null,
|
||||
@ -367,7 +366,8 @@ pub const Type = struct {
|
||||
try writer.writeAll("noinline ");
|
||||
}
|
||||
try writer.writeAll("fn(");
|
||||
for (fn_info.param_types, 0..) |param_ty, i| {
|
||||
const param_types = fn_info.param_types.get(&mod.intern_pool);
|
||||
for (param_types, 0..) |param_ty, i| {
|
||||
if (i != 0) try writer.writeAll(", ");
|
||||
if (std.math.cast(u5, i)) |index| {
|
||||
if (fn_info.paramIsComptime(index)) {
|
||||
@ -384,7 +384,7 @@ pub const Type = struct {
|
||||
}
|
||||
}
|
||||
if (fn_info.is_var_args) {
|
||||
if (fn_info.param_types.len != 0) {
|
||||
if (param_types.len != 0) {
|
||||
try writer.writeAll(", ");
|
||||
}
|
||||
try writer.writeAll("...");
|
||||
@ -534,6 +534,7 @@ pub const Type = struct {
|
||||
.c_longdouble,
|
||||
.bool,
|
||||
.anyerror,
|
||||
.adhoc_inferred_error_set,
|
||||
.anyopaque,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
@ -697,6 +698,7 @@ pub const Type = struct {
|
||||
=> true,
|
||||
|
||||
.anyerror,
|
||||
.adhoc_inferred_error_set,
|
||||
.anyopaque,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
@ -955,7 +957,9 @@ pub const Type = struct {
|
||||
},
|
||||
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
.anyerror => return AbiAlignmentAdvanced{ .scalar = 2 },
|
||||
.anyerror,
|
||||
.adhoc_inferred_error_set,
|
||||
=> return AbiAlignmentAdvanced{ .scalar = 2 },
|
||||
|
||||
.void,
|
||||
.type,
|
||||
@ -1419,7 +1423,9 @@ pub const Type = struct {
|
||||
=> return AbiSizeAdvanced{ .scalar = 0 },
|
||||
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
.anyerror => return AbiSizeAdvanced{ .scalar = 2 },
|
||||
.anyerror,
|
||||
.adhoc_inferred_error_set,
|
||||
=> return AbiSizeAdvanced{ .scalar = 2 },
|
||||
|
||||
.prefetch_options => unreachable, // missing call to resolveTypeFields
|
||||
.export_options => unreachable, // missing call to resolveTypeFields
|
||||
@ -1662,7 +1668,9 @@ pub const Type = struct {
|
||||
.void => return 0,
|
||||
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
.anyerror => return 16,
|
||||
.anyerror,
|
||||
.adhoc_inferred_error_set,
|
||||
=> return 16,
|
||||
|
||||
.anyopaque => unreachable,
|
||||
.type => unreachable,
|
||||
@ -2050,21 +2058,19 @@ pub const Type = struct {
|
||||
|
||||
/// Asserts that the type is an error union.
|
||||
pub fn errorUnionSet(ty: Type, mod: *Module) Type {
|
||||
return mod.intern_pool.indexToKey(ty.toIntern()).error_union_type.error_set_type.toType();
|
||||
return mod.intern_pool.errorUnionSet(ty.toIntern()).toType();
|
||||
}
|
||||
|
||||
/// Returns false for unresolved inferred error sets.
|
||||
pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool {
|
||||
const ip = &mod.intern_pool;
|
||||
return switch (ty.toIntern()) {
|
||||
.anyerror_type => false,
|
||||
else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
else => switch (ip.indexToKey(ty.toIntern())) {
|
||||
.error_set_type => |error_set_type| error_set_type.names.len == 0,
|
||||
.inferred_error_set_type => |index| {
|
||||
const inferred_error_set = mod.inferredErrorSetPtr(index);
|
||||
// Can't know for sure.
|
||||
if (!inferred_error_set.is_resolved) return false;
|
||||
if (inferred_error_set.is_anyerror) return false;
|
||||
return inferred_error_set.errors.count() == 0;
|
||||
.inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
|
||||
.none, .anyerror_type => false,
|
||||
else => |t| ip.indexToKey(t).error_set_type.names.len == 0,
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
@ -2075,10 +2081,11 @@ pub const Type = struct {
|
||||
/// Note that the result may be a false negative if the type did not get error set
|
||||
/// resolution prior to this call.
|
||||
pub fn isAnyError(ty: Type, mod: *Module) bool {
|
||||
const ip = &mod.intern_pool;
|
||||
return switch (ty.toIntern()) {
|
||||
.anyerror_type => true,
|
||||
else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
.inferred_error_set_type => |i| mod.inferredErrorSetPtr(i).is_anyerror,
|
||||
.inferred_error_set_type => |i| ip.funcIesResolved(i).* == .anyerror_type,
|
||||
else => false,
|
||||
},
|
||||
};
|
||||
@ -2102,13 +2109,11 @@ pub const Type = struct {
|
||||
return switch (ty) {
|
||||
.anyerror_type => true,
|
||||
else => switch (ip.indexToKey(ty)) {
|
||||
.error_set_type => |error_set_type| {
|
||||
return error_set_type.nameIndex(ip, name) != null;
|
||||
},
|
||||
.inferred_error_set_type => |index| {
|
||||
const ies = ip.inferredErrorSetPtrConst(index);
|
||||
if (ies.is_anyerror) return true;
|
||||
return ies.errors.contains(name);
|
||||
.error_set_type => |error_set_type| error_set_type.nameIndex(ip, name) != null,
|
||||
.inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
|
||||
.anyerror_type => true,
|
||||
.none => false,
|
||||
else => |t| ip.indexToKey(t).error_set_type.nameIndex(ip, name) != null,
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
@ -2128,12 +2133,14 @@ pub const Type = struct {
|
||||
const field_name_interned = ip.getString(name).unwrap() orelse return false;
|
||||
return error_set_type.nameIndex(ip, field_name_interned) != null;
|
||||
},
|
||||
.inferred_error_set_type => |index| {
|
||||
const ies = ip.inferredErrorSetPtr(index);
|
||||
if (ies.is_anyerror) return true;
|
||||
// If the string is not interned, then the field certainly is not present.
|
||||
const field_name_interned = ip.getString(name).unwrap() orelse return false;
|
||||
return ies.errors.contains(field_name_interned);
|
||||
.inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
|
||||
.anyerror_type => true,
|
||||
.none => false,
|
||||
else => |t| {
|
||||
// If the string is not interned, then the field certainly is not present.
|
||||
const field_name_interned = ip.getString(name).unwrap() orelse return false;
|
||||
return ip.indexToKey(t).error_set_type.nameIndex(ip, field_name_interned) != null;
|
||||
},
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
@ -2231,7 +2238,7 @@ pub const Type = struct {
|
||||
var ty = starting_ty;
|
||||
|
||||
while (true) switch (ty.toIntern()) {
|
||||
.anyerror_type => {
|
||||
.anyerror_type, .adhoc_inferred_error_set_type => {
|
||||
// TODO revisit this when error sets support custom int types
|
||||
return .{ .signedness = .unsigned, .bits = 16 };
|
||||
},
|
||||
@ -2365,7 +2372,7 @@ pub const Type = struct {
|
||||
|
||||
/// Asserts the type is a function or a function pointer.
|
||||
pub fn fnReturnType(ty: Type, mod: *Module) Type {
|
||||
return mod.intern_pool.funcReturnType(ty.toIntern()).toType();
|
||||
return mod.intern_pool.funcTypeReturnType(ty.toIntern()).toType();
|
||||
}
|
||||
|
||||
/// Asserts the type is a function.
|
||||
@ -2505,6 +2512,7 @@ pub const Type = struct {
|
||||
.export_options,
|
||||
.extern_options,
|
||||
.type_info,
|
||||
.adhoc_inferred_error_set,
|
||||
=> return null,
|
||||
|
||||
.void => return Value.void,
|
||||
@ -2699,6 +2707,7 @@ pub const Type = struct {
|
||||
.bool,
|
||||
.void,
|
||||
.anyerror,
|
||||
.adhoc_inferred_error_set,
|
||||
.noreturn,
|
||||
.generic_poison,
|
||||
.atomic_order,
|
||||
@ -2942,14 +2951,15 @@ pub const Type = struct {
|
||||
}
|
||||
|
||||
// Asserts that `ty` is an error set and not `anyerror`.
|
||||
// Asserts that `ty` is resolved if it is an inferred error set.
|
||||
pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {
|
||||
return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
.error_set_type => |x| x.names,
|
||||
.inferred_error_set_type => |index| {
|
||||
const inferred_error_set = mod.inferredErrorSetPtr(index);
|
||||
assert(inferred_error_set.is_resolved);
|
||||
assert(!inferred_error_set.is_anyerror);
|
||||
return inferred_error_set.errors.keys();
|
||||
const ip = &mod.intern_pool;
|
||||
return switch (ip.indexToKey(ty.toIntern())) {
|
||||
.error_set_type => |x| x.names.get(ip),
|
||||
.inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
|
||||
.none => unreachable, // unresolved inferred error set
|
||||
.anyerror_type => unreachable,
|
||||
else => |t| ip.indexToKey(t).error_set_type.names.get(ip),
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
@ -262,6 +262,11 @@ pub const Value = struct {
|
||||
return ip.getOrPutTrailingString(gpa, len);
|
||||
}
|
||||
|
||||
pub fn intern2(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
|
||||
if (val.ip_index != .none) return val.ip_index;
|
||||
return intern(val, ty, mod);
|
||||
}
|
||||
|
||||
pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
|
||||
if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern();
|
||||
switch (val.tag()) {
|
||||
@ -473,12 +478,15 @@ pub const Value = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getFunction(val: Value, mod: *Module) ?*Module.Fn {
|
||||
return mod.funcPtrUnwrap(val.getFunctionIndex(mod));
|
||||
pub fn isFuncBody(val: Value, mod: *Module) bool {
|
||||
return mod.intern_pool.isFuncBody(val.toIntern());
|
||||
}
|
||||
|
||||
pub fn getFunctionIndex(val: Value, mod: *Module) Module.Fn.OptionalIndex {
|
||||
return if (val.ip_index != .none) mod.intern_pool.indexToFunc(val.toIntern()) else .none;
|
||||
pub fn getFunction(val: Value, mod: *Module) ?InternPool.Key.Func {
|
||||
return switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
.func => |x| x,
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {
|
||||
@ -1462,7 +1470,7 @@ pub const Value = struct {
|
||||
return switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
.variable => |variable| variable.decl,
|
||||
.extern_func => |extern_func| extern_func.decl,
|
||||
.func => |func| mod.funcPtr(func.index).owner_decl,
|
||||
.func => |func| func.owner_decl,
|
||||
.ptr => |ptr| switch (ptr.addr) {
|
||||
.decl => |decl| decl,
|
||||
.mut_decl => |mut_decl| mut_decl.decl,
|
||||
|
||||
@ -443,3 +443,16 @@ test "generic function passed as comptime argument" {
|
||||
};
|
||||
try S.doMath(std.math.add, 5, 6);
|
||||
}
|
||||
|
||||
test "return type of generic function is function pointer" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
||||
|
||||
const S = struct {
|
||||
fn b(comptime T: type) ?*const fn () error{}!T {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
try expect(null == S.b(void));
|
||||
}
|
||||
|
||||
@ -16,5 +16,7 @@ pub export fn entry() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :7:14: error: unable to resolve comptime value
|
||||
// :7:14: note: argument to parameter with comptime-only type must be comptime-known
|
||||
// :7:14: error: runtime-known argument passed to comptime-only type parameter
|
||||
// :9:12: note: declared here
|
||||
// :4:16: note: struct requires comptime because of this field
|
||||
// :4:16: note: types are not available at runtime
|
||||
|
||||
@ -6,4 +6,4 @@ export fn foo(comptime x: anytype, y: i32) i32 {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:15: error: comptime parameters not allowed in function with calling convention 'C'
|
||||
// :1:27: error: comptime parameters not allowed in function with calling convention 'C'
|
||||
|
||||
@ -7,4 +7,4 @@ export fn foo(num: anytype) i32 {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:15: error: generic parameters not allowed in function with calling convention 'C'
|
||||
// :1:20: error: generic parameters not allowed in function with calling convention 'C'
|
||||
|
||||
@ -19,5 +19,5 @@ comptime {
|
||||
// target=native
|
||||
//
|
||||
// :5:30: error: comptime parameters not allowed in function with calling convention 'C'
|
||||
// :6:30: error: generic parameters not allowed in function with calling convention 'C'
|
||||
// :6:41: error: generic parameters not allowed in function with calling convention 'C'
|
||||
// :1:15: error: comptime parameters not allowed in function with calling convention 'C'
|
||||
|
||||
@ -13,5 +13,5 @@ export fn entry() usize {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :5:16: error: unable to resolve comptime value
|
||||
// :5:16: note: parameter is comptime
|
||||
// :5:16: error: runtime-known argument passed to comptime parameter
|
||||
// :1:17: note: declared comptime here
|
||||
|
||||
@ -213,10 +213,6 @@ pub const build_cases = [_]BuildCase{
|
||||
// .build_root = "test/standalone/sigpipe",
|
||||
// .import = @import("standalone/sigpipe/build.zig"),
|
||||
//},
|
||||
.{
|
||||
.build_root = "test/standalone/issue_13030",
|
||||
.import = @import("standalone/issue_13030/build.zig"),
|
||||
},
|
||||
// TODO restore this test
|
||||
//.{
|
||||
// .build_root = "test/standalone/options",
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test it");
|
||||
b.default_step = test_step;
|
||||
|
||||
add(b, test_step, .Debug);
|
||||
add(b, test_step, .ReleaseFast);
|
||||
add(b, test_step, .ReleaseSmall);
|
||||
add(b, test_step, .ReleaseSafe);
|
||||
}
|
||||
|
||||
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
|
||||
const obj = b.addObject(.{
|
||||
.name = "main",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = .{},
|
||||
});
|
||||
|
||||
test_step.dependOn(&obj.step);
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
fn b(comptime T: type) ?*const fn () error{}!T {
|
||||
return null;
|
||||
}
|
||||
|
||||
export fn entry() void {
|
||||
_ = b(void);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user