diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-02-04 21:26:50 -0500 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-02-04 21:26:50 -0500 |
| commit | f32f7a937fa7150aaba450b1282bba9f01918807 (patch) | |
| tree | ecb462e15546a50b2e948b8f2907872dd39a2dc6 /src/analyze.cpp | |
| parent | 1411df4e2705e677003e6e5b5cbe1ca30bf637d7 (diff) | |
| parent | 8c6fa982cd0a02775264b616c37da9907cc603bb (diff) | |
| download | zig-f32f7a937fa7150aaba450b1282bba9f01918807.tar.gz zig-f32f7a937fa7150aaba450b1282bba9f01918807.zip | |
Merge remote-tracking branch 'origin/master' into llvm8
Diffstat (limited to 'src/analyze.cpp')
| -rw-r--r-- | src/analyze.cpp | 512 |
1 files changed, 361 insertions, 151 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp index 15370983fc..ff961a7044 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -250,6 +250,7 @@ AstNode *type_decl_node(ZigType *type_entry) { case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdPromise: + case ZigTypeIdVector: return nullptr; } zig_unreachable(); @@ -311,6 +312,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdPromise: + case ZigTypeIdVector: return true; } zig_unreachable(); @@ -570,7 +572,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { if (child_type->zero_bits) { entry->type_ref = LLVMInt1Type(); entry->di_type = g->builtin_types.entry_bool->di_type; - } else if (type_is_codegen_pointer(child_type)) { + } else if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) { assert(child_type->di_type); // this is an optimization but also is necessary for calling C // functions where all pointers are maybe pointers @@ -1055,11 +1057,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { } if (g->zig_target.arch.arch == ZigLLVM_x86_64) { X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); - if (abi_class == X64CABIClass_MEMORY) { - return true; - } - zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481", - buf_ptr(&fn_type_id->return_type->name)); + return abi_class == X64CABIClass_MEMORY; } else if (target_is_arm(&g->zig_target)) { return type_size(g, fn_type_id->return_type) > 16; } @@ -1278,7 +1276,9 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind return entry; } -static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) { +static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, + Buf *type_name) +{ size_t backward_branch_count = 0; return ir_eval_const_value(g, scope, node, type_entry, &backward_branch_count, default_backward_branch_quota, @@ -1286,12 +1286,12 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod } ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { - IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); - if (result->value.type->id == ZigTypeIdInvalid) + ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); + if (type_is_invalid(result->type)) return g->builtin_types.entry_invalid; - assert(result->value.special != ConstValSpecialRuntime); - return result->value.data.x_type; + assert(result->special != ConstValSpecialRuntime); + return result->data.x_type; } ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) { @@ -1342,11 +1342,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou } static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) { - IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr); - if (type_is_invalid(align_result->value.type)) + ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr); + if (type_is_invalid(align_result->type)) return false; - uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint); + uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint); if (align_bytes == 0) { add_node_error(g, node, buf_sprintf("alignment must be >= 1")); return false; @@ -1364,12 +1364,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, PtrLenUnknown, 0, 0, 0); ZigType *str_type = get_slice_type(g, ptr_type); - IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr); - if (type_is_invalid(instr->value.type)) + ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr); + if (type_is_invalid(result_val->type)) return false; - ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index]; - ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index]; + ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index]; assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray); ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val; @@ -1422,6 +1422,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) { case ZigTypeIdPointer: case ZigTypeIdArray: case ZigTypeIdFn: + case ZigTypeIdVector: return true; case ZigTypeIdStruct: return type_entry->data.structure.layout == ContainerLayoutPacked; @@ -1470,6 +1471,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { default: return false; } + case ZigTypeIdVector: + return type_allowed_in_extern(g, type_entry->data.vector.elem_type); case ZigTypeIdFloat: return true; case ZigTypeIdArray: @@ -1623,6 +1626,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdPromise: + case ZigTypeIdVector: switch (type_requires_comptime(g, type_entry)) { case ReqCompTimeNo: break; @@ -1718,6 +1722,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdPromise: + case ZigTypeIdVector: switch (type_requires_comptime(g, fn_type_id.return_type)) { case ReqCompTimeInvalid: return g->builtin_types.entry_invalid; @@ -2504,20 +2509,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { // In this first pass we resolve explicit tag values. // In a second pass we will fill in the unspecified ones. if (tag_value != nullptr) { - IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); - if (result_inst->value.type->id == ZigTypeIdInvalid) { + ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); + if (type_is_invalid(result->type)) { enum_type->data.enumeration.is_invalid = true; continue; } - assert(result_inst->value.special != ConstValSpecialRuntime); - assert(result_inst->value.type->id == ZigTypeIdInt || - result_inst->value.type->id == ZigTypeIdComptimeInt); - auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); + assert(result->special != ConstValSpecialRuntime); + assert(result->type->id == ZigTypeIdInt || + result->type->id == ZigTypeIdComptimeInt); + auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); if (entry == nullptr) { - bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint); + bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); } else { Buf *val_buf = buf_alloc(); - bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); + bigint_append_buf(val_buf, &result->data.x_bigint, 10); ErrorMsg *msg = add_node_error(g, tag_value, buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); @@ -2944,19 +2949,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { // In a second pass we will fill in the unspecified ones. if (tag_value != nullptr) { ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type; - IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); - if (result_inst->value.type->id == ZigTypeIdInvalid) { + ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); + if (type_is_invalid(result->type)) { union_type->data.unionation.is_invalid = true; continue; } - assert(result_inst->value.special != ConstValSpecialRuntime); - assert(result_inst->value.type->id == ZigTypeIdInt); - auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); + assert(result->special != ConstValSpecialRuntime); + assert(result->type->id == ZigTypeIdInt); + auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); if (entry == nullptr) { - bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint); + bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint); } else { Buf *val_buf = buf_alloc(); - bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); + bigint_append_buf(val_buf, &result->data.x_bigint, 10); ErrorMsg *msg = add_node_error(g, tag_value, buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); @@ -3419,7 +3424,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) { resolve_top_level_decl(g, tld, false, tld->source_node); assert(tld->id == TldIdVar); TldVar *tld_var = (TldVar *)tld; - tld_var->var->value = value; + tld_var->var->const_value = value; + tld_var->var->var_type = value->type; tld_var->var->align_bytes = get_abi_alignment(g, value->type); } @@ -3513,7 +3519,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { case NodeTypeArrayType: case NodeTypeErrorType: case NodeTypeIfErrorExpr: - case NodeTypeTestExpr: + case NodeTypeIfOptional: case NodeTypeErrorSetDecl: case NodeTypeCancel: case NodeTypeResume: @@ -3574,6 +3580,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry case ZigTypeIdFn: case ZigTypeIdBoundFn: case ZigTypeIdPromise: + case ZigTypeIdVector: return type_entry; } zig_unreachable(); @@ -3582,13 +3589,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry // Set name to nullptr to make the variable anonymous (not visible to programmer). // TODO merge with definition of add_local_var in ir.cpp ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name, - bool is_const, ConstExprValue *value, Tld *src_tld) + bool is_const, ConstExprValue *const_value, Tld *src_tld, ZigType *var_type) { Error err; - assert(value); + assert(const_value != nullptr); + assert(var_type != nullptr); ZigVar *variable_entry = allocate<ZigVar>(1); - variable_entry->value = value; + variable_entry->const_value = const_value; + variable_entry->var_type = var_type; variable_entry->parent_scope = parent_scope; variable_entry->shadowable = false; variable_entry->mem_slot_index = SIZE_MAX; @@ -3597,23 +3606,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf assert(name); buf_init_from_buf(&variable_entry->name, name); - if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) { - variable_entry->value->type = g->builtin_types.entry_invalid; + if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) { + variable_entry->var_type = g->builtin_types.entry_invalid; } else { - variable_entry->align_bytes = get_abi_alignment(g, value->type); + variable_entry->align_bytes = get_abi_alignment(g, var_type); ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr); if (existing_var && !existing_var->shadowable) { ErrorMsg *msg = add_node_error(g, source_node, buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); - variable_entry->value->type = g->builtin_types.entry_invalid; + variable_entry->var_type = g->builtin_types.entry_invalid; } else { ZigType *type; if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) { add_node_error(g, source_node, buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); - variable_entry->value->type = g->builtin_types.entry_invalid; + variable_entry->var_type = g->builtin_types.entry_invalid; } else { Scope *search_scope = nullptr; if (src_tld == nullptr) { @@ -3627,7 +3636,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf ErrorMsg *msg = add_node_error(g, source_node, buf_sprintf("redefinition of '%s'", buf_ptr(name))); add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here")); - variable_entry->value->type = g->builtin_types.entry_invalid; + variable_entry->var_type = g->builtin_types.entry_invalid; } } } @@ -3677,7 +3686,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { linkage = VarLinkageInternal; } - IrInstruction *init_value = nullptr; + ConstExprValue *init_value = nullptr; // TODO more validation for types that can't be used for export/extern variables ZigType *implicit_type = nullptr; @@ -3686,7 +3695,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { } else if (var_decl->expr) { init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol); assert(init_value); - implicit_type = init_value->value.type; + implicit_type = init_value->type; if (implicit_type->id == ZigTypeIdUnreachable) { add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable")); @@ -3704,7 +3713,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant")); implicit_type = g->builtin_types.entry_invalid; } - assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime); + assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime); } else if (linkage != VarLinkageExternal) { add_node_error(g, source_node, buf_sprintf("variables must be initialized")); implicit_type = g->builtin_types.entry_invalid; @@ -3713,19 +3722,19 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { ZigType *type = explicit_type ? explicit_type : implicit_type; assert(type != nullptr); // should have been caught by the parser - ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type); + ConstExprValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type); tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol, - is_const, init_val, &tld_var->base); + is_const, init_val, &tld_var->base, type); tld_var->var->linkage = linkage; if (implicit_type != nullptr && type_is_invalid(implicit_type)) { - tld_var->var->value->type = g->builtin_types.entry_invalid; + tld_var->var->var_type = g->builtin_types.entry_invalid; } if (var_decl->align_expr != nullptr) { if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) { - tld_var->var->value->type = g->builtin_types.entry_invalid; + tld_var->var->var_type = g->builtin_types.entry_invalid; } } @@ -3938,6 +3947,7 @@ static bool is_container(ZigType *type_entry) { case ZigTypeIdArgTuple: case ZigTypeIdOpaque: case ZigTypeIdPromise: + case ZigTypeIdVector: return false; } zig_unreachable(); @@ -3997,6 +4007,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) { case ZigTypeIdArgTuple: case ZigTypeIdOpaque: case ZigTypeIdPromise: + case ZigTypeIdVector: zig_unreachable(); } } @@ -4090,7 +4101,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { } ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope, - param_name, true, create_const_runtime(param_type), nullptr); + param_name, true, create_const_runtime(param_type), nullptr, param_type); var->src_arg_index = i; fn_table_entry->child_scope = var->child_scope; var->shadowable = var->shadowable || is_var_args; @@ -4228,18 +4239,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * preview_use_decl(g, src_use_node); } - IrInstruction *use_target_value = src_use_node->data.use.value; - if (use_target_value->value.type->id == ZigTypeIdInvalid) { + ConstExprValue *use_target_value = src_use_node->data.use.value; + if (type_is_invalid(use_target_value->type)) { dst_use_node->owner->any_imports_failed = true; return; } dst_use_node->data.use.resolution = TldResolutionOk; - ConstExprValue *const_val = &use_target_value->value; - assert(const_val->special != ConstValSpecialRuntime); + assert(use_target_value->special != ConstValSpecialRuntime); - ImportTableEntry *target_import = const_val->data.x_import; + ImportTableEntry *target_import = use_target_value->data.x_import; assert(target_import); if (target_import->any_imports_failed) { @@ -4302,10 +4312,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) { } node->data.use.resolution = TldResolutionResolving; - IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base, + ConstExprValue *result = analyze_const_value(g, &node->owner->decls_scope->base, node->data.use.expr, g->builtin_types.entry_namespace, nullptr); - if (result->value.type->id == ZigTypeIdInvalid) + if (type_is_invalid(result->type)) node->owner->any_imports_failed = true; node->data.use.value = result; @@ -4447,6 +4457,42 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { return new_entry; } +bool is_valid_vector_elem_type(ZigType *elem_type) { + return elem_type->id == ZigTypeIdInt || + elem_type->id == ZigTypeIdFloat || + get_codegen_ptr_type(elem_type) != nullptr; +} + +ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) { + assert(is_valid_vector_elem_type(elem_type)); + + TypeId type_id = {}; + type_id.id = ZigTypeIdVector; + type_id.data.vector.len = len; + type_id.data.vector.elem_type = elem_type; + + { + auto entry = g->type_table.maybe_get(type_id); + if (entry) + return entry->value; + } + + ZigType *entry = new_type_table_entry(ZigTypeIdVector); + entry->zero_bits = (len == 0) || !type_has_bits(elem_type); + entry->type_ref = entry->zero_bits ? LLVMVoidType() : LLVMVectorType(elem_type->type_ref, len); + entry->data.vector.len = len; + entry->data.vector.elem_type = elem_type; + + buf_resize(&entry->name, 0); + buf_appendf(&entry->name, "@Vector(%u, %s)", len, buf_ptr(&elem_type->name)); + + entry->di_type = ZigLLVMDIBuilderCreateVectorType(g->dbuilder, len, + LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref), elem_type->di_type); + + g->type_table.put(type_id, entry); + return entry; +} + ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) { return &g->builtin_types.entry_c_int[c_int_type]; } @@ -4478,6 +4524,7 @@ bool handle_is_ptr(ZigType *type_entry) { case ZigTypeIdFn: case ZigTypeIdEnum: case ZigTypeIdPromise: + case ZigTypeIdVector: return false; case ZigTypeIdArray: case ZigTypeIdStruct: @@ -4486,7 +4533,8 @@ bool handle_is_ptr(ZigType *type_entry) { return type_has_bits(type_entry->data.error_union.payload_type); case ZigTypeIdOptional: return type_has_bits(type_entry->data.maybe.child_type) && - !type_is_codegen_pointer(type_entry->data.maybe.child_type); + !type_is_codegen_pointer(type_entry->data.maybe.child_type) && + type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet; case ZigTypeIdUnion: assert(type_entry->data.unionation.zero_bits_known); if (type_entry->data.unionation.gen_field_count == 0) @@ -4732,6 +4780,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) { return true; } +static uint32_t hash_const_val_error_set(ConstExprValue *const_val) { + assert(const_val->data.x_err_set != nullptr); + return const_val->data.x_err_set->value ^ 2630160122; +} + static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { uint32_t hash_val = 0; switch (const_val->data.x_ptr.mut) { @@ -4763,6 +4816,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val); hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index); return hash_val; + case ConstPtrSpecialBaseErrorUnionCode: + hash_val += (uint32_t)2994743799; + hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_code.err_union_val); + return hash_val; + case ConstPtrSpecialBaseErrorUnionPayload: + hash_val += (uint32_t)3456080131; + hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_payload.err_union_val); + return hash_val; + case ConstPtrSpecialBaseOptionalPayload: + hash_val += (uint32_t)3163140517; + hash_val += hash_ptr(const_val->data.x_ptr.data.base_optional_payload.optional_val); + return hash_val; case ConstPtrSpecialHardCodedAddr: hash_val += (uint32_t)4048518294; hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr); @@ -4774,6 +4839,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { hash_val += (uint32_t)2590901619; hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); return hash_val; + case ConstPtrSpecialNull: + hash_val += (uint32_t)1486246455; + return hash_val; } zig_unreachable(); } @@ -4872,7 +4940,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { return 2709806591; case ZigTypeIdOptional: if (get_codegen_ptr_type(const_val->type) != nullptr) { - return hash_const_val(const_val) * 1992916303; + return hash_const_val_ptr(const_val) * 1992916303; + } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) { + return hash_const_val_error_set(const_val) * 3147031929; } else { if (const_val->data.x_optional) { return hash_const_val(const_val->data.x_optional) * 1992916303; @@ -4884,10 +4954,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { // TODO better hashing algorithm return 3415065496; case ZigTypeIdErrorSet: - assert(const_val->data.x_err_set != nullptr); - return const_val->data.x_err_set->value ^ 2630160122; + return hash_const_val_error_set(const_val); case ZigTypeIdNamespace: return hash_ptr(const_val->data.x_import); + case ZigTypeIdVector: + // TODO better hashing algorithm + return 3647867726; case ZigTypeIdBoundFn: case ZigTypeIdInvalid: case ZigTypeIdUnreachable: @@ -4940,6 +5012,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { case ZigTypeIdBool: case ZigTypeIdUnreachable: case ZigTypeIdInt: + case ZigTypeIdVector: case ZigTypeIdFloat: case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: @@ -4987,7 +5060,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { return can_mutate_comptime_var_state(value->data.x_optional); case ZigTypeIdErrorUnion: - if (value->data.x_err_union.err != nullptr) + if (value->data.x_err_union.error_set->data.x_err_set != nullptr) return false; assert(value->data.x_err_union.payload != nullptr); return can_mutate_comptime_var_state(value->data.x_err_union.payload); @@ -5023,6 +5096,7 @@ static bool return_type_is_cacheable(ZigType *return_type) { case ZigTypeIdErrorSet: case ZigTypeIdEnum: case ZigTypeIdPointer: + case ZigTypeIdVector: return true; case ZigTypeIdArray: @@ -5048,9 +5122,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) { while (scope) { if (scope->id == ScopeIdVarDecl) { ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; - if (type_is_invalid(var_scope->var->value->type)) + if (type_is_invalid(var_scope->var->var_type)) return false; - if (can_mutate_comptime_var_state(var_scope->var->value)) + if (can_mutate_comptime_var_state(var_scope->var->const_value)) return false; } else if (scope->id == ScopeIdFnDef) { return true; @@ -5068,7 +5142,7 @@ uint32_t fn_eval_hash(Scope* scope) { while (scope) { if (scope->id == ScopeIdVarDecl) { ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; - result += hash_const_val(var_scope->var->value); + result += hash_const_val(var_scope->var->const_value); } else if (scope->id == ScopeIdFnDef) { ScopeFnDef *fn_scope = (ScopeFnDef *)scope; result += hash_ptr(fn_scope->fn_entry); @@ -5092,10 +5166,16 @@ bool fn_eval_eql(Scope *a, Scope *b) { if (a->id == ScopeIdVarDecl) { ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a; ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b; - if (a_var_scope->var->value->type != b_var_scope->var->value->type) - return false; - if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value)) + if (a_var_scope->var->var_type != b_var_scope->var->var_type) return false; + if (a_var_scope->var->var_type == a_var_scope->var->const_value->type && + b_var_scope->var->var_type == b_var_scope->var->const_value->type) + { + if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value)) + return false; + } else { + zig_panic("TODO comptime ptr reinterpret for fn_eval_eql"); + } } else if (a->id == ScopeIdFnDef) { ScopeFnDef *a_fn_scope = (ScopeFnDef *)a; ScopeFnDef *b_fn_scope = (ScopeFnDef *)b; @@ -5113,6 +5193,7 @@ bool fn_eval_eql(Scope *a, Scope *b) { return false; } +// Whether the type has bits at runtime. bool type_has_bits(ZigType *type_entry) { assert(type_entry); assert(!type_is_invalid(type_entry)); @@ -5120,6 +5201,66 @@ bool type_has_bits(ZigType *type_entry) { return !type_entry->zero_bits; } +// Whether you can infer the value based solely on the type. +OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { + assert(type_entry != nullptr); + Error err; + if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) + return OnePossibleValueInvalid; + switch (type_entry->id) { + case ZigTypeIdInvalid: + zig_unreachable(); + case ZigTypeIdOpaque: + case ZigTypeIdComptimeFloat: + case ZigTypeIdComptimeInt: + case ZigTypeIdMetaType: + case ZigTypeIdNamespace: + case ZigTypeIdBoundFn: + case ZigTypeIdArgTuple: + case ZigTypeIdOptional: + case ZigTypeIdFn: + case ZigTypeIdBool: + case ZigTypeIdFloat: + case ZigTypeIdPromise: + case ZigTypeIdErrorUnion: + return OnePossibleValueNo; + case ZigTypeIdUndefined: + case ZigTypeIdNull: + case ZigTypeIdVoid: + case ZigTypeIdUnreachable: + return OnePossibleValueYes; + case ZigTypeIdArray: + if (type_entry->data.array.len == 0) + return OnePossibleValueYes; + return type_has_one_possible_value(g, type_entry->data.array.child_type); + case ZigTypeIdStruct: + for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { + TypeStructField *field = &type_entry->data.structure.fields[i]; + switch (type_has_one_possible_value(g, field->type_entry)) { + case OnePossibleValueInvalid: + return OnePossibleValueInvalid; + case OnePossibleValueNo: + return OnePossibleValueNo; + case OnePossibleValueYes: + continue; + } + } + return OnePossibleValueYes; + case ZigTypeIdErrorSet: + case ZigTypeIdEnum: + case ZigTypeIdInt: + case ZigTypeIdVector: + return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes; + case ZigTypeIdPointer: + return type_has_one_possible_value(g, type_entry->data.pointer.child_type); + case ZigTypeIdUnion: + if (type_entry->data.unionation.src_field_count > 1) + return OnePossibleValueNo; + return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry); + } + zig_unreachable(); +} + ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { Error err; if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) @@ -5159,6 +5300,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { case ZigTypeIdErrorSet: case ZigTypeIdBool: case ZigTypeIdInt: + case ZigTypeIdVector: case ZigTypeIdFloat: case ZigTypeIdVoid: case ZigTypeIdUnreachable: @@ -5574,6 +5716,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index) return false; return true; + case ConstPtrSpecialBaseErrorUnionCode: + if (a->data.x_ptr.data.base_err_union_code.err_union_val != + b->data.x_ptr.data.base_err_union_code.err_union_val && + a->data.x_ptr.data.base_err_union_code.err_union_val->global_refs != + b->data.x_ptr.data.base_err_union_code.err_union_val->global_refs) + { + return false; + } + return true; + case ConstPtrSpecialBaseErrorUnionPayload: + if (a->data.x_ptr.data.base_err_union_payload.err_union_val != + b->data.x_ptr.data.base_err_union_payload.err_union_val && + a->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs != + b->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs) + { + return false; + } + return true; + case ConstPtrSpecialBaseOptionalPayload: + if (a->data.x_ptr.data.base_optional_payload.optional_val != + b->data.x_ptr.data.base_optional_payload.optional_val && + a->data.x_ptr.data.base_optional_payload.optional_val->global_refs != + b->data.x_ptr.data.base_optional_payload.optional_val->global_refs) + { + return false; + } + return true; case ConstPtrSpecialHardCodedAddr: if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr) return false; @@ -5582,10 +5751,34 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { return true; case ConstPtrSpecialFunction: return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry; + case ConstPtrSpecialNull: + return true; } zig_unreachable(); } +static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprValue *b, size_t len) { + assert(a->data.x_array.special != ConstArraySpecialUndef); + assert(b->data.x_array.special != ConstArraySpecialUndef); + if (a->data.x_array.special == ConstArraySpecialBuf && + b->data.x_array.special == ConstArraySpecialBuf) + { + return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf); + } + expand_undef_array(g, a); + expand_undef_array(g, b); + + ConstExprValue *a_elems = a->data.x_array.data.s_none.elements; + ConstExprValue *b_elems = b->data.x_array.data.s_none.elements; + + for (size_t i = 0; i < len; i += 1) { + if (!const_values_equal(g, &a_elems[i], &b_elems[i])) + return false; + } + + return true; +} + bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { assert(a->type->id == b->type->id); assert(a->special == ConstValSpecialStatic); @@ -5640,28 +5833,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { case ZigTypeIdPointer: case ZigTypeIdFn: return const_values_equal_ptr(a, b); + case ZigTypeIdVector: + assert(a->type->data.vector.len == b->type->data.vector.len); + return const_values_equal_array(g, a, b, a->type->data.vector.len); case ZigTypeIdArray: { assert(a->type->data.array.len == b->type->data.array.len); - assert(a->data.x_array.special != ConstArraySpecialUndef); - assert(b->data.x_array.special != ConstArraySpecialUndef); - if (a->data.x_array.special == ConstArraySpecialBuf && - b->data.x_array.special == ConstArraySpecialBuf) - { - return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf); - } - expand_undef_array(g, a); - expand_undef_array(g, b); - - size_t len = a->type->data.array.len; - ConstExprValue *a_elems = a->data.x_array.data.s_none.elements; - ConstExprValue *b_elems = b->data.x_array.data.s_none.elements; - - for (size_t i = 0; i < len; ++i) { - if (!const_values_equal(g, &a_elems[i], &b_elems[i])) - return false; - } - - return true; + return const_values_equal_array(g, a, b, a->type->data.array.len); } case ZigTypeIdStruct: for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) { @@ -5750,7 +5927,7 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v } } -void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { +static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { assert(type_entry->id == ZigTypeIdPointer); if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) { @@ -5763,6 +5940,9 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy zig_unreachable(); case ConstPtrSpecialRef: case ConstPtrSpecialBaseStruct: + case ConstPtrSpecialBaseErrorUnionCode: + case ConstPtrSpecialBaseErrorUnionPayload: + case ConstPtrSpecialBaseOptionalPayload: buf_appendf(buf, "*"); // TODO we need a source node for const_ptr_pointee because it can generate compile errors render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr)); @@ -5790,6 +5970,51 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name)); return; } + case ConstPtrSpecialNull: + buf_append_str(buf, "null"); + return; + } + zig_unreachable(); +} + +static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { + if (const_val->data.x_err_set == nullptr) { + buf_append_str(buf, "null"); + } else { + buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name)); + } +} + +static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_val, size_t len) { + switch (const_val->data.x_array.special) { + case ConstArraySpecialUndef: + buf_append_str(buf, "undefined"); + return; + case ConstArraySpecialBuf: { + Buf *array_buf = const_val->data.x_array.data.s_buf; + buf_append_char(buf, '"'); + for (size_t i = 0; i < buf_len(array_buf); i += 1) { + uint8_t c = buf_ptr(array_buf)[i]; + if (c == '"') { + buf_append_str(buf, "\\\""); + } else { + buf_append_char(buf, c); + } + } + buf_append_char(buf, '"'); + return; + } + case ConstArraySpecialNone: { + buf_appendf(buf, "%s{", buf_ptr(&const_val->type->name)); + for (uint64_t i = 0; i < len; i += 1) { + if (i != 0) + buf_appendf(buf, ","); + ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i]; + render_const_value(g, buf, child_value); + } + buf_appendf(buf, "}"); + return; + } } zig_unreachable(); } @@ -5874,39 +6099,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { } case ZigTypeIdPointer: return render_const_val_ptr(g, buf, const_val, type_entry); + case ZigTypeIdVector: + return render_const_val_array(g, buf, const_val, type_entry->data.vector.len); case ZigTypeIdArray: - switch (const_val->data.x_array.special) { - case ConstArraySpecialUndef: - buf_append_str(buf, "undefined"); - return; - case ConstArraySpecialBuf: { - Buf *array_buf = const_val->data.x_array.data.s_buf; - buf_append_char(buf, '"'); - for (size_t i = 0; i < buf_len(array_buf); i += 1) { - uint8_t c = buf_ptr(array_buf)[i]; - if (c == '"') { - buf_append_str(buf, "\\\""); - } else { - buf_append_char(buf, c); - } - } - buf_append_char(buf, '"'); - return; - } - case ConstArraySpecialNone: { - buf_appendf(buf, "%s{", buf_ptr(&type_entry->name)); - uint64_t len = type_entry->data.array.len; - for (uint64_t i = 0; i < len; i += 1) { - if (i != 0) - buf_appendf(buf, ","); - ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i]; - render_const_value(g, buf, child_value); - } - buf_appendf(buf, "}"); - return; - } - } - zig_unreachable(); + return render_const_val_array(g, buf, const_val, type_entry->data.array.len); case ZigTypeIdNull: { buf_appendf(buf, "null"); @@ -5921,6 +6117,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { { if (get_codegen_ptr_type(const_val->type) != nullptr) return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type); + if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet) + return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type); if (const_val->data.x_optional) { render_const_value(g, buf, const_val->data.x_optional); } else { @@ -5958,11 +6156,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { case ZigTypeIdErrorUnion: { buf_appendf(buf, "%s(", buf_ptr(&type_entry->name)); - if (const_val->data.x_err_union.err == nullptr) { + ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; + if (err_set == nullptr) { render_const_value(g, buf, const_val->data.x_err_union.payload); } else { buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name), - buf_ptr(&const_val->data.x_err_union.err->name)); + buf_ptr(&err_set->name)); } buf_appendf(buf, ")"); return; @@ -5977,10 +6176,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { return; } case ZigTypeIdErrorSet: - { - buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name)); - return; - } + return render_const_val_err_set(g, buf, const_val, type_entry); case ZigTypeIdArgTuple: { buf_appendf(buf, "(args value)"); @@ -6065,6 +6261,8 @@ uint32_t type_id_hash(TypeId x) { case ZigTypeIdInt: return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) + (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557); + case ZigTypeIdVector: + return hash_ptr(x.data.vector.elem_type) * (x.data.vector.len * 526582681); } zig_unreachable(); } @@ -6113,6 +6311,9 @@ bool type_id_eql(TypeId a, TypeId b) { case ZigTypeIdInt: return a.data.integer.is_signed == b.data.integer.is_signed && a.data.integer.bit_count == b.data.integer.bit_count; + case ZigTypeIdVector: + return a.data.vector.elem_type == b.data.vector.elem_type && + a.data.vector.len == b.data.vector.len; } zig_unreachable(); } @@ -6171,24 +6372,34 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { // Canonicalize the array value as ConstArraySpecialNone void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { - assert(const_val->type->id == ZigTypeIdArray); + size_t elem_count; + ZigType *elem_type; + if (const_val->type->id == ZigTypeIdArray) { + elem_count = const_val->type->data.array.len; + elem_type = const_val->type->data.array.child_type; + } else if (const_val->type->id == ZigTypeIdVector) { + elem_count = const_val->type->data.vector.len; + elem_type = const_val->type->data.vector.elem_type; + } else { + zig_unreachable(); + } + if (const_val->special == ConstValSpecialUndef) { + const_val->special = ConstValSpecialStatic; + const_val->data.x_array.special = ConstArraySpecialUndef; + } switch (const_val->data.x_array.special) { case ConstArraySpecialNone: return; case ConstArraySpecialUndef: { const_val->data.x_array.special = ConstArraySpecialNone; - size_t elem_count = const_val->type->data.array.len; const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); for (size_t i = 0; i < elem_count; i += 1) { ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i]; - element_val->type = const_val->type->data.array.child_type; + element_val->type = elem_type; init_const_undefined(g, element_val); - ConstParent *parent = get_const_val_parent(g, element_val); - if (parent != nullptr) { - parent->id = ConstParentIdArray; - parent->data.p_array.array_val = const_val; - parent->data.p_array.elem_index = i; - } + element_val->parent.id = ConstParentIdArray; + element_val->parent.data.p_array.array_val = const_val; + element_val->parent.data.p_array.elem_index = i; } return; } @@ -6199,7 +6410,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { g->string_literals_table.maybe_remove(buf); const_val->data.x_array.special = ConstArraySpecialNone; - size_t elem_count = const_val->type->data.array.len; assert(elem_count == buf_len(buf)); const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); for (size_t i = 0; i < elem_count; i += 1) { @@ -6207,6 +6417,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { this_char->special = ConstValSpecialStatic; this_char->type = g->builtin_types.entry_u8; bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]); + this_char->parent.id = ConstParentIdArray; + this_char->parent.data.p_array.array_val = const_val; + this_char->parent.data.p_array.elem_index = i; } return; } @@ -6214,18 +6427,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { zig_unreachable(); } +// Deprecated. Reference the parent field directly. ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) { - assert(value->type); - ZigType *type_entry = value->type; - if (type_entry->id == ZigTypeIdArray) { - expand_undef_array(g, value); - return &value->data.x_array.data.s_none.parent; - } else if (type_entry->id == ZigTypeIdStruct) { - return &value->data.x_struct.parent; - } else if (type_entry->id == ZigTypeIdUnion) { - return &value->data.x_union.parent; - } - return nullptr; + return &value->parent; } static const ZigTypeId all_type_ids[] = { @@ -6253,6 +6457,7 @@ static const ZigTypeId all_type_ids[] = { ZigTypeIdArgTuple, ZigTypeIdOpaque, ZigTypeIdPromise, + ZigTypeIdVector, }; ZigTypeId type_id_at_index(size_t index) { @@ -6318,6 +6523,8 @@ size_t type_id_index(ZigType *entry) { return 22; case ZigTypeIdPromise: return 23; + case ZigTypeIdVector: + return 24; } zig_unreachable(); } @@ -6374,6 +6581,8 @@ const char *type_id_name(ZigTypeId id) { return "Opaque"; case ZigTypeIdPromise: return "Promise"; + case ZigTypeIdVector: + return "Vector"; } zig_unreachable(); } @@ -6453,7 +6662,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { resolve_top_level_decl(codegen, tld, false, nullptr); assert(tld->id == TldIdVar); TldVar *tld_var = (TldVar *)tld; - ConstExprValue *var_value = tld_var->var->value; + ConstExprValue *var_value = tld_var->var->const_value; assert(var_value != nullptr); return var_value; } @@ -6529,6 +6738,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) { case ZigTypeIdBool: return X64CABIClass_INTEGER; case ZigTypeIdFloat: + case ZigTypeIdVector: return X64CABIClass_SSE; case ZigTypeIdStruct: { // "If the size of an object is larger than four eightbytes, or it contains unaligned |
