aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-08-12 11:15:12 +0100
committergingerBill <bill@gingerbill.org>2022-08-12 11:15:12 +0100
commitde8bd88d2a6f0e99af6fe76442bcccd159724872 (patch)
treeab83528aaac33902e2fb085e4a503c96695f776c /src
parentc041d15569cb828565b462bc11543ddf6e85ceda (diff)
Clean up how procedures are typed in LLVM's dumb type system
Diffstat (limited to 'src')
-rw-r--r--src/llvm_backend.cpp4
-rw-r--r--src/llvm_backend_general.cpp47
-rw-r--r--src/llvm_backend_proc.cpp22
3 files changed, 22 insertions, 51 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 6ee1541d6..6eec9103b 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_type_internal_for_procedures_raw(main_module, startup_type_info->type), startup_type_info->value, nullptr, 0, "");
+ OdinLLVMBuildCall(p, {startup_type_info->value, startup_type_info->type}, nullptr, 0);
}
if (objc_names) {
- LLVMBuildCall2(p->builder, lb_type_internal_for_procedures_raw(main_module, objc_names->type), objc_names->value, nullptr, 0, "");
+ OdinLLVMBuildCall(p, {objc_names->value, objc_names->type}, nullptr, 0);
}
for_array(i, global_variables) {
diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp
index ee6980de4..65cc8c41d 100644
--- a/src/llvm_backend_general.cpp
+++ b/src/llvm_backend_general.cpp
@@ -861,39 +861,6 @@ void lb_const_store(lbValue ptr, lbValue value) {
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);
@@ -953,7 +920,7 @@ void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
}
}
- if (lb_is_type_proc_recursive(a)) {
+ if (is_type_proc(a)) {
// NOTE(bill, 2020-11-11): Because of certain LLVM rules, a procedure value may be
// stored as regular pointer with no procedure information
@@ -1551,7 +1518,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)) {
@@ -2098,15 +2065,13 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
}
case Type_Proc:
- // 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 {
+ {
+ // NOTE(bill): we do an explicit cast to the correct procedure type when calling the procedure
LLVMTypeRef proc_raw_type = lb_type_internal_for_procedures_raw(m, type);
- return LLVMPointerType(proc_raw_type, 0);
+ gb_unused(proc_raw_type);
+ return lb_type(m, t_rawptr);
}
- 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 392ff14c2..ade2a55cf 100644
--- a/src/llvm_backend_proc.cpp
+++ b/src/llvm_backend_proc.cpp
@@ -1,6 +1,11 @@
+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);
@@ -740,6 +745,11 @@ 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) {
@@ -752,11 +762,7 @@ 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));
{
@@ -780,7 +786,7 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
}
}
- LLVMValueRef ret = LLVMBuildCall2(p->builder, fnp, fn, args, arg_count, "");
+ LLVMValueRef ret = OdinLLVMBuildCall(p, value, args, arg_count);
if (return_ptr.value != nullptr) {
LLVMAddCallSiteAttribute(ret, 1, lb_create_enum_attribute_with_type(p->module->ctx, "sret", LLVMTypeOf(args[0])));