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`.
master
Andrew Kelley 2019-09-09 15:54:03 -04:00
parent e4c3067617
commit f50bfb94b5
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
8 changed files with 122 additions and 73 deletions

View File

@ -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<GlobalExport> export_list;
uint32_t align_bytes;
uint32_t ref_count;
bool shadowable;
bool src_is_const;

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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<TldFn *>(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));
}

View File

@ -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<IrInstructionVarPtr *>(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;

View File

@ -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);

View File

@ -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;
}