diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2018-01-11 23:04:08 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2018-01-11 23:04:08 -0500 |
| commit | 7ec783876a565662223268a70ba984e0a132b94a (patch) | |
| tree | af0c952df4dd3896721713cfa54117cb30b0a1e3 /src/codegen.cpp | |
| parent | 3268276b58d8b65cb295b738d7c14174005bd84e (diff) | |
| download | zig-7ec783876a565662223268a70ba984e0a132b94a.tar.gz zig-7ec783876a565662223268a70ba984e0a132b94a.zip | |
functions which can return errors have secret stack trace param
See #651
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index 9ad71a936e..4de0fcec51 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -483,7 +483,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { LLVMSetUnnamedAddr(fn_table_entry->llvm_value, true); } - if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdUnreachable) { + TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; + if (return_type->id == TypeTableEntryIdUnreachable) { addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn"); } @@ -520,13 +521,11 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { // use the ABI alignment, which is fine. } - if (!type_has_bits(fn_type->data.fn.fn_type_id.return_type)) { + if (!type_has_bits(return_type)) { // nothing to do - } else if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdPointer || - fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdFn) - { + } else if (return_type->id == TypeTableEntryIdPointer || return_type->id == TypeTableEntryIdFn) { addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull"); - } else if (handle_is_ptr(fn_type->data.fn.fn_type_id.return_type) && + } else if (handle_is_ptr(return_type) && calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc)) { addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); @@ -562,6 +561,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "byval"); } } + if (return_type->id == TypeTableEntryIdErrorUnion || return_type->id == TypeTableEntryIdPureError) { + unsigned gen_index = LLVMCountParamTypes(fn_llvm_type) - 1; + addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "nonnull"); + } return fn_table_entry->llvm_value; } @@ -2330,7 +2333,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr TypeTableEntry *src_return_type = fn_type_id->return_type; bool ret_has_bits = type_has_bits(src_return_type); bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type); - size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0); + bool last_arg_err_ret_stack = src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError; + size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (last_arg_err_ret_stack ? 1 : 0); bool is_var_args = fn_type_id->is_var_args; LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); size_t gen_param_index = 0; @@ -2348,6 +2352,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr gen_param_index += 1; } } + if (last_arg_err_ret_stack) { + gen_param_values[gen_param_index] = LLVMGetUndef(g->ptr_to_stack_trace_type->type_ref); + gen_param_index += 1; + } ZigLLVM_FnInline fn_inline; switch (instruction->fn_inline) { @@ -5088,6 +5096,13 @@ static void define_builtin_compile_vars(CodeGen *g) { os_path_join(g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path); Buf *contents = buf_alloc(); + buf_append_str(contents, + "pub const StackTrace = struct {\n" + " index: usize,\n" + " instruction_addresses: [31]usize,\n" + "};\n\n" + ); + const char *cur_os = nullptr; { buf_appendf(contents, "pub const Os = enum {\n"); |
