diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 64b2ac5f3..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) { - OdinLLVMBuildCall(p, {startup_type_info->value, startup_type_info->type}, 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) { - OdinLLVMBuildCall(p, {objc_names->value, objc_names->type}, 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) { @@ -780,10 +780,6 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start var->init = init; } else if (lb_is_const_or_global(init)) { if (!var->is_initialized) { - if (is_type_proc(init.type)) { - LLVMTypeRef global_type = llvm_addr_type(p->module, var->var); - init.value = LLVMConstPointerCast(init.value, global_type); - } LLVMSetInitializer(var->var.value, init.value); var->is_initialized = true; continue; @@ -1653,10 +1649,6 @@ void lb_generate_code(lbGenerator *gen) { if (tav.value.kind != ExactValue_Invalid) { ExactValue v = tav.value; lbValue init = lb_const_value(m, tav.type, v); - if (is_type_proc(init.type)) { - LLVMTypeRef global_type = llvm_addr_type(m, var.var); - init.value = LLVMConstPointerCast(init.value, global_type); - } LLVMSetInitializer(g.value, init.value); var.is_initialized = true; } diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 98bfb841a..071986458 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -854,6 +854,46 @@ void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { lb_emit_store(p, addr.addr, value); } +void lb_const_store(lbValue ptr, lbValue value) { + GB_ASSERT(lb_is_const(ptr)); + GB_ASSERT(lb_is_const(value)); + GB_ASSERT(is_type_pointer(ptr.type)); + LLVMSetInitializer(ptr.value, value.value); +} + + +bool lb_is_type_proc_recursive(Type *t) { + for (;;) { + if (t == nullptr) { + return false; + } + switch (t->kind) { + case Type_Named: + t = t->Named.base; + break; + case Type_Pointer: + t = t->Pointer.elem; + break; + case Type_Array: + t = t->Array.elem; + break; + case Type_EnumeratedArray: + t = t->EnumeratedArray.elem; + break; + case Type_Slice: + t = t->Slice.elem; + break; + case Type_DynamicArray: + t = t->DynamicArray.elem; + break; + case Type_Proc: + return true; + default: + return false; + } + } +} + void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) { GB_ASSERT(value.value != nullptr); Type *a = type_deref(ptr.type); @@ -913,7 +953,7 @@ void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) { } } - if (is_type_proc(a)) { + if (lb_is_type_proc_recursive(a)) { // NOTE(bill, 2020-11-11): Because of certain LLVM rules, a procedure value may be // stored as regular pointer with no procedure information @@ -1511,7 +1551,7 @@ LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *type) { 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) { + type_size_of(e_type) <= 1) { param_type = LLVMInt1TypeInContext(m->ctx); } else { if (is_type_proc(e_type)) { @@ -2058,13 +2098,15 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { } case Type_Proc: - { - // NOTE(bill): we do an explicit cast to the correct procedure type when calling the procedure + // if (m->internal_type_level > 256) { // TODO HACK(bill): is this really enough? + if (m->internal_type_level > 1) { // TODO HACK(bill): is this really enough? + return LLVMPointerType(LLVMIntTypeInContext(m->ctx, 8), 0); + } else { LLVMTypeRef proc_raw_type = lb_type_internal_for_procedures_raw(m, type); - gb_unused(proc_raw_type); - return lb_type(m, t_rawptr); + return LLVMPointerType(proc_raw_type, 0); } + break; case Type_BitSet: { Type *ut = bit_set_to_int(type); diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 784366476..bdb562884 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1,11 +1,6 @@ -LLVMValueRef OdinLLVMBuildCall(lbProcedure *p, lbValue const &value, LLVMValueRef *args, unsigned arg_count) { - GB_ASSERT(is_type_proc(value.type)); - LLVMTypeRef type = lb_type_internal_for_procedures_raw(p->module, value.type); - LLVMValueRef func = LLVMBuildPointerCast(p->builder, value.value, LLVMPointerType(type, 0), ""); - return LLVMBuildCall2(p->builder, type, func, args, arg_count, ""); -} -LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLVMValueRef* args, unsigned arg_count, LLVMTypeRef* types, unsigned type_count) { +LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLVMValueRef* args, unsigned arg_count, LLVMTypeRef* types, unsigned type_count) +{ unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name)); GB_ASSERT_MSG(id != 0, "Unable to find %s", name); LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, type_count); @@ -745,11 +740,6 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr, } for_array(i, processed_args) { lbValue arg = processed_args[i]; - if (is_type_proc(arg.type)) { - // NOTE(bill): all procedure types (function pointers) are typed as if they are `rawptr` - // and then the correct type is set at the call site - arg.value = LLVMBuildPointerCast(p->builder, arg.value, lb_type(p->module, arg.type), ""); - } args[arg_index++] = arg.value; } if (context_ptr.addr.value != nullptr) { @@ -762,7 +752,11 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr, { 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, ""); + } GB_ASSERT_MSG(lb_is_type_kind(fnp, LLVMFunctionTypeKind), "%s", LLVMPrintTypeToString(fnp)); { @@ -786,7 +780,7 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr, } } - LLVMValueRef ret = OdinLLVMBuildCall(p, value, args, arg_count); + LLVMValueRef ret = LLVMBuildCall2(p->builder, fnp, fn, args, arg_count, ""); if (return_ptr.value != nullptr) { LLVMAddCallSiteAttribute(ret, 1, lb_create_enum_attribute_with_type(p->module->ctx, "sret", LLVMTypeOf(args[0]))); diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index c29713881..d424fa5b2 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -554,6 +554,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue index = lb_const_int(m, t_int, i); lbValue type_info = lb_emit_ptr_offset(p, memory_types, index); + // TODO(bill): Make this constant if possible, 'lb_const_store' does not work lb_emit_store(p, type_info, lb_type_info(m, f->type)); if (f->token.string.len > 0) { lbValue name = lb_emit_ptr_offset(p, memory_names, index);