From 2213722776ae6f10bd4b11bee7d9d23f0a772458 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 16 Feb 2022 12:37:22 +0000 Subject: [PATCH 1/6] Change debug declare to value --- src/llvm_backend_debug.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index f60096aad..1a2705988 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -962,7 +962,7 @@ void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos); LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0); lb_set_llvm_metadata(m, ptr, llvm_expr); - LLVMDIBuilderInsertDeclareBefore(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, instr); + LLVMDIBuilderInsertDbgValueBefore(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, instr); } @@ -1026,12 +1026,12 @@ void lb_add_debug_param_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0); lb_set_llvm_metadata(m, ptr, llvm_expr); if (LLVMIsAAllocaInst(instr)) { - LLVMDIBuilderInsertDeclareBefore(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, instr); + LLVMDIBuilderInsertDbgValueBefore(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, instr); } else { // NOTE(bill, 2022-02-01): For parameter values, you must insert them at the end of the decl block // The reason is that if the parameter is at index 0 and a pointer, there is not such things as an // instruction "before" it. - LLVMDIBuilderInsertDeclareAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block); + LLVMDIBuilderInsertDbgValueAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block); } } From 0738822dda2a863322b752b91ce7a4e0ac95e6e7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 16 Feb 2022 13:25:31 +0000 Subject: [PATCH 2/6] Change how parameter and variables are given debug values --- src/llvm_backend_debug.cpp | 18 +++++++----------- src/llvm_backend_opt.cpp | 2 +- src/llvm_backend_proc.cpp | 3 ++- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 1a2705988..88974bd24 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -958,11 +958,11 @@ void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T ); LLVMValueRef storage = ptr; - LLVMValueRef instr = ptr; + LLVMBasicBlockRef block = p->decl_block->block; LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos); LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0); lb_set_llvm_metadata(m, ptr, llvm_expr); - LLVMDIBuilderInsertDbgValueBefore(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, instr); + LLVMDIBuilderInsertDbgValueAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block); } @@ -1020,19 +1020,15 @@ void lb_add_debug_param_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T ); LLVMValueRef storage = ptr; - LLVMValueRef instr = ptr; LLVMBasicBlockRef block = p->decl_block->block; LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos); LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0); lb_set_llvm_metadata(m, ptr, llvm_expr); - if (LLVMIsAAllocaInst(instr)) { - LLVMDIBuilderInsertDbgValueBefore(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, instr); - } else { - // NOTE(bill, 2022-02-01): For parameter values, you must insert them at the end of the decl block - // The reason is that if the parameter is at index 0 and a pointer, there is not such things as an - // instruction "before" it. - LLVMDIBuilderInsertDbgValueAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block); - } + + // NOTE(bill, 2022-02-01): For parameter values, you must insert them at the end of the decl block + // The reason is that if the parameter is at index 0 and a pointer, there is not such things as an + // instruction "before" it. + LLVMDIBuilderInsertDbgValueAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block); } diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index 8f1c7ad59..d36bdec0b 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -56,7 +56,7 @@ LLVMBool lb_must_preserve_predicate_callback(LLVMValueRef value, void *user_data #endif void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm, i32 optimization_level) { - if (optimization_level == 0 && build_context.ODIN_DEBUG) { + if (false && optimization_level == 0 && build_context.ODIN_DEBUG) { LLVMAddMergedLoadStoreMotionPass(fpm); } else { LLVMAddPromoteMemoryToRegisterPass(fpm); diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 2a0380605..61cba53bd 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -491,7 +491,8 @@ void lb_begin_procedure_body(lbProcedure *p) { lbValue ptr = lb_address_from_load_or_generate_local(p, param); GB_ASSERT(LLVMIsAAllocaInst(ptr.value)); lb_add_entity(p->module, e, ptr); - lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1); + // lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1); + lb_add_debug_param_variable(p, value, e->type, e->token, param_index+1); } } else if (arg_type->kind == lbArg_Indirect) { if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { From e011d812ca5df522f937a4e3866310c6a24fd6c4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 16 Feb 2022 14:39:08 +0000 Subject: [PATCH 3/6] Improve debug information for direct procedure parmaters --- src/llvm_backend_debug.cpp | 5 ++--- src/llvm_backend_proc.cpp | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 88974bd24..0e86fbb59 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -966,7 +966,7 @@ void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T } -void lb_add_debug_param_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, Token const &token, unsigned arg_number) { +void lb_add_debug_param_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, Token const &token, unsigned arg_number, lbBlock *block) { if (p->debug_info == nullptr) { return; } @@ -1020,7 +1020,6 @@ void lb_add_debug_param_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T ); LLVMValueRef storage = ptr; - LLVMBasicBlockRef block = p->decl_block->block; LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos); LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0); lb_set_llvm_metadata(m, ptr, llvm_expr); @@ -1028,7 +1027,7 @@ void lb_add_debug_param_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T // NOTE(bill, 2022-02-01): For parameter values, you must insert them at the end of the decl block // The reason is that if the parameter is at index 0 and a pointer, there is not such things as an // instruction "before" it. - LLVMDIBuilderInsertDbgValueAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block); + LLVMDIBuilderInsertDbgValueAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block->block); } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 61cba53bd..ccb16ebe0 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -480,9 +480,8 @@ void lb_begin_procedure_body(lbProcedure *p) { } else if (arg_type->kind == lbArg_Direct) { if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { LLVMTypeRef param_type = lb_type(p->module, e->type); - LLVMValueRef value = LLVMGetParam(p->value, param_offset+param_index); - - value = OdinLLVMBuildTransmute(p, value, param_type); + LLVMValueRef original_value = LLVMGetParam(p->value, param_offset+param_index); + LLVMValueRef value = OdinLLVMBuildTransmute(p, original_value, param_type); lbValue param = {}; param.value = value; @@ -491,8 +490,16 @@ void lb_begin_procedure_body(lbProcedure *p) { lbValue ptr = lb_address_from_load_or_generate_local(p, param); GB_ASSERT(LLVMIsAAllocaInst(ptr.value)); lb_add_entity(p->module, e, ptr); - // lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1); - lb_add_debug_param_variable(p, value, e->type, e->token, param_index+1); + + lbBlock *block = p->decl_block; + if (original_value != value) { + block = p->curr_block; + } + LLVMValueRef debug_storage_value = value; + if (original_value != value && LLVMIsALoadInst(value)) { + debug_storage_value = ptr.value; + } + lb_add_debug_param_variable(p, debug_storage_value, e->type, e->token, param_index+1, block); } } else if (arg_type->kind == lbArg_Indirect) { if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { @@ -500,7 +507,7 @@ void lb_begin_procedure_body(lbProcedure *p) { ptr.value = LLVMGetParam(p->value, param_offset+param_index); ptr.type = alloc_type_pointer(e->type); lb_add_entity(p->module, e, ptr); - lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1); + lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1, p->decl_block); } } } From 1857bc7b02eec221bc0d89a4702b9c8c5e003e3f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 16 Feb 2022 14:51:54 +0000 Subject: [PATCH 4/6] Improve slice bounds checking runtime error messages --- core/runtime/error_checks.odin | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/runtime/error_checks.odin b/core/runtime/error_checks.odin index ed75cbea6..14d55c64c 100644 --- a/core/runtime/error_checks.odin +++ b/core/runtime/error_checks.odin @@ -25,7 +25,7 @@ bounds_check_error :: proc "contextless" (file: string, line, column: i32, index print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Index ") print_i64(i64(index)) - print_string(" is out of bounds range 0:") + print_string(" is out of range 0..<") print_i64(i64(count)) print_byte('\n') bounds_trap() @@ -35,11 +35,11 @@ bounds_check_error :: proc "contextless" (file: string, line, column: i32, index slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid slice indices: ") + print_string(" Invalid slice indices ") print_i64(i64(lo)) print_string(":") print_i64(i64(hi)) - print_string(":") + print_string(" is out of range 0..<") print_i64(i64(len)) print_byte('\n') bounds_trap() @@ -47,7 +47,7 @@ slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, h multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid slice indices: ") + print_string(" Invalid slice indices ") print_i64(i64(lo)) print_string(":") print_i64(i64(hi)) @@ -83,11 +83,11 @@ dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, } handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) { print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid dynamic array values: ") + print_string(" Invalid dynamic array indices ") print_i64(i64(low)) print_string(":") print_i64(i64(high)) - print_string(":") + print_string(" is out of range 0..<") print_i64(i64(max)) print_byte('\n') bounds_trap() @@ -107,7 +107,7 @@ matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32 print_i64(i64(row_index)) print_string(", ") print_i64(i64(column_index)) - print_string(" is out of bounds range [0..<") + print_string(" is out of range [0..<") print_i64(i64(row_count)) print_string(", 0..<") print_i64(i64(column_count)) From 42ad54c28ee013618c7ee0039bbe1ce5dd1f0ba6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 16 Feb 2022 15:18:22 +0000 Subject: [PATCH 5/6] Improve metadata for `context` --- src/llvm_backend_debug.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 0e86fbb59..ff1c5c7dc 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -1050,5 +1050,10 @@ void lb_add_debug_context_variable(lbProcedure *p, lbAddr const &ctx) { token.string = str_lit("context"); token.pos = pos; - lb_add_debug_local_variable(p, ctx.addr.value, t_context, token); + LLVMValueRef ptr = ctx.addr.value; + while (LLVMIsABitCastInst(ptr)) { + ptr = LLVMGetOperand(ptr, 0); + } + + lb_add_debug_local_variable(p, ptr, t_context, token); } From db6bd9b358f17c0259ff5fe6411ce93407613338 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 16 Feb 2022 16:03:49 +0000 Subject: [PATCH 6/6] Allow sysv and win64 calling conventions to be used on any platform on amd64 --- core/runtime/core.odin | 5 +++++ src/check_type.cpp | 19 +++++++++++++++++++ src/docs_writer.cpp | 35 +---------------------------------- src/llvm_abi.cpp | 6 ++++++ src/llvm_backend.hpp | 4 ++++ src/llvm_backend_proc.cpp | 2 +- src/parser.cpp | 6 ++++++ src/parser.hpp | 18 ++++++++++++++++++ 8 files changed, 60 insertions(+), 35 deletions(-) diff --git a/core/runtime/core.odin b/core/runtime/core.odin index fec51f236..229d70417 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -33,6 +33,11 @@ Calling_Convention :: enum u8 { None = 6, Naked = 7, + + _ = 8, // reserved + + Win64 = 9, + SysV = 10, } Type_Info_Enum_Value :: distinct i64 diff --git a/src/check_type.cpp b/src/check_type.cpp index 32340070e..a11f5234b 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1910,6 +1910,25 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, c->scope->flags &= ~ScopeFlag_ContextDefined; } + TargetArchKind arch = build_context.metrics.arch; + switch (cc) { + case ProcCC_StdCall: + case ProcCC_FastCall: + if (arch != TargetArch_i386 || arch != TargetArch_amd64) { + error(proc_type_node, "Invalid procedure calling convention \"%s\" for target architecture, expected either i386 or amd64, got %.*s", + proc_calling_convention_strings[cc], LIT(target_arch_names[arch])); + } + break; + case ProcCC_Win64: + case ProcCC_SysV: + if (arch != TargetArch_amd64) { + error(proc_type_node, "Invalid procedure calling convention \"%s\" for target architecture, expected amd64, got %.*s", + proc_calling_convention_strings[cc], LIT(target_arch_names[arch])); + } + break; + } + + bool variadic = false; isize variadic_index = -1; bool success = true; diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index 0474ce8ff..2c5186c39 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -683,40 +683,7 @@ OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { types[1] = odin_doc_type(w, type->Proc.results); doc_type.types = odin_write_slice(w, types, gb_count_of(types)); - String calling_convention = {}; - switch (type->Proc.calling_convention) { - case ProcCC_Invalid: - // no need - break; - case ProcCC_Odin: - if (default_calling_convention() != ProcCC_Odin) { - calling_convention = str_lit("odin"); - } - break; - case ProcCC_Contextless: - if (default_calling_convention() != ProcCC_Contextless) { - calling_convention = str_lit("contextless"); - } - break; - case ProcCC_CDecl: - calling_convention = str_lit("cdecl"); - break; - case ProcCC_StdCall: - calling_convention = str_lit("stdcall"); - break; - case ProcCC_FastCall: - calling_convention = str_lit("fastcall"); - break; - case ProcCC_None: - calling_convention = str_lit("none"); - break; - case ProcCC_Naked: - calling_convention = str_lit("naked"); - break; - case ProcCC_InlineAsm: - calling_convention = str_lit("inline-assembly"); - break; - } + String calling_convention = make_string_c(proc_calling_convention_strings[type->Proc.calling_convention]); doc_type.calling_convention = odin_doc_write_string(w, calling_convention); } break; diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index 310df6639..0244b73d6 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -1184,6 +1184,12 @@ LB_ABI_INFO(lb_get_abi_info) { ft->calling_convention = calling_convention; return ft; } + case ProcCC_Win64: + GB_ASSERT(build_context.metrics.arch == TargetArch_amd64); + return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); + case ProcCC_SysV: + GB_ASSERT(build_context.metrics.arch == TargetArch_amd64); + return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); } switch (build_context.metrics.arch) { diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 087cda22a..f2bcfaff6 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -548,6 +548,10 @@ lbCallingConventionKind const lb_calling_convention_map[ProcCC_MAX] = { lbCallingConvention_C, // ProcCC_None, lbCallingConvention_C, // ProcCC_Naked, lbCallingConvention_C, // ProcCC_InlineAsm, + + lbCallingConvention_Win64, // ProcCC_Win64, + lbCallingConvention_X86_64_SysV, // ProcCC_SysV, + }; enum : LLVMDWARFTypeEncoding { diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index ccb16ebe0..261e2819c 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -497,7 +497,7 @@ void lb_begin_procedure_body(lbProcedure *p) { } LLVMValueRef debug_storage_value = value; if (original_value != value && LLVMIsALoadInst(value)) { - debug_storage_value = ptr.value; + debug_storage_value = LLVMGetOperand(value, 0); } lb_add_debug_param_variable(p, debug_storage_value, e->type, e->token, param_index+1, block); } diff --git a/src/parser.cpp b/src/parser.cpp index 0914c77ca..bd0e55b7f 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3412,12 +3412,18 @@ ProcCallingConvention string_to_calling_convention(String s) { if (s == "fast") return ProcCC_FastCall; if (s == "none") return ProcCC_None; if (s == "naked") return ProcCC_Naked; + + if (s == "win64") return ProcCC_Win64; + if (s == "sysv") return ProcCC_SysV; + if (s == "system") { if (build_context.metrics.os == TargetOs_windows) { return ProcCC_StdCall; } return ProcCC_CDecl; } + + return ProcCC_Invalid; } diff --git a/src/parser.hpp b/src/parser.hpp index ff0df0382..9e93f4b26 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -249,12 +249,30 @@ enum ProcCallingConvention : i32 { ProcCC_InlineAsm = 8, + ProcCC_Win64 = 9, + ProcCC_SysV = 10, + + ProcCC_MAX, ProcCC_ForeignBlockDefault = -1, }; +char const *proc_calling_convention_strings[ProcCC_MAX] = { + "", + "odin", + "contextless", + "cdecl", + "stdcall", + "fastcall", + "none", + "naked", + "inlineasm", + "win64", + "sysv", +}; + ProcCallingConvention default_calling_convention(void) { return ProcCC_Odin; }