mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-07 14:24:43 +00:00
rework generic function calls
Abridged summary: * Move `Module.Fn` into `InternPool`. * Delete a lot of confusing and problematic `Sema` logic related to generic function calls. This commit removes `Module.Fn` and replaces it with two new `InternPool.Tag` values: * `func_decl` - corresponding to a function declared in the source code. This one contains line/column numbers, zir_body_inst, etc. * `func_instance` - one for each monomorphization of a generic function. Contains a reference to the `func_decl` from whence the instantiation came, along with the `comptime` parameter values (or types in the case of `anytype`) Since `InternPool` provides deduplication on these values, these fields are now deleted from `Module`: * `monomorphed_func_keys` * `monomorphed_funcs` * `align_stack_fns` Instead of these, Sema logic for generic function instantiation now unconditionally evaluates the function prototype expression for every generic callsite. This is technically required in order for type coercions to work. The previous code had some dubious, probably wrong hacks to make things work, such as `hashUncoerced`. I'm not 100% sure how we were able to eliminate that function and still pass all the behavior tests, but I'm pretty sure things were still broken without doing type coercion for every generic function call argument. After the function prototype is evaluated, it produces a deduplicated `func_instance` `InternPool.Index` which can then be used for the generic function call. Some other nice things made by this simplification are the removal of `comptime_args_fn_inst` and `preallocated_new_func` from `Sema`, and the messy logic associated with them. I have not yet been able to measure the perf of this against master branch. On one hand, it reduces memory usage and pointer chasing of the most heavily used `InternPool` Tag - function bodies - but on the other hand, it does evaluate function prototype expressions more than before. We will soon find out.
This commit is contained in:
parent
70c71935c7
commit
db33ee45b7
30 changed files with 1748 additions and 1973 deletions
|
|
@ -1003,7 +1003,7 @@ pub const Inst = struct {
|
||||||
},
|
},
|
||||||
ty_fn: struct {
|
ty_fn: struct {
|
||||||
ty: Ref,
|
ty: Ref,
|
||||||
func: Module.Fn.Index,
|
func: InternPool.Index,
|
||||||
},
|
},
|
||||||
br: struct {
|
br: struct {
|
||||||
block_inst: Index,
|
block_inst: Index,
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig");
|
||||||
const fatal = @import("main.zig").fatal;
|
const fatal = @import("main.zig").fatal;
|
||||||
const clangMain = @import("main.zig").clangMain;
|
const clangMain = @import("main.zig").clangMain;
|
||||||
const Module = @import("Module.zig");
|
const Module = @import("Module.zig");
|
||||||
|
const InternPool = @import("InternPool.zig");
|
||||||
const BuildId = std.Build.CompileStep.BuildId;
|
const BuildId = std.Build.CompileStep.BuildId;
|
||||||
const Cache = std.Build.Cache;
|
const Cache = std.Build.Cache;
|
||||||
const translate_c = @import("translate_c.zig");
|
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.
|
/// Write the constant value for a Decl to the output file.
|
||||||
codegen_decl: Module.Decl.Index,
|
codegen_decl: Module.Decl.Index,
|
||||||
/// Write the machine code for a function to the output file.
|
/// 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.
|
/// Render the .h file snippet for the Decl.
|
||||||
emit_h_decl: Module.Decl.Index,
|
emit_h_decl: Module.Decl.Index,
|
||||||
/// The Decl needs to be analyzed and possibly export itself.
|
/// The Decl needs to be analyzed and possibly export itself.
|
||||||
|
|
@ -3216,8 +3218,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
|
// Tests are always emitted in test binaries. The decl_refs are created by
|
||||||
// Module.populateTestFunctions, but this will not queue body analysis, so do
|
// Module.populateTestFunctions, but this will not queue body analysis, so do
|
||||||
// that now.
|
// that now.
|
||||||
const func_index = module.intern_pool.indexToFunc(decl.val.ip_index).unwrap().?;
|
try module.ensureFuncBodyAnalysisQueued(decl.val.toIntern());
|
||||||
try module.ensureFuncBodyAnalysisQueued(func_index);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.update_embed_file => |embed_file| {
|
.update_embed_file => |embed_file| {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
534
src/Module.zig
534
src/Module.zig
|
|
@ -101,16 +101,6 @@ tmp_hack_arena: std.heap.ArenaAllocator,
|
||||||
/// This is currently only used for string literals.
|
/// This is currently only used for string literals.
|
||||||
memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{},
|
memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{},
|
||||||
|
|
||||||
monomorphed_func_keys: std.ArrayListUnmanaged(InternPool.Index) = .{},
|
|
||||||
/// The set of all the generic function instantiations. This is used so that when a generic
|
|
||||||
/// function is called twice with the same comptime parameter arguments, both calls dispatch
|
|
||||||
/// to the same function.
|
|
||||||
monomorphed_funcs: MonomorphedFuncsSet = .{},
|
|
||||||
/// Contains the values from `@setAlignStack`. A sparse table is used here
|
|
||||||
/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while
|
|
||||||
/// functions are many.
|
|
||||||
align_stack_fns: std.AutoHashMapUnmanaged(Fn.Index, SetAlignStack) = .{},
|
|
||||||
|
|
||||||
/// We optimize memory usage for a compilation with no compile errors by storing the
|
/// We optimize memory usage for a compilation with no compile errors by storing the
|
||||||
/// error messages and mapping outside of `Decl`.
|
/// error messages and mapping outside of `Decl`.
|
||||||
/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.
|
/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.
|
||||||
|
|
@ -189,7 +179,8 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
|
||||||
}) = .{},
|
}) = .{},
|
||||||
|
|
||||||
panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len,
|
panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len,
|
||||||
panic_func_index: Fn.OptionalIndex = .none,
|
/// The panic function body.
|
||||||
|
panic_func_index: InternPool.Index = .none,
|
||||||
null_stack_trace: InternPool.Index = .none,
|
null_stack_trace: InternPool.Index = .none,
|
||||||
|
|
||||||
pub const PanicId = enum {
|
pub const PanicId = enum {
|
||||||
|
|
@ -239,50 +230,6 @@ pub const CImportError = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const MonomorphedFuncKey = struct { func: Fn.Index, args_index: u32, args_len: u32 };
|
|
||||||
|
|
||||||
pub const MonomorphedFuncAdaptedKey = struct { func: Fn.Index, args: []const InternPool.Index };
|
|
||||||
|
|
||||||
pub const MonomorphedFuncsSet = std.HashMapUnmanaged(
|
|
||||||
MonomorphedFuncKey,
|
|
||||||
InternPool.Index,
|
|
||||||
MonomorphedFuncsContext,
|
|
||||||
std.hash_map.default_max_load_percentage,
|
|
||||||
);
|
|
||||||
|
|
||||||
pub const MonomorphedFuncsContext = struct {
|
|
||||||
mod: *Module,
|
|
||||||
|
|
||||||
pub fn eql(_: @This(), a: MonomorphedFuncKey, b: MonomorphedFuncKey) bool {
|
|
||||||
return std.meta.eql(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hash(ctx: @This(), key: MonomorphedFuncKey) u64 {
|
|
||||||
const key_args = ctx.mod.monomorphed_func_keys.items[key.args_index..][0..key.args_len];
|
|
||||||
return std.hash.Wyhash.hash(@intFromEnum(key.func), std.mem.sliceAsBytes(key_args));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const MonomorphedFuncsAdaptedContext = struct {
|
|
||||||
mod: *Module,
|
|
||||||
|
|
||||||
pub fn eql(ctx: @This(), adapted_key: MonomorphedFuncAdaptedKey, other_key: MonomorphedFuncKey) bool {
|
|
||||||
const other_key_args = ctx.mod.monomorphed_func_keys.items[other_key.args_index..][0..other_key.args_len];
|
|
||||||
return adapted_key.func == other_key.func and std.mem.eql(InternPool.Index, adapted_key.args, other_key_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hash(_: @This(), adapted_key: MonomorphedFuncAdaptedKey) u64 {
|
|
||||||
return std.hash.Wyhash.hash(@intFromEnum(adapted_key.func), std.mem.sliceAsBytes(adapted_key.args));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const SetAlignStack = struct {
|
|
||||||
alignment: Alignment,
|
|
||||||
/// TODO: This needs to store a non-lazy source location for the case of an inline function
|
|
||||||
/// which does `@setAlignStack` (applying it to the caller).
|
|
||||||
src: LazySrcLoc,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.
|
/// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.
|
||||||
pub const GlobalEmitH = struct {
|
pub const GlobalEmitH = struct {
|
||||||
/// Where to put the output.
|
/// Where to put the output.
|
||||||
|
|
@ -625,13 +572,6 @@ pub const Decl = struct {
|
||||||
function_body,
|
function_body,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn clearValues(decl: *Decl, mod: *Module) void {
|
|
||||||
if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
|
|
||||||
_ = mod.align_stack_fns.remove(func);
|
|
||||||
mod.destroyFunc(func);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This name is relative to the containing namespace of the decl.
|
/// This name is relative to the containing namespace of the decl.
|
||||||
/// The memory is owned by the containing File ZIR.
|
/// The memory is owned by the containing File ZIR.
|
||||||
pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 {
|
pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 {
|
||||||
|
|
@ -816,14 +756,17 @@ pub const Decl = struct {
|
||||||
return mod.typeToUnion(decl.val.toType());
|
return mod.typeToUnion(decl.val.toType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the Decl owns its value and it is a function, return it,
|
pub fn getOwnedFunction(decl: Decl, mod: *Module) ?InternPool.Key.Func {
|
||||||
/// otherwise null.
|
const i = decl.getOwnedFunctionIndex();
|
||||||
pub fn getOwnedFunction(decl: Decl, mod: *Module) ?*Fn {
|
if (i == .none) return null;
|
||||||
return mod.funcPtrUnwrap(decl.getOwnedFunctionIndex(mod));
|
return switch (mod.intern_pool.indexToKey(i)) {
|
||||||
|
.func => |func| func,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getOwnedFunctionIndex(decl: Decl, mod: *Module) Fn.OptionalIndex {
|
pub fn getOwnedFunctionIndex(decl: Decl) InternPool.Index {
|
||||||
return if (decl.owns_tv) decl.val.getFunctionIndex(mod) else .none;
|
return if (decl.owns_tv) decl.val.toIntern() else .none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the Decl owns its value and it is an extern function, returns it,
|
/// If the Decl owns its value and it is an extern function, returns it,
|
||||||
|
|
@ -1385,114 +1328,14 @@ pub const ExternFn = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
|
/// This struct is used to keep track of any dependencies related to functions instances
|
||||||
/// Extern functions do not have this data structure; they are represented by `ExternFn`
|
/// that return inferred error sets. Note that a function may be associated to
|
||||||
/// instead.
|
/// multiple different error sets, for example an inferred error set which
|
||||||
pub const Fn = struct {
|
/// this function returns, but also any inferred error sets of called inline
|
||||||
/// The Decl that corresponds to the function itself.
|
/// or comptime functions.
|
||||||
owner_decl: Decl.Index,
|
pub const InferredErrorSet = struct {
|
||||||
/// The ZIR instruction that is a function instruction. Use this to find
|
|
||||||
/// the body. We store this rather than the body directly so that when ZIR
|
|
||||||
/// is regenerated on update(), we can map this to the new corresponding
|
|
||||||
/// ZIR instruction.
|
|
||||||
zir_body_inst: Zir.Inst.Index,
|
|
||||||
/// If this is not null, this function is a generic function instantiation, and
|
|
||||||
/// there is a `TypedValue` here for each parameter of the function.
|
|
||||||
/// Non-comptime parameters are marked with a `generic_poison` for the value.
|
|
||||||
/// Non-anytype parameters are marked with a `generic_poison` for the type.
|
|
||||||
/// These never have .generic_poison for the Type
|
|
||||||
/// because the Type is needed to pass to `Type.eql` and for inserting comptime arguments
|
|
||||||
/// into the inst_map when analyzing the body of a generic function instantiation.
|
|
||||||
/// Instead, the is_anytype knowledge is communicated via `isAnytypeParam`.
|
|
||||||
comptime_args: ?[*]TypedValue,
|
|
||||||
|
|
||||||
/// Precomputed hash for monomorphed_funcs.
|
|
||||||
/// This is important because it may be accessed when resizing monomorphed_funcs
|
|
||||||
/// while this Fn has already been added to the set, but does not have the
|
|
||||||
/// owner_decl, comptime_args, or other fields populated yet.
|
|
||||||
/// This field is undefined if comptime_args == null.
|
|
||||||
hash: u64,
|
|
||||||
|
|
||||||
/// Relative to owner Decl.
|
|
||||||
lbrace_line: u32,
|
|
||||||
/// Relative to owner Decl.
|
|
||||||
rbrace_line: u32,
|
|
||||||
lbrace_column: u16,
|
|
||||||
rbrace_column: u16,
|
|
||||||
|
|
||||||
/// When a generic function is instantiated, this value is inherited from the
|
|
||||||
/// active Sema context. Importantly, this value is also updated when an existing
|
|
||||||
/// generic function instantiation is found and called.
|
|
||||||
branch_quota: u32,
|
|
||||||
|
|
||||||
/// If this is not none, this function is a generic function instantiation, and
|
|
||||||
/// this is the generic function decl from which the instance was derived.
|
|
||||||
/// This information is redundant with a combination of checking if comptime_args is
|
|
||||||
/// not null and looking at the first decl dependency of owner_decl. This redundant
|
|
||||||
/// information is useful for three reasons:
|
|
||||||
/// 1. Improved perf of monomorphed_funcs when checking the eql() function because it
|
|
||||||
/// can do two fewer pointer chases by grabbing the info from this field directly
|
|
||||||
/// instead of accessing the decl and then the dependencies set.
|
|
||||||
/// 2. While a generic function instantiation is being initialized, we need hash()
|
|
||||||
/// and eql() to work before the initialization is complete. Completing the
|
|
||||||
/// insertion into the decl dependency set has more fallible operations than simply
|
|
||||||
/// setting this field.
|
|
||||||
/// 3. I forgot what the third thing was while typing up the other two.
|
|
||||||
generic_owner_decl: Decl.OptionalIndex,
|
|
||||||
|
|
||||||
state: Analysis,
|
|
||||||
is_cold: bool = false,
|
|
||||||
is_noinline: bool,
|
|
||||||
calls_or_awaits_errorable_fn: bool = false,
|
|
||||||
|
|
||||||
pub const Index = enum(u32) {
|
|
||||||
_,
|
|
||||||
|
|
||||||
pub fn toOptional(i: Index) OptionalIndex {
|
|
||||||
return @as(OptionalIndex, @enumFromInt(@intFromEnum(i)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const OptionalIndex = enum(u32) {
|
|
||||||
none = std.math.maxInt(u32),
|
|
||||||
_,
|
|
||||||
|
|
||||||
pub fn init(oi: ?Index) OptionalIndex {
|
|
||||||
return @as(OptionalIndex, @enumFromInt(@intFromEnum(oi orelse return .none)));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unwrap(oi: OptionalIndex) ?Index {
|
|
||||||
if (oi == .none) return null;
|
|
||||||
return @as(Index, @enumFromInt(@intFromEnum(oi)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Analysis = enum {
|
|
||||||
/// This function has not yet undergone analysis, because we have not
|
|
||||||
/// seen a potential runtime call. It may be analyzed in future.
|
|
||||||
none,
|
|
||||||
/// Analysis for this function has been queued, but not yet completed.
|
|
||||||
queued,
|
|
||||||
/// This function intentionally only has ZIR generated because it is marked
|
|
||||||
/// inline, which means no runtime version of the function will be generated.
|
|
||||||
inline_only,
|
|
||||||
in_progress,
|
|
||||||
/// There will be a corresponding ErrorMsg in Module.failed_decls
|
|
||||||
sema_failure,
|
|
||||||
/// This Fn might be OK but it depends on another Decl which did not
|
|
||||||
/// successfully complete semantic analysis.
|
|
||||||
dependency_failure,
|
|
||||||
success,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// This struct is used to keep track of any dependencies related to functions instances
|
|
||||||
/// that return inferred error sets. Note that a function may be associated to
|
|
||||||
/// multiple different error sets, for example an inferred error set which
|
|
||||||
/// this function returns, but also any inferred error sets of called inline
|
|
||||||
/// or comptime functions.
|
|
||||||
pub const InferredErrorSet = struct {
|
|
||||||
/// The function from which this error set originates.
|
/// The function from which this error set originates.
|
||||||
func: Fn.Index,
|
func: InternPool.Index,
|
||||||
|
|
||||||
/// All currently known errors that this error set contains. This includes
|
/// All currently known errors that this error set contains. This includes
|
||||||
/// direct additions via `return error.Foo;`, and possibly also errors that
|
/// direct additions via `return error.Foo;`, and possibly also errors that
|
||||||
|
|
@ -1558,60 +1401,6 @@ pub const Fn = struct {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool {
|
|
||||||
const file = mod.declPtr(func.owner_decl).getFileScope(mod);
|
|
||||||
|
|
||||||
const tags = file.zir.instructions.items(.tag);
|
|
||||||
|
|
||||||
const param_body = file.zir.getParamBody(func.zir_body_inst);
|
|
||||||
const param = param_body[index];
|
|
||||||
|
|
||||||
return switch (tags[param]) {
|
|
||||||
.param, .param_comptime => false,
|
|
||||||
.param_anytype, .param_anytype_comptime => true,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getParamName(func: Fn, mod: *Module, index: u32) [:0]const u8 {
|
|
||||||
const file = mod.declPtr(func.owner_decl).getFileScope(mod);
|
|
||||||
|
|
||||||
const tags = file.zir.instructions.items(.tag);
|
|
||||||
const data = file.zir.instructions.items(.data);
|
|
||||||
|
|
||||||
const param_body = file.zir.getParamBody(func.zir_body_inst);
|
|
||||||
const param = param_body[index];
|
|
||||||
|
|
||||||
return switch (tags[param]) {
|
|
||||||
.param, .param_comptime => blk: {
|
|
||||||
const extra = file.zir.extraData(Zir.Inst.Param, data[param].pl_tok.payload_index);
|
|
||||||
break :blk file.zir.nullTerminatedString(extra.data.name);
|
|
||||||
},
|
|
||||||
.param_anytype, .param_anytype_comptime => blk: {
|
|
||||||
const param_data = data[param].str_tok;
|
|
||||||
break :blk param_data.get(file.zir);
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hasInferredErrorSet(func: Fn, mod: *Module) bool {
|
|
||||||
const owner_decl = mod.declPtr(func.owner_decl);
|
|
||||||
const zir = owner_decl.getFileScope(mod).zir;
|
|
||||||
const zir_tags = zir.instructions.items(.tag);
|
|
||||||
switch (zir_tags[func.zir_body_inst]) {
|
|
||||||
.func => return false,
|
|
||||||
.func_inferred => return true,
|
|
||||||
.func_fancy => {
|
|
||||||
const inst_data = zir.instructions.items(.data)[func.zir_body_inst].pl_node;
|
|
||||||
const extra = zir.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
|
|
||||||
return extra.data.bits.is_inferred_error;
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DeclAdapter = struct {
|
pub const DeclAdapter = struct {
|
||||||
|
|
@ -2468,6 +2257,22 @@ pub const SrcLoc = struct {
|
||||||
}
|
}
|
||||||
} else unreachable;
|
} else unreachable;
|
||||||
},
|
},
|
||||||
|
.call_arg => |call_arg| {
|
||||||
|
const tree = try src_loc.file_scope.getTree(gpa);
|
||||||
|
const node = src_loc.declRelativeToNodeIndex(call_arg.call_node_offset);
|
||||||
|
var buf: [1]Ast.Node.Index = undefined;
|
||||||
|
const call_full = tree.fullCall(&buf, node).?;
|
||||||
|
const src_node = call_full.ast.params[call_arg.arg_index];
|
||||||
|
return nodeToSpan(tree, src_node);
|
||||||
|
},
|
||||||
|
.fn_proto_param => |fn_proto_param| {
|
||||||
|
const tree = try src_loc.file_scope.getTree(gpa);
|
||||||
|
const node = src_loc.declRelativeToNodeIndex(fn_proto_param.fn_proto_node_offset);
|
||||||
|
var buf: [1]Ast.Node.Index = undefined;
|
||||||
|
const fn_proto_full = tree.fullFnProto(&buf, node).?;
|
||||||
|
const src_node = fn_proto_full.ast.params[fn_proto_param.param_index];
|
||||||
|
return nodeToSpan(tree, src_node);
|
||||||
|
},
|
||||||
.node_offset_bin_lhs => |node_off| {
|
.node_offset_bin_lhs => |node_off| {
|
||||||
const tree = try src_loc.file_scope.getTree(gpa);
|
const tree = try src_loc.file_scope.getTree(gpa);
|
||||||
const node = src_loc.declRelativeToNodeIndex(node_off);
|
const node = src_loc.declRelativeToNodeIndex(node_off);
|
||||||
|
|
@ -3146,6 +2951,20 @@ pub const LazySrcLoc = union(enum) {
|
||||||
/// Next, navigate to the corresponding capture.
|
/// Next, navigate to the corresponding capture.
|
||||||
/// The Decl is determined contextually.
|
/// The Decl is determined contextually.
|
||||||
for_capture_from_input: i32,
|
for_capture_from_input: i32,
|
||||||
|
/// The source location points to the argument node of a function call.
|
||||||
|
/// The Decl is determined contextually.
|
||||||
|
call_arg: struct {
|
||||||
|
/// Points to the function call AST node.
|
||||||
|
call_node_offset: i32,
|
||||||
|
/// The index of the argument the source location points to.
|
||||||
|
arg_index: u32,
|
||||||
|
},
|
||||||
|
fn_proto_param: struct {
|
||||||
|
/// Points to the function prototype AST node.
|
||||||
|
fn_proto_node_offset: i32,
|
||||||
|
/// The index of the parameter the source location points to.
|
||||||
|
param_index: u32,
|
||||||
|
},
|
||||||
|
|
||||||
pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
|
pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
|
||||||
|
|
||||||
|
|
@ -3235,6 +3054,8 @@ pub const LazySrcLoc = union(enum) {
|
||||||
.node_offset_store_operand,
|
.node_offset_store_operand,
|
||||||
.for_input,
|
.for_input,
|
||||||
.for_capture_from_input,
|
.for_capture_from_input,
|
||||||
|
.call_arg,
|
||||||
|
.fn_proto_param,
|
||||||
=> .{
|
=> .{
|
||||||
.file_scope = decl.getFileScope(mod),
|
.file_scope = decl.getFileScope(mod),
|
||||||
.parent_decl_node = decl.src_node,
|
.parent_decl_node = decl.src_node,
|
||||||
|
|
@ -3373,8 +3194,6 @@ pub fn deinit(mod: *Module) void {
|
||||||
mod.global_error_set.deinit(gpa);
|
mod.global_error_set.deinit(gpa);
|
||||||
|
|
||||||
mod.test_functions.deinit(gpa);
|
mod.test_functions.deinit(gpa);
|
||||||
mod.align_stack_fns.deinit(gpa);
|
|
||||||
mod.monomorphed_funcs.deinit(gpa);
|
|
||||||
|
|
||||||
mod.decls_free_list.deinit(gpa);
|
mod.decls_free_list.deinit(gpa);
|
||||||
mod.allocated_decls.deinit(gpa);
|
mod.allocated_decls.deinit(gpa);
|
||||||
|
|
@ -3407,7 +3226,6 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (decl.src_scope) |scope| scope.decRef(gpa);
|
if (decl.src_scope) |scope| scope.decRef(gpa);
|
||||||
decl.clearValues(mod);
|
|
||||||
decl.dependants.deinit(gpa);
|
decl.dependants.deinit(gpa);
|
||||||
decl.dependencies.deinit(gpa);
|
decl.dependencies.deinit(gpa);
|
||||||
decl.* = undefined;
|
decl.* = undefined;
|
||||||
|
|
@ -3439,11 +3257,7 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {
|
||||||
return mod.intern_pool.structPtr(index);
|
return mod.intern_pool.structPtr(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn funcPtr(mod: *Module, index: Fn.Index) *Fn {
|
pub fn inferredErrorSetPtr(mod: *Module, index: InferredErrorSet.Index) *InferredErrorSet {
|
||||||
return mod.intern_pool.funcPtr(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.InferredErrorSet {
|
|
||||||
return mod.intern_pool.inferredErrorSetPtr(index);
|
return mod.intern_pool.inferredErrorSetPtr(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3457,10 +3271,6 @@ pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {
|
||||||
return mod.structPtr(index.unwrap() orelse return null);
|
return mod.structPtr(index.unwrap() orelse return null);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn funcPtrUnwrap(mod: *Module, index: Fn.OptionalIndex) ?*Fn {
|
|
||||||
return mod.funcPtr(index.unwrap() orelse return null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if and only if the Decl is the top level struct associated with a File.
|
/// Returns true if and only if the Decl is the top level struct associated with a File.
|
||||||
pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
|
pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
|
|
@ -3881,6 +3691,8 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
|
||||||
// to re-generate ZIR for the File.
|
// to re-generate ZIR for the File.
|
||||||
try file.outdated_decls.append(gpa, root_decl);
|
try file.outdated_decls.append(gpa, root_decl);
|
||||||
|
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
|
|
||||||
while (decl_stack.popOrNull()) |decl_index| {
|
while (decl_stack.popOrNull()) |decl_index| {
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
// Anonymous decls and the root decl have this set to 0. We still need
|
// Anonymous decls and the root decl have this set to 0. We still need
|
||||||
|
|
@ -3918,7 +3730,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decl.getOwnedFunction(mod)) |func| {
|
if (decl.getOwnedFunction(mod)) |func| {
|
||||||
func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {
|
func.zirBodyInst(ip).* = inst_map.get(func.zir_body_inst) orelse {
|
||||||
try file.deleted_decls.append(gpa, decl_index);
|
try file.deleted_decls.append(gpa, decl_index);
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
@ -4101,11 +3913,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
|
||||||
// prior to re-analysis.
|
// prior to re-analysis.
|
||||||
try mod.deleteDeclExports(decl_index);
|
try mod.deleteDeclExports(decl_index);
|
||||||
|
|
||||||
// Similarly, `@setAlignStack` invocations will be re-discovered.
|
|
||||||
if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
|
|
||||||
_ = mod.align_stack_fns.remove(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dependencies will be re-discovered, so we remove them here prior to re-analysis.
|
// Dependencies will be re-discovered, so we remove them here prior to re-analysis.
|
||||||
for (decl.dependencies.keys()) |dep_index| {
|
for (decl.dependencies.keys()) |dep_index| {
|
||||||
const dep = mod.declPtr(dep_index);
|
const dep = mod.declPtr(dep_index);
|
||||||
|
|
@ -4189,11 +3996,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void {
|
pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaError!void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
const func = mod.funcPtr(func_index);
|
const ip = &mod.intern_pool;
|
||||||
|
const func = mod.funcInfo(func_index);
|
||||||
const decl_index = func.owner_decl;
|
const decl_index = func.owner_decl;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
|
|
||||||
|
|
@ -4211,7 +4019,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
|
||||||
=> return error.AnalysisFail,
|
=> return error.AnalysisFail,
|
||||||
|
|
||||||
.complete, .codegen_failure_retryable => {
|
.complete, .codegen_failure_retryable => {
|
||||||
switch (func.state) {
|
switch (func.analysis(ip).state) {
|
||||||
.sema_failure, .dependency_failure => return error.AnalysisFail,
|
.sema_failure, .dependency_failure => return error.AnalysisFail,
|
||||||
.none, .queued => {},
|
.none, .queued => {},
|
||||||
.in_progress => unreachable,
|
.in_progress => unreachable,
|
||||||
|
|
@ -4227,11 +4035,11 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
|
||||||
|
|
||||||
var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
|
var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
|
||||||
error.AnalysisFail => {
|
error.AnalysisFail => {
|
||||||
if (func.state == .in_progress) {
|
if (func.analysis(ip).state == .in_progress) {
|
||||||
// If this decl caused the compile error, the analysis field would
|
// If this decl caused the compile error, the analysis field would
|
||||||
// be changed to indicate it was this Decl's fault. Because this
|
// be changed to indicate it was this Decl's fault. Because this
|
||||||
// did not happen, we infer here that it was a dependency failure.
|
// did not happen, we infer here that it was a dependency failure.
|
||||||
func.state = .dependency_failure;
|
func.analysis(ip).state = .dependency_failure;
|
||||||
}
|
}
|
||||||
return error.AnalysisFail;
|
return error.AnalysisFail;
|
||||||
},
|
},
|
||||||
|
|
@ -4251,14 +4059,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
|
||||||
|
|
||||||
if (no_bin_file and !dump_air and !dump_llvm_ir) return;
|
if (no_bin_file and !dump_air and !dump_llvm_ir) return;
|
||||||
|
|
||||||
var liveness = try Liveness.analyze(gpa, air, &mod.intern_pool);
|
var liveness = try Liveness.analyze(gpa, air, ip);
|
||||||
defer liveness.deinit(gpa);
|
defer liveness.deinit(gpa);
|
||||||
|
|
||||||
if (dump_air) {
|
if (dump_air) {
|
||||||
const fqn = try decl.getFullyQualifiedName(mod);
|
const fqn = try decl.getFullyQualifiedName(mod);
|
||||||
std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(&mod.intern_pool)});
|
std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)});
|
||||||
@import("print_air.zig").dump(mod, air, liveness);
|
@import("print_air.zig").dump(mod, air, liveness);
|
||||||
std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(&mod.intern_pool)});
|
std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std.debug.runtime_safety) {
|
if (std.debug.runtime_safety) {
|
||||||
|
|
@ -4266,7 +4074,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
|
||||||
.gpa = gpa,
|
.gpa = gpa,
|
||||||
.air = air,
|
.air = air,
|
||||||
.liveness = liveness,
|
.liveness = liveness,
|
||||||
.intern_pool = &mod.intern_pool,
|
.intern_pool = ip,
|
||||||
};
|
};
|
||||||
defer verify.deinit();
|
defer verify.deinit();
|
||||||
|
|
||||||
|
|
@ -4321,8 +4129,9 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
|
||||||
/// analyzed, and for ensuring it can exist at runtime (see
|
/// analyzed, and for ensuring it can exist at runtime (see
|
||||||
/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
|
/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
|
||||||
/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.
|
/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.
|
||||||
pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
|
pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) !void {
|
||||||
const func = mod.funcPtr(func_index);
|
const ip = &mod.intern_pool;
|
||||||
|
const func = mod.funcInfo(func_index);
|
||||||
const decl_index = func.owner_decl;
|
const decl_index = func.owner_decl;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
|
|
||||||
|
|
@ -4348,7 +4157,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
|
||||||
|
|
||||||
assert(decl.has_tv);
|
assert(decl.has_tv);
|
||||||
|
|
||||||
switch (func.state) {
|
switch (func.analysis(ip).state) {
|
||||||
.none => {},
|
.none => {},
|
||||||
.queued => return,
|
.queued => return,
|
||||||
// As above, we don't need to forward errors here.
|
// As above, we don't need to forward errors here.
|
||||||
|
|
@ -4366,7 +4175,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
|
||||||
// since the last update
|
// since the last update
|
||||||
try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });
|
try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });
|
||||||
}
|
}
|
||||||
func.state = .queued;
|
func.analysis(ip).state = .queued;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void {
|
pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void {
|
||||||
|
|
@ -4490,10 +4299,8 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
|
||||||
.code = file.zir,
|
.code = file.zir,
|
||||||
.owner_decl = new_decl,
|
.owner_decl = new_decl,
|
||||||
.owner_decl_index = new_decl_index,
|
.owner_decl_index = new_decl_index,
|
||||||
.func = null,
|
|
||||||
.func_index = .none,
|
.func_index = .none,
|
||||||
.fn_ret_ty = Type.void,
|
.fn_ret_ty = Type.void,
|
||||||
.owner_func = null,
|
|
||||||
.owner_func_index = .none,
|
.owner_func_index = .none,
|
||||||
.comptime_mutable_decls = &comptime_mutable_decls,
|
.comptime_mutable_decls = &comptime_mutable_decls,
|
||||||
};
|
};
|
||||||
|
|
@ -4573,10 +4380,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||||
.code = zir,
|
.code = zir,
|
||||||
.owner_decl = decl,
|
.owner_decl = decl,
|
||||||
.owner_decl_index = decl_index,
|
.owner_decl_index = decl_index,
|
||||||
.func = null,
|
|
||||||
.func_index = .none,
|
.func_index = .none,
|
||||||
.fn_ret_ty = Type.void,
|
.fn_ret_ty = Type.void,
|
||||||
.owner_func = null,
|
|
||||||
.owner_func_index = .none,
|
.owner_func_index = .none,
|
||||||
.comptime_mutable_decls = &comptime_mutable_decls,
|
.comptime_mutable_decls = &comptime_mutable_decls,
|
||||||
};
|
};
|
||||||
|
|
@ -4658,8 +4463,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mod.intern_pool.indexToFunc(decl_tv.val.toIntern()).unwrap()) |func_index| {
|
const ip = &mod.intern_pool;
|
||||||
const func = mod.funcPtr(func_index);
|
switch (ip.indexToKey(decl_tv.val.toIntern())) {
|
||||||
|
.func => |func| {
|
||||||
const owns_tv = func.owner_decl == decl_index;
|
const owns_tv = func.owner_decl == decl_index;
|
||||||
if (owns_tv) {
|
if (owns_tv) {
|
||||||
var prev_type_has_bits = false;
|
var prev_type_has_bits = false;
|
||||||
|
|
@ -4670,10 +4476,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||||
prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
|
prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
|
||||||
type_changed = !decl.ty.eql(decl_tv.ty, mod);
|
type_changed = !decl.ty.eql(decl_tv.ty, mod);
|
||||||
if (decl.getOwnedFunction(mod)) |prev_func| {
|
if (decl.getOwnedFunction(mod)) |prev_func| {
|
||||||
prev_is_inline = prev_func.state == .inline_only;
|
prev_is_inline = prev_func.analysis(ip).state == .inline_only;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
decl.clearValues(mod);
|
|
||||||
|
|
||||||
decl.ty = decl_tv.ty;
|
decl.ty = decl_tv.ty;
|
||||||
decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
|
decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
|
||||||
|
|
@ -4694,12 +4499,13 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||||
}
|
}
|
||||||
return type_changed or is_inline != prev_is_inline;
|
return type_changed or is_inline != prev_is_inline;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
}
|
}
|
||||||
var type_changed = true;
|
var type_changed = true;
|
||||||
if (decl.has_tv) {
|
if (decl.has_tv) {
|
||||||
type_changed = !decl.ty.eql(decl_tv.ty, mod);
|
type_changed = !decl.ty.eql(decl_tv.ty, mod);
|
||||||
}
|
}
|
||||||
decl.clearValues(mod);
|
|
||||||
|
|
||||||
decl.owns_tv = false;
|
decl.owns_tv = false;
|
||||||
var queue_linker_work = false;
|
var queue_linker_work = false;
|
||||||
|
|
@ -4707,7 +4513,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||||
switch (decl_tv.val.toIntern()) {
|
switch (decl_tv.val.toIntern()) {
|
||||||
.generic_poison => unreachable,
|
.generic_poison => unreachable,
|
||||||
.unreachable_value => unreachable,
|
.unreachable_value => unreachable,
|
||||||
else => switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {
|
else => switch (ip.indexToKey(decl_tv.val.toIntern())) {
|
||||||
.variable => |variable| if (variable.decl == decl_index) {
|
.variable => |variable| if (variable.decl == decl_index) {
|
||||||
decl.owns_tv = true;
|
decl.owns_tv = true;
|
||||||
queue_linker_work = true;
|
queue_linker_work = true;
|
||||||
|
|
@ -4743,11 +4549,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||||
} else if (bytes.len == 0) {
|
} else if (bytes.len == 0) {
|
||||||
return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
|
return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
|
||||||
}
|
}
|
||||||
const section = try mod.intern_pool.getOrPutString(gpa, bytes);
|
const section = try ip.getOrPutString(gpa, bytes);
|
||||||
break :blk section.toOptional();
|
break :blk section.toOptional();
|
||||||
};
|
};
|
||||||
decl.@"addrspace" = blk: {
|
decl.@"addrspace" = blk: {
|
||||||
const addrspace_ctx: Sema.AddressSpaceContext = switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {
|
const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) {
|
||||||
.variable => .variable,
|
.variable => .variable,
|
||||||
.extern_func, .func => .function,
|
.extern_func, .func => .function,
|
||||||
else => .constant,
|
else => .constant,
|
||||||
|
|
@ -5309,7 +5115,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
|
||||||
decl.has_align = has_align;
|
decl.has_align = has_align;
|
||||||
decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
|
decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
|
||||||
decl.zir_decl_index = @as(u32, @intCast(decl_sub_index));
|
decl.zir_decl_index = @as(u32, @intCast(decl_sub_index));
|
||||||
if (decl.getOwnedFunctionIndex(mod) != .none) {
|
if (decl.getOwnedFunctionIndex() != .none) {
|
||||||
switch (comp.bin_file.tag) {
|
switch (comp.bin_file.tag) {
|
||||||
.coff, .elf, .macho, .plan9 => {
|
.coff, .elf, .macho, .plan9 => {
|
||||||
// TODO Look into detecting when this would be unnecessary by storing enough state
|
// TODO Look into detecting when this would be unnecessary by storing enough state
|
||||||
|
|
@ -5386,7 +5192,6 @@ pub fn clearDecl(
|
||||||
try namespace.deleteAllDecls(mod, outdated_decls);
|
try namespace.deleteAllDecls(mod, outdated_decls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
decl.clearValues(mod);
|
|
||||||
|
|
||||||
if (decl.deletion_flag) {
|
if (decl.deletion_flag) {
|
||||||
decl.deletion_flag = false;
|
decl.deletion_flag = false;
|
||||||
|
|
@ -5497,19 +5302,26 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void
|
||||||
export_owners.deinit(mod.gpa);
|
export_owners.deinit(mod.gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaError!Air {
|
pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocator) SemaError!Air {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
const gpa = mod.gpa;
|
const gpa = mod.gpa;
|
||||||
const func = mod.funcPtr(func_index);
|
const ip = &mod.intern_pool;
|
||||||
|
const func = mod.funcInfo(func_index);
|
||||||
const decl_index = func.owner_decl;
|
const decl_index = func.owner_decl;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
|
|
||||||
var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
|
var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
|
||||||
defer comptime_mutable_decls.deinit();
|
defer comptime_mutable_decls.deinit();
|
||||||
|
|
||||||
|
// In the case of a generic function instance, this is the type of the
|
||||||
|
// instance, which has comptime parameters elided. In other words, it is
|
||||||
|
// the runtime-known parameters only, not to be confused with the
|
||||||
|
// generic_owner function type, which potentially has more parameters,
|
||||||
|
// including comptime parameters.
|
||||||
const fn_ty = decl.ty;
|
const fn_ty = decl.ty;
|
||||||
|
const fn_ty_info = mod.typeToFunc(fn_ty).?;
|
||||||
|
|
||||||
var sema: Sema = .{
|
var sema: Sema = .{
|
||||||
.mod = mod,
|
.mod = mod,
|
||||||
|
|
@ -5518,18 +5330,16 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
|
||||||
.code = decl.getFileScope(mod).zir,
|
.code = decl.getFileScope(mod).zir,
|
||||||
.owner_decl = decl,
|
.owner_decl = decl,
|
||||||
.owner_decl_index = decl_index,
|
.owner_decl_index = decl_index,
|
||||||
.func = func,
|
.func_index = func_index,
|
||||||
.func_index = func_index.toOptional(),
|
.fn_ret_ty = fn_ty_info.return_type.toType(),
|
||||||
.fn_ret_ty = mod.typeToFunc(fn_ty).?.return_type.toType(),
|
.owner_func_index = func_index,
|
||||||
.owner_func = func,
|
.branch_quota = @max(func.branchQuota(ip).*, Sema.default_branch_quota),
|
||||||
.owner_func_index = func_index.toOptional(),
|
|
||||||
.branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
|
|
||||||
.comptime_mutable_decls = &comptime_mutable_decls,
|
.comptime_mutable_decls = &comptime_mutable_decls,
|
||||||
};
|
};
|
||||||
defer sema.deinit();
|
defer sema.deinit();
|
||||||
|
|
||||||
// reset in case calls to errorable functions are removed.
|
// reset in case calls to errorable functions are removed.
|
||||||
func.calls_or_awaits_errorable_fn = false;
|
func.analysis(ip).calls_or_awaits_errorable_fn = false;
|
||||||
|
|
||||||
// First few indexes of extra are reserved and set at the end.
|
// First few indexes of extra are reserved and set at the end.
|
||||||
const reserved_count = @typeInfo(Air.ExtraIndex).Enum.fields.len;
|
const reserved_count = @typeInfo(Air.ExtraIndex).Enum.fields.len;
|
||||||
|
|
@ -5551,8 +5361,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
|
||||||
};
|
};
|
||||||
defer inner_block.instructions.deinit(gpa);
|
defer inner_block.instructions.deinit(gpa);
|
||||||
|
|
||||||
const fn_info = sema.code.getFnInfo(func.zir_body_inst);
|
const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).*);
|
||||||
const zir_tags = sema.code.instructions.items(.tag);
|
|
||||||
|
|
||||||
// Here we are performing "runtime semantic analysis" for a function body, which means
|
// Here we are performing "runtime semantic analysis" for a function body, which means
|
||||||
// we must map the parameter ZIR instructions to `arg` AIR instructions.
|
// we must map the parameter ZIR instructions to `arg` AIR instructions.
|
||||||
|
|
@ -5560,35 +5369,36 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
|
||||||
// This could be a generic function instantiation, however, in which case we need to
|
// This could be a generic function instantiation, however, in which case we need to
|
||||||
// map the comptime parameters to constant values and only emit arg AIR instructions
|
// map the comptime parameters to constant values and only emit arg AIR instructions
|
||||||
// for the runtime ones.
|
// for the runtime ones.
|
||||||
const runtime_params_len = @as(u32, @intCast(mod.typeToFunc(fn_ty).?.param_types.len));
|
const runtime_params_len = fn_ty_info.param_types.len;
|
||||||
try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);
|
try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);
|
||||||
try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`
|
try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len);
|
||||||
try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
|
try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
|
||||||
|
|
||||||
var runtime_param_index: usize = 0;
|
// In the case of a generic function instance, pre-populate all the comptime args.
|
||||||
var total_param_index: usize = 0;
|
if (func.comptime_args.len != 0) {
|
||||||
for (fn_info.param_body) |inst| {
|
for (
|
||||||
switch (zir_tags[inst]) {
|
fn_info.param_body[0..func.comptime_args.len],
|
||||||
.param, .param_comptime, .param_anytype, .param_anytype_comptime => {},
|
func.comptime_args.get(ip),
|
||||||
else => continue,
|
) |inst, comptime_arg| {
|
||||||
|
if (comptime_arg == .none) continue;
|
||||||
|
sema.inst_map.putAssumeCapacityNoClobber(inst, Air.internedToRef(comptime_arg));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const param_ty = if (func.comptime_args) |comptime_args| t: {
|
|
||||||
const arg_tv = comptime_args[total_param_index];
|
|
||||||
|
|
||||||
const arg_val = if (!arg_tv.val.isGenericPoison())
|
const src_params_len = if (func.comptime_args.len != 0)
|
||||||
arg_tv.val
|
func.comptime_args.len
|
||||||
else if (try arg_tv.ty.onePossibleValue(mod)) |opv|
|
|
||||||
opv
|
|
||||||
else
|
else
|
||||||
break :t arg_tv.ty;
|
runtime_params_len;
|
||||||
|
|
||||||
const arg = try sema.addConstant(arg_val);
|
var runtime_param_index: usize = 0;
|
||||||
sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
|
for (fn_info.param_body[0..src_params_len], 0..) |inst, src_param_index| {
|
||||||
total_param_index += 1;
|
const gop = sema.inst_map.getOrPutAssumeCapacity(inst);
|
||||||
continue;
|
if (gop.found_existing) continue; // provided above by comptime arg
|
||||||
} else mod.typeToFunc(fn_ty).?.param_types[runtime_param_index].toType();
|
|
||||||
|
|
||||||
const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {
|
const param_ty = fn_ty_info.param_types.get(ip)[runtime_param_index];
|
||||||
|
runtime_param_index += 1;
|
||||||
|
|
||||||
|
const opt_opv = sema.typeHasOnePossibleValue(param_ty.toType()) catch |err| switch (err) {
|
||||||
error.NeededSourceLocation => unreachable,
|
error.NeededSourceLocation => unreachable,
|
||||||
error.GenericPoison => unreachable,
|
error.GenericPoison => unreachable,
|
||||||
error.ComptimeReturn => unreachable,
|
error.ComptimeReturn => unreachable,
|
||||||
|
|
@ -5596,28 +5406,22 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
|
||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
if (opt_opv) |opv| {
|
if (opt_opv) |opv| {
|
||||||
const arg = try sema.addConstant(opv);
|
gop.value_ptr.* = Air.internedToRef(opv.toIntern());
|
||||||
sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
|
|
||||||
total_param_index += 1;
|
|
||||||
runtime_param_index += 1;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const air_ty = try sema.addType(param_ty);
|
const arg_index: u32 = @intCast(sema.air_instructions.len);
|
||||||
const arg_index = @as(u32, @intCast(sema.air_instructions.len));
|
gop.value_ptr.* = Air.indexToRef(arg_index);
|
||||||
inner_block.instructions.appendAssumeCapacity(arg_index);
|
inner_block.instructions.appendAssumeCapacity(arg_index);
|
||||||
sema.air_instructions.appendAssumeCapacity(.{
|
sema.air_instructions.appendAssumeCapacity(.{
|
||||||
.tag = .arg,
|
.tag = .arg,
|
||||||
.data = .{ .arg = .{
|
.data = .{ .arg = .{
|
||||||
.ty = air_ty,
|
.ty = Air.internedToRef(param_ty),
|
||||||
.src_index = @as(u32, @intCast(total_param_index)),
|
.src_index = @intCast(src_param_index),
|
||||||
} },
|
} },
|
||||||
});
|
});
|
||||||
sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index));
|
|
||||||
total_param_index += 1;
|
|
||||||
runtime_param_index += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func.state = .in_progress;
|
func.analysis(ip).state = .in_progress;
|
||||||
|
|
||||||
const last_arg_index = inner_block.instructions.items.len;
|
const last_arg_index = inner_block.instructions.items.len;
|
||||||
|
|
||||||
|
|
@ -5648,7 +5452,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we don't get an error return trace from a caller, create our own.
|
// If we don't get an error return trace from a caller, create our own.
|
||||||
if (func.calls_or_awaits_errorable_fn and
|
if (func.analysis(ip).calls_or_awaits_errorable_fn and
|
||||||
mod.comp.bin_file.options.error_return_tracing and
|
mod.comp.bin_file.options.error_return_tracing and
|
||||||
!sema.fn_ret_ty.isError(mod))
|
!sema.fn_ret_ty.isError(mod))
|
||||||
{
|
{
|
||||||
|
|
@ -5677,7 +5481,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
|
||||||
sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);
|
sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);
|
||||||
sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index;
|
sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index;
|
||||||
|
|
||||||
func.state = .success;
|
func.analysis(ip).state = .success;
|
||||||
|
|
||||||
// Finally we must resolve the return type and parameter types so that backends
|
// Finally we must resolve the return type and parameter types so that backends
|
||||||
// have full access to type information.
|
// have full access to type information.
|
||||||
|
|
@ -5716,7 +5520,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return Air{
|
return .{
|
||||||
.instructions = sema.air_instructions.toOwnedSlice(),
|
.instructions = sema.air_instructions.toOwnedSlice(),
|
||||||
.extra = try sema.air_extra.toOwnedSlice(gpa),
|
.extra = try sema.air_extra.toOwnedSlice(gpa),
|
||||||
};
|
};
|
||||||
|
|
@ -5731,9 +5535,6 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
|
||||||
if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
|
if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
|
||||||
for (kv.value) |err| err.deinit(mod.gpa);
|
for (kv.value) |err| err.deinit(mod.gpa);
|
||||||
}
|
}
|
||||||
if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
|
|
||||||
_ = mod.align_stack_fns.remove(func);
|
|
||||||
}
|
|
||||||
if (mod.emit_h) |emit_h| {
|
if (mod.emit_h) |emit_h| {
|
||||||
if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
|
if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
|
||||||
kv.value.destroy(mod.gpa);
|
kv.value.destroy(mod.gpa);
|
||||||
|
|
@ -5777,14 +5578,6 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void {
|
||||||
return mod.intern_pool.destroyUnion(mod.gpa, index);
|
return mod.intern_pool.destroyUnion(mod.gpa, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createFunc(mod: *Module, initialization: Fn) Allocator.Error!Fn.Index {
|
|
||||||
return mod.intern_pool.createFunc(mod.gpa, initialization);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn destroyFunc(mod: *Module, index: Fn.Index) void {
|
|
||||||
return mod.intern_pool.destroyFunc(mod.gpa, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn allocateNewDecl(
|
pub fn allocateNewDecl(
|
||||||
mod: *Module,
|
mod: *Module,
|
||||||
namespace: Namespace.Index,
|
namespace: Namespace.Index,
|
||||||
|
|
@ -6578,7 +6371,6 @@ pub fn populateTestFunctions(
|
||||||
|
|
||||||
// Since we are replacing the Decl's value we must perform cleanup on the
|
// Since we are replacing the Decl's value we must perform cleanup on the
|
||||||
// previous value.
|
// previous value.
|
||||||
decl.clearValues(mod);
|
|
||||||
decl.ty = new_ty;
|
decl.ty = new_ty;
|
||||||
decl.val = new_val;
|
decl.val = new_val;
|
||||||
decl.has_tv = true;
|
decl.has_tv = true;
|
||||||
|
|
@ -6657,7 +6449,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {
|
||||||
switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||||
.variable => |variable| try mod.markDeclIndexAlive(variable.decl),
|
.variable => |variable| try mod.markDeclIndexAlive(variable.decl),
|
||||||
.extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl),
|
.extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl),
|
||||||
.func => |func| try mod.markDeclIndexAlive(mod.funcPtr(func.index).owner_decl),
|
.func => |func| try mod.markDeclIndexAlive(func.owner_decl),
|
||||||
.error_union => |error_union| switch (error_union.val) {
|
.error_union => |error_union| switch (error_union.val) {
|
||||||
.err_name => {},
|
.err_name => {},
|
||||||
.payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()),
|
.payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()),
|
||||||
|
|
@ -6851,8 +6643,8 @@ pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator
|
||||||
return mod.ptrType(info);
|
return mod.ptrType(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn funcType(mod: *Module, info: InternPool.Key.FuncType) Allocator.Error!Type {
|
pub fn funcType(mod: *Module, key: InternPool.GetFuncTypeKey) Allocator.Error!Type {
|
||||||
return (try intern(mod, .{ .func_type = info })).toType();
|
return (try mod.intern_pool.getFuncType(mod.gpa, key)).toType();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use this for `anyframe->T` only.
|
/// Use this for `anyframe->T` only.
|
||||||
|
|
@ -7231,16 +7023,28 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType {
|
||||||
return mod.intern_pool.indexToFuncType(ty.toIntern());
|
return mod.intern_pool.indexToFuncType(ty.toIntern());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*Fn.InferredErrorSet {
|
pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*InferredErrorSet {
|
||||||
const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null;
|
const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null;
|
||||||
return mod.inferredErrorSetPtr(index);
|
return mod.inferredErrorSetPtr(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) Fn.InferredErrorSet.OptionalIndex {
|
pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) InferredErrorSet.OptionalIndex {
|
||||||
if (ty.ip_index == .none) return .none;
|
if (ty.ip_index == .none) return .none;
|
||||||
return mod.intern_pool.indexToInferredErrorSetType(ty.toIntern());
|
return mod.intern_pool.indexToInferredErrorSetType(ty.toIntern());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn funcOwnerDeclPtr(mod: *Module, func_index: InternPool.Index) *Decl {
|
||||||
|
return mod.declPtr(mod.funcOwnerDeclIndex(func_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn funcOwnerDeclIndex(mod: *Module, func_index: InternPool.Index) Decl.Index {
|
||||||
|
return mod.funcInfo(func_index).owner_decl;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn funcInfo(mod: *Module, func_index: InternPool.Index) InternPool.Key.Func {
|
||||||
|
return mod.intern_pool.indexToKey(func_index).func;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {
|
pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {
|
||||||
@setCold(true);
|
@setCold(true);
|
||||||
const owner_decl = mod.declPtr(owner_decl_index);
|
const owner_decl = mod.declPtr(owner_decl_index);
|
||||||
|
|
@ -7265,3 +7069,57 @@ pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQu
|
||||||
pub fn toEnum(mod: *Module, comptime E: type, val: Value) E {
|
pub fn toEnum(mod: *Module, comptime E: type, val: Value) E {
|
||||||
return mod.intern_pool.toEnum(E, val.toIntern());
|
return mod.intern_pool.toEnum(E, val.toIntern());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn isAnytypeParam(mod: *Module, func: InternPool.Index, index: u32) bool {
|
||||||
|
const file = mod.declPtr(func.owner_decl).getFileScope(mod);
|
||||||
|
|
||||||
|
const tags = file.zir.instructions.items(.tag);
|
||||||
|
|
||||||
|
const param_body = file.zir.getParamBody(func.zir_body_inst);
|
||||||
|
const param = param_body[index];
|
||||||
|
|
||||||
|
return switch (tags[param]) {
|
||||||
|
.param, .param_comptime => false,
|
||||||
|
.param_anytype, .param_anytype_comptime => true,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0]const u8 {
|
||||||
|
const func = mod.funcInfo(func_index);
|
||||||
|
const file = mod.declPtr(func.owner_decl).getFileScope(mod);
|
||||||
|
|
||||||
|
const tags = file.zir.instructions.items(.tag);
|
||||||
|
const data = file.zir.instructions.items(.data);
|
||||||
|
|
||||||
|
const param_body = file.zir.getParamBody(func.zir_body_inst);
|
||||||
|
const param = param_body[index];
|
||||||
|
|
||||||
|
return switch (tags[param]) {
|
||||||
|
.param, .param_comptime => blk: {
|
||||||
|
const extra = file.zir.extraData(Zir.Inst.Param, data[param].pl_tok.payload_index);
|
||||||
|
break :blk file.zir.nullTerminatedString(extra.data.name);
|
||||||
|
},
|
||||||
|
.param_anytype, .param_anytype_comptime => blk: {
|
||||||
|
const param_data = data[param].str_tok;
|
||||||
|
break :blk param_data.get(file.zir);
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hasInferredErrorSet(mod: *Module, func: InternPool.Key.Func) bool {
|
||||||
|
const owner_decl = mod.declPtr(func.owner_decl);
|
||||||
|
const zir = owner_decl.getFileScope(mod).zir;
|
||||||
|
const zir_tags = zir.instructions.items(.tag);
|
||||||
|
switch (zir_tags[func.zir_body_inst]) {
|
||||||
|
.func => return false,
|
||||||
|
.func_inferred => return true,
|
||||||
|
.func_fancy => {
|
||||||
|
const inst_data = zir.instructions.items(.data)[func.zir_body_inst].pl_node;
|
||||||
|
const extra = zir.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
|
||||||
|
return extra.data.bits.is_inferred_error;
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
1477
src/Sema.zig
1477
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),
|
mod.declPtr(extern_func.decl).name.fmt(ip),
|
||||||
}),
|
}),
|
||||||
.func => |func| return writer.print("(function '{}')", .{
|
.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) {
|
.int => |int| switch (int.storage) {
|
||||||
inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
|
inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
|
||||||
|
|
|
||||||
17
src/Zir.zig
17
src/Zir.zig
|
|
@ -90,13 +90,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 {
|
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) {
|
while (code.string_bytes[end] != 0) {
|
||||||
end += 1;
|
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 {
|
pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
|
||||||
const TypedValue = @import("../../TypedValue.zig");
|
const TypedValue = @import("../../TypedValue.zig");
|
||||||
const link = @import("../../link.zig");
|
const link = @import("../../link.zig");
|
||||||
const Module = @import("../../Module.zig");
|
const Module = @import("../../Module.zig");
|
||||||
|
const InternPool = @import("../../InternPool.zig");
|
||||||
const Compilation = @import("../../Compilation.zig");
|
const Compilation = @import("../../Compilation.zig");
|
||||||
const ErrorMsg = Module.ErrorMsg;
|
const ErrorMsg = Module.ErrorMsg;
|
||||||
const Target = std.Target;
|
const Target = std.Target;
|
||||||
|
|
@ -49,7 +50,8 @@ liveness: Liveness,
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
debug_output: DebugInfoOutput,
|
debug_output: DebugInfoOutput,
|
||||||
target: *const std.Target,
|
target: *const std.Target,
|
||||||
mod_fn: *const Module.Fn,
|
func_index: InternPool.Index,
|
||||||
|
owner_decl: Module.Decl.Index,
|
||||||
err_msg: ?*ErrorMsg,
|
err_msg: ?*ErrorMsg,
|
||||||
args: []MCValue,
|
args: []MCValue,
|
||||||
ret_mcv: MCValue,
|
ret_mcv: MCValue,
|
||||||
|
|
@ -199,7 +201,7 @@ const DbgInfoReloc = struct {
|
||||||
else => unreachable, // not a possible argument
|
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 => {},
|
.plan9 => {},
|
||||||
.none => {},
|
.none => {},
|
||||||
|
|
@ -245,7 +247,7 @@ const DbgInfoReloc = struct {
|
||||||
break :blk .nop;
|
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 => {},
|
.plan9 => {},
|
||||||
.none => {},
|
.none => {},
|
||||||
|
|
@ -328,7 +330,7 @@ const Self = @This();
|
||||||
pub fn generate(
|
pub fn generate(
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
src_loc: Module.SrcLoc,
|
src_loc: Module.SrcLoc,
|
||||||
module_fn_index: Module.Fn.Index,
|
func_index: InternPool.Index,
|
||||||
air: Air,
|
air: Air,
|
||||||
liveness: Liveness,
|
liveness: Liveness,
|
||||||
code: *std.ArrayList(u8),
|
code: *std.ArrayList(u8),
|
||||||
|
|
@ -339,8 +341,8 @@ pub fn generate(
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = bin_file.options.module.?;
|
const mod = bin_file.options.module.?;
|
||||||
const module_fn = mod.funcPtr(module_fn_index);
|
const func = mod.funcInfo(func_index);
|
||||||
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
|
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||||
assert(fn_owner_decl.has_tv);
|
assert(fn_owner_decl.has_tv);
|
||||||
const fn_type = fn_owner_decl.ty;
|
const fn_type = fn_owner_decl.ty;
|
||||||
|
|
||||||
|
|
@ -359,7 +361,8 @@ pub fn generate(
|
||||||
.debug_output = debug_output,
|
.debug_output = debug_output,
|
||||||
.target = &bin_file.options.target,
|
.target = &bin_file.options.target,
|
||||||
.bin_file = bin_file,
|
.bin_file = bin_file,
|
||||||
.mod_fn = module_fn,
|
.func_index = func_index,
|
||||||
|
.owner_decl = func.owner_decl,
|
||||||
.err_msg = null,
|
.err_msg = null,
|
||||||
.args = undefined, // populated after `resolveCallingConventionValues`
|
.args = undefined, // populated after `resolveCallingConventionValues`
|
||||||
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
|
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
|
||||||
|
|
@ -368,8 +371,8 @@ pub fn generate(
|
||||||
.branch_stack = &branch_stack,
|
.branch_stack = &branch_stack,
|
||||||
.src_loc = src_loc,
|
.src_loc = src_loc,
|
||||||
.stack_align = undefined,
|
.stack_align = undefined,
|
||||||
.end_di_line = module_fn.rbrace_line,
|
.end_di_line = func.rbrace_line,
|
||||||
.end_di_column = module_fn.rbrace_column,
|
.end_di_column = func.rbrace_column,
|
||||||
};
|
};
|
||||||
defer function.stack.deinit(bin_file.allocator);
|
defer function.stack.deinit(bin_file.allocator);
|
||||||
defer function.blocks.deinit(bin_file.allocator);
|
defer function.blocks.deinit(bin_file.allocator);
|
||||||
|
|
@ -416,8 +419,8 @@ pub fn generate(
|
||||||
.src_loc = src_loc,
|
.src_loc = src_loc,
|
||||||
.code = code,
|
.code = code,
|
||||||
.prev_di_pc = 0,
|
.prev_di_pc = 0,
|
||||||
.prev_di_line = module_fn.lbrace_line,
|
.prev_di_line = func.lbrace_line,
|
||||||
.prev_di_column = module_fn.lbrace_column,
|
.prev_di_column = func.lbrace_column,
|
||||||
.stack_size = function.max_end_stack,
|
.stack_size = function.max_end_stack,
|
||||||
.saved_regs_stack_space = function.saved_regs_stack_space,
|
.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) {
|
const atom_index = switch (self.bin_file.tag) {
|
||||||
.macho => blk: {
|
.macho => blk: {
|
||||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
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().?;
|
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||||
},
|
},
|
||||||
.coff => blk: {
|
.coff => blk: {
|
||||||
const coff_file = self.bin_file.cast(link.File.Coff).?;
|
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().?;
|
break :blk coff_file.getAtom(atom).getSymbolIndex().?;
|
||||||
},
|
},
|
||||||
else => unreachable, // unsupported target format
|
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;
|
while (self.args[arg_index] == .none) arg_index += 1;
|
||||||
self.arg_index = arg_index + 1;
|
self.arg_index = arg_index + 1;
|
||||||
|
|
||||||
|
const mod = self.bin_file.options.module.?;
|
||||||
const ty = self.typeOfIndex(inst);
|
const ty = self.typeOfIndex(inst);
|
||||||
const tag = self.air.instructions.items(.tag)[inst];
|
const tag = self.air.instructions.items(.tag)[inst];
|
||||||
const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
|
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, .{
|
try self.dbg_info_relocs.append(self.gpa, .{
|
||||||
.tag = tag,
|
.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);
|
const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
|
||||||
if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||||
const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
|
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().?;
|
const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
|
||||||
_ = try self.addInst(.{
|
_ = try self.addInst(.{
|
||||||
.tag = .call_extern,
|
.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 {
|
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||||
const mod = self.bin_file.options.module.?;
|
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
|
// TODO emit debug info for function change
|
||||||
_ = function;
|
_ = func;
|
||||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
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) {
|
const atom_index = switch (self.bin_file.tag) {
|
||||||
.macho => blk: {
|
.macho => blk: {
|
||||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
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().?;
|
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||||
},
|
},
|
||||||
.coff => blk: {
|
.coff => blk: {
|
||||||
const coff_file = self.bin_file.cast(link.File.Coff).?;
|
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().?;
|
break :blk coff_file.getAtom(atom).getSymbolIndex().?;
|
||||||
},
|
},
|
||||||
else => unreachable, // unsupported target format
|
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) {
|
const atom_index = switch (self.bin_file.tag) {
|
||||||
.macho => blk: {
|
.macho => blk: {
|
||||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
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().?;
|
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||||
},
|
},
|
||||||
.coff => blk: {
|
.coff => blk: {
|
||||||
const coff_file = self.bin_file.cast(link.File.Coff).?;
|
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().?;
|
break :blk coff_file.getAtom(atom).getSymbolIndex().?;
|
||||||
},
|
},
|
||||||
else => unreachable, // unsupported target format
|
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) {
|
const atom_index = switch (self.bin_file.tag) {
|
||||||
.macho => blk: {
|
.macho => blk: {
|
||||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
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().?;
|
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||||
},
|
},
|
||||||
.coff => blk: {
|
.coff => blk: {
|
||||||
const coff_file = self.bin_file.cast(link.File.Coff).?;
|
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().?;
|
break :blk coff_file.getAtom(atom).getSymbolIndex().?;
|
||||||
},
|
},
|
||||||
else => unreachable, // unsupported target format
|
else => unreachable, // unsupported target format
|
||||||
|
|
@ -6164,7 +6168,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
|
||||||
self.bin_file,
|
self.bin_file,
|
||||||
self.src_loc,
|
self.src_loc,
|
||||||
arg_tv,
|
arg_tv,
|
||||||
self.mod_fn.owner_decl,
|
self.owner_decl,
|
||||||
)) {
|
)) {
|
||||||
.mcv => |mcv| switch (mcv) {
|
.mcv => |mcv| switch (mcv) {
|
||||||
.none => .none,
|
.none => .none,
|
||||||
|
|
@ -6198,6 +6202,7 @@ const CallMCValues = struct {
|
||||||
/// Caller must call `CallMCValues.deinit`.
|
/// Caller must call `CallMCValues.deinit`.
|
||||||
fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||||
const mod = self.bin_file.options.module.?;
|
const mod = self.bin_file.options.module.?;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||||
const cc = fn_info.cc;
|
const cc = fn_info.cc;
|
||||||
var result: CallMCValues = .{
|
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)));
|
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||||
if (param_size == 0) {
|
if (param_size == 0) {
|
||||||
result.args[i] = .{ .none = {} };
|
result_arg.* = .{ .none = {} };
|
||||||
continue;
|
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 (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
|
||||||
if (param_size <= 8) {
|
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;
|
ncrn += 1;
|
||||||
} else {
|
} else {
|
||||||
return self.fail("TODO MCValues with multiple registers", .{});
|
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;
|
nsaa += param_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6305,16 +6310,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||||
|
|
||||||
var stack_offset: u32 = 0;
|
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) {
|
if (ty.toType().abiSize(mod) > 0) {
|
||||||
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||||
const param_alignment = ty.toType().abiAlignment(mod);
|
const param_alignment = ty.toType().abiAlignment(mod);
|
||||||
|
|
||||||
stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);
|
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;
|
stack_offset += param_size;
|
||||||
} else {
|
} else {
|
||||||
result.args[i] = .{ .none = {} };
|
result_arg.* = .{ .none = {} };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
|
||||||
const TypedValue = @import("../../TypedValue.zig");
|
const TypedValue = @import("../../TypedValue.zig");
|
||||||
const link = @import("../../link.zig");
|
const link = @import("../../link.zig");
|
||||||
const Module = @import("../../Module.zig");
|
const Module = @import("../../Module.zig");
|
||||||
|
const InternPool = @import("../../InternPool.zig");
|
||||||
const Compilation = @import("../../Compilation.zig");
|
const Compilation = @import("../../Compilation.zig");
|
||||||
const ErrorMsg = Module.ErrorMsg;
|
const ErrorMsg = Module.ErrorMsg;
|
||||||
const Target = std.Target;
|
const Target = std.Target;
|
||||||
|
|
@ -50,7 +51,7 @@ liveness: Liveness,
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
debug_output: DebugInfoOutput,
|
debug_output: DebugInfoOutput,
|
||||||
target: *const std.Target,
|
target: *const std.Target,
|
||||||
mod_fn: *const Module.Fn,
|
func_index: InternPool.Index,
|
||||||
err_msg: ?*ErrorMsg,
|
err_msg: ?*ErrorMsg,
|
||||||
args: []MCValue,
|
args: []MCValue,
|
||||||
ret_mcv: MCValue,
|
ret_mcv: MCValue,
|
||||||
|
|
@ -258,6 +259,7 @@ const DbgInfoReloc = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {
|
fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {
|
||||||
|
const mod = function.bin_file.options.module.?;
|
||||||
switch (function.debug_output) {
|
switch (function.debug_output) {
|
||||||
.dwarf => |dw| {
|
.dwarf => |dw| {
|
||||||
const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) {
|
const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) {
|
||||||
|
|
@ -278,7 +280,7 @@ const DbgInfoReloc = struct {
|
||||||
else => unreachable, // not a possible argument
|
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 => {},
|
.plan9 => {},
|
||||||
.none => {},
|
.none => {},
|
||||||
|
|
@ -286,6 +288,7 @@ const DbgInfoReloc = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
|
fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
|
||||||
|
const mod = function.bin_file.options.module.?;
|
||||||
const is_ptr = switch (reloc.tag) {
|
const is_ptr = switch (reloc.tag) {
|
||||||
.dbg_var_ptr => true,
|
.dbg_var_ptr => true,
|
||||||
.dbg_var_val => false,
|
.dbg_var_val => false,
|
||||||
|
|
@ -321,7 +324,7 @@ const DbgInfoReloc = struct {
|
||||||
break :blk .nop;
|
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 => {},
|
.plan9 => {},
|
||||||
.none => {},
|
.none => {},
|
||||||
|
|
@ -334,7 +337,7 @@ const Self = @This();
|
||||||
pub fn generate(
|
pub fn generate(
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
src_loc: Module.SrcLoc,
|
src_loc: Module.SrcLoc,
|
||||||
module_fn_index: Module.Fn.Index,
|
func_index: InternPool.Index,
|
||||||
air: Air,
|
air: Air,
|
||||||
liveness: Liveness,
|
liveness: Liveness,
|
||||||
code: *std.ArrayList(u8),
|
code: *std.ArrayList(u8),
|
||||||
|
|
@ -345,8 +348,8 @@ pub fn generate(
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = bin_file.options.module.?;
|
const mod = bin_file.options.module.?;
|
||||||
const module_fn = mod.funcPtr(module_fn_index);
|
const func = mod.funcInfo(func_index);
|
||||||
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
|
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||||
assert(fn_owner_decl.has_tv);
|
assert(fn_owner_decl.has_tv);
|
||||||
const fn_type = fn_owner_decl.ty;
|
const fn_type = fn_owner_decl.ty;
|
||||||
|
|
||||||
|
|
@ -365,7 +368,7 @@ pub fn generate(
|
||||||
.target = &bin_file.options.target,
|
.target = &bin_file.options.target,
|
||||||
.bin_file = bin_file,
|
.bin_file = bin_file,
|
||||||
.debug_output = debug_output,
|
.debug_output = debug_output,
|
||||||
.mod_fn = module_fn,
|
.func_index = func_index,
|
||||||
.err_msg = null,
|
.err_msg = null,
|
||||||
.args = undefined, // populated after `resolveCallingConventionValues`
|
.args = undefined, // populated after `resolveCallingConventionValues`
|
||||||
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
|
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
|
||||||
|
|
@ -374,8 +377,8 @@ pub fn generate(
|
||||||
.branch_stack = &branch_stack,
|
.branch_stack = &branch_stack,
|
||||||
.src_loc = src_loc,
|
.src_loc = src_loc,
|
||||||
.stack_align = undefined,
|
.stack_align = undefined,
|
||||||
.end_di_line = module_fn.rbrace_line,
|
.end_di_line = func.rbrace_line,
|
||||||
.end_di_column = module_fn.rbrace_column,
|
.end_di_column = func.rbrace_column,
|
||||||
};
|
};
|
||||||
defer function.stack.deinit(bin_file.allocator);
|
defer function.stack.deinit(bin_file.allocator);
|
||||||
defer function.blocks.deinit(bin_file.allocator);
|
defer function.blocks.deinit(bin_file.allocator);
|
||||||
|
|
@ -422,8 +425,8 @@ pub fn generate(
|
||||||
.src_loc = src_loc,
|
.src_loc = src_loc,
|
||||||
.code = code,
|
.code = code,
|
||||||
.prev_di_pc = 0,
|
.prev_di_pc = 0,
|
||||||
.prev_di_line = module_fn.lbrace_line,
|
.prev_di_line = func.lbrace_line,
|
||||||
.prev_di_column = module_fn.lbrace_column,
|
.prev_di_column = func.lbrace_column,
|
||||||
.stack_size = function.max_end_stack,
|
.stack_size = function.max_end_stack,
|
||||||
.saved_regs_stack_space = function.saved_regs_stack_space,
|
.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;
|
while (self.args[arg_index] == .none) arg_index += 1;
|
||||||
self.arg_index = arg_index + 1;
|
self.arg_index = arg_index + 1;
|
||||||
|
|
||||||
|
const mod = self.bin_file.options.module.?;
|
||||||
const ty = self.typeOfIndex(inst);
|
const ty = self.typeOfIndex(inst);
|
||||||
const tag = self.air.instructions.items(.tag)[inst];
|
const tag = self.air.instructions.items(.tag)[inst];
|
||||||
const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
|
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, .{
|
try self.dbg_info_relocs.append(self.gpa, .{
|
||||||
.tag = tag,
|
.tag = tag,
|
||||||
|
|
@ -4569,9 +4573,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
fn airDbgInline(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 ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||||
const mod = self.bin_file.options.module.?;
|
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
|
// TODO emit debug info for function change
|
||||||
_ = function;
|
_ = func;
|
||||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
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 {
|
fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
|
||||||
|
const mod = self.bin_file.options.module.?;
|
||||||
const mcv: MCValue = switch (try codegen.genTypedValue(
|
const mcv: MCValue = switch (try codegen.genTypedValue(
|
||||||
self.bin_file,
|
self.bin_file,
|
||||||
self.src_loc,
|
self.src_loc,
|
||||||
arg_tv,
|
arg_tv,
|
||||||
self.mod_fn.owner_decl,
|
mod.funcOwnerDeclIndex(self.func_index),
|
||||||
)) {
|
)) {
|
||||||
.mcv => |mcv| switch (mcv) {
|
.mcv => |mcv| switch (mcv) {
|
||||||
.none => .none,
|
.none => .none,
|
||||||
|
|
@ -6149,6 +6154,7 @@ const CallMCValues = struct {
|
||||||
/// Caller must call `CallMCValues.deinit`.
|
/// Caller must call `CallMCValues.deinit`.
|
||||||
fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||||
const mod = self.bin_file.options.module.?;
|
const mod = self.bin_file.options.module.?;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||||
const cc = fn_info.cc;
|
const cc = fn_info.cc;
|
||||||
var result: CallMCValues = .{
|
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)
|
if (ty.toType().abiAlignment(mod) == 8)
|
||||||
ncrn = std.mem.alignForward(usize, ncrn, 2);
|
ncrn = std.mem.alignForward(usize, ncrn, 2);
|
||||||
|
|
||||||
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||||
if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
|
if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
|
||||||
if (param_size <= 4) {
|
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;
|
ncrn += 1;
|
||||||
} else {
|
} else {
|
||||||
return self.fail("TODO MCValues with multiple registers", .{});
|
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)
|
if (ty.toType().abiAlignment(mod) == 8)
|
||||||
nsaa = std.mem.alignForward(u32, nsaa, 8);
|
nsaa = std.mem.alignForward(u32, nsaa, 8);
|
||||||
|
|
||||||
result.args[i] = .{ .stack_argument_offset = nsaa };
|
result_arg.* = .{ .stack_argument_offset = nsaa };
|
||||||
nsaa += param_size;
|
nsaa += param_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6244,16 +6250,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||||
|
|
||||||
var stack_offset: u32 = 0;
|
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) {
|
if (ty.toType().abiSize(mod) > 0) {
|
||||||
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||||
const param_alignment = ty.toType().abiAlignment(mod);
|
const param_alignment = ty.toType().abiAlignment(mod);
|
||||||
|
|
||||||
stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);
|
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;
|
stack_offset += param_size;
|
||||||
} else {
|
} else {
|
||||||
result.args[i] = .{ .none = {} };
|
result_arg.* = .{ .none = {} };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ const Value = @import("../../value.zig").Value;
|
||||||
const TypedValue = @import("../../TypedValue.zig");
|
const TypedValue = @import("../../TypedValue.zig");
|
||||||
const link = @import("../../link.zig");
|
const link = @import("../../link.zig");
|
||||||
const Module = @import("../../Module.zig");
|
const Module = @import("../../Module.zig");
|
||||||
|
const InternPool = @import("../../InternPool.zig");
|
||||||
const Compilation = @import("../../Compilation.zig");
|
const Compilation = @import("../../Compilation.zig");
|
||||||
const ErrorMsg = Module.ErrorMsg;
|
const ErrorMsg = Module.ErrorMsg;
|
||||||
const Target = std.Target;
|
const Target = std.Target;
|
||||||
|
|
@ -43,7 +44,7 @@ air: Air,
|
||||||
liveness: Liveness,
|
liveness: Liveness,
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
target: *const std.Target,
|
target: *const std.Target,
|
||||||
mod_fn: *const Module.Fn,
|
func_index: InternPool.Index,
|
||||||
code: *std.ArrayList(u8),
|
code: *std.ArrayList(u8),
|
||||||
debug_output: DebugInfoOutput,
|
debug_output: DebugInfoOutput,
|
||||||
err_msg: ?*ErrorMsg,
|
err_msg: ?*ErrorMsg,
|
||||||
|
|
@ -217,7 +218,7 @@ const Self = @This();
|
||||||
pub fn generate(
|
pub fn generate(
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
src_loc: Module.SrcLoc,
|
src_loc: Module.SrcLoc,
|
||||||
module_fn_index: Module.Fn.Index,
|
func_index: InternPool.Index,
|
||||||
air: Air,
|
air: Air,
|
||||||
liveness: Liveness,
|
liveness: Liveness,
|
||||||
code: *std.ArrayList(u8),
|
code: *std.ArrayList(u8),
|
||||||
|
|
@ -228,8 +229,8 @@ pub fn generate(
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = bin_file.options.module.?;
|
const mod = bin_file.options.module.?;
|
||||||
const module_fn = mod.funcPtr(module_fn_index);
|
const func = mod.funcInfo(func_index);
|
||||||
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
|
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||||
assert(fn_owner_decl.has_tv);
|
assert(fn_owner_decl.has_tv);
|
||||||
const fn_type = fn_owner_decl.ty;
|
const fn_type = fn_owner_decl.ty;
|
||||||
|
|
||||||
|
|
@ -247,7 +248,7 @@ pub fn generate(
|
||||||
.liveness = liveness,
|
.liveness = liveness,
|
||||||
.target = &bin_file.options.target,
|
.target = &bin_file.options.target,
|
||||||
.bin_file = bin_file,
|
.bin_file = bin_file,
|
||||||
.mod_fn = module_fn,
|
.func_index = func_index,
|
||||||
.code = code,
|
.code = code,
|
||||||
.debug_output = debug_output,
|
.debug_output = debug_output,
|
||||||
.err_msg = null,
|
.err_msg = null,
|
||||||
|
|
@ -258,8 +259,8 @@ pub fn generate(
|
||||||
.branch_stack = &branch_stack,
|
.branch_stack = &branch_stack,
|
||||||
.src_loc = src_loc,
|
.src_loc = src_loc,
|
||||||
.stack_align = undefined,
|
.stack_align = undefined,
|
||||||
.end_di_line = module_fn.rbrace_line,
|
.end_di_line = func.rbrace_line,
|
||||||
.end_di_column = module_fn.rbrace_column,
|
.end_di_column = func.rbrace_column,
|
||||||
};
|
};
|
||||||
defer function.stack.deinit(bin_file.allocator);
|
defer function.stack.deinit(bin_file.allocator);
|
||||||
defer function.blocks.deinit(bin_file.allocator);
|
defer function.blocks.deinit(bin_file.allocator);
|
||||||
|
|
@ -301,8 +302,8 @@ pub fn generate(
|
||||||
.src_loc = src_loc,
|
.src_loc = src_loc,
|
||||||
.code = code,
|
.code = code,
|
||||||
.prev_di_pc = 0,
|
.prev_di_pc = 0,
|
||||||
.prev_di_line = module_fn.lbrace_line,
|
.prev_di_line = func.lbrace_line,
|
||||||
.prev_di_column = module_fn.lbrace_column,
|
.prev_di_column = func.lbrace_column,
|
||||||
};
|
};
|
||||||
defer emit.deinit();
|
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 {
|
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 arg = self.air.instructions.items(.data)[inst].arg;
|
||||||
const ty = self.air.getRefType(arg.ty);
|
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) {
|
switch (self.debug_output) {
|
||||||
.dwarf => |dw| switch (mcv) {
|
.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(),
|
.register = reg.dwarfLocOp(),
|
||||||
}),
|
}),
|
||||||
.stack_offset => {},
|
.stack_offset => {},
|
||||||
|
|
@ -1742,7 +1745,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
}
|
}
|
||||||
|
|
||||||
if (try self.air.value(callee, mod)) |func_value| {
|
if (try self.air.value(callee, mod)) |func_value| {
|
||||||
if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
|
switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
|
||||||
|
.func => |func| {
|
||||||
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
||||||
const atom = elf_file.getAtom(atom_index);
|
const atom = elf_file.getAtom(atom_index);
|
||||||
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
|
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
|
||||||
|
|
@ -1756,10 +1760,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
.imm12 = 0,
|
.imm12 = 0,
|
||||||
} },
|
} },
|
||||||
});
|
});
|
||||||
} else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
|
},
|
||||||
|
.extern_func => {
|
||||||
return self.fail("TODO implement calling extern functions", .{});
|
return self.fail("TODO implement calling extern functions", .{});
|
||||||
} else {
|
},
|
||||||
|
else => {
|
||||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return self.fail("TODO implement calling runtime-known function pointer", .{});
|
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 {
|
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||||
const mod = self.bin_file.options.module.?;
|
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
|
// TODO emit debug info for function change
|
||||||
_ = function;
|
_ = func;
|
||||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
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 {
|
fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
|
||||||
|
const mod = self.bin_file.options.module.?;
|
||||||
const mcv: MCValue = switch (try codegen.genTypedValue(
|
const mcv: MCValue = switch (try codegen.genTypedValue(
|
||||||
self.bin_file,
|
self.bin_file,
|
||||||
self.src_loc,
|
self.src_loc,
|
||||||
typed_value,
|
typed_value,
|
||||||
self.mod_fn.owner_decl,
|
mod.funcOwnerDeclIndex(self.func_index),
|
||||||
)) {
|
)) {
|
||||||
.mcv => |mcv| switch (mcv) {
|
.mcv => |mcv| switch (mcv) {
|
||||||
.none => .none,
|
.none => .none,
|
||||||
|
|
@ -2605,6 +2613,7 @@ const CallMCValues = struct {
|
||||||
/// Caller must call `CallMCValues.deinit`.
|
/// Caller must call `CallMCValues.deinit`.
|
||||||
fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||||
const mod = self.bin_file.options.module.?;
|
const mod = self.bin_file.options.module.?;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||||
const cc = fn_info.cc;
|
const cc = fn_info.cc;
|
||||||
var result: CallMCValues = .{
|
var result: CallMCValues = .{
|
||||||
|
|
@ -2636,14 +2645,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||||
var next_stack_offset: u32 = 0;
|
var next_stack_offset: u32 = 0;
|
||||||
const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };
|
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)));
|
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||||
if (param_size <= 8) {
|
if (param_size <= 8) {
|
||||||
if (next_register < argument_registers.len) {
|
if (next_register < argument_registers.len) {
|
||||||
result.args[i] = .{ .register = argument_registers[next_register] };
|
result_arg.* = .{ .register = argument_registers[next_register] };
|
||||||
next_register += 1;
|
next_register += 1;
|
||||||
} else {
|
} else {
|
||||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||||
next_register += next_stack_offset;
|
next_register += next_stack_offset;
|
||||||
}
|
}
|
||||||
} else if (param_size <= 16) {
|
} else if (param_size <= 16) {
|
||||||
|
|
@ -2652,11 +2661,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
|
||||||
} else if (next_register < argument_registers.len) {
|
} else if (next_register < argument_registers.len) {
|
||||||
return self.fail("TODO MCValues split register + stack", .{});
|
return self.fail("TODO MCValues split register + stack", .{});
|
||||||
} else {
|
} else {
|
||||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||||
next_register += next_stack_offset;
|
next_register += next_stack_offset;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||||
next_register += next_stack_offset;
|
next_register += next_stack_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ const Allocator = mem.Allocator;
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const link = @import("../../link.zig");
|
const link = @import("../../link.zig");
|
||||||
const Module = @import("../../Module.zig");
|
const Module = @import("../../Module.zig");
|
||||||
|
const InternPool = @import("../../InternPool.zig");
|
||||||
const TypedValue = @import("../../TypedValue.zig");
|
const TypedValue = @import("../../TypedValue.zig");
|
||||||
const ErrorMsg = Module.ErrorMsg;
|
const ErrorMsg = Module.ErrorMsg;
|
||||||
const codegen = @import("../../codegen.zig");
|
const codegen = @import("../../codegen.zig");
|
||||||
|
|
@ -52,7 +53,7 @@ air: Air,
|
||||||
liveness: Liveness,
|
liveness: Liveness,
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
target: *const std.Target,
|
target: *const std.Target,
|
||||||
mod_fn: *const Module.Fn,
|
func_index: InternPool.Index,
|
||||||
code: *std.ArrayList(u8),
|
code: *std.ArrayList(u8),
|
||||||
debug_output: DebugInfoOutput,
|
debug_output: DebugInfoOutput,
|
||||||
err_msg: ?*ErrorMsg,
|
err_msg: ?*ErrorMsg,
|
||||||
|
|
@ -260,7 +261,7 @@ const BigTomb = struct {
|
||||||
pub fn generate(
|
pub fn generate(
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
src_loc: Module.SrcLoc,
|
src_loc: Module.SrcLoc,
|
||||||
module_fn_index: Module.Fn.Index,
|
func_index: InternPool.Index,
|
||||||
air: Air,
|
air: Air,
|
||||||
liveness: Liveness,
|
liveness: Liveness,
|
||||||
code: *std.ArrayList(u8),
|
code: *std.ArrayList(u8),
|
||||||
|
|
@ -271,8 +272,8 @@ pub fn generate(
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = bin_file.options.module.?;
|
const mod = bin_file.options.module.?;
|
||||||
const module_fn = mod.funcPtr(module_fn_index);
|
const func = mod.funcInfo(func_index);
|
||||||
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
|
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||||
assert(fn_owner_decl.has_tv);
|
assert(fn_owner_decl.has_tv);
|
||||||
const fn_type = fn_owner_decl.ty;
|
const fn_type = fn_owner_decl.ty;
|
||||||
|
|
||||||
|
|
@ -289,8 +290,8 @@ pub fn generate(
|
||||||
.air = air,
|
.air = air,
|
||||||
.liveness = liveness,
|
.liveness = liveness,
|
||||||
.target = &bin_file.options.target,
|
.target = &bin_file.options.target,
|
||||||
|
.func_index = func_index,
|
||||||
.bin_file = bin_file,
|
.bin_file = bin_file,
|
||||||
.mod_fn = module_fn,
|
|
||||||
.code = code,
|
.code = code,
|
||||||
.debug_output = debug_output,
|
.debug_output = debug_output,
|
||||||
.err_msg = null,
|
.err_msg = null,
|
||||||
|
|
@ -301,8 +302,8 @@ pub fn generate(
|
||||||
.branch_stack = &branch_stack,
|
.branch_stack = &branch_stack,
|
||||||
.src_loc = src_loc,
|
.src_loc = src_loc,
|
||||||
.stack_align = undefined,
|
.stack_align = undefined,
|
||||||
.end_di_line = module_fn.rbrace_line,
|
.end_di_line = func.rbrace_line,
|
||||||
.end_di_column = module_fn.rbrace_column,
|
.end_di_column = func.rbrace_column,
|
||||||
};
|
};
|
||||||
defer function.stack.deinit(bin_file.allocator);
|
defer function.stack.deinit(bin_file.allocator);
|
||||||
defer function.blocks.deinit(bin_file.allocator);
|
defer function.blocks.deinit(bin_file.allocator);
|
||||||
|
|
@ -344,8 +345,8 @@ pub fn generate(
|
||||||
.src_loc = src_loc,
|
.src_loc = src_loc,
|
||||||
.code = code,
|
.code = code,
|
||||||
.prev_di_pc = 0,
|
.prev_di_pc = 0,
|
||||||
.prev_di_line = module_fn.lbrace_line,
|
.prev_di_line = func.lbrace_line,
|
||||||
.prev_di_column = module_fn.lbrace_column,
|
.prev_di_column = func.lbrace_column,
|
||||||
};
|
};
|
||||||
defer emit.deinit();
|
defer emit.deinit();
|
||||||
|
|
||||||
|
|
@ -1345,7 +1346,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
// on linking.
|
// on linking.
|
||||||
if (try self.air.value(callee, mod)) |func_value| {
|
if (try self.air.value(callee, mod)) |func_value| {
|
||||||
if (self.bin_file.tag == link.File.Elf.base_tag) {
|
if (self.bin_file.tag == link.File.Elf.base_tag) {
|
||||||
if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
|
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 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_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
||||||
const atom = elf_file.getAtom(atom_index);
|
const atom = elf_file.getAtom(atom_index);
|
||||||
|
|
@ -1372,10 +1374,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
.tag = .nop,
|
.tag = .nop,
|
||||||
.data = .{ .nop = {} },
|
.data = .{ .nop = {} },
|
||||||
});
|
});
|
||||||
} else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
|
},
|
||||||
|
.extern_func => {
|
||||||
return self.fail("TODO implement calling extern functions", .{});
|
return self.fail("TODO implement calling extern functions", .{});
|
||||||
} else {
|
},
|
||||||
|
else => {
|
||||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
} else @panic("TODO SPARCv9 currently does not support non-ELF binaries");
|
} else @panic("TODO SPARCv9 currently does not support non-ELF binaries");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1660,9 +1665,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
fn airDbgInline(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 ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||||
const mod = self.bin_file.options.module.?;
|
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
|
// TODO emit debug info for function change
|
||||||
_ = function;
|
_ = func;
|
||||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
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 {
|
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 arg = self.air.instructions.items(.data)[inst].arg;
|
||||||
const ty = self.air.getRefType(arg.ty);
|
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) {
|
switch (self.debug_output) {
|
||||||
.dwarf => |dw| switch (mcv) {
|
.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(),
|
.register = reg.dwarfLocOp(),
|
||||||
}),
|
}),
|
||||||
else => {},
|
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 {
|
fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
|
||||||
|
const mod = self.bin_file.options.module.?;
|
||||||
const mcv: MCValue = switch (try codegen.genTypedValue(
|
const mcv: MCValue = switch (try codegen.genTypedValue(
|
||||||
self.bin_file,
|
self.bin_file,
|
||||||
self.src_loc,
|
self.src_loc,
|
||||||
typed_value,
|
typed_value,
|
||||||
self.mod_fn.owner_decl,
|
mod.funcOwnerDeclIndex(self.func_index),
|
||||||
)) {
|
)) {
|
||||||
.mcv => |mcv| switch (mcv) {
|
.mcv => |mcv| switch (mcv) {
|
||||||
.none => .none,
|
.none => .none,
|
||||||
|
|
@ -4452,6 +4460,7 @@ fn realStackOffset(off: u32) u32 {
|
||||||
/// Caller must call `CallMCValues.deinit`.
|
/// Caller must call `CallMCValues.deinit`.
|
||||||
fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
|
fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
|
||||||
const mod = self.bin_file.options.module.?;
|
const mod = self.bin_file.options.module.?;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||||
const cc = fn_info.cc;
|
const cc = fn_info.cc;
|
||||||
var result: CallMCValues = .{
|
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,
|
.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)));
|
const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
|
||||||
if (param_size <= 8) {
|
if (param_size <= 8) {
|
||||||
if (next_register < argument_registers.len) {
|
if (next_register < argument_registers.len) {
|
||||||
result.args[i] = .{ .register = argument_registers[next_register] };
|
result_arg.* = .{ .register = argument_registers[next_register] };
|
||||||
next_register += 1;
|
next_register += 1;
|
||||||
} else {
|
} else {
|
||||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||||
next_register += next_stack_offset;
|
next_register += next_stack_offset;
|
||||||
}
|
}
|
||||||
} else if (param_size <= 16) {
|
} 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) {
|
} else if (next_register < argument_registers.len) {
|
||||||
return self.fail("TODO MCValues split register + stack", .{});
|
return self.fail("TODO MCValues split register + stack", .{});
|
||||||
} else {
|
} else {
|
||||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||||
next_register += next_stack_offset;
|
next_register += next_stack_offset;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result.args[i] = .{ .stack_offset = next_stack_offset };
|
result_arg.* = .{ .stack_offset = next_stack_offset };
|
||||||
next_register += next_stack_offset;
|
next_register += next_stack_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -650,7 +650,7 @@ air: Air,
|
||||||
liveness: Liveness,
|
liveness: Liveness,
|
||||||
gpa: mem.Allocator,
|
gpa: mem.Allocator,
|
||||||
debug_output: codegen.DebugInfoOutput,
|
debug_output: codegen.DebugInfoOutput,
|
||||||
mod_fn: *const Module.Fn,
|
func_index: InternPool.Index,
|
||||||
/// Contains a list of current branches.
|
/// Contains a list of current branches.
|
||||||
/// When we return from a branch, the branch will be popped from this list,
|
/// 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,
|
/// which means branches can only contain references from within its own branch,
|
||||||
|
|
@ -1202,7 +1202,7 @@ fn genFunctype(
|
||||||
pub fn generate(
|
pub fn generate(
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
src_loc: Module.SrcLoc,
|
src_loc: Module.SrcLoc,
|
||||||
func_index: Module.Fn.Index,
|
func_index: InternPool.Index,
|
||||||
air: Air,
|
air: Air,
|
||||||
liveness: Liveness,
|
liveness: Liveness,
|
||||||
code: *std.ArrayList(u8),
|
code: *std.ArrayList(u8),
|
||||||
|
|
@ -1210,7 +1210,7 @@ pub fn generate(
|
||||||
) codegen.CodeGenError!codegen.Result {
|
) codegen.CodeGenError!codegen.Result {
|
||||||
_ = src_loc;
|
_ = src_loc;
|
||||||
const mod = bin_file.options.module.?;
|
const mod = bin_file.options.module.?;
|
||||||
const func = mod.funcPtr(func_index);
|
const func = mod.funcInfo(func_index);
|
||||||
var code_gen: CodeGen = .{
|
var code_gen: CodeGen = .{
|
||||||
.gpa = bin_file.allocator,
|
.gpa = bin_file.allocator,
|
||||||
.air = air,
|
.air = air,
|
||||||
|
|
@ -1223,7 +1223,7 @@ pub fn generate(
|
||||||
.target = bin_file.options.target,
|
.target = bin_file.options.target,
|
||||||
.bin_file = bin_file.cast(link.File.Wasm).?,
|
.bin_file = bin_file.cast(link.File.Wasm).?,
|
||||||
.debug_output = debug_output,
|
.debug_output = debug_output,
|
||||||
.mod_fn = func,
|
.func_index = func_index,
|
||||||
};
|
};
|
||||||
defer code_gen.deinit();
|
defer code_gen.deinit();
|
||||||
|
|
||||||
|
|
@ -1237,8 +1237,9 @@ pub fn generate(
|
||||||
|
|
||||||
fn genFunc(func: *CodeGen) InnerError!void {
|
fn genFunc(func: *CodeGen) InnerError!void {
|
||||||
const mod = func.bin_file.base.options.module.?;
|
const mod = func.bin_file.base.options.module.?;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const fn_info = mod.typeToFunc(func.decl.ty).?;
|
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);
|
defer func_type.deinit(func.gpa);
|
||||||
_ = try func.bin_file.storeDeclType(func.decl_index, func_type);
|
_ = 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 {
|
fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {
|
||||||
const mod = func.bin_file.base.options.module.?;
|
const mod = func.bin_file.base.options.module.?;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||||
const cc = fn_info.cc;
|
const cc = fn_info.cc;
|
||||||
var result: CallWValues = .{
|
var result: CallWValues = .{
|
||||||
|
|
@ -1369,7 +1371,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
|
||||||
|
|
||||||
switch (cc) {
|
switch (cc) {
|
||||||
.Unspecified => {
|
.Unspecified => {
|
||||||
for (fn_info.param_types) |ty| {
|
for (fn_info.param_types.get(ip)) |ty| {
|
||||||
if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {
|
if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -1379,7 +1381,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.C => {
|
.C => {
|
||||||
for (fn_info.param_types) |ty| {
|
for (fn_info.param_types.get(ip)) |ty| {
|
||||||
const ty_classes = abi.classifyType(ty.toType(), mod);
|
const ty_classes = abi.classifyType(ty.toType(), mod);
|
||||||
for (ty_classes) |class| {
|
for (ty_classes) |class| {
|
||||||
if (class == .none) continue;
|
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 ty = func.typeOf(pl_op.operand);
|
||||||
|
|
||||||
const mod = func.bin_file.base.options.module.?;
|
const mod = func.bin_file.base.options.module.?;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const fn_ty = switch (ty.zigTypeTag(mod)) {
|
const fn_ty = switch (ty.zigTypeTag(mod)) {
|
||||||
.Fn => ty,
|
.Fn => ty,
|
||||||
.Pointer => ty.childType(mod),
|
.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| {
|
} else if (func_val.getExternFunc(mod)) |extern_func| {
|
||||||
const ext_decl = mod.declPtr(extern_func.decl);
|
const ext_decl = mod.declPtr(extern_func.decl);
|
||||||
const ext_info = mod.typeToFunc(ext_decl.ty).?;
|
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);
|
defer func_type.deinit(func.gpa);
|
||||||
const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);
|
const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);
|
||||||
const atom = func.bin_file.getAtomPtr(atom_index);
|
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);
|
const operand = try func.resolveInst(pl_op.operand);
|
||||||
try func.emitWValue(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);
|
defer fn_type.deinit(func.gpa);
|
||||||
|
|
||||||
const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type);
|
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) {
|
switch (func.debug_output) {
|
||||||
.dwarf => |dwarf| {
|
.dwarf => |dwarf| {
|
||||||
const src_index = func.air.instructions.items(.data)[inst].arg.src_index;
|
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);
|
const name = mod.getParamName(func.func_index, src_index);
|
||||||
try dwarf.genArgDbgInfo(name, arg_ty, func.mod_fn.owner_decl, .{
|
try dwarf.genArgDbgInfo(name, arg_ty, mod.funcOwnerDeclIndex(func.func_index), .{
|
||||||
.wasm_local = arg.local.value,
|
.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 {
|
fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
|
||||||
if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
|
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 pl_op = func.air.instructions.items(.data)[inst].pl_op;
|
||||||
const ty = func.typeOf(pl_op.operand);
|
const ty = func.typeOf(pl_op.operand);
|
||||||
const operand = try func.resolveInst(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;
|
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, &.{});
|
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 RegisterOffset = struct { reg: Register, off: i32 = 0 };
|
||||||
|
|
||||||
const Owner = union(enum) {
|
const Owner = union(enum) {
|
||||||
mod_fn: *const Module.Fn,
|
func_index: InternPool.Index,
|
||||||
lazy_sym: link.File.LazySymbol,
|
lazy_sym: link.File.LazySymbol,
|
||||||
|
|
||||||
fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index {
|
fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index {
|
||||||
return switch (owner) {
|
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),
|
.lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(mod),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 {
|
fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 {
|
||||||
switch (owner) {
|
switch (owner) {
|
||||||
.mod_fn => |mod_fn| {
|
.func_index => |func_index| {
|
||||||
const decl_index = mod_fn.owner_decl;
|
const mod = ctx.bin_file.options.module.?;
|
||||||
|
const decl_index = mod.funcOwnerDeclIndex(func_index);
|
||||||
if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {
|
if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||||
const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
|
const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
|
||||||
return macho_file.getAtom(atom).getSymbolIndex().?;
|
return macho_file.getAtom(atom).getSymbolIndex().?;
|
||||||
|
|
@ -638,7 +639,7 @@ const Self = @This();
|
||||||
pub fn generate(
|
pub fn generate(
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
src_loc: Module.SrcLoc,
|
src_loc: Module.SrcLoc,
|
||||||
module_fn_index: Module.Fn.Index,
|
func_index: InternPool.Index,
|
||||||
air: Air,
|
air: Air,
|
||||||
liveness: Liveness,
|
liveness: Liveness,
|
||||||
code: *std.ArrayList(u8),
|
code: *std.ArrayList(u8),
|
||||||
|
|
@ -649,8 +650,8 @@ pub fn generate(
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = bin_file.options.module.?;
|
const mod = bin_file.options.module.?;
|
||||||
const module_fn = mod.funcPtr(module_fn_index);
|
const func = mod.funcInfo(func_index);
|
||||||
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
|
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||||
assert(fn_owner_decl.has_tv);
|
assert(fn_owner_decl.has_tv);
|
||||||
const fn_type = fn_owner_decl.ty;
|
const fn_type = fn_owner_decl.ty;
|
||||||
|
|
||||||
|
|
@ -662,15 +663,15 @@ pub fn generate(
|
||||||
.target = &bin_file.options.target,
|
.target = &bin_file.options.target,
|
||||||
.bin_file = bin_file,
|
.bin_file = bin_file,
|
||||||
.debug_output = debug_output,
|
.debug_output = debug_output,
|
||||||
.owner = .{ .mod_fn = module_fn },
|
.owner = .{ .func_index = func_index },
|
||||||
.err_msg = null,
|
.err_msg = null,
|
||||||
.args = undefined, // populated after `resolveCallingConventionValues`
|
.args = undefined, // populated after `resolveCallingConventionValues`
|
||||||
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
|
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
|
||||||
.fn_type = fn_type,
|
.fn_type = fn_type,
|
||||||
.arg_index = 0,
|
.arg_index = 0,
|
||||||
.src_loc = src_loc,
|
.src_loc = src_loc,
|
||||||
.end_di_line = module_fn.rbrace_line,
|
.end_di_line = func.rbrace_line,
|
||||||
.end_di_column = module_fn.rbrace_column,
|
.end_di_column = func.rbrace_column,
|
||||||
};
|
};
|
||||||
defer {
|
defer {
|
||||||
function.frame_allocs.deinit(gpa);
|
function.frame_allocs.deinit(gpa);
|
||||||
|
|
@ -687,17 +688,16 @@ pub fn generate(
|
||||||
if (builtin.mode == .Debug) function.mir_to_air_map.deinit(gpa);
|
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);
|
try function.frame_allocs.resize(gpa, FrameIndex.named_count);
|
||||||
function.frame_allocs.set(
|
function.frame_allocs.set(
|
||||||
@intFromEnum(FrameIndex.stack_frame),
|
@intFromEnum(FrameIndex.stack_frame),
|
||||||
FrameAlloc.init(.{
|
FrameAlloc.init(.{
|
||||||
.size = 0,
|
.size = 0,
|
||||||
.alignment = if (mod.align_stack_fns.get(module_fn_index)) |set_align_stack|
|
.alignment = @intCast(func.analysis(ip).stack_alignment.toByteUnitsOptional() orelse 1),
|
||||||
@intCast(set_align_stack.alignment.toByteUnitsOptional().?)
|
|
||||||
else
|
|
||||||
1,
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
function.frame_allocs.set(
|
function.frame_allocs.set(
|
||||||
|
|
@ -761,8 +761,8 @@ pub fn generate(
|
||||||
.debug_output = debug_output,
|
.debug_output = debug_output,
|
||||||
.code = code,
|
.code = code,
|
||||||
.prev_di_pc = 0,
|
.prev_di_pc = 0,
|
||||||
.prev_di_line = module_fn.lbrace_line,
|
.prev_di_line = func.lbrace_line,
|
||||||
.prev_di_column = module_fn.lbrace_column,
|
.prev_di_column = func.lbrace_column,
|
||||||
};
|
};
|
||||||
defer emit.deinit();
|
defer emit.deinit();
|
||||||
emit.emitMir() catch |err| switch (err) {
|
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 ty = self.typeOfIndex(inst);
|
||||||
const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
|
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);
|
try self.genArgDbgInfo(ty, name, dst_mcv);
|
||||||
|
|
||||||
break :result 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| {
|
if (try self.air.value(callee, mod)) |func_value| {
|
||||||
const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
|
const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
|
||||||
if (switch (func_key) {
|
if (switch (func_key) {
|
||||||
.func => |func| mod.funcPtr(func.index).owner_decl,
|
.func => |func| func.owner_decl,
|
||||||
.ptr => |ptr| switch (ptr.addr) {
|
.ptr => |ptr| switch (ptr.addr) {
|
||||||
.decl => |decl| decl,
|
.decl => |decl| decl,
|
||||||
else => null,
|
else => null,
|
||||||
|
|
@ -8582,9 +8582,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
fn airDbgInline(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 ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||||
const mod = self.bin_file.options.module.?;
|
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
|
// TODO emit debug info for function change
|
||||||
_ = function;
|
_ = func;
|
||||||
return self.finishAir(inst, .unreach, .{ .none, .none, .none });
|
return self.finishAir(inst, .unreach, .{ .none, .none, .none });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -11719,11 +11719,12 @@ fn resolveCallingConventionValues(
|
||||||
stack_frame_base: FrameIndex,
|
stack_frame_base: FrameIndex,
|
||||||
) !CallMCValues {
|
) !CallMCValues {
|
||||||
const mod = self.bin_file.options.module.?;
|
const mod = self.bin_file.options.module.?;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const cc = fn_info.cc;
|
const cc = fn_info.cc;
|
||||||
const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
|
const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
|
||||||
defer self.gpa.free(param_types);
|
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();
|
dest.* = src.toType();
|
||||||
}
|
}
|
||||||
// TODO: promote var arg types
|
// TODO: promote var arg types
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {
|
||||||
pub fn generateFunction(
|
pub fn generateFunction(
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
src_loc: Module.SrcLoc,
|
src_loc: Module.SrcLoc,
|
||||||
func_index: Module.Fn.Index,
|
func_index: InternPool.Index,
|
||||||
air: Air,
|
air: Air,
|
||||||
liveness: Liveness,
|
liveness: Liveness,
|
||||||
code: *std.ArrayList(u8),
|
code: *std.ArrayList(u8),
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,8 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
|
||||||
return .{ .data = ident };
|
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.
|
/// It is not available when generating .h file.
|
||||||
pub const Function = struct {
|
pub const Function = struct {
|
||||||
air: Air,
|
air: Air,
|
||||||
|
|
@ -268,7 +269,7 @@ pub const Function = struct {
|
||||||
next_block_index: usize = 0,
|
next_block_index: usize = 0,
|
||||||
object: Object,
|
object: Object,
|
||||||
lazy_fns: LazyFnMap,
|
lazy_fns: LazyFnMap,
|
||||||
func_index: Module.Fn.Index,
|
func_index: InternPool.Index,
|
||||||
/// All the locals, to be emitted at the top of the function.
|
/// All the locals, to be emitted at the top of the function.
|
||||||
locals: std.ArrayListUnmanaged(Local) = .{},
|
locals: std.ArrayListUnmanaged(Local) = .{},
|
||||||
/// Which locals are available for reuse, based on Type.
|
/// Which locals are available for reuse, based on Type.
|
||||||
|
|
@ -1487,6 +1488,7 @@ pub const DeclGen = struct {
|
||||||
) !void {
|
) !void {
|
||||||
const store = &dg.ctypes.set;
|
const store = &dg.ctypes.set;
|
||||||
const mod = dg.module;
|
const mod = dg.module;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
|
|
||||||
const fn_decl = mod.declPtr(fn_decl_index);
|
const fn_decl = mod.declPtr(fn_decl_index);
|
||||||
const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);
|
const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);
|
||||||
|
|
@ -1499,7 +1501,7 @@ pub const DeclGen = struct {
|
||||||
else => unreachable,
|
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 ");
|
if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
|
||||||
|
|
||||||
const trailing = try renderTypePrefix(
|
const trailing = try renderTypePrefix(
|
||||||
|
|
@ -1744,7 +1746,7 @@ pub const DeclGen = struct {
|
||||||
return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
|
return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
|
||||||
.variable => |variable| mod.decl_exports.contains(variable.decl),
|
.variable => |variable| mod.decl_exports.contains(variable.decl),
|
||||||
.extern_func => true,
|
.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,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -4161,7 +4163,7 @@ fn airCall(
|
||||||
const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
|
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)) {
|
break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
|
||||||
.extern_func => |extern_func| extern_func.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) {
|
.ptr => |ptr| switch (ptr.addr) {
|
||||||
.decl => |decl| decl,
|
.decl => |decl| decl,
|
||||||
else => break :known,
|
else => break :known,
|
||||||
|
|
@ -4238,9 +4240,9 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||||
const ty_fn = f.air.instructions.items(.data)[inst].ty_fn;
|
const ty_fn = f.air.instructions.items(.data)[inst].ty_fn;
|
||||||
const mod = f.object.dg.module;
|
const mod = f.object.dg.module;
|
||||||
const writer = f.object.writer();
|
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", .{
|
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;
|
return .none;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1722,6 +1722,7 @@ pub const CType = extern union {
|
||||||
|
|
||||||
.Fn => {
|
.Fn => {
|
||||||
const info = mod.typeToFunc(ty).?;
|
const info = mod.typeToFunc(ty).?;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
if (!info.is_generic) {
|
if (!info.is_generic) {
|
||||||
if (lookup.isMutable()) {
|
if (lookup.isMutable()) {
|
||||||
const param_kind: Kind = switch (kind) {
|
const param_kind: Kind = switch (kind) {
|
||||||
|
|
@ -1730,7 +1731,7 @@ pub const CType = extern union {
|
||||||
.payload => unreachable,
|
.payload => unreachable,
|
||||||
};
|
};
|
||||||
_ = try lookup.typeToIndex(info.return_type.toType(), param_kind);
|
_ = 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;
|
if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||||
_ = try lookup.typeToIndex(param_type.toType(), param_kind);
|
_ = try lookup.typeToIndex(param_type.toType(), param_kind);
|
||||||
}
|
}
|
||||||
|
|
@ -2014,6 +2015,7 @@ pub const CType = extern union {
|
||||||
.function,
|
.function,
|
||||||
.varargs_function,
|
.varargs_function,
|
||||||
=> {
|
=> {
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const info = mod.typeToFunc(ty).?;
|
const info = mod.typeToFunc(ty).?;
|
||||||
assert(!info.is_generic);
|
assert(!info.is_generic);
|
||||||
const param_kind: Kind = switch (kind) {
|
const param_kind: Kind = switch (kind) {
|
||||||
|
|
@ -2023,14 +2025,14 @@ pub const CType = extern union {
|
||||||
};
|
};
|
||||||
|
|
||||||
var c_params_len: usize = 0;
|
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;
|
if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||||
c_params_len += 1;
|
c_params_len += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const params_pl = try arena.alloc(Index, c_params_len);
|
const params_pl = try arena.alloc(Index, c_params_len);
|
||||||
var c_param_i: usize = 0;
|
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 (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||||
params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;
|
params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;
|
||||||
c_param_i += 1;
|
c_param_i += 1;
|
||||||
|
|
@ -2147,6 +2149,7 @@ pub const CType = extern union {
|
||||||
=> {
|
=> {
|
||||||
if (ty.zigTypeTag(mod) != .Fn) return false;
|
if (ty.zigTypeTag(mod) != .Fn) return false;
|
||||||
|
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const info = mod.typeToFunc(ty).?;
|
const info = mod.typeToFunc(ty).?;
|
||||||
assert(!info.is_generic);
|
assert(!info.is_generic);
|
||||||
const data = cty.cast(Payload.Function).?.data;
|
const data = cty.cast(Payload.Function).?.data;
|
||||||
|
|
@ -2160,7 +2163,7 @@ pub const CType = extern union {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var c_param_i: usize = 0;
|
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 (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||||
|
|
||||||
if (c_param_i >= data.param_types.len) return false;
|
if (c_param_i >= data.param_types.len) return false;
|
||||||
|
|
@ -2202,6 +2205,7 @@ pub const CType = extern union {
|
||||||
autoHash(hasher, t);
|
autoHash(hasher, t);
|
||||||
|
|
||||||
const mod = self.lookup.getModule();
|
const mod = self.lookup.getModule();
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
switch (t) {
|
switch (t) {
|
||||||
.fwd_anon_struct,
|
.fwd_anon_struct,
|
||||||
.fwd_anon_union,
|
.fwd_anon_union,
|
||||||
|
|
@ -2270,7 +2274,7 @@ pub const CType = extern union {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind);
|
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;
|
if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||||
self.updateHasherRecurse(hasher, param_type.toType(), param_kind);
|
self.updateHasherRecurse(hasher, param_type.toType(), param_kind);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -867,14 +867,15 @@ pub const Object = struct {
|
||||||
pub fn updateFunc(
|
pub fn updateFunc(
|
||||||
o: *Object,
|
o: *Object,
|
||||||
mod: *Module,
|
mod: *Module,
|
||||||
func_index: Module.Fn.Index,
|
func_index: InternPool.Index,
|
||||||
air: Air,
|
air: Air,
|
||||||
liveness: Liveness,
|
liveness: Liveness,
|
||||||
) !void {
|
) !void {
|
||||||
const func = mod.funcPtr(func_index);
|
const func = mod.funcInfo(func_index);
|
||||||
const decl_index = func.owner_decl;
|
const decl_index = func.owner_decl;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
const target = mod.getTarget();
|
const target = mod.getTarget();
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
|
|
||||||
var dg: DeclGen = .{
|
var dg: DeclGen = .{
|
||||||
.object = o,
|
.object = o,
|
||||||
|
|
@ -885,26 +886,25 @@ pub const Object = struct {
|
||||||
|
|
||||||
const llvm_func = try o.resolveLlvmFunction(decl_index);
|
const llvm_func = try o.resolveLlvmFunction(decl_index);
|
||||||
|
|
||||||
if (mod.align_stack_fns.get(func_index)) |align_info| {
|
if (func.analysis(ip).is_noinline) {
|
||||||
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) {
|
|
||||||
o.addFnAttr(llvm_func, "noinline");
|
o.addFnAttr(llvm_func, "noinline");
|
||||||
} else {
|
} else {
|
||||||
Object.removeFnAttr(llvm_func, "noinline");
|
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
|
// TODO: disable this if safety is off for the function scope
|
||||||
const ssp_buf_size = mod.comp.bin_file.options.stack_protector;
|
const ssp_buf_size = mod.comp.bin_file.options.stack_protector;
|
||||||
if (ssp_buf_size != 0) {
|
if (ssp_buf_size != 0) {
|
||||||
|
|
@ -921,7 +921,7 @@ pub const Object = struct {
|
||||||
o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
|
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);
|
llvm_func.setSection(section);
|
||||||
|
|
||||||
// Remove all the basic blocks of a function in order to start over, generating
|
// Remove all the basic blocks of a function in order to start over, generating
|
||||||
|
|
@ -968,7 +968,7 @@ pub const Object = struct {
|
||||||
.byval => {
|
.byval => {
|
||||||
assert(!it.byval_attr);
|
assert(!it.byval_attr);
|
||||||
const param_index = it.zig_index - 1;
|
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);
|
const param = llvm_func.getParam(llvm_arg_i);
|
||||||
try args.ensureUnusedCapacity(1);
|
try args.ensureUnusedCapacity(1);
|
||||||
|
|
||||||
|
|
@ -987,7 +987,7 @@ pub const Object = struct {
|
||||||
llvm_arg_i += 1;
|
llvm_arg_i += 1;
|
||||||
},
|
},
|
||||||
.byref => {
|
.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_ty = try o.lowerType(param_ty);
|
||||||
const param = llvm_func.getParam(llvm_arg_i);
|
const param = llvm_func.getParam(llvm_arg_i);
|
||||||
const alignment = param_ty.abiAlignment(mod);
|
const alignment = param_ty.abiAlignment(mod);
|
||||||
|
|
@ -1006,7 +1006,7 @@ pub const Object = struct {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.byref_mut => {
|
.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_ty = try o.lowerType(param_ty);
|
||||||
const param = llvm_func.getParam(llvm_arg_i);
|
const param = llvm_func.getParam(llvm_arg_i);
|
||||||
const alignment = param_ty.abiAlignment(mod);
|
const alignment = param_ty.abiAlignment(mod);
|
||||||
|
|
@ -1026,7 +1026,7 @@ pub const Object = struct {
|
||||||
},
|
},
|
||||||
.abi_sized_int => {
|
.abi_sized_int => {
|
||||||
assert(!it.byval_attr);
|
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);
|
const param = llvm_func.getParam(llvm_arg_i);
|
||||||
llvm_arg_i += 1;
|
llvm_arg_i += 1;
|
||||||
|
|
||||||
|
|
@ -1053,7 +1053,7 @@ pub const Object = struct {
|
||||||
},
|
},
|
||||||
.slice => {
|
.slice => {
|
||||||
assert(!it.byval_attr);
|
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 ptr_info = param_ty.ptrInfo(mod);
|
||||||
|
|
||||||
if (math.cast(u5, it.zig_index - 1)) |i| {
|
if (math.cast(u5, it.zig_index - 1)) |i| {
|
||||||
|
|
@ -1083,7 +1083,7 @@ pub const Object = struct {
|
||||||
.multiple_llvm_types => {
|
.multiple_llvm_types => {
|
||||||
assert(!it.byval_attr);
|
assert(!it.byval_attr);
|
||||||
const field_types = it.llvm_types_buffer[0..it.llvm_types_len];
|
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_llvm_ty = try o.lowerType(param_ty);
|
||||||
const param_alignment = param_ty.abiAlignment(mod);
|
const param_alignment = param_ty.abiAlignment(mod);
|
||||||
const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);
|
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);
|
args.appendAssumeCapacity(casted);
|
||||||
},
|
},
|
||||||
.float_array => {
|
.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_ty = try o.lowerType(param_ty);
|
||||||
const param = llvm_func.getParam(llvm_arg_i);
|
const param = llvm_func.getParam(llvm_arg_i);
|
||||||
llvm_arg_i += 1;
|
llvm_arg_i += 1;
|
||||||
|
|
@ -1132,7 +1132,7 @@ pub const Object = struct {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.i32_array, .i64_array => {
|
.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_ty = try o.lowerType(param_ty);
|
||||||
const param = llvm_func.getParam(llvm_arg_i);
|
const param = llvm_func.getParam(llvm_arg_i);
|
||||||
llvm_arg_i += 1;
|
llvm_arg_i += 1;
|
||||||
|
|
@ -1168,7 +1168,7 @@ pub const Object = struct {
|
||||||
const decl_di_ty = try o.lowerDebugType(decl.ty, .full);
|
const decl_di_ty = try o.lowerDebugType(decl.ty, .full);
|
||||||
const subprogram = dib.createFunction(
|
const subprogram = dib.createFunction(
|
||||||
di_file.?.toScope(),
|
di_file.?.toScope(),
|
||||||
mod.intern_pool.stringToSlice(decl.name),
|
ip.stringToSlice(decl.name),
|
||||||
llvm_func.getValueName(),
|
llvm_func.getValueName(),
|
||||||
di_file.?,
|
di_file.?,
|
||||||
line_number,
|
line_number,
|
||||||
|
|
@ -1460,6 +1460,7 @@ pub const Object = struct {
|
||||||
const target = o.target;
|
const target = o.target;
|
||||||
const dib = o.di_builder.?;
|
const dib = o.di_builder.?;
|
||||||
const mod = o.module;
|
const mod = o.module;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
switch (ty.zigTypeTag(mod)) {
|
switch (ty.zigTypeTag(mod)) {
|
||||||
.Void, .NoReturn => {
|
.Void, .NoReturn => {
|
||||||
const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
|
const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
|
||||||
|
|
@ -1492,7 +1493,6 @@ pub const Object = struct {
|
||||||
return enum_di_ty;
|
return enum_di_ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ip = &mod.intern_pool;
|
|
||||||
const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
|
const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
|
||||||
|
|
||||||
const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);
|
const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);
|
||||||
|
|
@ -1518,7 +1518,7 @@ pub const Object = struct {
|
||||||
if (@sizeOf(usize) == @sizeOf(u64)) {
|
if (@sizeOf(usize) == @sizeOf(u64)) {
|
||||||
enumerators[i] = dib.createEnumerator2(
|
enumerators[i] = dib.createEnumerator2(
|
||||||
field_name_z,
|
field_name_z,
|
||||||
@as(c_uint, @intCast(bigint.limbs.len)),
|
@intCast(bigint.limbs.len),
|
||||||
bigint.limbs.ptr,
|
bigint.limbs.ptr,
|
||||||
int_info.bits,
|
int_info.bits,
|
||||||
int_info.signedness == .unsigned,
|
int_info.signedness == .unsigned,
|
||||||
|
|
@ -2320,8 +2320,8 @@ pub const Object = struct {
|
||||||
try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
|
try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (0..mod.typeToFunc(ty).?.param_types.len) |i| {
|
for (0..fn_info.param_types.len) |i| {
|
||||||
const param_ty = mod.typeToFunc(ty).?.param_types[i].toType();
|
const param_ty = fn_info.param_types.get(ip)[i].toType();
|
||||||
if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
|
if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||||
|
|
||||||
if (isByRef(param_ty, mod)) {
|
if (isByRef(param_ty, mod)) {
|
||||||
|
|
@ -2475,9 +2475,10 @@ pub const Object = struct {
|
||||||
const fn_type = try o.lowerType(zig_fn_type);
|
const fn_type = try o.lowerType(zig_fn_type);
|
||||||
|
|
||||||
const fqn = try decl.getFullyQualifiedName(mod);
|
const fqn = try decl.getFullyQualifiedName(mod);
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
|
|
||||||
const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
|
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;
|
gop.value_ptr.* = llvm_fn;
|
||||||
|
|
||||||
const is_extern = decl.isExtern(mod);
|
const is_extern = decl.isExtern(mod);
|
||||||
|
|
@ -2486,8 +2487,8 @@ pub const Object = struct {
|
||||||
llvm_fn.setUnnamedAddr(.True);
|
llvm_fn.setUnnamedAddr(.True);
|
||||||
} else {
|
} else {
|
||||||
if (target.isWasm()) {
|
if (target.isWasm()) {
|
||||||
o.addFnAttrString(llvm_fn, "wasm-import-name", mod.intern_pool.stringToSlice(decl.name));
|
o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name));
|
||||||
if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
|
if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
|
||||||
if (!std.mem.eql(u8, lib_name, "c")) {
|
if (!std.mem.eql(u8, lib_name, "c")) {
|
||||||
o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
|
o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
|
||||||
}
|
}
|
||||||
|
|
@ -2546,13 +2547,13 @@ pub const Object = struct {
|
||||||
while (it.next()) |lowering| switch (lowering) {
|
while (it.next()) |lowering| switch (lowering) {
|
||||||
.byval => {
|
.byval => {
|
||||||
const param_index = it.zig_index - 1;
|
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)) {
|
if (!isByRef(param_ty, mod)) {
|
||||||
o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
|
o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.byref => {
|
.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 param_llvm_ty = try o.lowerType(param_ty.toType());
|
||||||
const alignment = param_ty.toType().abiAlignment(mod);
|
const alignment = param_ty.toType().abiAlignment(mod);
|
||||||
o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
|
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 {
|
fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type {
|
||||||
const mod = o.module;
|
const mod = o.module;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const fn_info = mod.typeToFunc(fn_ty).?;
|
const fn_info = mod.typeToFunc(fn_ty).?;
|
||||||
const llvm_ret_ty = try lowerFnRetTy(o, fn_info);
|
const llvm_ret_ty = try lowerFnRetTy(o, fn_info);
|
||||||
|
|
||||||
|
|
@ -3052,19 +3054,19 @@ pub const Object = struct {
|
||||||
while (it.next()) |lowering| switch (lowering) {
|
while (it.next()) |lowering| switch (lowering) {
|
||||||
.no_bits => continue,
|
.no_bits => continue,
|
||||||
.byval => {
|
.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));
|
try llvm_params.append(try o.lowerType(param_ty));
|
||||||
},
|
},
|
||||||
.byref, .byref_mut => {
|
.byref, .byref_mut => {
|
||||||
try llvm_params.append(o.context.pointerType(0));
|
try llvm_params.append(o.context.pointerType(0));
|
||||||
},
|
},
|
||||||
.abi_sized_int => {
|
.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)));
|
const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));
|
||||||
try llvm_params.append(o.context.intType(abi_size * 8));
|
try llvm_params.append(o.context.intType(abi_size * 8));
|
||||||
},
|
},
|
||||||
.slice => {
|
.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)
|
const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)
|
||||||
param_ty.optionalChild(mod).slicePtrFieldType(mod)
|
param_ty.optionalChild(mod).slicePtrFieldType(mod)
|
||||||
else
|
else
|
||||||
|
|
@ -3083,7 +3085,7 @@ pub const Object = struct {
|
||||||
try llvm_params.append(o.context.intType(16));
|
try llvm_params.append(o.context.intType(16));
|
||||||
},
|
},
|
||||||
.float_array => |count| {
|
.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 float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
|
||||||
const field_count = @as(c_uint, @intCast(count));
|
const field_count = @as(c_uint, @intCast(count));
|
||||||
const arr_ty = float_ty.arrayType(field_count);
|
const arr_ty = float_ty.arrayType(field_count);
|
||||||
|
|
@ -3137,8 +3139,7 @@ pub const Object = struct {
|
||||||
return llvm_type.getUndef();
|
return llvm_type.getUndef();
|
||||||
}
|
}
|
||||||
|
|
||||||
const val_key = mod.intern_pool.indexToKey(tv.val.toIntern());
|
switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
|
||||||
switch (val_key) {
|
|
||||||
.int_type,
|
.int_type,
|
||||||
.ptr_type,
|
.ptr_type,
|
||||||
.array_type,
|
.array_type,
|
||||||
|
|
@ -3175,12 +3176,14 @@ pub const Object = struct {
|
||||||
.enum_literal,
|
.enum_literal,
|
||||||
.empty_enum_value,
|
.empty_enum_value,
|
||||||
=> unreachable, // non-runtime values
|
=> unreachable, // non-runtime values
|
||||||
.extern_func, .func => {
|
.extern_func => |extern_func| {
|
||||||
const fn_decl_index = switch (val_key) {
|
const fn_decl_index = extern_func.decl;
|
||||||
.extern_func => |extern_func| extern_func.decl,
|
const fn_decl = mod.declPtr(fn_decl_index);
|
||||||
.func => |func| mod.funcPtr(func.index).owner_decl,
|
try mod.markDeclAlive(fn_decl);
|
||||||
else => unreachable,
|
return o.resolveLlvmFunction(fn_decl_index);
|
||||||
};
|
},
|
||||||
|
.func => |func| {
|
||||||
|
const fn_decl_index = func.owner_decl;
|
||||||
const fn_decl = mod.declPtr(fn_decl_index);
|
const fn_decl = mod.declPtr(fn_decl_index);
|
||||||
try mod.markDeclAlive(fn_decl);
|
try mod.markDeclAlive(fn_decl);
|
||||||
return o.resolveLlvmFunction(fn_decl_index);
|
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 args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]));
|
||||||
const o = self.dg.object;
|
const o = self.dg.object;
|
||||||
const mod = o.module;
|
const mod = o.module;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const callee_ty = self.typeOf(pl_op.operand);
|
const callee_ty = self.typeOf(pl_op.operand);
|
||||||
const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
|
const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
|
||||||
.Fn => callee_ty,
|
.Fn => callee_ty,
|
||||||
|
|
@ -4801,14 +4805,14 @@ pub const FuncGen = struct {
|
||||||
while (it.next()) |lowering| switch (lowering) {
|
while (it.next()) |lowering| switch (lowering) {
|
||||||
.byval => {
|
.byval => {
|
||||||
const param_index = it.zig_index - 1;
|
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)) {
|
if (!isByRef(param_ty, mod)) {
|
||||||
o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
|
o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.byref => {
|
.byref => {
|
||||||
const param_index = it.zig_index - 1;
|
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 param_llvm_ty = try o.lowerType(param_ty);
|
||||||
const alignment = param_ty.abiAlignment(mod);
|
const alignment = param_ty.abiAlignment(mod);
|
||||||
o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
|
o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
|
||||||
|
|
@ -4828,7 +4832,7 @@ pub const FuncGen = struct {
|
||||||
|
|
||||||
.slice => {
|
.slice => {
|
||||||
assert(!it.byval_attr);
|
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 ptr_info = param_ty.ptrInfo(mod);
|
||||||
const llvm_arg_i = it.llvm_index - 2;
|
const llvm_arg_i = it.llvm_index - 2;
|
||||||
|
|
||||||
|
|
@ -4930,7 +4934,7 @@ pub const FuncGen = struct {
|
||||||
fg.context.pointerType(0).constNull(),
|
fg.context.pointerType(0).constNull(),
|
||||||
null_opt_addr_global,
|
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 panic_decl = mod.declPtr(panic_func.owner_decl);
|
||||||
const fn_info = mod.typeToFunc(panic_decl.ty).?;
|
const fn_info = mod.typeToFunc(panic_decl.ty).?;
|
||||||
const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl);
|
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 ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||||
|
|
||||||
const mod = o.module;
|
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_index = func.owner_decl;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
|
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();
|
const cur_debug_location = self.builder.getCurrentDebugLocation2();
|
||||||
|
|
||||||
try self.dbg_inlined.append(self.gpa, .{
|
try self.dbg_inlined.append(self.gpa, .{
|
||||||
.loc = @as(*llvm.DILocation, @ptrCast(cur_debug_location)),
|
.loc = @ptrCast(cur_debug_location),
|
||||||
.scope = self.di_scope.?,
|
.scope = self.di_scope.?,
|
||||||
.base_line = self.base_line,
|
.base_line = self.base_line,
|
||||||
});
|
});
|
||||||
|
|
@ -6090,8 +6094,7 @@ pub const FuncGen = struct {
|
||||||
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
|
||||||
|
|
||||||
const mod = o.module;
|
const mod = o.module;
|
||||||
const func = mod.funcPtr(ty_fn.func);
|
const decl = mod.funcOwnerDeclPtr(ty_fn.func);
|
||||||
const decl = mod.declPtr(func.owner_decl);
|
|
||||||
const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
|
const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
|
||||||
self.di_file = di_file;
|
self.di_file = di_file;
|
||||||
const old = self.dbg_inlined.pop();
|
const old = self.dbg_inlined.pop();
|
||||||
|
|
@ -8137,12 +8140,13 @@ pub const FuncGen = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
|
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_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
|
||||||
const lbrace_col = func.lbrace_column + 1;
|
const lbrace_col = func.lbrace_column + 1;
|
||||||
const di_local_var = dib.createParameterVariable(
|
const di_local_var = dib.createParameterVariable(
|
||||||
self.di_scope.?,
|
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.?,
|
self.di_file.?,
|
||||||
lbrace_line,
|
lbrace_line,
|
||||||
try o.lowerDebugType(inst_ty, .full),
|
try o.lowerDebugType(inst_ty, .full),
|
||||||
|
|
@ -10888,13 +10892,17 @@ const ParamTypeIterator = struct {
|
||||||
|
|
||||||
pub fn next(it: *ParamTypeIterator) ?Lowering {
|
pub fn next(it: *ParamTypeIterator) ?Lowering {
|
||||||
if (it.zig_index >= it.fn_info.param_types.len) return null;
|
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;
|
it.byval_attr = false;
|
||||||
return nextInner(it, ty.toType());
|
return nextInner(it, ty.toType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `airCall` uses this instead of `next` so that it can take into account variadic functions.
|
/// `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 {
|
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 >= it.fn_info.param_types.len) {
|
||||||
if (it.zig_index >= args.len) {
|
if (it.zig_index >= args.len) {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -10902,7 +10910,7 @@ const ParamTypeIterator = struct {
|
||||||
return nextInner(it, fg.typeOf(args[it.zig_index]));
|
return nextInner(it, fg.typeOf(args[it.zig_index]));
|
||||||
}
|
}
|
||||||
} else {
|
} 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) {
|
if (ty.zigTypeTag(mod) == .Fn) {
|
||||||
const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
|
const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
|
||||||
.extern_func => |extern_func| extern_func.decl,
|
.extern_func => |extern_func| extern_func.decl,
|
||||||
.func => |func| mod.funcPtr(func.index).owner_decl,
|
.func => |func| func.owner_decl,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
const spv_decl_index = try self.resolveDecl(fn_decl_index);
|
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.
|
/// 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.
|
/// Note: Function does not actually generate the decl.
|
||||||
fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {
|
fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {
|
||||||
const decl = self.module.declPtr(decl_index);
|
const mod = self.module;
|
||||||
try self.module.markDeclAlive(decl);
|
const decl = mod.declPtr(decl_index);
|
||||||
|
try mod.markDeclAlive(decl);
|
||||||
|
|
||||||
const entry = try self.decl_link.getOrPut(decl_index);
|
const entry = try self.decl_link.getOrPut(decl_index);
|
||||||
if (!entry.found_existing) {
|
if (!entry.found_existing) {
|
||||||
// TODO: Extern fn?
|
// TODO: Extern fn?
|
||||||
const kind: SpvModule.DeclKind = if (decl.val.getFunctionIndex(self.module) != .none)
|
const kind: SpvModule.DeclKind = if (decl.val.isFuncBody(mod))
|
||||||
.func
|
.func
|
||||||
else
|
else
|
||||||
.global;
|
.global;
|
||||||
|
|
@ -1268,6 +1269,7 @@ pub const DeclGen = struct {
|
||||||
},
|
},
|
||||||
.Fn => switch (repr) {
|
.Fn => switch (repr) {
|
||||||
.direct => {
|
.direct => {
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const fn_info = mod.typeToFunc(ty).?;
|
const fn_info = mod.typeToFunc(ty).?;
|
||||||
// TODO: Put this somewhere in Sema.zig
|
// TODO: Put this somewhere in Sema.zig
|
||||||
if (fn_info.is_var_args)
|
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);
|
const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len);
|
||||||
defer self.gpa.free(param_ty_refs);
|
defer self.gpa.free(param_ty_refs);
|
||||||
for (param_ty_refs, 0..) |*param_type, i| {
|
for (param_ty_refs, fn_info.param_types.get(ip)) |*param_type, fn_param_type| {
|
||||||
param_type.* = try self.resolveType(fn_info.param_types[i].toType(), .direct);
|
param_type.* = try self.resolveType(fn_param_type.toType(), .direct);
|
||||||
}
|
}
|
||||||
const return_ty_ref = try self.resolveType(fn_info.return_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 {
|
fn genDecl(self: *DeclGen) !void {
|
||||||
const mod = self.module;
|
const mod = self.module;
|
||||||
|
const ip = &mod.intern_pool;
|
||||||
const decl = mod.declPtr(self.decl_index);
|
const decl = mod.declPtr(self.decl_index);
|
||||||
const spv_decl_index = try self.resolveDecl(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).?;
|
const fn_info = mod.typeToFunc(decl.ty).?;
|
||||||
|
|
||||||
try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);
|
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 param_type_id = try self.resolveTypeId(param_type.toType());
|
||||||
const arg_result_id = self.spv.allocId();
|
const arg_result_id = self.spv.allocId();
|
||||||
try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
|
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.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
|
||||||
try self.spv.addFunction(spv_decl_index, self.func);
|
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, .{
|
try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{
|
||||||
.target = decl_id,
|
.target = decl_id,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ const Compilation = @import("Compilation.zig");
|
||||||
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
|
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
|
||||||
const Liveness = @import("Liveness.zig");
|
const Liveness = @import("Liveness.zig");
|
||||||
const Module = @import("Module.zig");
|
const Module = @import("Module.zig");
|
||||||
|
const InternPool = @import("InternPool.zig");
|
||||||
const Package = @import("Package.zig");
|
const Package = @import("Package.zig");
|
||||||
const Type = @import("type.zig").Type;
|
const Type = @import("type.zig").Type;
|
||||||
const TypedValue = @import("TypedValue.zig");
|
const TypedValue = @import("TypedValue.zig");
|
||||||
|
|
@ -562,7 +563,7 @@ pub const File = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// May be called before or after updateDeclExports for any given Decl.
|
/// 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) {
|
if (build_options.only_c) {
|
||||||
assert(base.tag == .c);
|
assert(base.tag == .c);
|
||||||
return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness);
|
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());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
const gpa = self.base.allocator;
|
const gpa = self.base.allocator;
|
||||||
|
|
||||||
const func = module.funcPtr(func_index);
|
const func = module.funcInfo(func_index);
|
||||||
const decl_index = func.owner_decl;
|
const decl_index = func.owner_decl;
|
||||||
const gop = try self.decl_table.getOrPut(gpa, decl_index);
|
const gop = try self.decl_table.getOrPut(gpa, decl_index);
|
||||||
if (!gop.found_existing) {
|
if (!gop.found_existing) {
|
||||||
|
|
|
||||||
|
|
@ -1032,7 +1032,7 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {
|
||||||
self.getAtomPtr(atom_index).sym_index = 0;
|
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) {
|
if (build_options.skip_non_native and builtin.object_format != .coff) {
|
||||||
@panic("Attempted to compile for object format that was disabled by build configuration");
|
@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());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
const func = mod.funcPtr(func_index);
|
const func = mod.funcInfo(func_index);
|
||||||
const decl_index = func.owner_decl;
|
const decl_index = func.owner_decl;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
|
|
||||||
|
|
@ -1424,7 +1424,7 @@ pub fn updateDeclExports(
|
||||||
// detect the default subsystem.
|
// detect the default subsystem.
|
||||||
for (exports) |exp| {
|
for (exports) |exp| {
|
||||||
const exported_decl = mod.declPtr(exp.exported_decl);
|
const exported_decl = mod.declPtr(exp.exported_decl);
|
||||||
if (exported_decl.getOwnedFunctionIndex(mod) == .none) continue;
|
if (exported_decl.getOwnedFunctionIndex() == .none) continue;
|
||||||
const winapi_cc = switch (self.base.options.target.cpu.arch) {
|
const winapi_cc = switch (self.base.options.target.cpu.arch) {
|
||||||
.x86 => std.builtin.CallingConvention.Stdcall,
|
.x86 => std.builtin.CallingConvention.Stdcall,
|
||||||
else => std.builtin.CallingConvention.C,
|
else => std.builtin.CallingConvention.C,
|
||||||
|
|
|
||||||
|
|
@ -2575,7 +2575,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
|
||||||
return local_sym;
|
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) {
|
if (build_options.skip_non_native and builtin.object_format != .elf) {
|
||||||
@panic("Attempted to compile for object format that was disabled by build configuration");
|
@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());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
const func = mod.funcPtr(func_index);
|
const func = mod.funcInfo(func_index);
|
||||||
const decl_index = func.owner_decl;
|
const decl_index = func.owner_decl;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1845,7 +1845,7 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
|
||||||
self.markRelocsDirtyByTarget(target);
|
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) {
|
if (build_options.skip_non_native and builtin.object_format != .macho) {
|
||||||
@panic("Attempted to compile for object format that was disabled by build configuration");
|
@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());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
const func = mod.funcPtr(func_index);
|
const func = mod.funcInfo(func_index);
|
||||||
const decl_index = func.owner_decl;
|
const decl_index = func.owner_decl;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ const assert = std.debug.assert;
|
||||||
const log = std.log.scoped(.link);
|
const log = std.log.scoped(.link);
|
||||||
|
|
||||||
const Module = @import("../Module.zig");
|
const Module = @import("../Module.zig");
|
||||||
|
const InternPool = @import("../InternPool.zig");
|
||||||
const Compilation = @import("../Compilation.zig");
|
const Compilation = @import("../Compilation.zig");
|
||||||
const link = @import("../link.zig");
|
const link = @import("../link.zig");
|
||||||
const trace = @import("../tracy.zig").trace;
|
const trace = @import("../tracy.zig").trace;
|
||||||
|
|
@ -68,7 +69,7 @@ pub fn deinit(self: *NvPtx) void {
|
||||||
self.base.allocator.free(self.ptx_file_name);
|
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;
|
if (!build_options.have_llvm) return;
|
||||||
try self.llvm_object.updateFunc(module, func_index, air, liveness);
|
try self.llvm_object.updateFunc(module, func_index, air, liveness);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
const Plan9 = @This();
|
const Plan9 = @This();
|
||||||
const link = @import("../link.zig");
|
const link = @import("../link.zig");
|
||||||
const Module = @import("../Module.zig");
|
const Module = @import("../Module.zig");
|
||||||
|
const InternPool = @import("../InternPool.zig");
|
||||||
const Compilation = @import("../Compilation.zig");
|
const Compilation = @import("../Compilation.zig");
|
||||||
const aout = @import("Plan9/aout.zig");
|
const aout = @import("Plan9/aout.zig");
|
||||||
const codegen = @import("../codegen.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) {
|
if (build_options.skip_non_native and builtin.object_format != .plan9) {
|
||||||
@panic("Attempted to compile for object format that was disabled by build configuration");
|
@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_index = func.owner_decl;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
self.freeUnnamedConsts(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.
|
// in the deleteUnusedDecl function.
|
||||||
const mod = self.base.options.module.?;
|
const mod = self.base.options.module.?;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
const is_fn = decl.val.getFunctionIndex(mod) != .none;
|
const is_fn = decl.val.isFuncBody(mod);
|
||||||
if (is_fn) {
|
if (is_fn) {
|
||||||
var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;
|
var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;
|
||||||
var submap = symidx_and_submap.functions;
|
var submap = symidx_and_submap.functions;
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ const assert = std.debug.assert;
|
||||||
const log = std.log.scoped(.link);
|
const log = std.log.scoped(.link);
|
||||||
|
|
||||||
const Module = @import("../Module.zig");
|
const Module = @import("../Module.zig");
|
||||||
|
const InternPool = @import("../InternPool.zig");
|
||||||
const Compilation = @import("../Compilation.zig");
|
const Compilation = @import("../Compilation.zig");
|
||||||
const link = @import("../link.zig");
|
const link = @import("../link.zig");
|
||||||
const codegen = @import("../codegen/spirv.zig");
|
const codegen = @import("../codegen/spirv.zig");
|
||||||
|
|
@ -103,12 +104,12 @@ pub fn deinit(self: *SpirV) void {
|
||||||
self.decl_link.deinit();
|
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) {
|
if (build_options.skip_non_native) {
|
||||||
@panic("Attempted to compile for architecture that was disabled by build configuration");
|
@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);
|
var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
|
||||||
defer decl_gen.deinit();
|
defer decl_gen.deinit();
|
||||||
|
|
@ -138,7 +139,7 @@ pub fn updateDeclExports(
|
||||||
exports: []const *Module.Export,
|
exports: []const *Module.Export,
|
||||||
) !void {
|
) !void {
|
||||||
const decl = mod.declPtr(decl_index);
|
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.
|
// TODO: Unify with resolveDecl in spirv.zig.
|
||||||
const entry = try self.decl_link.getOrPut(decl_index);
|
const entry = try self.decl_link.getOrPut(decl_index);
|
||||||
if (!entry.found_existing) {
|
if (!entry.found_existing) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ const log = std.log.scoped(.link);
|
||||||
pub const Atom = @import("Wasm/Atom.zig");
|
pub const Atom = @import("Wasm/Atom.zig");
|
||||||
const Dwarf = @import("Dwarf.zig");
|
const Dwarf = @import("Dwarf.zig");
|
||||||
const Module = @import("../Module.zig");
|
const Module = @import("../Module.zig");
|
||||||
|
const InternPool = @import("../InternPool.zig");
|
||||||
const Compilation = @import("../Compilation.zig");
|
const Compilation = @import("../Compilation.zig");
|
||||||
const CodeGen = @import("../arch/wasm/CodeGen.zig");
|
const CodeGen = @import("../arch/wasm/CodeGen.zig");
|
||||||
const codegen = @import("../codegen.zig");
|
const codegen = @import("../codegen.zig");
|
||||||
|
|
@ -1338,7 +1339,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {
|
||||||
return index;
|
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) {
|
if (build_options.skip_non_native and builtin.object_format != .wasm) {
|
||||||
@panic("Attempted to compile for object format that was disabled by build configuration");
|
@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());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
const func = mod.funcPtr(func_index);
|
const func = mod.funcInfo(func_index);
|
||||||
const decl_index = func.owner_decl;
|
const decl_index = func.owner_decl;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
const atom_index = try wasm.getOrCreateAtomForDecl(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 {
|
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 ty_fn = w.air.instructions.items(.data)[inst].ty_fn;
|
||||||
const func_index = ty_fn.func;
|
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)});
|
try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,7 @@ pub const Type = struct {
|
||||||
const func = ies.func;
|
const func = ies.func;
|
||||||
|
|
||||||
try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
|
try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
|
||||||
const owner_decl = mod.declPtr(mod.funcPtr(func).owner_decl);
|
const owner_decl = mod.funcOwnerDeclPtr(func);
|
||||||
try owner_decl.renderFullyQualifiedName(mod, writer);
|
try owner_decl.renderFullyQualifiedName(mod, writer);
|
||||||
try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
|
try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
|
||||||
},
|
},
|
||||||
|
|
@ -367,7 +367,8 @@ pub const Type = struct {
|
||||||
try writer.writeAll("noinline ");
|
try writer.writeAll("noinline ");
|
||||||
}
|
}
|
||||||
try writer.writeAll("fn(");
|
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 (i != 0) try writer.writeAll(", ");
|
||||||
if (std.math.cast(u5, i)) |index| {
|
if (std.math.cast(u5, i)) |index| {
|
||||||
if (fn_info.paramIsComptime(index)) {
|
if (fn_info.paramIsComptime(index)) {
|
||||||
|
|
@ -384,7 +385,7 @@ pub const Type = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fn_info.is_var_args) {
|
if (fn_info.is_var_args) {
|
||||||
if (fn_info.param_types.len != 0) {
|
if (param_types.len != 0) {
|
||||||
try writer.writeAll(", ");
|
try writer.writeAll(", ");
|
||||||
}
|
}
|
||||||
try writer.writeAll("...");
|
try writer.writeAll("...");
|
||||||
|
|
|
||||||
|
|
@ -473,12 +473,15 @@ pub const Value = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getFunction(val: Value, mod: *Module) ?*Module.Fn {
|
pub fn isFuncBody(val: Value, mod: *Module) bool {
|
||||||
return mod.funcPtrUnwrap(val.getFunctionIndex(mod));
|
return mod.intern_pool.isFuncBody(val.toIntern());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getFunctionIndex(val: Value, mod: *Module) Module.Fn.OptionalIndex {
|
pub fn getFunction(val: Value, mod: *Module) ?InternPool.Key.Func {
|
||||||
return if (val.ip_index != .none) mod.intern_pool.indexToFunc(val.toIntern()) else .none;
|
return switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||||
|
.func => |x| x,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {
|
pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {
|
||||||
|
|
@ -1462,7 +1465,7 @@ pub const Value = struct {
|
||||||
return switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
return switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||||
.variable => |variable| variable.decl,
|
.variable => |variable| variable.decl,
|
||||||
.extern_func => |extern_func| extern_func.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) {
|
.ptr => |ptr| switch (ptr.addr) {
|
||||||
.decl => |decl| decl,
|
.decl => |decl| decl,
|
||||||
.mut_decl => |mut_decl| mut_decl.decl,
|
.mut_decl => |mut_decl| mut_decl.decl,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue