From f50bfb94b52424f2145b9a18b731a47b3faf9648 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 9 Sep 2019 15:54:03 -0400 Subject: [PATCH] fix bad LLVM IR when for target expr needs to be spilled Also reduce the size of ZigVar in memory by making the name a `const char *` rather than a `Buf`. --- src/all_types.hpp | 4 +- src/analyze.cpp | 24 ++++---- src/analyze.hpp | 4 +- src/buffer.hpp | 5 ++ src/codegen.cpp | 92 +++++++++++++++++-------------- src/ir.cpp | 28 ++++++---- src/ir_print.cpp | 6 +- test/stage1/behavior/async_fn.zig | 32 +++++++++++ 8 files changed, 122 insertions(+), 73 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index a9c2409c19..2f3f56f0ed 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2070,7 +2070,7 @@ struct CodeGen { }; struct ZigVar { - Buf name; + const char *name; ConstExprValue *const_value; ZigType *var_type; LLVMValueRef value_ref; @@ -2085,7 +2085,6 @@ struct ZigVar { LLVMValueRef param_value_ref; size_t mem_slot_index; IrExecutable *owner_exec; - size_t ref_count; // In an inline loop, multiple variables may be created, // In this case, a reference to a variable should follow @@ -2095,6 +2094,7 @@ struct ZigVar { ZigList export_list; uint32_t align_bytes; + uint32_t ref_count; bool shadowable; bool src_is_const; diff --git a/src/analyze.cpp b/src/analyze.cpp index 7a91d6b821..32cb3c0624 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3148,26 +3148,26 @@ ZigType *get_test_fn_type(CodeGen *g) { return g->test_fn_type; } -void add_var_export(CodeGen *g, ZigVar *var, Buf *symbol_name, GlobalLinkageId linkage) { +void add_var_export(CodeGen *g, ZigVar *var, const char *symbol_name, GlobalLinkageId linkage) { GlobalExport *global_export = var->export_list.add_one(); memset(global_export, 0, sizeof(GlobalExport)); - buf_init_from_buf(&global_export->name, symbol_name); + buf_init_from_str(&global_export->name, symbol_name); global_export->linkage = linkage; } -void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc) { +void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage, bool ccc) { if (ccc) { - if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) { + if (strcmp(symbol_name, "main") == 0 && g->libc_link_lib != nullptr) { g->have_c_main = true; - } else if (buf_eql_str(symbol_name, "WinMain") && + } else if (strcmp(symbol_name, "WinMain") == 0 && g->zig_target->os == OsWindows) { g->have_winmain = true; - } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") && + } else if (strcmp(symbol_name, "WinMainCRTStartup") == 0 && g->zig_target->os == OsWindows) { g->have_winmain_crt_startup = true; - } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") && + } else if (strcmp(symbol_name, "DllMainCRTStartup") == 0 && g->zig_target->os == OsWindows) { g->have_dllmain_crt_startup = true; @@ -3176,7 +3176,7 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi GlobalExport *fn_export = fn_table_entry->export_list.add_one(); memset(fn_export, 0, sizeof(GlobalExport)); - buf_init_from_buf(&fn_export->name, symbol_name); + buf_init_from_str(&fn_export->name, symbol_name); fn_export->linkage = linkage; } @@ -3200,7 +3200,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { if (fn_proto->is_export) { bool ccc = (fn_proto->cc == CallingConventionUnspecified || fn_proto->cc == CallingConventionC); - add_fn_export(g, fn_table_entry, &fn_table_entry->symbol_name, GlobalLinkageIdStrong, ccc); + add_fn_export(g, fn_table_entry, buf_ptr(&fn_table_entry->symbol_name), GlobalLinkageIdStrong, ccc); } if (!is_extern) { @@ -3559,7 +3559,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf variable_entry->src_arg_index = SIZE_MAX; assert(name); - buf_init_from_buf(&variable_entry->name, name); + variable_entry->name = strdup(buf_ptr(name)); if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) { variable_entry->var_type = g->builtin_types.entry_invalid; @@ -3707,7 +3707,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { } if (is_export) { - add_var_export(g, tld_var->var, &tld_var->var->name, GlobalLinkageIdStrong); + add_var_export(g, tld_var->var, tld_var->var->name, GlobalLinkageIdStrong); } g->global_vars.append(tld_var); @@ -3916,7 +3916,7 @@ ZigVar *find_variable(CodeGen *g, Scope *scope, Buf *name, ScopeFnDef **crossed_ while (scope) { if (scope->id == ScopeIdVarDecl) { ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; - if (buf_eql_buf(name, &var_scope->var->name)) { + if (buf_eql_str(name, var_scope->var->name)) { if (crossed_fndef_scope != nullptr) *crossed_fndef_scope = my_crossed_fndef_scope; return var_scope->var; diff --git a/src/analyze.hpp b/src/analyze.hpp index 78eac4491a..842125dcab 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -189,8 +189,8 @@ ZigType *get_align_amt_type(CodeGen *g); ZigPackage *new_anonymous_package(void); Buf *const_value_to_buffer(ConstExprValue *const_val); -void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc); -void add_var_export(CodeGen *g, ZigVar *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage); +void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage, bool ccc); +void add_var_export(CodeGen *g, ZigVar *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage); ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name); diff --git a/src/buffer.hpp b/src/buffer.hpp index d7254c18a7..251b5c2f27 100644 --- a/src/buffer.hpp +++ b/src/buffer.hpp @@ -57,6 +57,11 @@ static inline void buf_deinit(Buf *buf) { buf->list.deinit(); } +static inline void buf_destroy(Buf *buf) { + buf_deinit(buf); + free(buf); +} + static inline void buf_init_from_mem(Buf *buf, const char *ptr, size_t len) { assert(len != SIZE_MAX); buf->list.resize(len + 1); diff --git a/src/codegen.cpp b/src/codegen.cpp index 0533cc85b5..a4ceae57d9 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -234,18 +234,23 @@ static void addLLVMArgAttrInt(LLVMValueRef fn_val, unsigned param_index, const c return addLLVMAttrInt(fn_val, param_index + 1, attr_name, attr_val); } -static bool is_symbol_available(CodeGen *g, Buf *name) { - return g->exported_symbol_names.maybe_get(name) == nullptr && g->external_prototypes.maybe_get(name) == nullptr; +static bool is_symbol_available(CodeGen *g, const char *name) { + Buf *buf_name = buf_create_from_str(name); + bool result = + g->exported_symbol_names.maybe_get(buf_name) == nullptr && + g->external_prototypes.maybe_get(buf_name) == nullptr; + buf_destroy(buf_name); + return result; } -static Buf *get_mangled_name(CodeGen *g, Buf *original_name, bool external_linkage) { +static const char *get_mangled_name(CodeGen *g, const char *original_name, bool external_linkage) { if (external_linkage || is_symbol_available(g, original_name)) { return original_name; } int n = 0; for (;; n += 1) { - Buf *new_name = buf_sprintf("%s.%d", buf_ptr(original_name), n); + const char *new_name = buf_ptr(buf_sprintf("%s.%d", original_name, n)); if (is_symbol_available(g, new_name)) { return new_name; } @@ -387,8 +392,8 @@ static bool codegen_have_frame_pointer(CodeGen *g) { } static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { - Buf *unmangled_name = &fn->symbol_name; - Buf *symbol_name; + const char *unmangled_name = buf_ptr(&fn->symbol_name); + const char *symbol_name; GlobalLinkageId linkage; if (fn->body_node == nullptr) { symbol_name = unmangled_name; @@ -398,7 +403,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { linkage = GlobalLinkageIdInternal; } else { GlobalExport *fn_export = &fn->export_list.items[0]; - symbol_name = &fn_export->name; + symbol_name = buf_ptr(&fn_export->name); linkage = fn_export->linkage; } @@ -408,7 +413,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { g->zig_target->arch == ZigLLVM_x86) { // prevent llvm name mangling - symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name)); + symbol_name = buf_ptr(buf_sprintf("\x01_%s", symbol_name)); } bool is_async = fn_is_async(fn); @@ -420,13 +425,16 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { LLVMTypeRef fn_llvm_type = fn->raw_type_ref; LLVMValueRef llvm_fn = nullptr; if (fn->body_node == nullptr) { - LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); + LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, symbol_name); if (existing_llvm_fn) { return LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0)); } else { - auto entry = g->exported_symbol_names.maybe_get(symbol_name); + Buf *buf_symbol_name = buf_create_from_str(symbol_name); + auto entry = g->exported_symbol_names.maybe_get(buf_symbol_name); + buf_destroy(buf_symbol_name); + if (entry == nullptr) { - llvm_fn = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); + llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type); if (target_is_wasm(g->zig_target)) { assert(fn->proto_node->type == NodeTypeFnProto); @@ -440,7 +448,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { TldFn *tld_fn = reinterpret_cast(entry->value); // Make the raw_type_ref populated resolve_llvm_types_fn(g, tld_fn->fn_entry); - tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), + tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, symbol_name, tld_fn->fn_entry->raw_type_ref); llvm_fn = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, LLVMPointerType(fn_llvm_type, 0)); return llvm_fn; @@ -448,7 +456,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { } } else { if (llvm_fn == nullptr) { - llvm_fn = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); + llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type); } for (size_t i = 1; i < fn->export_list.length; i += 1) { @@ -1058,8 +1066,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { }; LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false); - Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_add_err_ret_trace_addr"), false); - LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); + const char *fn_name = get_mangled_name(g, "__zig_add_err_ret_trace_addr", false); + LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref); addLLVMFnAttr(fn_val, "alwaysinline"); LLVMSetLinkage(fn_val, LLVMInternalLinkage); LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); @@ -1138,8 +1146,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { }; LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false); - Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_return_error"), false); - LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); + const char *fn_name = get_mangled_name(g, "__zig_return_error", false); + LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref); addLLVMFnAttr(fn_val, "noinline"); // so that we can look at return address addLLVMFnAttr(fn_val, "cold"); LLVMSetLinkage(fn_val, LLVMInternalLinkage); @@ -1208,7 +1216,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { LLVMSetLinkage(msg_prefix, LLVMInternalLinkage); LLVMSetGlobalConstant(msg_prefix, true); - Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false); + const char *fn_name = get_mangled_name(g, "__zig_fail_unwrap", false); LLVMTypeRef fn_type_ref; if (g->have_err_ret_tracing) { LLVMTypeRef arg_types[] = { @@ -1222,7 +1230,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { }; fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false); } - LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); + LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref); addLLVMFnAttr(fn_val, "noreturn"); addLLVMFnAttr(fn_val, "cold"); LLVMSetLinkage(fn_val, LLVMInternalLinkage); @@ -1805,7 +1813,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, ty)); break; case FnWalkIdVars: { - var->value_ref = build_alloca(g, ty, buf_ptr(&var->name), var->align_bytes); + var->value_ref = build_alloca(g, ty, var->name, var->align_bytes); di_arg_index = fn_walk->data.vars.gen_i; fn_walk->data.vars.gen_i += 1; dest_ty = ty; @@ -1916,7 +1924,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ } case FnWalkIdVars: { di_arg_index = fn_walk->data.vars.gen_i; - var->value_ref = build_alloca(g, ty, buf_ptr(&var->name), var->align_bytes); + var->value_ref = build_alloca(g, ty, var->name, var->align_bytes); fn_walk->data.vars.gen_i += 1; dest_ty = ty; goto var_ok; @@ -1949,7 +1957,7 @@ var_ok: if (dest_ty != nullptr && var->decl_node) { // arg index + 1 because the 0 index is return value var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), - buf_ptr(&var->name), fn_walk->data.vars.import->data.structure.root_struct->di_file, + var->name, fn_walk->data.vars.import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), get_llvm_di_type(g, dest_ty), !g->strip_debug_symbols, 0, di_arg_index + 1); } @@ -2060,8 +2068,8 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { }; LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), param_types, 2, false); - Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_merge_error_return_traces"), false); - LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); + const char *fn_name = get_mangled_name(g, "__zig_merge_error_return_traces", false); + LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref); LLVMSetLinkage(fn_val, LLVMInternalLinkage); LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); addLLVMFnAttr(fn_val, "nounwind"); @@ -3743,12 +3751,11 @@ static void render_async_spills(CodeGen *g) { continue; } - var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, async_var_index, - buf_ptr(&var->name)); + var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, async_var_index, var->name); async_var_index += 1; if (var->decl_node) { var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), - buf_ptr(&var->name), import->data.structure.root_struct->di_file, + var->name, import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); gen_var_debug_decl(g, var); @@ -4653,8 +4660,9 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(get_llvm_type(g, u8_slice_type), 0), &tag_int_llvm_type, 1, false); - Buf *fn_name = get_mangled_name(g, buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name)), false); - LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); + const char *fn_name = get_mangled_name(g, + buf_ptr(buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name))), false); + LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref); LLVMSetLinkage(fn_val, LLVMInternalLinkage); LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); addLLVMFnAttr(fn_val, "nounwind"); @@ -6919,7 +6927,7 @@ static void generate_error_name_table(CodeGen *g) { LLVMValueRef err_name_table_init = LLVMConstArray(get_llvm_type(g, str_type), values, (unsigned)g->errors_by_index.length); g->err_name_table = LLVMAddGlobal(g->module, LLVMTypeOf(err_name_table_init), - buf_ptr(get_mangled_name(g, buf_create_from_str("__zig_err_name_table"), false))); + get_mangled_name(g, buf_ptr(buf_create_from_str("__zig_err_name_table")), false)); LLVMSetInitializer(g->err_name_table, err_name_table_init); LLVMSetLinkage(g->err_name_table, LLVMPrivateLinkage); LLVMSetGlobalConstant(g->err_name_table, true); @@ -6960,8 +6968,8 @@ static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val, assert(import); bool is_local_to_unit = true; - ZigLLVMCreateGlobalVariable(g->dbuilder, get_di_scope(g, var->parent_scope), buf_ptr(&var->name), - buf_ptr(&var->name), import->data.structure.root_struct->di_file, + ZigLLVMCreateGlobalVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->name, + var->name, import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), get_llvm_di_type(g, type_entry), is_local_to_unit); @@ -7043,8 +7051,8 @@ static void do_code_gen(CodeGen *g) { assert(var->decl_node); GlobalLinkageId linkage; - Buf *unmangled_name = &var->name; - Buf *symbol_name; + const char *unmangled_name = var->name; + const char *symbol_name; if (var->export_list.length == 0) { if (var->decl_node->data.variable_declaration.is_extern) { symbol_name = unmangled_name; @@ -7055,19 +7063,19 @@ static void do_code_gen(CodeGen *g) { } } else { GlobalExport *global_export = &var->export_list.items[0]; - symbol_name = &global_export->name; + symbol_name = buf_ptr(&global_export->name); linkage = global_export->linkage; } LLVMValueRef global_value; bool externally_initialized = var->decl_node->data.variable_declaration.expr == nullptr; if (externally_initialized) { - LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(symbol_name)); + LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, symbol_name); if (existing_llvm_var) { global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(get_llvm_type(g, var->var_type), 0)); } else { - global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), buf_ptr(symbol_name)); + global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), symbol_name); // TODO debug info for the extern variable LLVMSetLinkage(global_value, to_llvm_linkage(linkage)); @@ -7078,8 +7086,8 @@ static void do_code_gen(CodeGen *g) { } } else { bool exported = (linkage != GlobalLinkageIdInternal); - render_const_val(g, var->const_value, buf_ptr(symbol_name)); - render_const_val_global(g, var->const_value, buf_ptr(symbol_name)); + render_const_val(g, var->const_value, symbol_name); + render_const_val_global(g, var->const_value, symbol_name); global_value = var->const_value->global_refs->llvm_global; if (exported) { @@ -7234,7 +7242,7 @@ static void do_code_gen(CodeGen *g) { if (var->src_arg_index == SIZE_MAX) { var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), - buf_ptr(&var->name), import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), + var->name, import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); } else if (is_c_abi) { @@ -7254,11 +7262,11 @@ static void do_code_gen(CodeGen *g) { var->value_ref = LLVMGetParam(fn, gen_info->gen_index); } else { gen_type = var->var_type; - var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes); + var->value_ref = build_alloca(g, var->var_type, var->name, var->align_bytes); } if (var->decl_node) { var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), - buf_ptr(&var->name), import->data.structure.root_struct->di_file, + var->name, import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(gen_info->gen_index+1)); } diff --git a/src/ir.cpp b/src/ir.cpp index 6b71fa8d17..ca2c59e342 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -3628,7 +3628,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s } if (name) { - buf_init_from_buf(&variable_entry->name, name); + variable_entry->name = strdup(buf_ptr(name)); if (!skip_name_check) { ZigVar *existing_var = find_variable(codegen, parent_scope, name, nullptr); @@ -3661,7 +3661,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s // TODO make this name not actually be in scope. user should be able to make a variable called "_anon" // might already be solved, let's just make sure it has test coverage // maybe we put a prefix on this so the debug info doesn't clobber user debug info for same named variables - buf_init_from_str(&variable_entry->name, "_anon"); + variable_entry->name = "_anon"; } variable_entry->src_is_const = src_is_const; @@ -6467,15 +6467,15 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo } assert(elem_node->type == NodeTypeSymbol); - IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, parent_scope, LValPtr, nullptr); + ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, parent_scope); + + IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, &spill_scope->base, LValPtr, nullptr); if (array_val_ptr == irb->codegen->invalid_instruction) return array_val_ptr; IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node, ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline); - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, parent_scope); - AstNode *index_var_source_node; ZigVar *index_var; const char *index_var_name; @@ -14559,7 +14559,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, // We make a new variable so that it can hold a different type, and so the debug info can // be distinct. ZigVar *new_var = create_local_var(ira->codegen, var->decl_node, var->child_scope, - &var->name, var->src_is_const, var->gen_is_const, var->shadowable, var->is_comptime, true); + buf_create_from_str(var->name), var->src_is_const, var->gen_is_const, + var->shadowable, var->is_comptime, true); new_var->owner_exec = var->owner_exec; new_var->align_bytes = var->align_bytes; if (var->mem_slot_index != SIZE_MAX) { @@ -14702,7 +14703,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio case CallingConventionNaked: case CallingConventionCold: case CallingConventionStdcall: - add_fn_export(ira->codegen, fn_entry, symbol_name, global_linkage_id, cc == CallingConventionC); + add_fn_export(ira->codegen, fn_entry, buf_ptr(symbol_name), global_linkage_id, + cc == CallingConventionC); break; } } break; @@ -14840,7 +14842,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio if (load_ptr->ptr->id == IrInstructionIdVarPtr) { IrInstructionVarPtr *var_ptr = reinterpret_cast(load_ptr->ptr); ZigVar *var = var_ptr->var; - add_var_export(ira->codegen, var, symbol_name, global_linkage_id); + add_var_export(ira->codegen, var, buf_ptr(symbol_name), global_linkage_id); } } @@ -17023,7 +17025,7 @@ static IrInstruction *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructi IrInstruction *result = ir_get_var_ptr(ira, &instruction->base, var); if (instruction->crossed_fndef_scope != nullptr && !instr_is_comptime(result)) { ErrorMsg *msg = ir_add_error(ira, &instruction->base, - buf_sprintf("'%s' not accessible from inner function", buf_ptr(&var->name))); + buf_sprintf("'%s' not accessible from inner function", var->name)); add_error_note(ira->codegen, msg, instruction->crossed_fndef_scope->base.source_node, buf_sprintf("crossed function definition here")); add_error_note(ira->codegen, msg, var->decl_node, @@ -17735,7 +17737,8 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_ return ir_error_dependency_loop(ira, source_instruction); } if (tld_var->extern_lib_name != nullptr) { - add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, source_instruction->source_node); + add_link_lib_symbol(ira, tld_var->extern_lib_name, buf_create_from_str(var->name), + source_instruction->source_node); } return ir_get_var_ptr(ira, source_instruction, var); @@ -20189,8 +20192,9 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) { ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index); ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index]; - ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name); - init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true); + ConstExprValue *arg_name = create_const_str_lit(ira->codegen, + buf_create_from_str(arg_var->name)); + init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, strlen(arg_var->name), true); fn_arg_name_val->parent.id = ConstParentIdArray; fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array; fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index; diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 30b8735244..f2877b46e6 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -531,7 +531,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) { const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; - const char *name = buf_ptr(&decl_var_instruction->var->name); + const char *name = decl_var_instruction->var->name; if (decl_var_instruction->var_type) { fprintf(irp->f, "%s %s: ", var_or_const, name); ir_print_other_instruction(irp, decl_var_instruction->var_type); @@ -747,7 +747,7 @@ static void ir_print_elem_ptr(IrPrint *irp, IrInstructionElemPtr *instruction) { } static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) { - fprintf(irp->f, "&%s", buf_ptr(&instruction->var->name)); + fprintf(irp->f, "&%s", instruction->var->name); } static void ir_print_return_ptr(IrPrint *irp, IrInstructionReturnPtr *instruction) { @@ -1852,7 +1852,7 @@ static void ir_print_mul_add(IrPrint *irp, IrInstructionMulAdd *instruction) { static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) { ZigVar *var = decl_var_instruction->var; const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; - const char *name = buf_ptr(&decl_var_instruction->var->name); + const char *name = decl_var_instruction->var->name; fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name), var->align_bytes); diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index 3ee728f8a5..86a0b659a8 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1201,3 +1201,35 @@ test "correctly spill when returning the error union result of another async fn" resume S.global_frame; } + +test "spill target expr in a for loop" { + const S = struct { + var global_frame: anyframe = undefined; + + fn doTheTest() void { + var foo = Foo{ + .slice = [_]i32{1, 2}, + }; + expect(atest(&foo) == 3); + } + + const Foo = struct { + slice: []i32, + }; + + fn atest(foo: *Foo) i32 { + var sum: i32 = 0; + for (foo.slice) |x| { + suspend { + global_frame = @frame(); + } + sum += x; + } + return sum; + } + }; + _ = async S.doTheTest(); + resume S.global_frame; + resume S.global_frame; +} +