diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-12-01 09:56:01 -0500 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-12-01 09:56:01 -0500 |
| commit | b36c07a95a6cf9b2cc120133b44cbd0673e6823a (patch) | |
| tree | 2c2bf8ff9137d51b80ae56dc70ef9375b8c13583 /src | |
| parent | b220be7a33a9835a1ec7a033e472830290332d57 (diff) | |
| parent | 4b6740e19d57454f3c4eac0c2e9a92ce08e7ec04 (diff) | |
| download | zig-b36c07a95a6cf9b2cc120133b44cbd0673e6823a.tar.gz zig-b36c07a95a6cf9b2cc120133b44cbd0673e6823a.zip | |
Merge remote-tracking branch 'origin/master' into remove-array-type-coercion
Diffstat (limited to 'src')
| -rw-r--r-- | src/all_types.hpp | 4 | ||||
| -rw-r--r-- | src/analyze.cpp | 41 | ||||
| -rw-r--r-- | src/codegen.cpp | 301 | ||||
| -rw-r--r-- | src/ir.cpp | 486 | ||||
| -rw-r--r-- | src/libc_installation.cpp | 2 | ||||
| -rw-r--r-- | src/list.hpp | 2 | ||||
| -rw-r--r-- | src/memory_profiling.cpp | 7 | ||||
| -rw-r--r-- | src/os.cpp | 8 | ||||
| -rw-r--r-- | src/util.hpp | 2 |
9 files changed, 677 insertions, 176 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index a5fa7241e3..4dac878315 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1565,7 +1565,7 @@ struct ZigFn { // in the case of async functions this is the implicit return type according to the // zig source code, not according to zig ir ZigType *src_implicit_return_type; - IrExecutable ir_executable; + IrExecutable *ir_executable; IrExecutable analyzed_executable; size_t prealloc_bbc; size_t prealloc_backward_branch_quota; @@ -2204,6 +2204,8 @@ struct ZigVar { bool src_is_const; bool gen_is_const; bool is_thread_local; + bool is_comptime_memoized; + bool is_comptime_memoized_value; }; struct ErrorTableEntry { diff --git a/src/analyze.cpp b/src/analyze.cpp index 894b2416f1..0f2df5835c 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3275,14 +3275,15 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i } ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) { - ZigFn *fn_entry = allocate<ZigFn>(1); + ZigFn *fn_entry = allocate<ZigFn>(1, "ZigFn"); + fn_entry->ir_executable = allocate<IrExecutable>(1, "IrExecutablePass1"); fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota; fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc; fn_entry->analyzed_executable.backward_branch_quota = &fn_entry->prealloc_backward_branch_quota; fn_entry->analyzed_executable.fn_entry = fn_entry; - fn_entry->ir_executable.fn_entry = fn_entry; + fn_entry->ir_executable->fn_entry = fn_entry; fn_entry->fn_inline = inline_value; return fn_entry; @@ -3792,6 +3793,16 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf return variable_entry; } +static void validate_export_var_type(CodeGen *g, ZigType* type, AstNode *source_node) { + switch (type->id) { + case ZigTypeIdMetaType: + add_node_error(g, source_node, buf_sprintf("cannot export variable of type 'type'")); + break; + default: + break; + } +} + static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { AstNode *source_node = tld_var->base.source_node; AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration; @@ -3881,6 +3892,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { } if (is_export) { + validate_export_var_type(g, type, source_node); add_var_export(g, tld_var->var, tld_var->var->name, GlobalLinkageIdStrong); } @@ -4599,7 +4611,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { assert(!fn_type->data.fn.is_generic); FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; - ZigType *block_return_type = ir_analyze(g, &fn->ir_executable, + ZigType *block_return_type = ir_analyze(g, fn->ir_executable, &fn->analyzed_executable, fn_type_id->return_type, return_type_node); fn->src_implicit_return_type = block_return_type; @@ -4695,7 +4707,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { assert(!fn_type->data.fn.is_generic); ir_gen_fn(g, fn_table_entry); - if (fn_table_entry->ir_executable.first_err_trace_msg != nullptr) { + if (fn_table_entry->ir_executable->first_err_trace_msg != nullptr) { fn_table_entry->anal_state = FnAnalStateInvalid; return; } @@ -4703,7 +4715,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { fprintf(stderr, "\n"); ast_render(stderr, fn_table_entry->body_node, 4); fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name)); - ir_print(g, stderr, &fn_table_entry->ir_executable, 4, IrPassSrc); + ir_print(g, stderr, fn_table_entry->ir_executable, 4, IrPassSrc); fprintf(stderr, "}\n"); } @@ -6442,20 +6454,31 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { } bool ir_get_var_is_comptime(ZigVar *var) { + if (var->is_comptime_memoized) + return var->is_comptime_memoized_value; + + var->is_comptime_memoized = true; + // The is_comptime field can be left null, which means not comptime. - if (var->is_comptime == nullptr) - return false; + if (var->is_comptime == nullptr) { + var->is_comptime_memoized_value = false; + return var->is_comptime_memoized_value; + } // When the is_comptime field references an instruction that has to get analyzed, this // is the value. if (var->is_comptime->child != nullptr) { assert(var->is_comptime->child->value->type->id == ZigTypeIdBool); - return var->is_comptime->child->value->data.x_bool; + var->is_comptime_memoized_value = var->is_comptime->child->value->data.x_bool; + var->is_comptime = nullptr; + return var->is_comptime_memoized_value; } // As an optimization, is_comptime values which are constant are allowed // to be omitted from analysis. In this case, there is no child instruction // and we simply look at the unanalyzed const parent instruction. assert(var->is_comptime->value->type->id == ZigTypeIdBool); - return var->is_comptime->value->data.x_bool; + var->is_comptime_memoized_value = var->is_comptime->value->data.x_bool; + var->is_comptime = nullptr; + return var->is_comptime_memoized_value; } bool const_values_equal_ptr(ZigValue *a, ZigValue *b) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 327ab76425..32dd6091f3 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -9563,7 +9563,11 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e case ZigTypeIdVoid: case ZigTypeIdUnreachable: case ZigTypeIdBool: + g->c_want_stdbool = true; + return; case ZigTypeIdInt: + g->c_want_stdint = true; + return; case ZigTypeIdFloat: return; case ZigTypeIdOpaque: @@ -9644,7 +9648,6 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu break; case ZigTypeIdBool: buf_init_from_str(out_buf, "bool"); - g->c_want_stdbool = true; break; case ZigTypeIdUnreachable: buf_init_from_str(out_buf, "__attribute__((__noreturn__)) void"); @@ -9668,7 +9671,6 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu } break; case ZigTypeIdInt: - g->c_want_stdint = true; buf_resize(out_buf, 0); buf_appendf(out_buf, "%sint%" PRIu32 "_t", type_entry->data.integral.is_signed ? "" : "u", @@ -9780,113 +9782,7 @@ static Buf *preprocessor_mangle(Buf *src) { return result; } -static void gen_h_file(CodeGen *g) { - GenH gen_h_data = {0}; - GenH *gen_h = &gen_h_data; - - assert(!g->is_test_build); - assert(!g->disable_gen_h); - - Buf *out_h_path = buf_sprintf("%s" OS_SEP "%s.h", buf_ptr(g->output_dir), buf_ptr(g->root_out_name)); - - FILE *out_h = fopen(buf_ptr(out_h_path), "wb"); - if (!out_h) - zig_panic("unable to open %s: %s\n", buf_ptr(out_h_path), strerror(errno)); - - Buf *export_macro = nullptr; - if (g->is_dynamic) { - export_macro = preprocessor_mangle(buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name))); - buf_upcase(export_macro); - } - - Buf *extern_c_macro = preprocessor_mangle(buf_sprintf("%s_EXTERN_C", buf_ptr(g->root_out_name))); - buf_upcase(extern_c_macro); - - Buf h_buf = BUF_INIT; - buf_resize(&h_buf, 0); - for (size_t fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) { - ZigFn *fn_table_entry = g->fn_defs.at(fn_def_i); - - if (fn_table_entry->export_list.length == 0) - continue; - - FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id; - - Buf return_type_c = BUF_INIT; - get_c_type(g, gen_h, fn_type_id->return_type, &return_type_c); - - Buf *symbol_name; - if (fn_table_entry->export_list.length == 0) { - symbol_name = &fn_table_entry->symbol_name; - } else { - GlobalExport *fn_export = &fn_table_entry->export_list.items[0]; - symbol_name = &fn_export->name; - } - - buf_appendf(&h_buf, "%s %s %s(", - buf_ptr(g->is_dynamic ? export_macro : extern_c_macro), - buf_ptr(&return_type_c), - buf_ptr(symbol_name)); - - Buf param_type_c = BUF_INIT; - if (fn_type_id->param_count > 0) { - for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) { - FnTypeParamInfo *param_info = &fn_type_id->param_info[param_i]; - AstNode *param_decl_node = get_param_decl_node(fn_table_entry, param_i); - Buf *param_name = param_decl_node->data.param_decl.name; - - const char *comma_str = (param_i == 0) ? "" : ", "; - const char *restrict_str = param_info->is_noalias ? "restrict" : ""; - get_c_type(g, gen_h, param_info->type, ¶m_type_c); - - if (param_info->type->id == ZigTypeIdArray) { - // Arrays decay to pointers - buf_appendf(&h_buf, "%s%s%s %s[]", comma_str, buf_ptr(¶m_type_c), - restrict_str, buf_ptr(param_name)); - } else { - buf_appendf(&h_buf, "%s%s%s %s", comma_str, buf_ptr(¶m_type_c), - restrict_str, buf_ptr(param_name)); - } - } - buf_appendf(&h_buf, ")"); - } else { - buf_appendf(&h_buf, "void)"); - } - - buf_appendf(&h_buf, ";\n"); - - } - - Buf *ifdef_dance_name = preprocessor_mangle(buf_sprintf("%s_H", buf_ptr(g->root_out_name))); - buf_upcase(ifdef_dance_name); - - fprintf(out_h, "#ifndef %s\n", buf_ptr(ifdef_dance_name)); - fprintf(out_h, "#define %s\n\n", buf_ptr(ifdef_dance_name)); - - if (g->c_want_stdbool) - fprintf(out_h, "#include <stdbool.h>\n"); - if (g->c_want_stdint) - fprintf(out_h, "#include <stdint.h>\n"); - - fprintf(out_h, "\n"); - - fprintf(out_h, "#ifdef __cplusplus\n"); - fprintf(out_h, "#define %s extern \"C\"\n", buf_ptr(extern_c_macro)); - fprintf(out_h, "#else\n"); - fprintf(out_h, "#define %s\n", buf_ptr(extern_c_macro)); - fprintf(out_h, "#endif\n"); - fprintf(out_h, "\n"); - - if (g->is_dynamic) { - fprintf(out_h, "#if defined(_WIN32)\n"); - fprintf(out_h, "#define %s %s __declspec(dllimport)\n", buf_ptr(export_macro), buf_ptr(extern_c_macro)); - fprintf(out_h, "#else\n"); - fprintf(out_h, "#define %s %s __attribute__((visibility (\"default\")))\n", - buf_ptr(export_macro), buf_ptr(extern_c_macro)); - fprintf(out_h, "#endif\n"); - fprintf(out_h, "\n"); - } - +static void gen_h_file_types(CodeGen* g, GenH* gen_h, Buf* out_buf) { for (size_t type_i = 0; type_i < gen_h->types_to_declare.length; type_i += 1) { ZigType *type_entry = gen_h->types_to_declare.at(type_i); switch (type_entry->id) { @@ -9917,25 +9813,25 @@ static void gen_h_file(CodeGen *g) { case ZigTypeIdEnum: if (type_entry->data.enumeration.layout == ContainerLayoutExtern) { - fprintf(out_h, "enum %s {\n", buf_ptr(type_h_name(type_entry))); + buf_appendf(out_buf, "enum %s {\n", buf_ptr(type_h_name(type_entry))); for (uint32_t field_i = 0; field_i < type_entry->data.enumeration.src_field_count; field_i += 1) { TypeEnumField *enum_field = &type_entry->data.enumeration.fields[field_i]; Buf *value_buf = buf_alloc(); bigint_append_buf(value_buf, &enum_field->value, 10); - fprintf(out_h, " %s = %s", buf_ptr(enum_field->name), buf_ptr(value_buf)); + buf_appendf(out_buf, " %s = %s", buf_ptr(enum_field->name), buf_ptr(value_buf)); if (field_i != type_entry->data.enumeration.src_field_count - 1) { - fprintf(out_h, ","); + buf_appendf(out_buf, ","); } - fprintf(out_h, "\n"); + buf_appendf(out_buf, "\n"); } - fprintf(out_h, "};\n\n"); + buf_appendf(out_buf, "};\n\n"); } else { - fprintf(out_h, "enum %s;\n", buf_ptr(type_h_name(type_entry))); + buf_appendf(out_buf, "enum %s;\n\n", buf_ptr(type_h_name(type_entry))); } break; case ZigTypeIdStruct: if (type_entry->data.structure.layout == ContainerLayoutExtern) { - fprintf(out_h, "struct %s {\n", buf_ptr(type_h_name(type_entry))); + buf_appendf(out_buf, "struct %s {\n", buf_ptr(type_h_name(type_entry))); for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) { TypeStructField *struct_field = type_entry->data.structure.fields[field_i]; @@ -9943,43 +9839,194 @@ static void gen_h_file(CodeGen *g) { get_c_type(g, gen_h, struct_field->type_entry, type_name_buf); if (struct_field->type_entry->id == ZigTypeIdArray) { - fprintf(out_h, " %s %s[%" ZIG_PRI_u64 "];\n", buf_ptr(type_name_buf), + buf_appendf(out_buf, " %s %s[%" ZIG_PRI_u64 "];\n", buf_ptr(type_name_buf), buf_ptr(struct_field->name), struct_field->type_entry->data.array.len); } else { - fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(struct_field->name)); + buf_appendf(out_buf, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(struct_field->name)); } } - fprintf(out_h, "};\n\n"); + buf_appendf(out_buf, "};\n\n"); } else { - fprintf(out_h, "struct %s;\n", buf_ptr(type_h_name(type_entry))); + buf_appendf(out_buf, "struct %s;\n\n", buf_ptr(type_h_name(type_entry))); } break; case ZigTypeIdUnion: if (type_entry->data.unionation.layout == ContainerLayoutExtern) { - fprintf(out_h, "union %s {\n", buf_ptr(type_h_name(type_entry))); + buf_appendf(out_buf, "union %s {\n", buf_ptr(type_h_name(type_entry))); for (uint32_t field_i = 0; field_i < type_entry->data.unionation.src_field_count; field_i += 1) { TypeUnionField *union_field = &type_entry->data.unionation.fields[field_i]; Buf *type_name_buf = buf_alloc(); get_c_type(g, gen_h, union_field->type_entry, type_name_buf); - fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(union_field->name)); + buf_appendf(out_buf, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(union_field->name)); } - fprintf(out_h, "};\n\n"); + buf_appendf(out_buf, "};\n\n"); } else { - fprintf(out_h, "union %s;\n", buf_ptr(type_h_name(type_entry))); + buf_appendf(out_buf, "union %s;\n\n", buf_ptr(type_h_name(type_entry))); } break; case ZigTypeIdOpaque: - fprintf(out_h, "struct %s;\n\n", buf_ptr(type_h_name(type_entry))); + buf_appendf(out_buf, "struct %s;\n\n", buf_ptr(type_h_name(type_entry))); break; } } +} + +static void gen_h_file_functions(CodeGen* g, GenH* gen_h, Buf* out_buf, Buf* export_macro) { + for (size_t fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) { + ZigFn *fn_table_entry = g->fn_defs.at(fn_def_i); + + if (fn_table_entry->export_list.length == 0) + continue; + + FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id; + + Buf return_type_c = BUF_INIT; + get_c_type(g, gen_h, fn_type_id->return_type, &return_type_c); + + Buf *symbol_name; + if (fn_table_entry->export_list.length == 0) { + symbol_name = &fn_table_entry->symbol_name; + } else { + GlobalExport *fn_export = &fn_table_entry->export_list.items[0]; + symbol_name = &fn_export->name; + } + + if (export_macro != nullptr) { + buf_appendf(out_buf, "%s %s %s(", + buf_ptr(export_macro), + buf_ptr(&return_type_c), + buf_ptr(symbol_name)); + } else { + buf_appendf(out_buf, "%s %s(", + buf_ptr(&return_type_c), + buf_ptr(symbol_name)); + } + + Buf param_type_c = BUF_INIT; + if (fn_type_id->param_count > 0) { + for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) { + FnTypeParamInfo *param_info = &fn_type_id->param_info[param_i]; + AstNode *param_decl_node = get_param_decl_node(fn_table_entry, param_i); + Buf *param_name = param_decl_node->data.param_decl.name; + + const char *comma_str = (param_i == 0) ? "" : ", "; + const char *restrict_str = param_info->is_noalias ? "restrict" : ""; + get_c_type(g, gen_h, param_info->type, ¶m_type_c); + + if (param_info->type->id == ZigTypeIdArray) { + // Arrays decay to pointers + buf_appendf(out_buf, "%s%s%s %s[]", comma_str, buf_ptr(¶m_type_c), + restrict_str, buf_ptr(param_name)); + } else { + buf_appendf(out_buf, "%s%s%s %s", comma_str, buf_ptr(¶m_type_c), + restrict_str, buf_ptr(param_name)); + } + } + buf_appendf(out_buf, ")"); + } else { + buf_appendf(out_buf, "void)"); + } + + buf_appendf(out_buf, ";\n"); + } +} + +static void gen_h_file_variables(CodeGen* g, GenH* gen_h, Buf* h_buf, Buf* export_macro) { + for (size_t exp_var_i = 0; exp_var_i < g->global_vars.length; exp_var_i += 1) { + ZigVar* var = g->global_vars.at(exp_var_i)->var; + if (var->export_list.length == 0) + continue; + + Buf var_type_c = BUF_INIT; + get_c_type(g, gen_h, var->var_type, &var_type_c); + + if (export_macro != nullptr) { + buf_appendf(h_buf, "extern %s %s %s;\n", + buf_ptr(export_macro), + buf_ptr(&var_type_c), + var->name); + } else { + buf_appendf(h_buf, "extern %s %s;\n", + buf_ptr(&var_type_c), + var->name); + } + } +} + +static void gen_h_file(CodeGen *g) { + GenH gen_h_data = {0}; + GenH *gen_h = &gen_h_data; + + assert(!g->is_test_build); + assert(!g->disable_gen_h); + + Buf *out_h_path = buf_sprintf("%s" OS_SEP "%s.h", buf_ptr(g->output_dir), buf_ptr(g->root_out_name)); + + FILE *out_h = fopen(buf_ptr(out_h_path), "wb"); + if (!out_h) + zig_panic("unable to open %s: %s\n", buf_ptr(out_h_path), strerror(errno)); + + Buf *export_macro = nullptr; + if (g->is_dynamic) { + export_macro = preprocessor_mangle(buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name))); + buf_upcase(export_macro); + } + + Buf fns_buf = BUF_INIT; + buf_resize(&fns_buf, 0); + gen_h_file_functions(g, gen_h, &fns_buf, export_macro); + + Buf vars_buf = BUF_INIT; + buf_resize(&vars_buf, 0); + gen_h_file_variables(g, gen_h, &vars_buf, export_macro); + + // Types will be populated by exported functions and variables so it has to run last. + Buf types_buf = BUF_INIT; + buf_resize(&types_buf, 0); + gen_h_file_types(g, gen_h, &types_buf); + + Buf *ifdef_dance_name = preprocessor_mangle(buf_sprintf("%s_H", buf_ptr(g->root_out_name))); + buf_upcase(ifdef_dance_name); + + fprintf(out_h, "#ifndef %s\n", buf_ptr(ifdef_dance_name)); + fprintf(out_h, "#define %s\n\n", buf_ptr(ifdef_dance_name)); + + if (g->c_want_stdbool) + fprintf(out_h, "#include <stdbool.h>\n"); + if (g->c_want_stdint) + fprintf(out_h, "#include <stdint.h>\n"); + + fprintf(out_h, "\n"); + + if (g->is_dynamic) { + fprintf(out_h, "#if defined(_WIN32)\n"); + fprintf(out_h, "#define %s __declspec(dllimport)\n", buf_ptr(export_macro)); + fprintf(out_h, "#else\n"); + fprintf(out_h, "#define %s __attribute__((visibility (\"default\")))\n", + buf_ptr(export_macro)); + fprintf(out_h, "#endif\n"); + fprintf(out_h, "\n"); + } + + fprintf(out_h, "%s", buf_ptr(&types_buf)); + + fprintf(out_h, "#ifdef __cplusplus\n"); + fprintf(out_h, "extern \"C\" {\n"); + fprintf(out_h, "#endif\n"); + fprintf(out_h, "\n"); + + fprintf(out_h, "%s\n", buf_ptr(&fns_buf)); + + fprintf(out_h, "#ifdef __cplusplus\n"); + fprintf(out_h, "} // extern \"C\"\n"); + fprintf(out_h, "#endif\n\n"); - fprintf(out_h, "%s", buf_ptr(&h_buf)); + fprintf(out_h, "%s\n", buf_ptr(&vars_buf)); - fprintf(out_h, "\n#endif\n"); + fprintf(out_h, "#endif // %s\n", buf_ptr(ifdef_dance_name)); if (fclose(out_h)) zig_panic("unable to close h file: %s", strerror(errno)); diff --git a/src/ir.cpp b/src/ir.cpp index 8f79841df3..a2c5a4318a 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -41,6 +41,7 @@ struct IrAnalyze { ZigList<IrInstruction *> src_implicit_return_type_list; ZigList<IrSuspendPosition> resume_stack; IrBasicBlock *const_predecessor_bb; + size_t ref_count; // For the purpose of using in a debugger void dump(); @@ -74,6 +75,7 @@ enum ConstCastResultId { ConstCastResultIdPtrLens, ConstCastResultIdCV, ConstCastResultIdPtrSentinel, + ConstCastResultIdIntShorten, }; struct ConstCastOnly; @@ -100,6 +102,7 @@ struct ConstCastBadAllowsZero; struct ConstCastBadNullTermArrays; struct ConstCastBadCV; struct ConstCastPtrSentinel; +struct ConstCastIntShorten; struct ConstCastOnly { ConstCastResultId id; @@ -120,6 +123,7 @@ struct ConstCastOnly { ConstCastBadNullTermArrays *sentinel_arrays; ConstCastBadCV *bad_cv; ConstCastPtrSentinel *bad_ptr_sentinel; + ConstCastIntShorten *int_shorten; } data; }; @@ -189,6 +193,11 @@ struct ConstCastPtrSentinel { ZigType *actual_type; }; +struct ConstCastIntShorten { + ZigType *wanted_type; + ZigType *actual_type; +}; + static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval, ResultLoc *result_loc); @@ -248,6 +257,381 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type); static ResultLoc *no_result_loc(void); +static void destroy_instruction(IrInstruction *inst) { +#ifdef ZIG_ENABLE_MEM_PROFILE + const char *name = ir_instruction_type_str(inst->id); +#else + const char *name = nullptr; +#endif + switch (inst->id) { + case IrInstructionIdInvalid: + zig_unreachable(); + case IrInstructionIdReturn: + return destroy(reinterpret_cast<IrInstructionReturn *>(inst), name); + case IrInstructionIdConst: + return destroy(reinterpret_cast<IrInstructionConst *>(inst), name); + case IrInstructionIdBinOp: + return destroy(reinterpret_cast<IrInstructionBinOp *>(inst), name); + case IrInstructionIdMergeErrSets: + return destroy(reinterpret_cast<IrInstructionMergeErrSets *>(inst), name); + case IrInstructionIdDeclVarSrc: + return destroy(reinterpret_cast<IrInstructionDeclVarSrc *>(inst), name); + case IrInstructionIdCast: + return destroy(reinterpret_cast<IrInstructionCast *>(inst), name); + case IrInstructionIdCallSrc: + return destroy(reinterpret_cast<IrInstructionCallSrc *>(inst), name); + case IrInstructionIdCallGen: + return destroy(reinterpret_cast<IrInstructionCallGen *>(inst), name); + case IrInstructionIdUnOp: + return destroy(reinterpret_cast<IrInstructionUnOp *>(inst), name); + case IrInstructionIdCondBr: + return destroy(reinterpret_cast<IrInstructionCondBr *>(inst), name); + case IrInstructionIdBr: + return destroy(reinterpret_cast<IrInstructionBr *>(inst), name); + case IrInstructionIdPhi: + return destroy(reinterpret_cast<IrInstructionPhi *>(inst), name); + case IrInstructionIdContainerInitList: + return destroy(reinterpret_cast<IrInstructionContainerInitList *>(inst), name); + case IrInstructionIdContainerInitFields: + return destroy(reinterpret_cast<IrInstructionContainerInitFields *>(inst), name); + case IrInstructionIdUnreachable: + return destroy(reinterpret_cast<IrInstructionUnreachable *>(inst), name); + case IrInstructionIdElemPtr: + return destroy(reinterpret_cast<IrInstructionElemPtr *>(inst), name); + case IrInstructionIdVarPtr: + return destroy(reinterpret_cast<IrInstructionVarPtr *>(inst), name); + case IrInstructionIdReturnPtr: + return destroy(reinterpret_cast<IrInstructionReturnPtr *>(inst), name); + case IrInstructionIdLoadPtr: + return destroy(reinterpret_cast<IrInstructionLoadPtr *>(inst), name); + case IrInstructionIdLoadPtrGen: + return destroy(reinterpret_cast<IrInstructionLoadPtrGen *>(inst), name); + case IrInstructionIdStorePtr: + return destroy(reinterpret_cast<IrInstructionStorePtr *>(inst), name); + case IrInstructionIdVectorStoreElem: + return destroy(reinterpret_cast<IrInstructionVectorStoreElem *>(inst), name); + case IrInstructionIdTypeOf: + return destroy(reinterpret_cast<IrInstructionTypeOf *>(inst), name); + case IrInstructionIdFieldPtr: + return destroy(reinterpret_cast<IrInstructionFieldPtr *>(inst), name); + case IrInstructionIdStructFieldPtr: + return destroy(reinterpret_cast<IrInstructionStructFieldPtr *>(inst), name); + case IrInstructionIdUnionFieldPtr: + return destroy(reinterpret_cast<IrInstructionUnionFieldPtr *>(inst), name); + case IrInstructionIdSetCold: + return destroy(reinterpret_cast<IrInstructionSetCold *>(inst), name); + case IrInstructionIdSetRuntimeSafety: + return destroy(reinterpret_cast<IrInstructionSetRuntimeSafety *>(inst), name); + case IrInstructionIdSetFloatMode: + return destroy(reinterpret_cast<IrInstructionSetFloatMode *>(inst), name); + case IrInstructionIdArrayType: + return destroy(reinterpret_cast<IrInstructionArrayType *>(inst), name); + case IrInstructionIdSliceType: + return destroy(reinterpret_cast<IrInstructionSliceType *>(inst), name); + case IrInstructionIdAnyFrameType: + return destroy(reinterpret_cast<IrInstructionAnyFrameType *>(inst), name); + case IrInstructionIdGlobalAsm: + return destroy(reinterpret_cast<IrInstructionGlobalAsm *>(inst), name); + case IrInstructionIdAsm: + return destroy(reinterpret_cast<IrInstructionAsm *>(inst), name); + case IrInstructionIdSizeOf: + return destroy(reinterpret_cast<IrInstructionSizeOf *>(inst), name); + case IrInstructionIdTestNonNull: + return destroy(reinterpret_cast<IrInstructionTestNonNull *>(inst), name); + case IrInstructionIdOptionalUnwrapPtr: + return destroy(reinterpret_cast<IrInstructionOptionalUnwrapPtr *>(inst), name); + case IrInstructionIdPopCount: + return destroy(reinterpret_cast<IrInstructionPopCount *>(inst), name); + case IrInstructionIdClz: + return destroy(reinterpret_cast<IrInstructionClz *>(inst), name); + case IrInstructionIdCtz: + return destroy(reinterpret_cast<IrInstructionCtz *>(inst), name); + case IrInstructionIdBswap: + return destroy(reinterpret_cast<IrInstructionBswap *>(inst), name); + case IrInstructionIdBitReverse: + return destroy(reinterpret_cast<IrInstructionBitReverse *>(inst), name); + case IrInstructionIdSwitchBr: + return destroy(reinterpret_cast<IrInstructionSwitchBr *>(inst), name); + case IrInstructionIdSwitchVar: + return destroy(reinterpret_cast<IrInstructionSwitchVar *>(inst), name); + case IrInstructionIdSwitchElseVar: + return destroy(reinterpret_cast<IrInstructionSwitchElseVar *>(inst), name); + case IrInstructionIdSwitchTarget: + return destroy(reinterpret_cast<IrInstructionSwitchTarget *>(inst), name); + case IrInstructionIdUnionTag: + return destroy(reinterpret_cast<IrInstructionUnionTag *>(inst), name); + case IrInstructionIdImport: + return destroy(reinterpret_cast<IrInstructionImport *>(inst), name); + case IrInstructionIdRef: + return destroy(reinterpret_cast<IrInstructionRef *>(inst), name); + case IrInstructionIdRefGen: + return destroy(reinterpret_cast<IrInstructionRefGen *>(inst), name); + case IrInstructionIdCompileErr: + return destroy(reinterpret_cast<IrInstructionCompileErr *>(inst), name); + case IrInstructionIdCompileLog: + return destroy(reinterpret_cast<IrInstructionCompileLog *>(inst), name); + case IrInstructionIdErrName: + return destroy(reinterpret_cast<IrInstructionErrName *>(inst), name); + case IrInstructionIdCImport: + return destroy(reinterpret_cast<IrInstructionCImport *>(inst), name); + case IrInstructionIdCInclude: + return destroy(reinterpret_cast<IrInstructionCInclude *>(inst), name); + case IrInstructionIdCDefine: + return destroy(reinterpret_cast<IrInstructionCDefine *>(inst), name); + case IrInstructionIdCUndef: + return destroy(reinterpret_cast<IrInstructionCUndef *>(inst), name); + case IrInstructionIdEmbedFile: + return destroy(reinterpret_cast<IrInstructionEmbedFile *>(inst), name); + case IrInstructionIdCmpxchgSrc: + return destroy(reinterpret_cast<IrInstructionCmpxchgSrc *>(inst), name); + case IrInstructionIdCmpxchgGen: + return destroy(reinterpret_cast<IrInstructionCmpxchgGen *>(inst), name); + case IrInstructionIdFence: + return destroy(reinterpret_cast<IrInstructionFence *>(inst), name); + case IrInstructionIdTruncate: + return destroy(reinterpret_cast<IrInstructionTruncate *>(inst), name); + case IrInstructionIdIntCast: + return destroy(reinterpret_cast<IrInstructionIntCast *>(inst), name); + case IrInstructionIdFloatCast: + return destroy(reinterpret_cast<IrInstructionFloatCast *>(inst), name); + case IrInstructionIdErrSetCast: + return destroy(reinterpret_cast<IrInstructionErrSetCast *>(inst), name); + case IrInstructionIdFromBytes: + return destroy(reinterpret_cast<IrInstructionFromBytes *>(inst), name); + case IrInstructionIdToBytes: + return destroy(reinterpret_cast<IrInstructionToBytes *>(inst), name); + case IrInstructionIdIntToFloat: + return destroy(reinterpret_cast<IrInstructionIntToFloat *>(inst), name); + case IrInstructionIdFloatToInt: + return destroy(reinterpret_cast<IrInstructionFloatToInt *>(inst), name); + case IrInstructionIdBoolToInt: + return destroy(reinterpret_cast<IrInstructionBoolToInt *>(inst), name); + case IrInstructionIdIntType: + return destroy(reinterpret_cast<IrInstructionIntType *>(inst), name); + case IrInstructionIdVectorType: + return destroy(reinterpret_cast<IrInstructionVectorType *>(inst), name); + case IrInstructionIdShuffleVector: + return destroy(reinterpret_cast<IrInstructionShuffleVector *>(inst), name); + case IrInstructionIdSplatSrc: + return destroy(reinterpret_cast<IrInstructionSplatSrc *>(inst), name); + case IrInstructionIdSplatGen: + return destroy(reinterpret_cast<IrInstructionSplatGen *>(inst), name); + case IrInstructionIdBoolNot: + return destroy(reinterpret_cast<IrInstructionBoolNot *>(inst), name); + case IrInstructionIdMemset: + return destroy(reinterpret_cast<IrInstructionMemset *>(inst), name); + case IrInstructionIdMemcpy: + return destroy(reinterpret_cast<IrInstructionMemcpy *>(inst), name); + case IrInstructionIdSliceSrc: + return destroy(reinterpret_cast<IrInstructionSliceSrc *>(inst), name); + case IrInstructionIdSliceGen: + return destroy(reinterpret_cast<IrInstructionSliceGen *>(inst), name); + case IrInstructionIdMemberCount: + return destroy(reinterpret_cast<IrInstructionMemberCount *>(inst), name); + case IrInstructionIdMemberType: + return destroy(reinterpret_cast<IrInstructionMemberType *>(inst), name); + case IrInstructionIdMemberName: + return destroy(reinterpret_cast<IrInstructionMemberName *>(inst), name); + case IrInstructionIdBreakpoint: + return destroy(reinterpret_cast<IrInstructionBreakpoint *>(inst), name); + case IrInstructionIdReturnAddress: + return destroy(reinterpret_cast<IrInstructionReturnAddress *>(inst), name); + case IrInstructionIdFrameAddress: + return destroy(reinterpret_cast<IrInstructionFrameAddress *>(inst), name); + case IrInstructionIdFrameHandle: + return destroy(reinterpret_cast<IrInstructionFrameHandle *>(inst), name); + case IrInstructionIdFrameType: + return destroy(reinterpret_cast<IrInstructionFrameType *>(inst), name); + case IrInstructionIdFrameSizeSrc: + return destroy(reinterpret_cast<IrInstructionFrameSizeSrc *>(inst), name); + case IrInstructionIdFrameSizeGen: + return destroy(reinterpret_cast<IrInstructionFrameSizeGen *>(inst), name); + case IrInstructionIdAlignOf: + return destroy(reinterpret_cast<IrInstructionAlignOf *>(inst), name); + case IrInstructionIdOverflowOp: + return destroy(reinterpret_cast<IrInstructionOverflowOp *>(inst), name); + case IrInstructionIdTestErrSrc: + return destroy(reinterpret_cast<IrInstructionTestErrSrc *>(inst), name); + case IrInstructionIdTestErrGen: + return destroy(reinterpret_cast<IrInstructionTestErrGen *>(inst), name); + case IrInstructionIdUnwrapErrCode: + return destroy(reinterpret_cast<IrInstructionUnwrapErrCode *>(inst), name); + case IrInstructionIdUnwrapErrPayload: + return destroy(reinterpret_cast<IrInstructionUnwrapErrPayload *>(inst), name); + case IrInstructionIdOptionalWrap: + return destroy(reinterpret_cast<IrInstructionOptionalWrap *>(inst), name); + case IrInstructionIdErrWrapCode: + return destroy(reinterpret_cast<IrInstructionErrWrapCode *>(inst), name); + case IrInstructionIdErrWrapPayload: + return destroy(reinterpret_cast<IrInstructionErrWrapPayload *>(inst), name); + case IrInstructionIdFnProto: + return destroy(reinterpret_cast<IrInstructionFnProto *>(inst), name); + case IrInstructionIdTestComptime: + return destroy(reinterpret_cast<IrInstructionTestComptime *>(inst), name); + case IrInstructionIdPtrCastSrc: + return destroy(reinterpret_cast<IrInstructionPtrCastSrc *>(inst), name); + case IrInstructionIdPtrCastGen: + return destroy(reinterpret_cast<IrInstructionPtrCastGen *>(inst), name); + case IrInstructionIdBitCastSrc: + return destroy(reinterpret_cast<IrInstructionBitCastSrc *>(inst), name); + case IrInstructionIdBitCastGen: + return destroy(reinterpret_cast<IrInstructionBitCastGen *>(inst), name); + case IrInstructionIdWidenOrShorten: + return destroy(reinterpret_cast<IrInstructionWidenOrShorten *>(inst), name); + case IrInstructionIdPtrToInt: + return destroy(reinterpret_cast<IrInstructionPtrToInt *>(inst), name); + case IrInstructionIdIntToPtr: + return destroy(reinterpret_cast<IrInstructionIntToPtr *>(inst), name); + case IrInstructionIdIntToEnum: + return destroy(reinterpret_cast<IrInstructionIntToEnum *>(inst), name); + case IrInstructionIdIntToErr: + return destroy(reinterpret_cast<IrInstructionIntToErr *>(inst), name); + case IrInstructionIdErrToInt: + return destroy(reinterpret_cast<IrInstructionErrToInt *>(inst), name); + case IrInstructionIdCheckSwitchProngs: + return destroy(reinterpret_cast<IrInstructionCheckSwitchProngs *>(inst), name); + case IrInstructionIdCheckStatementIsVoid: + return destroy(reinterpret_cast<IrInstructionCheckStatementIsVoid *>(inst), name); + case IrInstructionIdTypeName: + return destroy(reinterpret_cast<IrInstructionTypeName *>(inst), name); + case IrInstructionIdTagName: + return destroy(reinterpret_cast<IrInstructionTagName *>(inst), name); + case IrInstructionIdPtrType: + return destroy(reinterpret_cast<IrInstructionPtrType *>(inst), name); + case IrInstructionIdDeclRef: + return destroy(reinterpret_cast<IrInstructionDeclRef *>(inst), name); + case IrInstructionIdPanic: + return destroy(reinterpret_cast<IrInstructionPanic *>(inst), name); + case IrInstructionIdFieldParentPtr: + return destroy(reinterpret_cast<IrInstructionFieldParentPtr *>(inst), name); + case IrInstructionIdByteOffsetOf: + return destroy(reinterpret_cast<IrInstructionByteOffsetOf *>(inst), name); + case IrInstructionIdBitOffsetOf: + return destroy(reinterpret_cast<IrInstructionBitOffsetOf *>(inst), name); + case IrInstructionIdTypeInfo: + return destroy(reinterpret_cast<IrInstructionTypeInfo *>(inst), name); + case IrInstructionIdType: + return destroy(reinterpret_cast<IrInstructionType *>(inst), name); + case IrInstructionIdHasField: + return destroy(reinterpret_cast<IrInstructionHasField *>(inst), name); + case IrInstructionIdTypeId: + return destroy(reinterpret_cast<IrInstructionTypeId *>(inst), name); + case IrInstructionIdSetEvalBranchQuota: + return destroy(reinterpret_cast<IrInstructionSetEvalBranchQuota *>(inst), name); + case IrInstructionIdAlignCast: + return destroy(reinterpret_cast<IrInstructionAlignCast *>(inst), name); + case IrInstructionIdImplicitCast: + return destroy(reinterpret_cast<IrInstructionImplicitCast *>(inst), name); + case IrInstructionIdResolveResult: + return destroy(reinterpret_cast<IrInstructionResolveResult *>(inst), name); + case IrInstructionIdResetResult: + return destroy(reinterpret_cast<IrInstructionResetResult *>(inst), name); + case IrInstructionIdOpaqueType: + return destroy(reinterpret_cast<IrInstructionOpaqueType *>(inst), name); + case IrInstructionIdSetAlignStack: + return destroy(reinterpret_cast<IrInstructionSetAlignStack *>(inst), name); + case IrInstructionIdArgType: + return destroy(reinterpret_cast<IrInstructionArgType *>(inst), name); + case IrInstructionIdTagType: + return destroy(reinterpret_cast<IrInstructionTagType *>(inst), name); + case IrInstructionIdExport: + return destroy(reinterpret_cast<IrInstructionExport *>(inst), name); + case IrInstructionIdErrorReturnTrace: + return destroy(reinterpret_cast<IrInstructionErrorReturnTrace *>(inst), name); + case IrInstructionIdErrorUnion: + return destroy(reinterpret_cast<IrInstructionErrorUnion *>(inst), name); + case IrInstructionIdAtomicRmw: + return destroy(reinterpret_cast<IrInstructionAtomicRmw *>(inst), name); + case IrInstructionIdSaveErrRetAddr: + return destroy(reinterpret_cast<IrInstructionSaveErrRetAddr *>(inst), name); + case IrInstructionIdAddImplicitReturnType: + return destroy(reinterpret_cast<IrInstructionAddImplicitReturnType *>(inst), name); + case IrInstructionIdFloatOp: + return destroy(reinterpret_cast<IrInstructionFloatOp *>(inst), name); + case IrInstructionIdMulAdd: + return destroy(reinterpret_cast<IrInstructionMulAdd *>(inst), name); + case IrInstructionIdAtomicLoad: + return destroy(reinterpret_cast<IrInstructionAtomicLoad *>(inst), name); + case IrInstructionIdAtomicStore: + return destroy(reinterpret_cast<IrInstructionAtomicStore *>(inst), name); + case IrInstructionIdEnumToInt: + return destroy(reinterpret_cast<IrInstructionEnumToInt *>(inst), name); + case IrInstructionIdCheckRuntimeScope: + return destroy(reinterpret_cast<IrInstructionCheckRuntimeScope *>(inst), name); + case IrInstructionIdDeclVarGen: + return destroy(reinterpret_cast<IrInstructionDeclVarGen *>(inst), name); + case IrInstructionIdArrayToVector: + return destroy(reinterpret_cast<IrInstructionArrayToVector *>(inst), name); + case IrInstructionIdVectorToArray: + return destroy(reinterpret_cast<IrInstructionVectorToArray *>(inst), name); + case IrInstructionIdPtrOfArrayToSlice: + return destroy(reinterpret_cast<IrInstructionPtrOfArrayToSlice *>(inst), name); + case IrInstructionIdAssertZero: + return destroy(reinterpret_cast<IrInstructionAssertZero *>(inst), name); + case IrInstructionIdAssertNonNull: + return destroy(reinterpret_cast<IrInstructionAssertNonNull *>(inst), name); + case IrInstructionIdResizeSlice: + return destroy(reinterpret_cast<IrInstructionResizeSlice *>(inst), name); + case IrInstructionIdHasDecl: + return destroy(reinterpret_cast<IrInstructionHasDecl *>(inst), name); + case IrInstructionIdUndeclaredIdent: + return destroy(reinterpret_cast<IrInstructionUndeclaredIdent *>(inst), name); + case IrInstructionIdAllocaSrc: + return destroy(reinterpret_cast<IrInstructionAllocaSrc *>(inst), name); + case IrInstructionIdAllocaGen: + return destroy(reinterpret_cast<IrInstructionAllocaGen *>(inst), name); + case IrInstructionIdEndExpr: + return destroy(reinterpret_cast<IrInstructionEndExpr *>(inst), name); + case IrInstructionIdUnionInitNamedField: + return destroy(reinterpret_cast<IrInstructionUnionInitNamedField *>(inst), name); + case IrInstructionIdSuspendBegin: + return destroy(reinterpret_cast<IrInstructionSuspendBegin *>(inst), name); + case IrInstructionIdSuspendFinish: + return destroy(reinterpret_cast<IrInstructionSuspendFinish *>(inst), name); + case IrInstructionIdResume: + return destroy(reinterpret_cast<IrInstructionResume *>(inst), name); + case IrInstructionIdAwaitSrc: + return destroy(reinterpret_cast<IrInstructionAwaitSrc *>(inst), name); + case IrInstructionIdAwaitGen: + return destroy(reinterpret_cast<IrInstructionAwaitGen *>(inst), name); + case IrInstructionIdSpillBegin: + return destroy(reinterpret_cast<IrInstructionSpillBegin *>(inst), name); + case IrInstructionIdSpillEnd: + return destroy(reinterpret_cast<IrInstructionSpillEnd *>(inst), name); + case IrInstructionIdVectorExtractElem: + return destroy(reinterpret_cast<IrInstructionVectorExtractElem *>(inst), name); + } + zig_unreachable(); +} + +static void ira_ref(IrAnalyze *ira) { + ira->ref_count += 1; +} +static void ira_deref(IrAnalyze *ira) { + if (ira->ref_count > 1) { + ira->ref_count -= 1; + return; + } + assert(ira->ref_count != 0); + + for (size_t bb_i = 0; bb_i < ira->old_irb.exec->basic_block_list.length; bb_i += 1) { + IrBasicBlock *pass1_bb = ira->old_irb.exec->basic_block_list.items[bb_i]; + for (size_t inst_i = 0; inst_i < pass1_bb->instruction_list.length; inst_i += 1) { + IrInstruction *pass1_inst = pass1_bb->instruction_list.items[inst_i]; + destroy_instruction(pass1_inst); + } + destroy(pass1_bb, "IrBasicBlock"); + } + ira->old_irb.exec->basic_block_list.deinit(); + ira->old_irb.exec->tld_list.deinit(); + // cannot destroy here because of var->owner_exec + //destroy(ira->old_irb.exec, "IrExecutablePass1"); + ira->src_implicit_return_type_list.deinit(); + ira->resume_stack.deinit(); + ira->exec_context.mem_slot_list.deinit(); + destroy(ira, "IrAnalyze"); +} + static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) { assert(get_src_ptr_type(const_val->type) != nullptr); assert(const_val->special == ConstValSpecialStatic); @@ -4186,7 +4570,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod IrInstruction **incoming_values = allocate<IrInstruction *>(2); incoming_values[0] = val1; incoming_values[1] = val2; - IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); + IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2, "IrBasicBlock *"); incoming_blocks[0] = post_val1_block; incoming_blocks[1] = post_val2_block; @@ -4277,7 +4661,7 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode IrInstruction **incoming_values = allocate<IrInstruction *>(2); incoming_values[0] = null_result; incoming_values[1] = unwrapped_payload; - IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); + IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2, "IrBasicBlock *"); incoming_blocks[0] = after_null_block; incoming_blocks[1] = after_ok_block; IrInstruction *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); @@ -6044,7 +6428,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode IrInstruction **incoming_values = allocate<IrInstruction *>(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); + IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2, "IrBasicBlock *"); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; @@ -7398,7 +7782,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN IrInstruction **incoming_values = allocate<IrInstruction *>(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); + IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2, "IrBasicBlock *"); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; @@ -7495,7 +7879,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * IrInstruction **incoming_values = allocate<IrInstruction *>(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); + IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2, "IrBasicBlock *"); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; @@ -8092,7 +8476,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode IrInstruction **incoming_values = allocate<IrInstruction *>(2); incoming_values[0] = err_result; incoming_values[1] = unwrapped_payload; - IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); + IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2, "IrBasicBlock *"); incoming_blocks[0] = after_err_block; incoming_blocks[1] = after_ok_block; IrInstruction *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); @@ -8680,7 +9064,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { assert(fn_entry); - IrExecutable *ir_executable = &fn_entry->ir_executable; + IrExecutable *ir_executable = fn_entry->ir_executable; AstNode *body_node = fn_entry->body_node; assert(fn_entry->child_scope); @@ -10224,6 +10608,14 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return result; } + if (wanted_type->id == ZigTypeIdInt && actual_type->id == ZigTypeIdInt) { + result.id = ConstCastResultIdIntShorten; + result.data.int_shorten = allocate_nonzero<ConstCastIntShorten>(1); + result.data.int_shorten->wanted_type = wanted_type; + result.data.int_shorten->actual_type = actual_type; + return result; + } + result.id = ConstCastResultIdType; result.data.type_mismatch = allocate_nonzero<ConstCastTypeMismatch>(1); result.data.type_mismatch->wanted_type = wanted_type; @@ -11490,7 +11882,7 @@ ZigValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, if (expected_type != nullptr && type_is_invalid(expected_type)) return codegen->invalid_instruction->value; - IrExecutable *ir_executable = allocate<IrExecutable>(1); + IrExecutable *ir_executable = allocate<IrExecutable>(1, "IrExecutablePass1"); ir_executable->source_node = source_node; ir_executable->parent_exec = parent_exec; ir_executable->name = exec_name; @@ -11512,7 +11904,7 @@ ZigValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ir_print(codegen, stderr, ir_executable, 2, IrPassSrc); fprintf(stderr, "}\n"); } - IrExecutable *analyzed_executable = allocate<IrExecutable>(1); + IrExecutable *analyzed_executable = allocate<IrExecutable>(1, "IrExecutablePass2"); analyzed_executable->source_node = source_node; analyzed_executable->parent_exec = parent_exec; analyzed_executable->source_exec = ir_executable; @@ -12641,6 +13033,17 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("calling convention mismatch")); break; + case ConstCastResultIdIntShorten: { + ZigType *wanted_type = cast_result->data.int_shorten->wanted_type; + ZigType *actual_type = cast_result->data.int_shorten->actual_type; + const char *wanted_signed = wanted_type->data.integral.is_signed ? "signed" : "unsigned"; + const char *actual_signed = actual_type->data.integral.is_signed ? "signed" : "unsigned"; + add_error_note(ira->codegen, parent_msg, source_node, + buf_sprintf("%s %" PRIu32 "-bit int cannot represent all possible %s %" PRIu32 "-bit values", + wanted_signed, wanted_type->data.integral.bit_count, + actual_signed, actual_type->data.integral.bit_count)); + break; + } case ConstCastResultIdFnAlign: // TODO case ConstCastResultIdFnVarArgs: // TODO case ConstCastResultIdFnReturnType: // TODO @@ -15597,6 +16000,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length); ZigValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index); copy_const_val(mem_slot, init_val, !is_comptime_var || var->gen_is_const); + ira_ref(var->owner_exec->analysis); if (is_comptime_var || (var_class_requires_const && var->gen_is_const)) { return ir_const_void(ira, &decl_var_instruction->base); @@ -15869,8 +16273,8 @@ static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira, IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; - LazyValueErrUnionType *lazy_err_union_type = allocate<LazyValueErrUnionType>(1); - lazy_err_union_type->ira = ira; + LazyValueErrUnionType *lazy_err_union_type = allocate<LazyValueErrUnionType>(1, "LazyValueErrUnionType"); + lazy_err_union_type->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_err_union_type->base; lazy_err_union_type->base.id = LazyValueIdErrUnionType; @@ -17368,8 +17772,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c if (type_is_invalid(impl_fn->type_entry)) return ira->codegen->invalid_instruction; - impl_fn->ir_executable.source_node = call_instruction->base.source_node; - impl_fn->ir_executable.parent_exec = ira->new_irb.exec; + impl_fn->ir_executable->source_node = call_instruction->base.source_node; + impl_fn->ir_executable->parent_exec = ira->new_irb.exec; impl_fn->analyzed_executable.source_node = call_instruction->base.source_node; impl_fn->analyzed_executable.parent_exec = ira->new_irb.exec; impl_fn->analyzed_executable.backward_branch_quota = ira->new_irb.exec->backward_branch_quota; @@ -17722,8 +18126,8 @@ static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; - LazyValueOptType *lazy_opt_type = allocate<LazyValueOptType>(1); - lazy_opt_type->ira = ira; + LazyValueOptType *lazy_opt_type = allocate<LazyValueOptType>(1, "LazyValueOptType"); + lazy_opt_type->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_opt_type->base; lazy_opt_type->base.id = LazyValueIdOptType; @@ -19668,8 +20072,8 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, IrInstruction *result = ir_const(ira, &slice_type_instruction->base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; - LazyValueSliceType *lazy_slice_type = allocate<LazyValueSliceType>(1); - lazy_slice_type->ira = ira; + LazyValueSliceType *lazy_slice_type = allocate<LazyValueSliceType>(1, "LazyValueSliceType"); + lazy_slice_type->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_slice_type->base; lazy_slice_type->base.id = LazyValueIdSliceType; @@ -19828,8 +20232,8 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructi IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); result->value->special = ConstValSpecialLazy; - LazyValueSizeOf *lazy_size_of = allocate<LazyValueSizeOf>(1); - lazy_size_of->ira = ira; + LazyValueSizeOf *lazy_size_of = allocate<LazyValueSizeOf>(1, "LazyValueSizeOf"); + lazy_size_of->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_size_of->base; lazy_size_of->base.id = LazyValueIdSizeOf; @@ -24556,8 +24960,8 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); result->value->special = ConstValSpecialLazy; - LazyValueAlignOf *lazy_align_of = allocate<LazyValueAlignOf>(1); - lazy_align_of->ira = ira; + LazyValueAlignOf *lazy_align_of = allocate<LazyValueAlignOf>(1, "LazyValueAlignOf"); + lazy_align_of->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_align_of->base; lazy_align_of->base.id = LazyValueIdAlignOf; @@ -25040,8 +25444,8 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; - LazyValueFnType *lazy_fn_type = allocate<LazyValueFnType>(1); - lazy_fn_type->ira = ira; + LazyValueFnType *lazy_fn_type = allocate<LazyValueFnType>(1, "LazyValueFnType"); + lazy_fn_type->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_fn_type->base; lazy_fn_type->base.id = LazyValueIdFnType; @@ -26081,8 +26485,8 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; - LazyValuePtrType *lazy_ptr_type = allocate<LazyValuePtrType>(1); - lazy_ptr_type->ira = ira; + LazyValuePtrType *lazy_ptr_type = allocate<LazyValuePtrType>(1, "LazyValuePtrType"); + lazy_ptr_type->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_ptr_type->base; lazy_ptr_type->base.id = LazyValueIdPtrType; @@ -27551,7 +27955,8 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ assert(old_exec->first_err_trace_msg == nullptr); assert(expected_type == nullptr || !type_is_invalid(expected_type)); - IrAnalyze *ira = allocate<IrAnalyze>(1); + IrAnalyze *ira = allocate<IrAnalyze>(1, "IrAnalyze"); + ira->ref_count = 1; old_exec->analysis = ira; ira->codegen = codegen; @@ -27618,6 +28023,7 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ ira->instruction_index += 1; } + ZigType *res_type; if (new_exec->first_err_trace_msg != nullptr) { codegen->trace_err = new_exec->first_err_trace_msg; if (codegen->trace_err != nullptr && new_exec->source_node != nullptr && @@ -27627,13 +28033,18 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ codegen->trace_err = add_error_note(codegen, codegen->trace_err, new_exec->source_node, buf_create_from_str("referenced here")); } - return ira->codegen->builtin_types.entry_invalid; + res_type = ira->codegen->builtin_types.entry_invalid; } else if (ira->src_implicit_return_type_list.length == 0) { - return codegen->builtin_types.entry_unreachable; + res_type = codegen->builtin_types.entry_unreachable; } else { - return ir_resolve_peer_types(ira, expected_type_source_node, expected_type, ira->src_implicit_return_type_list.items, + res_type = ir_resolve_peer_types(ira, expected_type_source_node, expected_type, ira->src_implicit_return_type_list.items, ira->src_implicit_return_type_list.length); } + + // It is now safe to free Pass 1 IR instructions. + ira_deref(ira); + + return res_type; } bool ir_has_side_effects(IrInstruction *instruction) { @@ -27969,6 +28380,8 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { val->special = ConstValSpecialStatic; assert(val->type->id == ZigTypeIdComptimeInt || val->type->id == ZigTypeIdInt); bigint_init_unsigned(&val->data.x_bigint, align_in_bytes); + + // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. return ErrorNone; } case LazyValueIdSizeOf: { @@ -28024,6 +28437,8 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { val->special = ConstValSpecialStatic; assert(val->type->id == ZigTypeIdComptimeInt || val->type->id == ZigTypeIdInt); bigint_init_unsigned(&val->data.x_bigint, abi_size); + + // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. return ErrorNone; } case LazyValueIdSliceType: { @@ -28102,6 +28517,8 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { val->special = ConstValSpecialStatic; assert(val->type->id == ZigTypeIdMetaType); val->data.x_type = get_slice_type(ira->codegen, slice_ptr_type); + + // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. return ErrorNone; } case LazyValueIdPtrType: { @@ -28173,6 +28590,8 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { lazy_ptr_type->bit_offset_in_host, lazy_ptr_type->host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr, sentinel_val); val->special = ConstValSpecialStatic; + + // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. return ErrorNone; } case LazyValueIdOptType: { @@ -28195,16 +28614,21 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { assert(val->type->id == ZigTypeIdMetaType); val->data.x_type = get_optional_type(ira->codegen, payload_type); val->special = ConstValSpecialStatic; + + // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. return ErrorNone; } case LazyValueIdFnType: { LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(val->data.x_lazy); - ZigType *fn_type = ir_resolve_lazy_fn_type(lazy_fn_type->ira, source_node, lazy_fn_type); + IrAnalyze *ira = lazy_fn_type->ira; + ZigType *fn_type = ir_resolve_lazy_fn_type(ira, source_node, lazy_fn_type); if (fn_type == nullptr) return ErrorSemanticAnalyzeFail; val->special = ConstValSpecialStatic; assert(val->type->id == ZigTypeIdMetaType); val->data.x_type = fn_type; + + // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. return ErrorNone; } case LazyValueIdErrUnionType: { @@ -28233,6 +28657,8 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { assert(val->type->id == ZigTypeIdMetaType); val->data.x_type = get_error_union_type(ira->codegen, err_set_type, payload_type); val->special = ConstValSpecialStatic; + + // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. return ErrorNone; } } diff --git a/src/libc_installation.cpp b/src/libc_installation.cpp index 6ae6bb9075..2adc1cb69d 100644 --- a/src/libc_installation.cpp +++ b/src/libc_installation.cpp @@ -389,7 +389,7 @@ static Error zig_libc_find_native_msvc_include_dir(ZigLibCInstallation *self, Zi } Buf search_path = BUF_INIT; buf_init_from_mem(&search_path, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len); - buf_append_str(&search_path, "\\..\\..\\include"); + buf_append_str(&search_path, "..\\..\\include"); Buf *vcruntime_path = buf_sprintf("%s\\vcruntime.h", buf_ptr(&search_path)); bool exists; diff --git a/src/list.hpp b/src/list.hpp index 59782b46a8..4b2833843b 100644 --- a/src/list.hpp +++ b/src/list.hpp @@ -13,7 +13,7 @@ template<typename T> struct ZigList { void deinit() { - free(items); + deallocate(items, capacity); } void append(const T& item) { ensure_capacity(length + 1); diff --git a/src/memory_profiling.cpp b/src/memory_profiling.cpp index a44dfc4450..4bd4cea7ba 100644 --- a/src/memory_profiling.cpp +++ b/src/memory_profiling.cpp @@ -35,7 +35,9 @@ static const char *get_default_name(const char *name_or_null, size_t type_size) if (name_or_null != nullptr) return name_or_null; if (type_size >= unknown_names.length) { table_active = false; - unknown_names.resize(type_size + 1); + while (type_size >= unknown_names.length) { + unknown_names.append(nullptr); + } table_active = true; } if (unknown_names.at(type_size) == nullptr) { @@ -66,7 +68,8 @@ void memprof_dealloc(const char *name, size_t count, size_t type_size) { name = get_default_name(name, type_size); auto existing_entry = usage_table.maybe_get(name); if (existing_entry == nullptr) { - zig_panic("deallocated more than allocated; compromised memory usage stats"); + zig_panic("deallocated name '%s' (size %zu) not found in allocated table; compromised memory usage stats", + name, type_size); } if (existing_entry->value.type_size != type_size) { zig_panic("deallocated name '%s' does not match expected type size %zu", name, type_size); diff --git a/src/os.cpp b/src/os.cpp index da1f4ecfb0..f6a0b4fbd8 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -1554,7 +1554,7 @@ void os_stderr_set_color(TermColor color) { Error os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { #if defined(ZIG_OS_WINDOWS) buf_resize(output_buf, 0); - buf_appendf(output_buf, "%s\\Lib\\%s\\ucrt\\", sdk->path10_ptr, sdk->version10_ptr); + buf_appendf(output_buf, "%sLib\\%s\\ucrt\\", sdk->path10_ptr, sdk->version10_ptr); switch (platform_type) { case ZigLLVM_x86: buf_append_str(output_buf, "x86\\"); @@ -1586,7 +1586,7 @@ Error os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Ar Error os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) { #if defined(ZIG_OS_WINDOWS) buf_resize(output_buf, 0); - buf_appendf(output_buf, "%s\\Include\\%s\\ucrt", sdk->path10_ptr, sdk->version10_ptr); + buf_appendf(output_buf, "%sInclude\\%s\\ucrt", sdk->path10_ptr, sdk->version10_ptr); if (GetFileAttributesA(buf_ptr(output_buf)) != INVALID_FILE_ATTRIBUTES) { return ErrorNone; } @@ -1603,7 +1603,7 @@ Error os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch #if defined(ZIG_OS_WINDOWS) { buf_resize(output_buf, 0); - buf_appendf(output_buf, "%s\\Lib\\%s\\um\\", sdk->path10_ptr, sdk->version10_ptr); + buf_appendf(output_buf, "%sLib\\%s\\um\\", sdk->path10_ptr, sdk->version10_ptr); switch (platform_type) { case ZigLLVM_x86: buf_append_str(output_buf, "x86\\"); @@ -1626,7 +1626,7 @@ Error os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch } { buf_resize(output_buf, 0); - buf_appendf(output_buf, "%s\\Lib\\%s\\um\\", sdk->path81_ptr, sdk->version81_ptr); + buf_appendf(output_buf, "%sLib\\%s\\um\\", sdk->path81_ptr, sdk->version81_ptr); switch (platform_type) { case ZigLLVM_x86: buf_append_str(output_buf, "x86\\"); diff --git a/src/util.hpp b/src/util.hpp index 79bebd3355..91535cce18 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -165,7 +165,7 @@ static inline void deallocate(T *old, size_t count, const char *name = nullptr) template<typename T> static inline void destroy(T *old, const char *name = nullptr) { - return deallocate(old, 1); + return deallocate(old, 1, name); } template <typename T, size_t n> |
