| ... | ... | @@ -406,6 +406,16 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { |
| 406 | 406 | zig_unreachable(); |
| 407 | 407 | } |
| 408 | 408 | |
| 409 | static uint32_t get_err_ret_trace_arg_index(FnTableEntry *fn_table_entry) { |
| 410 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 411 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; |
| 412 | if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdPureError) { |
| 413 | return UINT32_MAX; |
| 414 | } |
| 415 | bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type); |
| 416 | return first_arg_ret ? 1 : 0; |
| 417 | } |
| 418 | |
| 409 | 419 | static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 410 | 420 | if (fn_table_entry->llvm_value) |
| 411 | 421 | return fn_table_entry->llvm_value; |
| ... | ... | @@ -563,9 +573,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 563 | 573 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "byval"); |
| 564 | 574 | } |
| 565 | 575 | } |
| 566 | | if (return_type->id == TypeTableEntryIdErrorUnion || return_type->id == TypeTableEntryIdPureError) { |
| 567 | | unsigned gen_index = LLVMCountParamTypes(fn_llvm_type) - 1; |
| 568 | | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "nonnull"); |
| 576 | |
| 577 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(fn_table_entry); |
| 578 | if (err_ret_trace_arg_index != UINT32_MAX) { |
| 579 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull"); |
| 569 | 580 | } |
| 570 | 581 | |
| 571 | 582 | return fn_table_entry->llvm_value; |
| ... | ... | @@ -2400,8 +2411,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2400 | 2411 | TypeTableEntry *src_return_type = fn_type_id->return_type; |
| 2401 | 2412 | bool ret_has_bits = type_has_bits(src_return_type); |
| 2402 | 2413 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type); |
| 2403 | | bool last_arg_err_ret_stack = src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError; |
| 2404 | | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (last_arg_err_ret_stack ? 1 : 0); |
| 2414 | bool prefix_arg_err_ret_stack = src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError; |
| 2415 | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0); |
| 2405 | 2416 | bool is_var_args = fn_type_id->is_var_args; |
| 2406 | 2417 | LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); |
| 2407 | 2418 | size_t gen_param_index = 0; |
| ... | ... | @@ -2409,6 +2420,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2409 | 2420 | gen_param_values[gen_param_index] = instruction->tmp_ptr; |
| 2410 | 2421 | gen_param_index += 1; |
| 2411 | 2422 | } |
| 2423 | if (prefix_arg_err_ret_stack) { |
| 2424 | gen_param_values[gen_param_index] = g->cur_err_ret_trace_val; |
| 2425 | gen_param_index += 1; |
| 2426 | } |
| 2412 | 2427 | for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) { |
| 2413 | 2428 | IrInstruction *param_instruction = instruction->args[call_i]; |
| 2414 | 2429 | TypeTableEntry *param_type = param_instruction->value.type; |
| ... | ... | @@ -2419,10 +2434,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2419 | 2434 | gen_param_index += 1; |
| 2420 | 2435 | } |
| 2421 | 2436 | } |
| 2422 | | if (last_arg_err_ret_stack) { |
| 2423 | | gen_param_values[gen_param_index] = g->cur_err_ret_trace_val; |
| 2424 | | gen_param_index += 1; |
| 2425 | | } |
| 2426 | 2437 | |
| 2427 | 2438 | ZigLLVM_FnInline fn_inline; |
| 2428 | 2439 | switch (instruction->fn_inline) { |
| ... | ... | @@ -4578,8 +4589,9 @@ static void do_code_gen(CodeGen *g) { |
| 4578 | 4589 | build_all_basic_blocks(g, fn_table_entry); |
| 4579 | 4590 | clear_debug_source_node(g); |
| 4580 | 4591 | |
| 4581 | | if (return_type->id == TypeTableEntryIdPureError || return_type->id == TypeTableEntryIdErrorUnion) { |
| 4582 | | g->cur_err_ret_trace_val = LLVMGetParam(fn, LLVMCountParamTypes(fn_table_entry->type_entry->data.fn.raw_type_ref) - 1); |
| 4592 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(fn_table_entry); |
| 4593 | if (err_ret_trace_arg_index != UINT32_MAX) { |
| 4594 | g->cur_err_ret_trace_val = LLVMGetParam(fn, err_ret_trace_arg_index); |
| 4583 | 4595 | } else if (fn_table_entry->calls_errorable_function) { |
| 4584 | 4596 | g->cur_err_ret_trace_val = build_alloca(g, g->stack_trace_type, "error_return_trace", get_abi_alignment(g, g->stack_trace_type)); |
| 4585 | 4597 | size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; |