aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/spirv.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-07-03 22:09:30 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-07-18 19:02:05 -0700
commitdb33ee45b7261c9ec62a1087cfc9377bc4e7aa8f (patch)
tree81e1f629c296a8a9c9573879382586dac3784737 /src/codegen/spirv.zig
parent70c71935c7c9f20353dc2a50b497b752d70d3452 (diff)
downloadzig-db33ee45b7261c9ec62a1087cfc9377bc4e7aa8f.tar.gz
zig-db33ee45b7261c9ec62a1087cfc9377bc4e7aa8f.zip
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.
Diffstat (limited to 'src/codegen/spirv.zig')
-rw-r--r--src/codegen/spirv.zig20
1 files changed, 12 insertions, 8 deletions
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig
index eb697ea94e..9f84781966 100644
--- a/src/codegen/spirv.zig
+++ b/src/codegen/spirv.zig
@@ -238,7 +238,7 @@ pub const DeclGen = struct {
if (ty.zigTypeTag(mod) == .Fn) {
const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
.extern_func => |extern_func| extern_func.decl,
- .func => |func| mod.funcPtr(func.index).owner_decl,
+ .func => |func| func.owner_decl,
else => unreachable,
};
const spv_decl_index = try self.resolveDecl(fn_decl_index);
@@ -255,13 +255,14 @@ pub const DeclGen = struct {
/// Fetch or allocate a result id for decl index. This function also marks the decl as alive.
/// Note: Function does not actually generate the decl.
fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {
- const decl = self.module.declPtr(decl_index);
- try self.module.markDeclAlive(decl);
+ const mod = self.module;
+ const decl = mod.declPtr(decl_index);
+ try mod.markDeclAlive(decl);
const entry = try self.decl_link.getOrPut(decl_index);
if (!entry.found_existing) {
// TODO: Extern fn?
- const kind: SpvModule.DeclKind = if (decl.val.getFunctionIndex(self.module) != .none)
+ const kind: SpvModule.DeclKind = if (decl.val.isFuncBody(mod))
.func
else
.global;
@@ -1268,6 +1269,7 @@ pub const DeclGen = struct {
},
.Fn => switch (repr) {
.direct => {
+ const ip = &mod.intern_pool;
const fn_info = mod.typeToFunc(ty).?;
// TODO: Put this somewhere in Sema.zig
if (fn_info.is_var_args)
@@ -1275,8 +1277,8 @@ pub const DeclGen = struct {
const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len);
defer self.gpa.free(param_ty_refs);
- for (param_ty_refs, 0..) |*param_type, i| {
- param_type.* = try self.resolveType(fn_info.param_types[i].toType(), .direct);
+ for (param_ty_refs, fn_info.param_types.get(ip)) |*param_type, fn_param_type| {
+ param_type.* = try self.resolveType(fn_param_type.toType(), .direct);
}
const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct);
@@ -1576,6 +1578,7 @@ pub const DeclGen = struct {
fn genDecl(self: *DeclGen) !void {
const mod = self.module;
+ const ip = &mod.intern_pool;
const decl = mod.declPtr(self.decl_index);
const spv_decl_index = try self.resolveDecl(self.decl_index);
@@ -1594,7 +1597,8 @@ pub const DeclGen = struct {
const fn_info = mod.typeToFunc(decl.ty).?;
try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);
- for (fn_info.param_types) |param_type| {
+ for (0..fn_info.param_types.len) |i| {
+ const param_type = fn_info.param_types.get(ip)[i];
const param_type_id = try self.resolveTypeId(param_type.toType());
const arg_result_id = self.spv.allocId();
try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
@@ -1621,7 +1625,7 @@ pub const DeclGen = struct {
try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
try self.spv.addFunction(spv_decl_index, self.func);
- const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(self.module));
+ const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module));
try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{
.target = decl_id,