aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp135
1 files changed, 80 insertions, 55 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 37f15f43a7..b1431a9c33 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -112,10 +112,10 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
// that's for native compilation
g->zig_target = *target;
resolve_target_object_format(&g->zig_target);
- g->dynamic_linker = buf_create_from_str("");
- g->libc_lib_dir = buf_create_from_str("");
- g->libc_static_lib_dir = buf_create_from_str("");
- g->libc_include_dir = buf_create_from_str("");
+ g->dynamic_linker = nullptr;
+ g->libc_lib_dir = nullptr;
+ g->libc_static_lib_dir = nullptr;
+ g->libc_include_dir = nullptr;
g->msvc_lib_dir = nullptr;
g->kernel32_lib_dir = nullptr;
g->each_lib_rpath = false;
@@ -123,16 +123,13 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
// native compilation, we can rely on the configuration stuff
g->is_native_target = true;
get_native_target(&g->zig_target);
- g->dynamic_linker = buf_create_from_str(ZIG_DYNAMIC_LINKER);
- g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR);
- g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR);
- g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR);
+ g->dynamic_linker = nullptr; // find it at runtime
+ g->libc_lib_dir = nullptr; // find it at runtime
+ g->libc_static_lib_dir = nullptr; // find it at runtime
+ g->libc_include_dir = nullptr; // find it at runtime
g->msvc_lib_dir = nullptr; // find it at runtime
g->kernel32_lib_dir = nullptr; // find it at runtime
-
-#ifdef ZIG_EACH_LIB_RPATH
g->each_lib_rpath = true;
-#endif
if (g->zig_target.os == OsMacOSX ||
g->zig_target.os == OsIOS)
@@ -657,6 +654,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
case ScopeIdDeferExpr:
case ScopeIdLoop:
case ScopeIdCompTime:
+ case ScopeIdCoroPrelude:
return get_di_scope(g, scope->parent);
}
zig_unreachable();
@@ -1295,9 +1293,34 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
return fn_val;
}
-static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) {
+static bool is_coro_prelude_scope(Scope *scope) {
+ while (scope != nullptr) {
+ if (scope->id == ScopeIdCoroPrelude) {
+ return true;
+ } else if (scope->id == ScopeIdFnDef) {
+ break;
+ }
+ scope = scope->parent;
+ }
+ return false;
+}
+
+static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) {
+ if (!g->have_err_ret_tracing) {
+ return nullptr;
+ }
+ if (g->cur_fn->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync) {
+ return is_coro_prelude_scope(scope) ? g->cur_err_ret_trace_val_arg : g->cur_err_ret_trace_val_stack;
+ }
+ if (g->cur_err_ret_trace_val_stack != nullptr) {
+ return g->cur_err_ret_trace_val_stack;
+ }
+ return g->cur_err_ret_trace_val_arg;
+}
+
+static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) {
LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g);
- LLVMValueRef err_ret_trace_val = g->cur_err_ret_trace_val;
+ LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope);
if (err_ret_trace_val == nullptr) {
TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
err_ret_trace_val = LLVMConstNull(ptr_to_stack_trace_type->type_ref);
@@ -1574,32 +1597,25 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
return instruction->llvm_value;
}
+static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *executable,
+ IrInstructionSaveErrRetAddr *save_err_ret_addr_instruction)
+{
+ assert(g->have_err_ret_tracing);
+
+ LLVMValueRef return_err_fn = get_return_err_fn(g);
+ LLVMValueRef args[] = {
+ get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope),
+ };
+ LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 1,
+ get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
+ LLVMSetTailCall(call_instruction, true);
+ return call_instruction;
+}
+
static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
TypeTableEntry *return_type = return_instruction->value->value.type;
- if (g->have_err_ret_tracing) {
- bool is_err_return = false;
- if (return_type->id == TypeTableEntryIdErrorUnion) {
- if (return_instruction->value->value.special == ConstValSpecialStatic) {
- is_err_return = return_instruction->value->value.data.x_err_union.err != nullptr;
- } else if (return_instruction->value->value.special == ConstValSpecialRuntime) {
- is_err_return = return_instruction->value->value.data.rh_error_union == RuntimeHintErrorUnionError;
- // TODO: emit a branch to check if the return value is an error
- }
- } else if (return_type->id == TypeTableEntryIdErrorSet) {
- is_err_return = true;
- }
- if (is_err_return) {
- LLVMValueRef return_err_fn = get_return_err_fn(g);
- LLVMValueRef args[] = {
- g->cur_err_ret_trace_val,
- };
- LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 1,
- get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
- LLVMSetTailCall(call_instruction, true);
- }
- }
if (handle_is_ptr(return_type)) {
if (calling_convention_does_first_arg_return(g->cur_fn->type_entry->data.fn.fn_type_id.cc)) {
assert(g->cur_ret_ptr);
@@ -2671,7 +2687,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
gen_param_index += 1;
}
if (prefix_arg_err_ret_stack) {
- gen_param_values[gen_param_index] = g->cur_err_ret_trace_val;
+ gen_param_values[gen_param_index] = get_cur_err_ret_trace_val(g, instruction->base.scope);
gen_param_index += 1;
}
if (instruction->is_async) {
@@ -3238,11 +3254,12 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *executable,
IrInstructionErrorReturnTrace *instruction)
{
- if (g->cur_err_ret_trace_val == nullptr) {
+ LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
+ if (cur_err_ret_trace_val == nullptr) {
TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
return LLVMConstNull(ptr_to_stack_trace_type->type_ref);
}
- return g->cur_err_ret_trace_val;
+ return cur_err_ret_trace_val;
}
static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrInstructionCancel *instruction) {
@@ -3648,7 +3665,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
LLVMPositionBuilderAtEnd(g->builder, err_block);
- gen_safety_crash_for_err(g, err_val);
+ gen_safety_crash_for_err(g, err_val, instruction->base.scope);
LLVMPositionBuilderAtEnd(g->builder, ok_block);
}
@@ -3840,7 +3857,7 @@ static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *exec
}
static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) {
- gen_panic(g, ir_llvm_value(g, instruction->msg), g->cur_err_ret_trace_val);
+ gen_panic(g, ir_llvm_value(g, instruction->msg), get_cur_err_ret_trace_val(g, instruction->base.scope));
return nullptr;
}
@@ -4127,6 +4144,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdSetRuntimeSafety:
case IrInstructionIdSetFloatMode:
case IrInstructionIdArrayType:
+ case IrInstructionIdPromiseType:
case IrInstructionIdSliceType:
case IrInstructionIdSizeOf:
case IrInstructionIdSwitchTarget:
@@ -4167,6 +4185,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdErrorUnion:
case IrInstructionIdPromiseResultType:
case IrInstructionIdAwaitBookkeeping:
+ case IrInstructionIdAddImplicitReturnType:
zig_unreachable();
case IrInstructionIdReturn:
@@ -4315,6 +4334,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_coro_alloc_helper(g, executable, (IrInstructionCoroAllocHelper *)instruction);
case IrInstructionIdAtomicRmw:
return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction);
+ case IrInstructionIdSaveErrRetAddr:
+ return ir_render_save_err_ret_addr(g, executable, (IrInstructionSaveErrRetAddr *)instruction);
}
zig_unreachable();
}
@@ -5197,9 +5218,17 @@ static void do_code_gen(CodeGen *g) {
clear_debug_source_node(g);
uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
- if (err_ret_trace_arg_index != UINT32_MAX) {
- g->cur_err_ret_trace_val = LLVMGetParam(fn, err_ret_trace_arg_index);
- } else if (g->have_err_ret_tracing && fn_table_entry->calls_or_awaits_errorable_fn) {
+ bool have_err_ret_trace_arg = err_ret_trace_arg_index != UINT32_MAX;
+ if (have_err_ret_trace_arg) {
+ g->cur_err_ret_trace_val_arg = LLVMGetParam(fn, err_ret_trace_arg_index);
+ } else {
+ g->cur_err_ret_trace_val_arg = nullptr;
+ }
+
+ bool is_async = fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
+ bool have_err_ret_trace_stack = g->have_err_ret_tracing && fn_table_entry->calls_or_awaits_errorable_fn &&
+ (is_async || !have_err_ret_trace_arg);
+ if (have_err_ret_trace_stack) {
// TODO call graph analysis to find out what this number needs to be for every function
static const size_t stack_trace_ptr_count = 30;
@@ -5207,13 +5236,13 @@ static void do_code_gen(CodeGen *g) {
TypeTableEntry *array_type = get_array_type(g, usize, stack_trace_ptr_count);
LLVMValueRef err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses",
get_abi_alignment(g, array_type));
- g->cur_err_ret_trace_val = build_alloca(g, g->stack_trace_type, "error_return_trace", get_abi_alignment(g, g->stack_trace_type));
+ g->cur_err_ret_trace_val_stack = build_alloca(g, g->stack_trace_type, "error_return_trace", get_abi_alignment(g, g->stack_trace_type));
size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index;
- LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val, (unsigned)index_field_index, "");
+ LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, "");
gen_store_untyped(g, LLVMConstNull(usize->type_ref), index_field_ptr, 0, false);
size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index;
- LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val, (unsigned)addresses_field_index, "");
+ LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, "");
TypeTableEntry *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;
size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
@@ -5229,7 +5258,7 @@ static void do_code_gen(CodeGen *g) {
LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, "");
gen_store(g, LLVMConstInt(usize->type_ref, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false));
} else {
- g->cur_err_ret_trace_val = nullptr;
+ g->cur_err_ret_trace_val_stack = nullptr;
}
// allocate temporary stack data
@@ -6172,7 +6201,7 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package
zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
}
Buf *import_code = buf_alloc();
- if ((err = os_fetch_file_path(abs_full_path, import_code))) {
+ if ((err = os_fetch_file_path(abs_full_path, import_code, false))) {
zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
}
@@ -6260,7 +6289,7 @@ static void gen_root_source(CodeGen *g) {
}
Buf *source_code = buf_alloc();
- if ((err = os_fetch_file_path(rel_full_path, source_code))) {
+ if ((err = os_fetch_file_path(rel_full_path, source_code, true))) {
zig_panic("unable to open '%s': %s", buf_ptr(rel_full_path), err_str(err));
}
@@ -6325,7 +6354,7 @@ static void gen_global_asm(CodeGen *g) {
int err;
for (size_t i = 0; i < g->assembly_files.length; i += 1) {
Buf *asm_file = g->assembly_files.at(i);
- if ((err = os_fetch_file_path(asm_file, &contents))) {
+ if ((err = os_fetch_file_path(asm_file, &contents, false))) {
zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err));
}
buf_append_buf(&g->global_asm, &contents);
@@ -6507,6 +6536,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
}
}
case TypeTableEntryIdStruct:
+ case TypeTableEntryIdOpaque:
{
buf_init_from_str(out_buf, "struct ");
buf_append_buf(out_buf, &type_entry->name);
@@ -6524,11 +6554,6 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
buf_append_buf(out_buf, &type_entry->name);
return;
}
- case TypeTableEntryIdOpaque:
- {
- buf_init_from_buf(out_buf, &type_entry->name);
- return;
- }
case TypeTableEntryIdArray:
{
TypeTableEntryArray *array_data = &type_entry->data.array;