From 2b27300387030c635acee783a2e573960ae3f748 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 22 Jun 2020 16:57:21 +0100 Subject: [PATCH] Fix LLVM code gen bug --- core/runtime/core.odin | 2 +- src/check_expr.cpp | 4 ++-- src/check_type.cpp | 3 +-- src/ir.cpp | 24 +++++++++++++++++------- src/llvm_backend.cpp | 27 +++++++++++++++++++-------- 5 files changed, 40 insertions(+), 20 deletions(-) diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 5cad2d5cd..105b2bde6 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -426,7 +426,7 @@ typeid_base_without_enum :: typeid_core; -@(default_calling_convention = "c") +@(default_calling_convention = "none") foreign { @(link_name="llvm.assume") assume :: proc(cond: bool) ---; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index fa25fd899..a2b7bb057 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -58,7 +58,7 @@ ExprKind check_expr_base (CheckerContext *c, Operand *operand, As void check_expr_with_type_hint (CheckerContext *c, Operand *o, Ast *e, Type *t); Type * check_type (CheckerContext *c, Ast *expression); Type * check_type_expr (CheckerContext *c, Ast *expression, Type *named_type); -Type * make_optional_ok_type (Type *value); +Type * make_optional_ok_type (Type *value, bool typed=true); void check_type_decl (CheckerContext *c, Entity *e, Ast *type_expr, Type *def); Entity * check_selector (CheckerContext *c, Operand *operand, Ast *node, Type *type_hint); Entity * check_ident (CheckerContext *c, Operand *o, Ast *n, Type *named_type, Type *type_hint, bool allow_import_name); @@ -5532,7 +5532,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 check_assignment(c, &y, elem, builtin_name); operand->mode = Addressing_Value; - operand->type = make_optional_ok_type(elem); + operand->type = make_optional_ok_type(elem, /*typed*/false); break; } break; diff --git a/src/check_type.cpp b/src/check_type.cpp index d826860a6..61ad34133 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2683,10 +2683,9 @@ i64 check_array_count(CheckerContext *ctx, Operand *o, Ast *e) { return 0; } -Type *make_optional_ok_type(Type *value) { +Type *make_optional_ok_type(Type *value, bool typed) { // LEAK TODO(bill): probably don't reallocate everything here and reuse the same one for the same type if possible gbAllocator a = heap_allocator(); - bool typed = true; Type *t = alloc_type_tuple(); array_init(&t->Tuple.variables, a, 0, 2); array_add (&t->Tuple.variables, alloc_entity_field(nullptr, blank_token, value, false, 0)); diff --git a/src/ir.cpp b/src/ir.cpp index d6b6f49cd..923837293 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -976,9 +976,14 @@ irValue *ir_value_param(irProcedure *parent, Entity *e, Type *abi_type, i32 inde if (e != nullptr && abi_type != e->type) { if (is_type_pointer(abi_type)) { GB_ASSERT(e->kind == Entity_Variable); - v->Param.kind = irParamPass_Pointer; - if (e->flags&EntityFlag_Value) { - v->Param.kind = irParamPass_ConstRef; + Type *av = type_deref(abi_type); + if (are_types_identical(abi_type, e->type)) { + v->Param.kind = irParamPass_Pointer; + if (e->flags&EntityFlag_Value) { + v->Param.kind = irParamPass_ConstRef; + } + } else { + v->Param.kind = irParamPass_BitCast; } } else if (is_type_integer(abi_type)) { v->Param.kind = irParamPass_Integer; @@ -3241,10 +3246,15 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, Array const &ar array_add(&processed_args, args[i]); } else if (!are_types_identical(original_type, new_type)) { if (is_type_pointer(new_type) && !is_type_pointer(original_type)) { - if (e->flags&EntityFlag_ImplicitReference) { - array_add(&processed_args, ir_address_from_load_or_generate_local(p, args[i])); - } else if (!is_type_pointer(arg_type)) { - array_add(&processed_args, ir_copy_value_to_ptr(p, args[i], original_type, 16)); + Type *av = type_deref(new_type); + if (are_types_identical(av, original_type)) { + if (e->flags&EntityFlag_ImplicitReference) { + array_add(&processed_args, ir_address_from_load_or_generate_local(p, args[i])); + } else if (!is_type_pointer(arg_type)) { + array_add(&processed_args, ir_copy_value_to_ptr(p, args[i], original_type, 16)); + } + } else { + array_add(&processed_args, ir_emit_transmute(p, args[i], new_type)); } } else if (is_type_integer(new_type) || is_type_float(new_type)) { array_add(&processed_args, ir_emit_transmute(p, args[i], new_type)); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index d24f40040..050bff9e3 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2270,12 +2270,17 @@ lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name, Type *type lbValue lb_value_param(lbProcedure *p, Entity *e, Type *abi_type, i32 index, lbParamPasskind *kind_) { lbParamPasskind kind = lbParamPass_Value; - if (e != nullptr && abi_type != e->type) { + if (e != nullptr && !are_types_identical(abi_type, e->type)) { if (is_type_pointer(abi_type)) { GB_ASSERT(e->kind == Entity_Variable); - kind = lbParamPass_Pointer; - if (e->flags&EntityFlag_Value) { - kind = lbParamPass_ConstRef; + Type *av = type_deref(abi_type); + if (are_types_identical(av, e->type)) { + kind = lbParamPass_Pointer; + if (e->flags&EntityFlag_Value) { + kind = lbParamPass_ConstRef; + } + } else { + kind = lbParamPass_BitCast; } } else if (is_type_integer(abi_type)) { kind = lbParamPass_Integer; @@ -2364,6 +2369,7 @@ lbValue lb_add_param(lbProcedure *p, Entity *e, Ast *expr, Type *abi_type, i32 i } + GB_PANIC("Unreachable"); return {}; } @@ -7035,10 +7041,15 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, array_add(&processed_args, args[i]); } else if (!are_types_identical(original_type, new_type)) { if (is_type_pointer(new_type) && !is_type_pointer(original_type)) { - if (e->flags&EntityFlag_ImplicitReference) { - array_add(&processed_args, lb_address_from_load_or_generate_local(p, args[i])); - } else if (!is_type_pointer(arg_type)) { - array_add(&processed_args, lb_copy_value_to_ptr(p, args[i], original_type, 16)); + Type *av = type_deref(new_type); + if (are_types_identical(av, arg_type)) { + if (e->flags&EntityFlag_ImplicitReference) { + array_add(&processed_args, lb_address_from_load_or_generate_local(p, args[i])); + } else if (!is_type_pointer(arg_type)) { + array_add(&processed_args, lb_copy_value_to_ptr(p, args[i], original_type, 16)); + } + } else { + array_add(&processed_args, lb_emit_transmute(p, args[i], new_type)); } } else if (new_type == t_llvm_bool) { array_add(&processed_args, lb_emit_conv(p, args[i], new_type));