From cb0a59bb2cfdeb971e88f329f07783ba1f93a5c9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Aug 2022 15:36:18 +0100 Subject: [PATCH] Eliminate use of LLVMGetElementType for pointers --- core/log/log_allocator.odin | 31 ++++-- src/llvm_abi.cpp | 10 +- src/llvm_backend.cpp | 4 +- src/llvm_backend.hpp | 5 +- src/llvm_backend_expr.cpp | 2 +- src/llvm_backend_general.cpp | 210 +++++++++++++++++++---------------- src/llvm_backend_proc.cpp | 14 +-- src/llvm_backend_type.cpp | 10 +- src/llvm_backend_utility.cpp | 4 +- 9 files changed, 164 insertions(+), 126 deletions(-) diff --git a/core/log/log_allocator.odin b/core/log/log_allocator.odin index eb7a6b377..997bd1a68 100644 --- a/core/log/log_allocator.odin +++ b/core/log/log_allocator.odin @@ -29,6 +29,8 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode, old_memory: rawptr, old_size: int, location := #caller_location) -> ([]byte, runtime.Allocator_Error) { la := (^Log_Allocator)(allocator_data) + padding := " " if la.prefix != "" else "" + if !la.locked { la.locked = true defer la.locked = false @@ -38,7 +40,7 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode, logf( level=la.level, fmt_str = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)", - args = {la.prefix, " " if la.prefix != "" else "", size, alignment}, + args = {la.prefix, padding, size, alignment}, location = location, ) case .Free: @@ -46,14 +48,14 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode, logf( level=la.level, fmt_str = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)", - args = {la.prefix, " " if la.prefix != "" else "", old_memory, old_size}, + args = {la.prefix, padding, old_memory, old_size}, location = location, ) } else { logf( level=la.level, fmt_str = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)", - args = {la.prefix, " " if la.prefix != "" else "", old_memory}, + args = {la.prefix, padding, old_memory}, location = location, ) } @@ -61,32 +63,45 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode, logf( level=la.level, fmt_str = "%s%s<<< ALLOCATOR(mode=.Free_All)", - args = {la.prefix, " " if la.prefix != "" else ""}, + args = {la.prefix, padding}, location = location, ) case .Resize: logf( level=la.level, fmt_str = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)", - args = {la.prefix, " " if la.prefix != "" else "", old_memory, old_size, size, alignment}, + args = {la.prefix, padding, old_memory, old_size, size, alignment}, location = location, ) case .Query_Features: logf( level=la.level, fmt_str = "%s%ALLOCATOR(mode=.Query_Features)", - args = {la.prefix, " " if la.prefix != "" else ""}, + args = {la.prefix, padding}, location = location, ) case .Query_Info: logf( level=la.level, fmt_str = "%s%ALLOCATOR(mode=.Query_Info)", - args = {la.prefix, " " if la.prefix != "" else ""}, + args = {la.prefix, padding}, location = location, ) } } - return la.allocator.procedure(la.allocator.data, mode, size, alignment, old_memory, old_size, location) + data, err := la.allocator.procedure(la.allocator.data, mode, size, alignment, old_memory, old_size, location) + if !la.locked { + la.locked = true + defer la.locked = false + if err != nil { + logf( + level=la.level, + fmt_str = "%s%ALLOCATOR ERROR=%v", + args = {la.prefix, padding, error}, + location = location, + ) + } + } + return data, err } \ No newline at end of file diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index b22a839b3..2ff55c79b 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -62,7 +62,7 @@ bool lb_is_type_kind(LLVMTypeRef type, LLVMTypeKind kind) { return LLVMGetTypeKind(type) == kind; } -LLVMTypeRef lb_function_type_to_llvm_ptr(lbFunctionType *ft, bool is_var_arg) { +LLVMTypeRef lb_function_type_to_llvm_raw(lbFunctionType *ft, bool is_var_arg) { unsigned arg_count = cast(unsigned)ft->args.count; unsigned offset = 0; @@ -108,10 +108,16 @@ LLVMTypeRef lb_function_type_to_llvm_ptr(lbFunctionType *ft, bool is_var_arg) { } unsigned total_arg_count = arg_index; LLVMTypeRef func_type = LLVMFunctionType(ret, args, total_arg_count, is_var_arg); - return LLVMPointerType(func_type, 0); + return func_type; } +// LLVMTypeRef lb_function_type_to_llvm_ptr(lbFunctionType *ft, bool is_var_arg) { +// LLVMTypeRef func_type = lb_function_type_to_llvm_raw(ft, is_var_arg); +// return LLVMPointerType(func_type, 0); +// } + + void lb_add_function_type_attributes(LLVMValueRef fn, lbFunctionType *ft, ProcCallingConvention calling_convention) { if (ft == nullptr) { return; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index bcd11c8ea..6ee1541d6 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -739,11 +739,11 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start lb_begin_procedure_body(p); if (startup_type_info) { - LLVMBuildCall2(p->builder, lb_llvm_get_pointer_type(lb_type(main_module, startup_type_info->type)), startup_type_info->value, nullptr, 0, ""); + LLVMBuildCall2(p->builder, lb_type_internal_for_procedures_raw(main_module, startup_type_info->type), startup_type_info->value, nullptr, 0, ""); } if (objc_names) { - LLVMBuildCall2(p->builder, lb_llvm_get_pointer_type(lb_type(main_module, objc_names->type)), objc_names->value, nullptr, 0, ""); + LLVMBuildCall2(p->builder, lb_type_internal_for_procedures_raw(main_module, objc_names->type), objc_names->value, nullptr, 0, ""); } for_array(i, global_variables) { diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 05dfb3734..149f1e711 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -127,6 +127,7 @@ struct lbModule { AstPackage *pkg; // associated PtrMap types; + PtrMap func_raw_types; PtrMap struct_field_remapping; // Key: LLVMTypeRef or Type * i32 internal_type_level; @@ -330,7 +331,8 @@ lbProcedure *lb_create_procedure(lbModule *module, Entity *entity, bool ignore_b void lb_end_procedure(lbProcedure *p); -LLVMTypeRef lb_type(lbModule *m, Type *type); +LLVMTypeRef lb_type(lbModule *m, Type *type); +LLVMTypeRef llvm_get_element_type(LLVMTypeRef type); lbBlock *lb_create_block(lbProcedure *p, char const *name, bool append=false); @@ -343,7 +345,6 @@ lbValue lb_const_int(lbModule *m, Type *type, u64 value); lbAddr lb_addr(lbValue addr); Type *lb_addr_type(lbAddr const &addr); -LLVMTypeRef lb_llvm_get_pointer_type(LLVMTypeRef type); LLVMTypeRef llvm_addr_type(lbModule *module, lbValue addr_val); void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value); lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 4ae46aeb8..7568f975e 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3345,7 +3345,7 @@ lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) { default: GB_PANIC("Unhandled inline asm dialect"); break; } - LLVMTypeRef func_type = lb_llvm_get_pointer_type(lb_type(p->module, t)); + LLVMTypeRef func_type = lb_type_internal_for_procedures_raw(p->module, t); LLVMValueRef the_asm = llvm_get_inline_asm(func_type, asm_string, constraints_string, ia->has_side_effects, ia->has_side_effects, dialect); GB_ASSERT(the_asm != nullptr); return {the_asm, t}; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index b212ee8b8..eb5cf371c 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -56,6 +56,7 @@ void lb_init_module(lbModule *m, Checker *c) { gbAllocator a = heap_allocator(); map_init(&m->types, a); + map_init(&m->func_raw_types, a); map_init(&m->struct_field_remapping, a); map_init(&m->values, a); map_init(&m->soa_values, a); @@ -1416,6 +1417,116 @@ String lb_get_entity_name(lbModule *m, Entity *e, String default_name) { } +LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *type) { + Type *original_type = type; + type = base_type(original_type); + GB_ASSERT(type->kind == Type_Proc); + + LLVMTypeRef *found = map_get(&m->func_raw_types, type); + if (found) { + return *found; + } + + unsigned param_count = 0; + if (type->Proc.calling_convention == ProcCC_Odin) { + param_count += 1; + } + + if (type->Proc.param_count != 0) { + GB_ASSERT(type->Proc.params->kind == Type_Tuple); + for_array(i, type->Proc.params->Tuple.variables) { + Entity *e = type->Proc.params->Tuple.variables[i]; + if (e->kind != Entity_Variable) { + continue; + } + if (e->flags & EntityFlag_CVarArg) { + continue; + } + param_count += 1; + } + } + m->internal_type_level += 1; + defer (m->internal_type_level -= 1); + + LLVMTypeRef ret = nullptr; + LLVMTypeRef *params = gb_alloc_array(permanent_allocator(), LLVMTypeRef, param_count); + if (type->Proc.result_count != 0) { + Type *single_ret = reduce_tuple_to_single_type(type->Proc.results); + ret = lb_type(m, single_ret); + if (ret != nullptr) { + if (is_type_boolean(single_ret) && + is_calling_convention_none(type->Proc.calling_convention) && + type_size_of(single_ret) <= 1) { + ret = LLVMInt1TypeInContext(m->ctx); + } + } + } + + unsigned param_index = 0; + if (type->Proc.param_count != 0) { + GB_ASSERT(type->Proc.params->kind == Type_Tuple); + for_array(i, type->Proc.params->Tuple.variables) { + Entity *e = type->Proc.params->Tuple.variables[i]; + if (e->kind != Entity_Variable) { + continue; + } + if (e->flags & EntityFlag_CVarArg) { + continue; + } + Type *e_type = reduce_tuple_to_single_type(e->type); + + LLVMTypeRef param_type = nullptr; + if (e->flags & EntityFlag_ByPtr) { + param_type = lb_type(m, alloc_type_pointer(e_type)); + } else if (is_type_boolean(e_type) && + type_size_of(e_type) <= 1) { + param_type = LLVMInt1TypeInContext(m->ctx); + } else { + if (is_type_proc(e_type)) { + param_type = lb_type(m, t_rawptr); + } else { + param_type = lb_type(m, e_type); + } + } + + params[param_index++] = param_type; + } + } + if (param_index < param_count) { + params[param_index++] = lb_type(m, t_rawptr); + } + GB_ASSERT(param_index == param_count); + + lbFunctionType *ft = lb_get_abi_info(m->ctx, params, param_count, ret, ret != nullptr, type->Proc.calling_convention); + { + for_array(j, ft->args) { + auto arg = ft->args[j]; + GB_ASSERT_MSG(LLVMGetTypeContext(arg.type) == ft->ctx, + "\n\t%s %td/%td" + "\n\tArgTypeCtx: %p\n\tCurrentCtx: %p\n\tGlobalCtx: %p", + LLVMPrintTypeToString(arg.type), + j, ft->args.count, + LLVMGetTypeContext(arg.type), ft->ctx, LLVMGetGlobalContext()); + } + GB_ASSERT_MSG(LLVMGetTypeContext(ft->ret.type) == ft->ctx, + "\n\t%s" + "\n\tRetTypeCtx: %p\n\tCurrentCtx: %p\n\tGlobalCtx: %p", + LLVMPrintTypeToString(ft->ret.type), + LLVMGetTypeContext(ft->ret.type), ft->ctx, LLVMGetGlobalContext()); + } + + map_set(&m->function_type_map, type, ft); + LLVMTypeRef new_abi_fn_type = lb_function_type_to_llvm_raw(ft, type->Proc.c_vararg); + + GB_ASSERT_MSG(LLVMGetTypeContext(new_abi_fn_type) == m->ctx, + "\n\tFuncTypeCtx: %p\n\tCurrentCtx: %p\n\tGlobalCtx: %p", + LLVMGetTypeContext(new_abi_fn_type), m->ctx, LLVMGetGlobalContext()); + + map_set(&m->func_raw_types, type, new_abi_fn_type); + + return new_abi_fn_type; + +} LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { LLVMContextRef ctx = m->ctx; i64 size = type_size_of(type); // Check size @@ -1919,103 +2030,8 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { if (m->internal_type_level > 1) { // TODO HACK(bill): is this really enough? return LLVMPointerType(LLVMIntTypeInContext(m->ctx, 8), 0); } else { - unsigned param_count = 0; - if (type->Proc.calling_convention == ProcCC_Odin) { - param_count += 1; - } - - if (type->Proc.param_count != 0) { - GB_ASSERT(type->Proc.params->kind == Type_Tuple); - for_array(i, type->Proc.params->Tuple.variables) { - Entity *e = type->Proc.params->Tuple.variables[i]; - if (e->kind != Entity_Variable) { - continue; - } - if (e->flags & EntityFlag_CVarArg) { - continue; - } - param_count += 1; - } - } - m->internal_type_level += 1; - defer (m->internal_type_level -= 1); - - LLVMTypeRef ret = nullptr; - LLVMTypeRef *params = gb_alloc_array(permanent_allocator(), LLVMTypeRef, param_count); - if (type->Proc.result_count != 0) { - Type *single_ret = reduce_tuple_to_single_type(type->Proc.results); - ret = lb_type(m, single_ret); - if (ret != nullptr) { - if (is_type_boolean(single_ret) && - is_calling_convention_none(type->Proc.calling_convention) && - type_size_of(single_ret) <= 1) { - ret = LLVMInt1TypeInContext(m->ctx); - } - } - } - - unsigned param_index = 0; - if (type->Proc.param_count != 0) { - GB_ASSERT(type->Proc.params->kind == Type_Tuple); - for_array(i, type->Proc.params->Tuple.variables) { - Entity *e = type->Proc.params->Tuple.variables[i]; - if (e->kind != Entity_Variable) { - continue; - } - if (e->flags & EntityFlag_CVarArg) { - continue; - } - Type *e_type = reduce_tuple_to_single_type(e->type); - - LLVMTypeRef param_type = nullptr; - if (e->flags & EntityFlag_ByPtr) { - param_type = lb_type(m, alloc_type_pointer(e_type)); - } else if (is_type_boolean(e_type) && - type_size_of(e_type) <= 1) { - param_type = LLVMInt1TypeInContext(m->ctx); - } else { - if (is_type_proc(e_type)) { - param_type = lb_type(m, t_rawptr); - } else { - param_type = lb_type(m, e_type); - } - } - - params[param_index++] = param_type; - } - } - if (param_index < param_count) { - params[param_index++] = lb_type(m, t_rawptr); - } - GB_ASSERT(param_index == param_count); - - lbFunctionType *ft = lb_get_abi_info(m->ctx, params, param_count, ret, ret != nullptr, type->Proc.calling_convention); - { - for_array(j, ft->args) { - auto arg = ft->args[j]; - GB_ASSERT_MSG(LLVMGetTypeContext(arg.type) == ft->ctx, - "\n\t%s %td/%td" - "\n\tArgTypeCtx: %p\n\tCurrentCtx: %p\n\tGlobalCtx: %p", - LLVMPrintTypeToString(arg.type), - j, ft->args.count, - LLVMGetTypeContext(arg.type), ft->ctx, LLVMGetGlobalContext()); - } - GB_ASSERT_MSG(LLVMGetTypeContext(ft->ret.type) == ft->ctx, - "\n\t%s" - "\n\tRetTypeCtx: %p\n\tCurrentCtx: %p\n\tGlobalCtx: %p", - LLVMPrintTypeToString(ft->ret.type), - LLVMGetTypeContext(ft->ret.type), ft->ctx, LLVMGetGlobalContext()); - } - - map_set(&m->function_type_map, type, ft); - LLVMTypeRef new_abi_fn_ptr_type = lb_function_type_to_llvm_ptr(ft, type->Proc.c_vararg); - LLVMTypeRef new_abi_fn_type = lb_llvm_get_pointer_type(new_abi_fn_ptr_type); - - GB_ASSERT_MSG(LLVMGetTypeContext(new_abi_fn_type) == m->ctx, - "\n\tFuncTypeCtx: %p\n\tCurrentCtx: %p\n\tGlobalCtx: %p", - LLVMGetTypeContext(new_abi_fn_type), m->ctx, LLVMGetGlobalContext()); - - return new_abi_fn_ptr_type; + LLVMTypeRef proc_raw_type = lb_type_internal_for_procedures_raw(m, type); + return LLVMPointerType(proc_raw_type, 0); } break; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 756a93db7..392ff14c2 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -129,8 +129,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) } char *c_link_name = alloc_cstring(permanent_allocator(), p->name); - LLVMTypeRef func_ptr_type = lb_type(m, p->type); - LLVMTypeRef func_type = lb_llvm_get_pointer_type(func_ptr_type); + LLVMTypeRef func_type = lb_get_procedure_raw_type(m, p->type); p->value = LLVMAddFunction(m->mod, c_link_name, func_type); @@ -354,8 +353,7 @@ lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name, Type *type char *c_link_name = alloc_cstring(permanent_allocator(), p->name); - LLVMTypeRef func_ptr_type = lb_type(m, p->type); - LLVMTypeRef func_type = lb_llvm_get_pointer_type(func_ptr_type); + LLVMTypeRef func_type = lb_get_procedure_raw_type(m, p->type); p->value = LLVMAddFunction(m->mod, c_link_name, func_type); @@ -753,12 +751,12 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr, GB_ASSERT(curr_block != p->decl_block->block); { - LLVMTypeRef ftp = lb_type(p->module, value.type); + LLVMTypeRef fnp = lb_type_internal_for_procedures_raw(p->module, value.type); + LLVMTypeRef ftp = LLVMPointerType(fnp, 0); LLVMValueRef fn = value.value; if (!lb_is_type_kind(LLVMTypeOf(value.value), LLVMFunctionTypeKind)) { fn = LLVMBuildPointerCast(p->builder, fn, ftp, ""); } - LLVMTypeRef fnp = lb_llvm_get_pointer_type(LLVMTypeOf(fn)); GB_ASSERT_MSG(lb_is_type_kind(fnp, LLVMFunctionTypeKind), "%s", LLVMPrintTypeToString(fnp)); { @@ -2723,7 +2721,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, { Type *param_types[2] = {t_u32, t_u32}; Type *type = alloc_type_proc_from_types(param_types, gb_count_of(param_types), tv.type, false, ProcCC_None); - LLVMTypeRef func_type = lb_llvm_get_pointer_type(lb_type(p->module, type)); + LLVMTypeRef func_type = lb_get_procedure_raw_type(p->module, type); LLVMValueRef the_asm = llvm_get_inline_asm( func_type, str_lit("cpuid"), @@ -2743,7 +2741,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, case BuiltinProc_x86_xgetbv: { Type *type = alloc_type_proc_from_types(&t_u32, 1, tv.type, false, ProcCC_None); - LLVMTypeRef func_type = lb_llvm_get_pointer_type(lb_type(p->module, type)); + LLVMTypeRef func_type = lb_get_procedure_raw_type(p->module, type); LLVMValueRef the_asm = llvm_get_inline_asm( func_type, str_lit("xgetbv"), diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 10cae9e6c..ba4135901 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -130,12 +130,16 @@ lbValue lb_get_type_info_ptr(lbModule *m, Type *type) { return res; } -// The use of this method needs to be eliminated. -LLVMTypeRef lb_llvm_get_pointer_type(LLVMTypeRef type) -{ +// NOTE: The use of this method needs to be eliminated for pointers. +LLVMTypeRef llvm_get_element_type(LLVMTypeRef type) { return LLVMGetElementType(type); } +LLVMTypeRef lb_get_procedure_raw_type(lbModule *m, Type *type) { + return lb_type_internal_for_procedures_raw(m, type); +} + + lbValue lb_type_info_member_types_offset(lbProcedure *p, isize count) { GB_ASSERT(p->module == &p->module->gen->default_module); lbValue offset = lb_emit_array_epi(p, lb_global_type_info_member_types.addr, lb_global_type_info_member_types_index); diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index b6589a080..665ba1553 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -96,9 +96,7 @@ LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValu args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, ""); // We always get the function pointer type rather than the function and there is apparently no way around that? - LLVMTypeRef type = lb_type(p->module, pr.type); - - type = lb_llvm_get_pointer_type(type); + LLVMTypeRef type = lb_type_internal_for_procedures_raw(p->module, pr.type); return LLVMBuildCall2(p->builder, type, pr.value, args, gb_count_of(args), ""); }