aboutsummaryrefslogtreecommitdiff
path: root/src/stage1/ir.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-07-06 13:20:15 -0400
committerGitHub <noreply@github.com>2021-07-06 13:20:15 -0400
commit6ba843ee0fee75490655544bb9442f20e271cc2c (patch)
tree4400ca112e5638a9c7d201e50f9c8aeeda797e91 /src/stage1/ir.cpp
parentcff7ecee070df59683dbbe3ede04b494d4619f7f (diff)
parentf02ee7a9f5a72f24a645f36db7ae7828f29d3393 (diff)
downloadzig-6ba843ee0fee75490655544bb9442f20e271cc2c.tar.gz
zig-6ba843ee0fee75490655544bb9442f20e271cc2c.zip
Merge pull request #9310 from ziglang/stage1-better-hashing
Speed up stage 1 by improving hash functions
Diffstat (limited to 'src/stage1/ir.cpp')
-rw-r--r--src/stage1/ir.cpp168
1 files changed, 164 insertions, 4 deletions
diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp
index 22a4bdf92f..ab8aac9a91 100644
--- a/src/stage1/ir.cpp
+++ b/src/stage1/ir.cpp
@@ -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);
@@ -554,7 +558,10 @@ static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_
case ConstPtrSpecialBaseStruct: {
ZigValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;
expand_undef_struct(g, struct_val);
- result = struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index];
+ size_t field_index = const_val->data.x_ptr.data.base_struct.field_index;
+ assert(struct_val->type->id == ZigTypeIdStruct);
+ assert(!struct_val->type->data.structure.fields[field_index]->is_comptime);
+ result = struct_val->data.x_struct.fields[field_index];
break;
}
case ConstPtrSpecialBaseErrorUnionCode:
@@ -7018,6 +7025,17 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, Scope *sco
buf_sprintf("field '%s' declared here", buf_ptr(src_field->name)));
return ira->codegen->invalid_inst_gen;
}
+ if (dst_field->is_comptime) {
+ ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("field '%s' in struct '%s' is comptime, it cannot be assigned",
+ buf_ptr(src_field->name), buf_ptr(&wanted_type->name)));
+ if (wanted_type->data.structure.decl_node) {
+ add_error_note(ira->codegen, msg, wanted_type->data.structure.decl_node,
+ buf_sprintf("struct '%s' declared here", buf_ptr(&wanted_type->name)));
+ }
+ add_error_note(ira->codegen, msg, src_field->decl_node,
+ buf_sprintf("field '%s' declared here", buf_ptr(src_field->name)));
+ return ira->codegen->invalid_inst_gen;
+ }
src_assert(src_field->decl_node != nullptr, source_node);
AstNode *existing_assign_node = field_assign_nodes[dst_field->src_index];
@@ -7062,6 +7080,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, Scope *sco
// look for a default field value
TypeStructField *field = wanted_type->data.structure.fields[i];
+ assert(!field->is_comptime); // field_assign_nodes[i] should be null for comptime fields
memoize_field_init_val(ira->codegen, wanted_type, field);
if (field->init_val == nullptr) {
ir_add_error_node(ira, source_node,
@@ -7097,6 +7116,9 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, Scope *sco
for (size_t i = 0; i < actual_field_count; i += 1) {
TypeStructField *field = wanted_type->data.structure.fields[i];
+ if (field->is_comptime)
+ continue;
+
IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, scope, source_node, field, result_loc_inst, wanted_type, true);
if (type_is_invalid(field_ptr->value->type))
return ira->codegen->invalid_inst_gen;
@@ -12750,6 +12772,29 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, Scope *scope, AstNode *sour
bool cacheable = fn_eval_cacheable(exec_scope, return_type);
ZigValue *result = nullptr;
if (cacheable) {
+ // 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.
+ {
+ Scope *scope = exec_scope;
+ while (scope) {
+ if (scope->id == ScopeIdVarDecl) {
+ ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
+ if ((err = ir_resolve_lazy_recurse(
+ var_scope->var->decl_node,
+ var_scope->var->const_value)))
+ {
+ return ira->codegen->invalid_inst_gen;
+ }
+ } else if (scope->id == ScopeIdFnDef) {
+ break;
+ } else {
+ zig_unreachable();
+ }
+ scope = scope->parent;
+ }
+ }
+
auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);
if (entry)
result = entry->value;
@@ -12935,6 +12980,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
@@ -14873,6 +14930,8 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, Scope *scope, AstN
struct_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, struct_type->data.structure.src_field_count);
struct_val->special = ConstValSpecialStatic;
for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
+ if (struct_type->data.structure.fields[i]->is_comptime)
+ continue;
ZigValue *field_val = struct_val->data.x_struct.fields[i];
field_val->special = ConstValSpecialUndef;
field_val->type = resolve_struct_field_type(ira->codegen,
@@ -18247,7 +18306,9 @@ static ZigValue *get_const_field(IrAnalyze *ira, AstNode *source_node, ZigValue
{
Error err;
ensure_field_index(struct_value->type, name, field_index);
- ZigValue *val = struct_value->data.x_struct.fields[field_index];
+ TypeStructField *field = struct_value->type->data.structure.fields[field_index];
+ ZigValue *val = field->is_comptime ? field->init_val :
+ struct_value->data.x_struct.fields[field_index];
if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, source_node, val, UndefBad)))
return nullptr;
return val;
@@ -22422,7 +22483,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val)
size_t src_field_count = val->type->data.structure.src_field_count;
for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
TypeStructField *struct_field = val->type->data.structure.fields[field_i];
- if (struct_field->gen_index == SIZE_MAX)
+ if (struct_field->gen_index == SIZE_MAX || struct_field->is_comptime)
continue;
ZigValue *field_val = val->data.x_struct.fields[field_i];
size_t offset = struct_field->offset;
@@ -22451,6 +22512,10 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val)
size_t used_bits = 0;
while (src_i < src_field_count) {
TypeStructField *field = val->type->data.structure.fields[src_i];
+ if (field->is_comptime) {
+ src_i += 1;
+ continue;
+ }
assert(field->gen_index != SIZE_MAX);
if (field->gen_index != gen_i)
break;
@@ -22599,9 +22664,11 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
size_t src_field_count = val->type->data.structure.src_field_count;
val->data.x_struct.fields = alloc_const_vals_ptrs(codegen, src_field_count);
for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
+ TypeStructField *struct_field = val->type->data.structure.fields[field_i];
+ if (struct_field->is_comptime)
+ continue;
ZigValue *field_val = val->data.x_struct.fields[field_i];
field_val->special = ConstValSpecialStatic;
- TypeStructField *struct_field = val->type->data.structure.fields[field_i];
field_val->type = struct_field->type_entry;
if (struct_field->gen_index == SIZE_MAX)
continue;
@@ -22634,6 +22701,10 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
uint64_t bit_offset = 0;
while (src_i < src_field_count) {
TypeStructField *field = val->type->data.structure.fields[src_i];
+ if (field->is_comptime) {
+ src_i += 1;
+ continue;
+ }
src_assert(field->gen_index != SIZE_MAX, source_node);
if (field->gen_index != gen_i)
break;
@@ -25515,6 +25586,95 @@ 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;
+ assert(val->special != ConstValSpecialRuntime);
+ assert(val->special != ConstValSpecialLazy);
+ 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 (val->type->data.structure.fields[i]->is_comptime) {
+ // comptime struct fields do not need to be resolved because
+ // they are not part of the value.
+ continue;
+ }
+ 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))) {