aboutsummaryrefslogtreecommitdiff
path: root/src/Module.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Module.zig')
-rw-r--r--src/Module.zig44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 2c3e745c11..2556ad3f0e 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -61,6 +61,11 @@ export_owners: std.AutoArrayHashMapUnmanaged(*Decl, []*Export) = .{},
/// Keys are fully resolved file paths. This table owns the keys and values.
import_table: std.StringArrayHashMapUnmanaged(*Scope.File) = .{},
+/// 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 = .{},
+
/// We optimize memory usage for a compilation with no compile errors by storing the
/// error messages and mapping outside of `Decl`.
/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.
@@ -114,6 +119,44 @@ emit_h: ?*GlobalEmitH,
test_functions: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
+const MonomorphedFuncsSet = std.HashMapUnmanaged(
+ *Fn,
+ void,
+ MonomorphedFuncsContext,
+ std.hash_map.default_max_load_percentage,
+);
+
+const MonomorphedFuncsContext = struct {
+ pub fn eql(ctx: @This(), a: *Fn, b: *Fn) bool {
+ _ = ctx;
+ return a == b;
+ }
+
+ /// Must match `Sema.GenericCallAdapter.hash`.
+ pub fn hash(ctx: @This(), key: *Fn) u64 {
+ _ = ctx;
+ var hasher = std.hash.Wyhash.init(0);
+
+ // The generic function Decl is guaranteed to be the first dependency
+ // of each of its instantiations.
+ const generic_owner_decl = key.owner_decl.dependencies.keys()[0];
+ const generic_func = generic_owner_decl.val.castTag(.function).?.data;
+ std.hash.autoHash(&hasher, @ptrToInt(generic_func));
+
+ // This logic must be kept in sync with the logic in `analyzeCall` that
+ // computes the hash.
+ const comptime_args = key.comptime_args.?;
+ const generic_ty_info = generic_owner_decl.ty.fnInfo();
+ for (generic_ty_info.param_types) |param_ty, i| {
+ if (generic_ty_info.paramIsComptime(i) and param_ty.tag() != .generic_poison) {
+ comptime_args[i].val.hash(param_ty, &hasher);
+ }
+ }
+
+ return hasher.final();
+ }
+};
+
/// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.
pub const GlobalEmitH = struct {
/// Where to put the output.
@@ -2205,6 +2248,7 @@ pub fn deinit(mod: *Module) void {
mod.error_name_list.deinit(gpa);
mod.test_functions.deinit(gpa);
+ mod.monomorphed_funcs.deinit(gpa);
}
fn freeExportList(gpa: *Allocator, export_list: []*Export) void {