From a64ea342df4cffa881b5829b8864e22fb9e116ab Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 12 Nov 2020 23:40:13 +0000 Subject: Improve USE_NEW_LLVM_ABI_SYSTEM's System V ABI --- src/llvm_backend.cpp | 160 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 125 insertions(+), 35 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index a01dd7ede..fbddb893e 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1380,7 +1380,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { LLVMTypeRef *params = gb_alloc_array(heap_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, type->Proc.results); + ret = lb_type(m, single_ret); if (ret != nullptr) { if (is_calling_convention_none(type->Proc.calling_convention) && is_type_boolean(single_ret) && @@ -1399,13 +1399,15 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { continue; } + Type *e_type = reduce_tuple_to_single_type(e->type); + LLVMTypeRef param_type = nullptr; if (is_calling_convention_none(type->Proc.calling_convention) && - is_type_boolean(e->type) && - type_size_of(e->type) <= 1) { + is_type_boolean(e_type) && + type_size_of(e_type) <= 1) { param_type = LLVMInt1TypeInContext(m->ctx); } else { - param_type = lb_type(m, e->type); + param_type = lb_type(m, e_type); } params[param_index++] = param_type; } @@ -2511,7 +2513,13 @@ void lb_start_block(lbProcedure *p, lbBlock *b) { LLVMValueRef OdinLLVMBuildTransmute(lbProcedure *p, LLVMValueRef val, LLVMTypeRef dst_type) { LLVMTypeRef src_type = LLVMTypeOf(val); - GB_ASSERT(lb_sizeof(src_type) == lb_sizeof(dst_type)); + i64 src_size = lb_sizeof(src_type); + i64 dst_size = lb_sizeof(dst_type); + if (src_size != dst_size && (lb_is_type_kind(src_type, LLVMVectorTypeKind) ^ lb_is_type_kind(dst_type, LLVMVectorTypeKind))) { + // Okay + } else { + GB_ASSERT_MSG(src_size == dst_size, "%s == %s", LLVMPrintTypeToString(src_type), LLVMPrintTypeToString(dst_type)); + } LLVMTypeKind src_kind = LLVMGetTypeKind(src_type); LLVMTypeKind dst_kind = LLVMGetTypeKind(dst_type); @@ -4538,27 +4546,51 @@ void lb_build_stmt(lbProcedure *p, Ast *node) { } - if (p->type->Proc.return_by_pointer) { - if (res.value != nullptr) { - lb_addr_store(p, p->return_ptr, res); + if (p->abi_function_type) { + if (p->abi_function_type->ret.kind == lbArg_Indirect) { + if (res.value != nullptr) { + LLVMBuildStore(p->builder, res.value, p->return_ptr.addr.value); + } else { + LLVMBuildStore(p->builder, LLVMConstNull(p->abi_function_type->ret.type), p->return_ptr.addr.value); + } + + lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); + + LLVMBuildRetVoid(p->builder); } else { - lb_addr_store(p, p->return_ptr, lb_const_nil(p->module, p->type->Proc.abi_compat_result_type)); + LLVMValueRef ret_val = res.value; + if (p->abi_function_type->ret.cast_type != nullptr) { + ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.cast_type); + } + lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); + LLVMBuildRet(p->builder, ret_val); } + } else { + GB_ASSERT(!USE_LLVM_ABI); - lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); + if (p->type->Proc.return_by_pointer) { + if (res.value != nullptr) { + lb_addr_store(p, p->return_ptr, res); + } else { + lb_addr_store(p, p->return_ptr, lb_const_nil(p->module, p->type->Proc.abi_compat_result_type)); + } - LLVMBuildRetVoid(p->builder); - } else { - GB_ASSERT_MSG(res.value != nullptr, "%.*s", LIT(p->name)); - Type *abi_rt = p->type->Proc.abi_compat_result_type; - if (!are_types_identical(res.type, abi_rt)) { - res = lb_emit_transmute(p, res, abi_rt); - } + lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); - lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); + LLVMBuildRetVoid(p->builder); + } else { + GB_ASSERT_MSG(res.value != nullptr, "%.*s", LIT(p->name)); - LLVMBuildRet(p->builder, res.value); + Type *abi_rt = p->type->Proc.abi_compat_result_type; + if (!are_types_identical(res.type, abi_rt)) { + res = lb_emit_transmute(p, res, abi_rt); + } + lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); + LLVMBuildRet(p->builder, res.value); + } } + + case_end; case_ast_node(is, IfStmt, node); @@ -6585,8 +6617,6 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { return res; } - - // []byte/[]u8 <-> string if (is_type_u8_slice(src) && is_type_string(dst)) { return lb_emit_transmute(p, value, t); @@ -6636,6 +6666,34 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { return lb_addr_load(p, result); } + + i64 src_sz = type_size_of(src); + i64 dst_sz = type_size_of(dst); + + if (src_sz == dst_sz) { + // bit_set <-> integer + if (is_type_integer(src) && is_type_bit_set(dst)) { + lbValue res = lb_emit_conv(p, value, bit_set_to_int(dst)); + res.type = dst; + return res; + } + if (is_type_bit_set(src) && is_type_integer(dst)) { + lbValue bs = value; + bs.type = bit_set_to_int(src); + return lb_emit_conv(p, bs, dst); + } + + // typeid <-> integer + if (is_type_integer(src) && is_type_typeid(dst)) { + return lb_emit_transmute(p, value, dst); + } + if (is_type_typeid(src) && is_type_integer(dst)) { + return lb_emit_transmute(p, value, dst); + } + } + + + if (is_type_untyped(src)) { if (is_type_string(src) && is_type_string(dst)) { lbAddr result = lb_add_local_generated(p, t, false); @@ -6716,6 +6774,14 @@ lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t) { i64 sz = type_size_of(src); i64 dz = type_size_of(dst); + if (sz != dz) { + LLVMTypeRef s = lb_type(m, src); + LLVMTypeRef d = lb_type(m, dst); + i64 llvm_sz = lb_sizeof(s); + i64 llvm_dz = lb_sizeof(d); + GB_ASSERT_MSG(llvm_sz == llvm_dz, "%s %s", LLVMPrintTypeToString(s), LLVMPrintTypeToString(d)); + } + GB_ASSERT_MSG(sz == dz, "Invalid transmute conversion: '%s' to '%s'", type_to_string(src_type), type_to_string(t)); // NOTE(bill): Casting between an integer and a pointer cannot be done through a bitcast @@ -7353,8 +7419,8 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, } GB_ASSERT(ft_found != nullptr); - lbFunctionType *abi_ft = *ft_found; - bool return_by_pointer = abi_ft->ret.kind == lbArg_Indirect; + lbFunctionType *ft = *ft_found; + bool return_by_pointer = ft->ret.kind == lbArg_Indirect; unsigned param_index = 0; for (isize i = 0; i < param_count; i++) { @@ -7365,7 +7431,7 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, GB_ASSERT(e->flags & EntityFlag_Param); Type *original_type = e->type; - lbArgType *arg = &abi_ft->args[param_index]; + lbArgType *arg = &ft->args[param_index]; if (arg->kind == lbArg_Ignore) { continue; } @@ -7381,9 +7447,15 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, if (xt == abi_type) { array_add(&processed_args, x); } else { - Type *at = lb_abi_to_odin_type(abi_type); + Type *at = lb_abi_to_odin_type(abi_type, false); if (at == t_llvm_bool) { x = lb_emit_conv(p, x, at); + } else if (is_type_simd_vector(at) && lb_sizeof(abi_type) > lb_sizeof(xt)) { + lbAddr v = lb_add_local_generated(p, at, false); + lbValue ptr = lb_addr_get_ptr(p, v); + ptr = lb_emit_conv(p, ptr, alloc_type_pointer(x.type)); + lb_emit_store(p, ptr, x); + x = lb_addr_load(p, v); } else { x = lb_emit_transmute(p, x, at); } @@ -7420,16 +7492,27 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, GB_ASSERT(is_type_pointer(return_ptr.type)); lb_emit_call_internal(p, value, return_ptr, processed_args, nullptr, context_ptr, inlining); result = lb_emit_load(p, return_ptr); - } else { - LLVMTypeRef ret_type = abi_ft->ret.cast_type; + } else if (rt != nullptr) { + LLVMTypeRef ret_type = ft->ret.cast_type; if (!ret_type) { - ret_type = abi_ft->ret.type; + ret_type = ft->ret.type; } - Type *abi_rt = lb_abi_to_odin_type(ret_type); + Type *abi_rt = lb_abi_to_odin_type(ret_type, true); result = lb_emit_call_internal(p, value, {}, processed_args, abi_rt, context_ptr, inlining); - if (abi_rt != rt) { - result = lb_emit_transmute(p, result, rt); + if (ret_type != lb_type(m, rt)) { + if (is_type_simd_vector(abi_rt) && lb_sizeof(ret_type) > type_size_of(rt)) { + lbValue ptr = lb_address_from_load_or_generate_local(p, result); + ptr = lb_emit_conv(p, ptr, alloc_type_pointer(rt)); + result = lb_emit_load(p, ptr); + } else { + result = lb_emit_transmute(p, result, rt); + } } + if (!is_type_tuple(rt)) { + result = lb_emit_conv(p, result, rt); + } + } else { + lb_emit_call_internal(p, value, {}, processed_args, nullptr, context_ptr, inlining); } } else { @@ -12856,6 +12939,10 @@ void lb_generate_code(lbGenerator *gen) { LLVMRunFunctionPassManager(default_function_pass_manager, p->value); } + + String filepath_ll = concatenate_strings(heap_allocator(), gen->output_base, STR_LIT(".ll")); + defer (gb_free(heap_allocator(), filepath_ll.text)); + TIME_SECTION("LLVM Procedure Generation"); for_array(i, m->procedures_to_generate) { lbProcedure *p = m->procedures_to_generate[i]; @@ -12886,7 +12973,11 @@ void lb_generate_code(lbGenerator *gen) { gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name)); LLVMDumpValue(p->value); gb_printf_err("\n\n\n\n"); - LLVMVerifyFunction(p->value, LLVMAbortProcessAction); + if (LLVMPrintModuleToFile(mod, cast(char const *)filepath_ll.text, &llvm_error)) { + gb_printf_err("LLVM Error: %s\n", llvm_error); + } + LLVMVerifyFunction(p->value, LLVMPrintMessageAction); + gb_exit(1); } } @@ -12933,9 +13024,6 @@ void lb_generate_code(lbGenerator *gen) { llvm_error = nullptr; defer (LLVMDisposeMessage(llvm_error)); - String filepath_ll = concatenate_strings(heap_allocator(), gen->output_base, STR_LIT(".ll")); - defer (gb_free(heap_allocator(), filepath_ll.text)); - String filepath_obj = {}; LLVMCodeGenFileType code_gen_file_type = LLVMObjectFile; @@ -12962,6 +13050,7 @@ void lb_generate_code(lbGenerator *gen) { LLVMDIBuilderFinalize(m->debug_builder); if (LLVMVerifyModule(mod, LLVMAbortProcessAction, &llvm_error)) { gb_printf_err("LLVM Error: %s\n", llvm_error); + gb_exit(1); return; } llvm_error = nullptr; @@ -12969,6 +13058,7 @@ void lb_generate_code(lbGenerator *gen) { TIME_SECTION("LLVM Print Module to File"); if (LLVMPrintModuleToFile(mod, cast(char const *)filepath_ll.text, &llvm_error)) { gb_printf_err("LLVM Error: %s\n", llvm_error); + gb_exit(1); return; } } -- cgit v1.2.3