aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-08-05 16:37:21 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-08-05 16:37:21 -0700
commite9e3a2994696a3131125ebc4b1f0eec7ca5306d9 (patch)
treede6bf27daddd48b9ab15144312f558d3cd0c53c2 /src/type.zig
parentf58cbef1659742e57377d3f8c92a0b9b97af91ad (diff)
downloadzig-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.zig34
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];