stage1: recursively resolve lazy values before hashing

When putting ZigValues into a hash map. The hash of a lazy value
and a fully resolved value must equal, and so we must resolve
the lazy values prior. The hash function asserts that none of
the values are lazy.
This commit is contained in:
Andrew Kelley 2021-07-05 13:05:03 -07:00
parent b7da1b2d45
commit 9b08687766

View File

@ -272,6 +272,10 @@ static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *r
static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field);
static void value_to_bigfloat(BigFloat *out, ZigValue *val);
static Error ir_resolve_lazy_recurse(AstNode *source_node, ZigValue *val);
static Error ir_resolve_lazy_recurse_array(AstNode *source_node, ZigValue *val, size_t len);
static void ir_assert_impl(bool ok, IrInstGen *source_instruction, char const *file, unsigned int line) {
if (ok) return;
src_assert_impl(ok, source_instruction->source_node, file, line);
@ -12935,6 +12939,18 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, Scope *scope, AstNode *sour
break;
}
// We are about to put ZigValues into a hash map. The hash of a lazy value and a
// fully resolved value must equal, and so we must resolve the lazy values here.
// The hash function asserts that none of the values are lazy.
for (size_t i = 0; i < generic_id->param_count; i += 1) {
ZigValue *generic_param = &generic_id->params[i];
if (generic_param->special != ConstValSpecialRuntime) {
if ((err = ir_resolve_lazy_recurse(source_node, generic_param))) {
return ira->codegen->invalid_inst_gen;
}
}
}
auto existing_entry = ira->codegen->generic_table.put_unique(generic_id, impl_fn);
if (existing_entry) {
// throw away all our work and use the existing function
@ -25515,6 +25531,88 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
zig_unreachable();
}
static Error ir_resolve_lazy_recurse_array(AstNode *source_node, ZigValue *val, size_t len) {
Error err;
switch (val->data.x_array.special) {
case ConstArraySpecialUndef:
case ConstArraySpecialBuf:
return ErrorNone;
case ConstArraySpecialNone:
break;
}
ZigValue *elems = val->data.x_array.data.s_none.elements;
for (size_t i = 0; i < len; i += 1) {
if ((err = ir_resolve_lazy_recurse(source_node, &elems[i])))
return err;
}
return ErrorNone;
}
static Error ir_resolve_lazy_recurse(AstNode *source_node, ZigValue *val) {
Error err;
if ((err = ir_resolve_lazy_raw(source_node, val)))
return err;
if (val->special != ConstValSpecialStatic)
return ErrorNone;
switch (val->type->id) {
case ZigTypeIdOpaque:
case ZigTypeIdEnum:
case ZigTypeIdMetaType:
case ZigTypeIdBool:
case ZigTypeIdVoid:
case ZigTypeIdComptimeFloat:
case ZigTypeIdInt:
case ZigTypeIdComptimeInt:
case ZigTypeIdEnumLiteral:
case ZigTypeIdErrorSet:
case ZigTypeIdUndefined:
case ZigTypeIdNull:
case ZigTypeIdPointer:
case ZigTypeIdFn:
case ZigTypeIdAnyFrame:
case ZigTypeIdBoundFn:
case ZigTypeIdInvalid:
case ZigTypeIdUnreachable:
case ZigTypeIdFloat:
return ErrorNone;
case ZigTypeIdFnFrame:
zig_panic("TODO: ir_resolve_lazy_recurse ZigTypeIdFnFrame");
case ZigTypeIdUnion: {
ConstUnionValue *union_val = &val->data.x_union;
return ir_resolve_lazy_recurse(source_node, union_val->payload);
}
case ZigTypeIdVector:
return ir_resolve_lazy_recurse_array(source_node, val, val->type->data.vector.len);
case ZigTypeIdArray:
return ir_resolve_lazy_recurse_array(source_node, val, val->type->data.array.len);
case ZigTypeIdStruct:
for (size_t i = 0; i < val->type->data.structure.src_field_count; i += 1) {
ZigValue *field = val->data.x_struct.fields[i];
if ((err = ir_resolve_lazy_recurse(source_node, field)))
return err;
}
return ErrorNone;
case ZigTypeIdOptional:
if (get_src_ptr_type(val->type) != nullptr)
return ErrorNone;
if (val->data.x_optional == nullptr)
return ErrorNone;
return ir_resolve_lazy_recurse(source_node, val->data.x_optional);
case ZigTypeIdErrorUnion: {
bool is_err = val->data.x_err_union.error_set->data.x_err_set != nullptr;
if (is_err) {
return ir_resolve_lazy_recurse(source_node, val->data.x_err_union.error_set);
} else {
return ir_resolve_lazy_recurse(source_node, val->data.x_err_union.payload);
}
}
}
zig_unreachable();
}
Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val) {
Error err;
if ((err = ir_resolve_lazy_raw(source_node, val))) {