diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-08-05 16:37:21 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-08-05 16:37:21 -0700 |
| commit | e9e3a2994696a3131125ebc4b1f0eec7ca5306d9 (patch) | |
| tree | de6bf27daddd48b9ab15144312f558d3cd0c53c2 /src/type.zig | |
| parent | f58cbef1659742e57377d3f8c92a0b9b97af91ad (diff) | |
| download | zig-e9e3a2994696a3131125ebc4b1f0eec7ca5306d9.tar.gz zig-e9e3a2994696a3131125ebc4b1f0eec7ca5306d9.zip | |
stage2: implement generic function memoization
Module has a new field `monomorphed_funcs` which stores the set of
`*Module.Fn` objects which are generic function instantiations.
The hash is based on hashes of comptime values of parameters known to be
comptime based on an explicit comptime keyword or must-be-comptime
type expressions that can be evaluated without performing monomorphization.
This allows function calls to be semantically analyzed cheaply for
generic functions which are already instantiated.
The table is updated with a single `getOrPutAdapted` in the semantic
analysis of `call` instructions, by pre-allocating the `Fn` object and
passing it to the child `Sema`.
Diffstat (limited to 'src/type.zig')
| -rw-r--r-- | src/type.zig | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/src/type.zig b/src/type.zig index 0e99a929f0..180fb92bf0 100644 --- a/src/type.zig +++ b/src/type.zig @@ -549,8 +549,13 @@ pub const Type = extern union { pub fn hash(self: Type) u64 { var hasher = std.hash.Wyhash.init(0); + self.hashWithHasher(&hasher); + return hasher.final(); + } + + pub fn hashWithHasher(self: Type, hasher: *std.hash.Wyhash) void { const zig_type_tag = self.zigTypeTag(); - std.hash.autoHash(&hasher, zig_type_tag); + std.hash.autoHash(hasher, zig_type_tag); switch (zig_type_tag) { .Type, .Void, @@ -568,34 +573,34 @@ pub const Type = extern union { .Int => { // Detect that e.g. u64 != usize, even if the bits match on a particular target. if (self.isNamedInt()) { - std.hash.autoHash(&hasher, self.tag()); + std.hash.autoHash(hasher, self.tag()); } else { // Remaining cases are arbitrary sized integers. // The target will not be branched upon, because we handled target-dependent cases above. const info = self.intInfo(@as(Target, undefined)); - std.hash.autoHash(&hasher, info.signedness); - std.hash.autoHash(&hasher, info.bits); + std.hash.autoHash(hasher, info.signedness); + std.hash.autoHash(hasher, info.bits); } }, .Array, .Vector => { - std.hash.autoHash(&hasher, self.arrayLen()); - std.hash.autoHash(&hasher, self.elemType().hash()); + std.hash.autoHash(hasher, self.arrayLen()); + std.hash.autoHash(hasher, self.elemType().hash()); // TODO hash array sentinel }, .Fn => { - std.hash.autoHash(&hasher, self.fnReturnType().hash()); - std.hash.autoHash(&hasher, self.fnCallingConvention()); + std.hash.autoHash(hasher, self.fnReturnType().hash()); + std.hash.autoHash(hasher, self.fnCallingConvention()); const params_len = self.fnParamLen(); - std.hash.autoHash(&hasher, params_len); + std.hash.autoHash(hasher, params_len); var i: usize = 0; while (i < params_len) : (i += 1) { - std.hash.autoHash(&hasher, self.fnParamType(i).hash()); + std.hash.autoHash(hasher, self.fnParamType(i).hash()); } - std.hash.autoHash(&hasher, self.fnIsVarArgs()); + std.hash.autoHash(hasher, self.fnIsVarArgs()); }, .Optional => { var buf: Payload.ElemType = undefined; - std.hash.autoHash(&hasher, self.optionalChild(&buf).hash()); + std.hash.autoHash(hasher, self.optionalChild(&buf).hash()); }, .Float, .Struct, @@ -612,7 +617,6 @@ pub const Type = extern union { // TODO implement more type hashing }, } - return hasher.final(); } pub const HashContext64 = struct { @@ -3373,7 +3377,7 @@ pub const Type = extern union { data: Data, // TODO look into optimizing this memory to take fewer bytes - const Data = struct { + pub const Data = struct { param_types: []Type, comptime_params: [*]bool, return_type: Type, @@ -3381,7 +3385,7 @@ pub const Type = extern union { is_var_args: bool, is_generic: bool, - fn paramIsComptime(self: @This(), i: usize) bool { + pub fn paramIsComptime(self: @This(), i: usize) bool { if (!self.is_generic) return false; assert(i < self.param_types.len); return self.comptime_params[i]; |
