authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-16 23:18:35-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-17 00:22:53-05:00
log4bdfc8a10aec3c7bd02037312840315a5fccbbb0
treea0074f9099e22d852dc38ba17ca8e3a072c431f8
parent24c2ff5caea15d3d6953414cd4a984993e8fa36e

fix error return traces pointing to off-by-one source line

See #651

1 files changed, 20 insertions(+), 28 deletions(-)

src/codegen.cpp+20-28
......@@ -921,31 +921,41 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) {
921921 return g->memcpy_fn_val;
922922}
923923
924static LLVMValueRef get_return_address_fn_val(CodeGen *g) {
925 if (g->return_address_fn_val)
926 return g->return_address_fn_val;
927
928 TypeTableEntry *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
929
930 LLVMTypeRef fn_type = LLVMFunctionType(return_type->type_ref,
931 &g->builtin_types.entry_i32->type_ref, 1, false);
932 g->return_address_fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type);
933 assert(LLVMGetIntrinsicID(g->return_address_fn_val));
934
935 return g->return_address_fn_val;
936}
937
924938static LLVMValueRef get_return_err_fn(CodeGen *g) {
925939 if (g->return_err_fn != nullptr)
926940 return g->return_err_fn;
927941
928942 assert(g->err_tag_type != nullptr);
929943
930 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
931
932944 LLVMTypeRef arg_types[] = {
933945 // error return trace pointer
934946 get_ptr_to_stack_trace_type(g)->type_ref,
935 // return address
936 ptr_u8,
937947 };
938 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);
948 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false);
939949
940950 Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_return_error"), false);
941951 LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref);
952 addLLVMFnAttr(fn_val, "noinline"); // so that we can look at return address
942953 addLLVMFnAttr(fn_val, "cold");
943954 LLVMSetLinkage(fn_val, LLVMInternalLinkage);
944955 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
945956 addLLVMFnAttr(fn_val, "nounwind");
946957 add_uwtable_attr(g, fn_val);
947958 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
948 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
949959 if (g->build_mode == BuildModeDebug) {
950960 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
951961 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr);
......@@ -983,7 +993,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
983993 LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, "");
984994 LLVMValueRef address_slot = LLVMBuildInBoundsGEP(g->builder, ptr_value, address_indices, 1, "");
985995
986 LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, LLVMGetParam(fn_val, 1), usize_type_ref, "");
996 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref);
997 LLVMValueRef return_address_ptr = LLVMBuildCall(g->builder, get_return_address_fn_val(g), &zero, 1, "");
998 LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, return_address_ptr, usize_type_ref, "");
987999
9881000 LLVMValueRef address_value = LLVMBuildPtrToInt(g->builder, return_address, usize_type_ref, "");
9891001 gen_store_untyped(g, address_value, address_slot, 0, false);
......@@ -1431,17 +1443,11 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
14311443 is_err_return = true;
14321444 }
14331445 if (is_err_return) {
1434 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn_val, "ReturnError");
1435 LLVMValueRef block_address = LLVMBlockAddress(g->cur_fn_val, return_block);
1436
14371446 LLVMValueRef return_err_fn = get_return_err_fn(g);
14381447 LLVMValueRef args[] = {
14391448 g->cur_err_ret_trace_val,
1440 block_address,
14411449 };
1442 LLVMBuildBr(g->builder, return_block);
1443 LLVMPositionBuilderAtEnd(g->builder, return_block);
1444 LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 2,
1450 LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 1,
14451451 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
14461452 LLVMSetTailCall(call_instruction, true);
14471453 }
......@@ -3291,20 +3297,6 @@ static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, I
32913297 return nullptr;
32923298}
32933299
3294static LLVMValueRef get_return_address_fn_val(CodeGen *g) {
3295 if (g->return_address_fn_val)
3296 return g->return_address_fn_val;
3297
3298 TypeTableEntry *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
3299
3300 LLVMTypeRef fn_type = LLVMFunctionType(return_type->type_ref,
3301 &g->builtin_types.entry_i32->type_ref, 1, false);
3302 g->return_address_fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type);
3303 assert(LLVMGetIntrinsicID(g->return_address_fn_val));
3304
3305 return g->return_address_fn_val;
3306}
3307
33083300static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable,
33093301 IrInstructionReturnAddress *instruction)
33103302{