|
@@ -1,12 +1,6 @@
|
|
#include "llvm_backend.hpp"
|
|
#include "llvm_backend.hpp"
|
|
#include "llvm_abi.cpp"
|
|
#include "llvm_abi.cpp"
|
|
|
|
|
|
-#ifdef USE_NEW_LLVM_ABI_SYSTEM
|
|
|
|
-#define USE_LLVM_ABI 1
|
|
|
|
-#else
|
|
|
|
-#define USE_LLVM_ABI 0
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
gb_global lbAddr lb_global_type_info_data = {};
|
|
gb_global lbAddr lb_global_type_info_data = {};
|
|
gb_global lbAddr lb_global_type_info_member_types = {};
|
|
gb_global lbAddr lb_global_type_info_member_types = {};
|
|
gb_global lbAddr lb_global_type_info_member_names = {};
|
|
gb_global lbAddr lb_global_type_info_member_names = {};
|
|
@@ -434,11 +428,7 @@ void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) {
|
|
GB_ASSERT(value.value != nullptr);
|
|
GB_ASSERT(value.value != nullptr);
|
|
value = lb_emit_conv(p, value, lb_addr_type(addr));
|
|
value = lb_emit_conv(p, value, lb_addr_type(addr));
|
|
|
|
|
|
- if (USE_LLVM_ABI) {
|
|
|
|
- lb_emit_store(p, addr.addr, value);
|
|
|
|
- } else {
|
|
|
|
- LLVMBuildStore(p->builder, value.value, addr.addr.value);
|
|
|
|
- }
|
|
|
|
|
|
+ lb_emit_store(p, addr.addr, value);
|
|
}
|
|
}
|
|
|
|
|
|
void lb_const_store(lbValue ptr, lbValue value) {
|
|
void lb_const_store(lbValue ptr, lbValue value) {
|
|
@@ -1280,146 +1270,85 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
|
}
|
|
}
|
|
|
|
|
|
case Type_Proc:
|
|
case Type_Proc:
|
|
- {
|
|
|
|
- if (USE_LLVM_ABI) {
|
|
|
|
- if (m->internal_type_level > 256) { // 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 (m->internal_type_level > 256) { // 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;
|
|
|
|
- }
|
|
|
|
- param_count += 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- m->internal_type_level += 1;
|
|
|
|
- defer (m->internal_type_level -= 1);
|
|
|
|
-
|
|
|
|
- LLVMTypeRef ret = nullptr;
|
|
|
|
- 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, 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);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ 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;
|
|
}
|
|
}
|
|
|
|
+ param_count += 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ m->internal_type_level += 1;
|
|
|
|
+ defer (m->internal_type_level -= 1);
|
|
|
|
|
|
- isize 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;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Type *e_type = reduce_tuple_to_single_type(e->type);
|
|
|
|
-
|
|
|
|
- LLVMTypeRef param_type = nullptr;
|
|
|
|
- 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);
|
|
|
|
- // params[param_index++] = lb_type(m, t_context_ptr);
|
|
|
|
|
|
+ LLVMTypeRef ret = nullptr;
|
|
|
|
+ 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, 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);
|
|
}
|
|
}
|
|
- GB_ASSERT(param_index == param_count);
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- lbFunctionType *ft = lb_get_abi_info(m->ctx, params, param_count, ret, ret != nullptr, type->Proc.calling_convention);
|
|
|
|
- map_set(&m->function_type_map, hash_type(type), ft);
|
|
|
|
- LLVMTypeRef new_abi_fn_ptr_type = lb_function_type_to_llvm_ptr(ft, type->Proc.c_vararg);
|
|
|
|
- LLVMTypeRef new_abi_fn_type = LLVMGetElementType(new_abi_fn_ptr_type);
|
|
|
|
-
|
|
|
|
- // LLVMTypeRef new_ret = LLVMGetReturnType(new_abi_fn_type);
|
|
|
|
- // LLVMTypeRef old_ret = LLVMGetReturnType(old_abi_fn_type);
|
|
|
|
- // unsigned new_count = LLVMCountParamTypes(new_abi_fn_type);
|
|
|
|
- // unsigned old_count = LLVMCountParamTypes(old_abi_fn_type);
|
|
|
|
- // GB_ASSERT_MSG(new_count == old_count, "%u %u, %s %s", new_count, old_count, LLVMPrintTypeToString(new_abi_fn_type), LLVMPrintTypeToString(old_abi_fn_type));
|
|
|
|
- return new_abi_fn_ptr_type;
|
|
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
- LLVMTypeRef old_abi_fn_type = nullptr;
|
|
|
|
-
|
|
|
|
- set_procedure_abi_types(type);
|
|
|
|
- LLVMTypeRef return_type = LLVMVoidTypeInContext(ctx);
|
|
|
|
- if (type->Proc.return_by_pointer) {
|
|
|
|
- // Void
|
|
|
|
- } else if (type->Proc.abi_compat_result_type != nullptr) {
|
|
|
|
- return_type = lb_type(m, type->Proc.abi_compat_result_type);
|
|
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- isize extra_param_count = 0;
|
|
|
|
- if (type->Proc.return_by_pointer) {
|
|
|
|
- extra_param_count += 1;
|
|
|
|
- }
|
|
|
|
- if (type->Proc.calling_convention == ProcCC_Odin) {
|
|
|
|
- extra_param_count += 1;
|
|
|
|
|
|
+ isize 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;
|
|
}
|
|
}
|
|
|
|
|
|
- isize param_count = type->Proc.abi_compat_params.count + extra_param_count;
|
|
|
|
- auto param_types = array_make<LLVMTypeRef>(temporary_allocator(), 0, param_count);
|
|
|
|
-
|
|
|
|
- if (type->Proc.return_by_pointer) {
|
|
|
|
- array_add(¶m_types, LLVMPointerType(lb_type(m, type->Proc.abi_compat_result_type), 0));
|
|
|
|
- }
|
|
|
|
|
|
+ Type *e_type = reduce_tuple_to_single_type(e->type);
|
|
|
|
|
|
- for_array(i, type->Proc.abi_compat_params) {
|
|
|
|
- Type *param = type->Proc.abi_compat_params[i];
|
|
|
|
- if (param == nullptr) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- if (type->Proc.params->Tuple.variables[i]->flags & EntityFlag_CVarArg) {
|
|
|
|
- GB_ASSERT(i+1 == type->Proc.abi_compat_params.count);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- if (is_type_tuple(param)) {
|
|
|
|
- param = base_type(param);
|
|
|
|
- for_array(j, param->Tuple.variables) {
|
|
|
|
- Entity *v = param->Tuple.variables[j];
|
|
|
|
- if (v->kind != Entity_Variable) {
|
|
|
|
- // Sanity check
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- LLVMTypeRef t = lb_type(m, v->type);
|
|
|
|
- array_add(¶m_types, t);
|
|
|
|
- }
|
|
|
|
|
|
+ LLVMTypeRef param_type = nullptr;
|
|
|
|
+ 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 {
|
|
} else {
|
|
- array_add(¶m_types, lb_type(m, param));
|
|
|
|
|
|
+ param_type = lb_type(m, e_type);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if (type->Proc.calling_convention == ProcCC_Odin) {
|
|
|
|
- array_add(¶m_types, lb_type(m, t_rawptr));
|
|
|
|
- // array_add(¶m_types, lb_type(m, t_context_ptr));
|
|
|
|
- }
|
|
|
|
|
|
|
|
- old_abi_fn_type = LLVMFunctionType(return_type, param_types.data, cast(unsigned)param_types.count, type->Proc.c_vararg);
|
|
|
|
- return LLVMPointerType(old_abi_fn_type, 0);
|
|
|
|
|
|
+ params[param_index++] = param_type;
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
+ if (param_index < param_count) {
|
|
|
|
+ params[param_index++] = lb_type(m, t_rawptr);
|
|
|
|
+ // params[param_index++] = lb_type(m, t_context_ptr);
|
|
|
|
+ }
|
|
|
|
+ GB_ASSERT(param_index == param_count);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ lbFunctionType *ft = lb_get_abi_info(m->ctx, params, param_count, ret, ret != nullptr, type->Proc.calling_convention);
|
|
|
|
+ map_set(&m->function_type_map, hash_type(type), ft);
|
|
|
|
+ LLVMTypeRef new_abi_fn_ptr_type = lb_function_type_to_llvm_ptr(ft, type->Proc.c_vararg);
|
|
|
|
+ LLVMTypeRef new_abi_fn_type = LLVMGetElementType(new_abi_fn_ptr_type);
|
|
|
|
+
|
|
|
|
+ // LLVMTypeRef new_ret = LLVMGetReturnType(new_abi_fn_type);
|
|
|
|
+ // LLVMTypeRef old_ret = LLVMGetReturnType(old_abi_fn_type);
|
|
|
|
+ // unsigned new_count = LLVMCountParamTypes(new_abi_fn_type);
|
|
|
|
+ // unsigned old_count = LLVMCountParamTypes(old_abi_fn_type);
|
|
|
|
+ // GB_ASSERT_MSG(new_count == old_count, "%u %u, %s %s", new_count, old_count, LLVMPrintTypeToString(new_abi_fn_type), LLVMPrintTypeToString(old_abi_fn_type));
|
|
|
|
+ return new_abi_fn_ptr_type;
|
|
}
|
|
}
|
|
|
|
|
|
break;
|
|
break;
|
|
@@ -1467,7 +1396,7 @@ LLVMTypeRef lb_type(lbModule *m, Type *type) {
|
|
m->internal_type_level += 1;
|
|
m->internal_type_level += 1;
|
|
llvm_type = lb_type_internal(m, type);
|
|
llvm_type = lb_type_internal(m, type);
|
|
m->internal_type_level -= 1;
|
|
m->internal_type_level -= 1;
|
|
- if (USE_LLVM_ABI && m->internal_type_level == 0) {
|
|
|
|
|
|
+ if (m->internal_type_level == 0) {
|
|
map_set(&m->types, hash_type(type), llvm_type);
|
|
map_set(&m->types, hash_type(type), llvm_type);
|
|
if (is_type_named(type)) {
|
|
if (is_type_named(type)) {
|
|
map_set(&m->llvm_types, hash_pointer(llvm_type), type);
|
|
map_set(&m->llvm_types, hash_pointer(llvm_type), type);
|
|
@@ -2009,6 +1938,20 @@ void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *nam
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+void lb_ensure_abi_function_type(lbModule *m, lbProcedure *p) {
|
|
|
|
+ if (p->abi_function_type != nullptr) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ auto hash = hash_type(p->type);
|
|
|
|
+ lbFunctionType **ft_found = map_get(&m->function_type_map, hash);
|
|
|
|
+ if (ft_found == nullptr) {
|
|
|
|
+ LLVMTypeRef llvm_proc_type = lb_type(p->module, p->type);
|
|
|
|
+ ft_found = map_get(&m->function_type_map, hash);
|
|
|
|
+ }
|
|
|
|
+ GB_ASSERT(ft_found != nullptr);
|
|
|
|
+ p->abi_function_type = *ft_found;
|
|
|
|
+ GB_ASSERT(p->abi_function_type != nullptr);
|
|
|
|
+}
|
|
|
|
|
|
lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
|
|
lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
|
|
GB_ASSERT(entity != nullptr);
|
|
GB_ASSERT(entity != nullptr);
|
|
@@ -2070,12 +2013,9 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
|
|
|
|
|
|
p->value = LLVMAddFunction(m->mod, c_link_name, func_type);
|
|
p->value = LLVMAddFunction(m->mod, c_link_name, func_type);
|
|
|
|
|
|
- lbFunctionType **ft_found = map_get(&m->function_type_map, hash_type(p->type));
|
|
|
|
- if (USE_LLVM_ABI && ft_found) {
|
|
|
|
- lbFunctionType *abi_ft = *ft_found;
|
|
|
|
- p->abi_function_type = abi_ft;
|
|
|
|
- lb_add_function_type_attributes(p->value, abi_ft, abi_ft->calling_convention);
|
|
|
|
- } else {
|
|
|
|
|
|
+ lb_ensure_abi_function_type(m, p);
|
|
|
|
+ lb_add_function_type_attributes(p->value, p->abi_function_type, p->abi_function_type->calling_convention);
|
|
|
|
+ if (false) {
|
|
lbCallingConventionKind cc_kind = lbCallingConvention_C;
|
|
lbCallingConventionKind cc_kind = lbCallingConvention_C;
|
|
// TODO(bill): Clean up this logic
|
|
// TODO(bill): Clean up this logic
|
|
if (build_context.metrics.os != TargetOs_js) {
|
|
if (build_context.metrics.os != TargetOs_js) {
|
|
@@ -2124,10 +2064,6 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
|
|
// NOTE(bill): offset==0 is the return value
|
|
// NOTE(bill): offset==0 is the return value
|
|
isize offset = 1;
|
|
isize offset = 1;
|
|
if (pt->Proc.return_by_pointer) {
|
|
if (pt->Proc.return_by_pointer) {
|
|
- if (!USE_LLVM_ABI) {
|
|
|
|
- lb_add_proc_attribute_at_index(p, 1, "sret");
|
|
|
|
- lb_add_proc_attribute_at_index(p, 1, "noalias");
|
|
|
|
- }
|
|
|
|
offset = 2;
|
|
offset = 2;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2160,14 +2096,6 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (!USE_LLVM_ABI && pt->Proc.calling_convention == ProcCC_Odin) {
|
|
|
|
- lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias");
|
|
|
|
- lb_add_proc_attribute_at_index(p, offset+parameter_index, "nonnull");
|
|
|
|
- lb_add_proc_attribute_at_index(p, offset+parameter_index, "nocapture");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
|
|
{ // Debug Information
|
|
{ // Debug Information
|
|
unsigned line = cast(unsigned)entity->token.pos.line;
|
|
unsigned line = cast(unsigned)entity->token.pos.line;
|
|
@@ -2252,34 +2180,6 @@ lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name, Type *type
|
|
}
|
|
}
|
|
|
|
|
|
isize parameter_index = 0;
|
|
isize parameter_index = 0;
|
|
- if (!USE_LLVM_ABI && pt->Proc.param_count) {
|
|
|
|
- TypeTuple *params = &pt->Proc.params->Tuple;
|
|
|
|
- for (isize i = 0; i < pt->Proc.param_count; i++) {
|
|
|
|
- Entity *e = params->variables[i];
|
|
|
|
- Type *original_type = e->type;
|
|
|
|
- Type *abi_type = pt->Proc.abi_compat_params[i];
|
|
|
|
- if (e->kind != Entity_Variable) continue;
|
|
|
|
-
|
|
|
|
- if (i+1 == params->variables.count && pt->Proc.c_vararg) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- if (is_type_tuple(abi_type)) {
|
|
|
|
- for_array(j, abi_type->Tuple.variables) {
|
|
|
|
- Type *tft = abi_type->Tuple.variables[j]->type;
|
|
|
|
- if (e->flags&EntityFlag_NoAlias) {
|
|
|
|
- lb_add_proc_attribute_at_index(p, offset+parameter_index+j, "noalias");
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- parameter_index += abi_type->Tuple.variables.count;
|
|
|
|
- } else {
|
|
|
|
- if (e->flags&EntityFlag_NoAlias) {
|
|
|
|
- lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias");
|
|
|
|
- }
|
|
|
|
- parameter_index += 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (pt->Proc.calling_convention == ProcCC_Odin) {
|
|
if (pt->Proc.calling_convention == ProcCC_Odin) {
|
|
lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias");
|
|
lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias");
|
|
lb_add_proc_attribute_at_index(p, offset+parameter_index, "nonnull");
|
|
lb_add_proc_attribute_at_index(p, offset+parameter_index, "nonnull");
|
|
@@ -2504,7 +2404,8 @@ void lb_begin_procedure_body(lbProcedure *p) {
|
|
|
|
|
|
GB_ASSERT(p->type != nullptr);
|
|
GB_ASSERT(p->type != nullptr);
|
|
|
|
|
|
- if (p->abi_function_type) {
|
|
|
|
|
|
+ lb_ensure_abi_function_type(p->module, p);
|
|
|
|
+ {
|
|
lbFunctionType *ft = p->abi_function_type;
|
|
lbFunctionType *ft = p->abi_function_type;
|
|
|
|
|
|
unsigned param_offset = 0;
|
|
unsigned param_offset = 0;
|
|
@@ -2602,80 +2503,6 @@ void lb_begin_procedure_body(lbProcedure *p) {
|
|
res = lb_add_local(p, e->type, e);
|
|
res = lb_add_local(p, e->type, e);
|
|
}
|
|
}
|
|
|
|
|
|
- if (e->Variable.param_value.kind != ParameterValue_Invalid) {
|
|
|
|
- lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos);
|
|
|
|
- lb_addr_store(p, res, c);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- i32 parameter_index = 0;
|
|
|
|
- lbValue return_ptr_value = {};
|
|
|
|
- if (p->type->Proc.return_by_pointer) {
|
|
|
|
- // NOTE(bill): this must be parameter 0
|
|
|
|
- Type *ptr_type = alloc_type_pointer(reduce_tuple_to_single_type(p->type->Proc.results));
|
|
|
|
- Entity *e = alloc_entity_param(nullptr, make_token_ident(str_lit("agg.result")), ptr_type, false, false);
|
|
|
|
- e->flags |= EntityFlag_Sret | EntityFlag_NoAlias;
|
|
|
|
-
|
|
|
|
- return_ptr_value.value = LLVMGetParam(p->value, 0);
|
|
|
|
- return_ptr_value.type = ptr_type;
|
|
|
|
- p->return_ptr = lb_addr(return_ptr_value);
|
|
|
|
-
|
|
|
|
- lb_add_entity(p->module, e, return_ptr_value);
|
|
|
|
-
|
|
|
|
- parameter_index += 1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (p->type->Proc.params != nullptr) {
|
|
|
|
- TypeTuple *params = &p->type->Proc.params->Tuple;
|
|
|
|
- auto abi_types = p->type->Proc.abi_compat_params;
|
|
|
|
-
|
|
|
|
- for_array(i, params->variables) {
|
|
|
|
- Entity *e = params->variables[i];
|
|
|
|
- if (e->kind != Entity_Variable) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- Type *abi_type = e->type;
|
|
|
|
- if (abi_types.count > 0) {
|
|
|
|
- abi_type = abi_types[i];
|
|
|
|
- }
|
|
|
|
- if (e->token.string != "") {
|
|
|
|
- lb_add_param(p, e, nullptr, abi_type, parameter_index);
|
|
|
|
- }
|
|
|
|
- if (is_type_tuple(abi_type)) {
|
|
|
|
- parameter_index += cast(i32)abi_type->Tuple.variables.count;
|
|
|
|
- } else {
|
|
|
|
- parameter_index += 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- if (p->type->Proc.has_named_results) {
|
|
|
|
- GB_ASSERT(p->type->Proc.result_count > 0);
|
|
|
|
- TypeTuple *results = &p->type->Proc.results->Tuple;
|
|
|
|
-
|
|
|
|
- for_array(i, results->variables) {
|
|
|
|
- Entity *e = results->variables[i];
|
|
|
|
- GB_ASSERT(e->kind == Entity_Variable);
|
|
|
|
-
|
|
|
|
- if (e->token.string != "") {
|
|
|
|
- GB_ASSERT(!is_blank_ident(e->token));
|
|
|
|
-
|
|
|
|
- lbAddr res = {};
|
|
|
|
- if (p->type->Proc.return_by_pointer) {
|
|
|
|
- lbValue ptr = return_ptr_value;
|
|
|
|
- if (results->variables.count != 1) {
|
|
|
|
- ptr = lb_emit_struct_ep(p, ptr, cast(i32)i);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- res = lb_addr(ptr);
|
|
|
|
- lb_add_entity(p->module, e, ptr);
|
|
|
|
- } else {
|
|
|
|
- res = lb_add_local(p, e->type, e);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (e->Variable.param_value.kind != ParameterValue_Invalid) {
|
|
if (e->Variable.param_value.kind != ParameterValue_Invalid) {
|
|
lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos);
|
|
lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos);
|
|
lb_addr_store(p, res, c);
|
|
lb_addr_store(p, res, c);
|
|
@@ -4469,53 +4296,30 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
- 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);
|
|
|
|
|
|
+ lb_ensure_abi_function_type(p->module, p);
|
|
|
|
+ if (p->abi_function_type->ret.kind == lbArg_Indirect) {
|
|
|
|
+ if (res.value != nullptr) {
|
|
|
|
+ LLVMBuildStore(p->builder, res.value, p->return_ptr.addr.value);
|
|
} else {
|
|
} else {
|
|
- LLVMValueRef ret_val = res.value;
|
|
|
|
- ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.type);
|
|
|
|
- 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);
|
|
|
|
|
|
+ LLVMBuildStore(p->builder, LLVMConstNull(p->abi_function_type->ret.type), p->return_ptr.addr.value);
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
- GB_ASSERT(!USE_LLVM_ABI);
|
|
|
|
-
|
|
|
|
- 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));
|
|
|
|
- }
|
|
|
|
|
|
|
|
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
|
|
|
-
|
|
|
|
- LLVMBuildRetVoid(p->builder);
|
|
|
|
- } else {
|
|
|
|
- GB_ASSERT_MSG(res.value != nullptr, "%.*s", LIT(p->name));
|
|
|
|
|
|
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
|
|
|
|
|
- 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);
|
|
|
|
|
|
+ LLVMBuildRetVoid(p->builder);
|
|
|
|
+ } else {
|
|
|
|
+ LLVMValueRef ret_val = res.value;
|
|
|
|
+ ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.type);
|
|
|
|
+ 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);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
case_end;
|
|
case_end;
|
|
|
|
|
|
case_ast_node(is, IfStmt, node);
|
|
case_ast_node(is, IfStmt, node);
|
|
@@ -7279,8 +7083,7 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
|
|
LLVMBasicBlockRef curr_block = LLVMGetInsertBlock(p->builder);
|
|
LLVMBasicBlockRef curr_block = LLVMGetInsertBlock(p->builder);
|
|
GB_ASSERT(curr_block != p->decl_block->block);
|
|
GB_ASSERT(curr_block != p->decl_block->block);
|
|
|
|
|
|
- if (USE_LLVM_ABI) {
|
|
|
|
-
|
|
|
|
|
|
+ {
|
|
LLVMTypeRef ftp = lb_type(p->module, value.type);
|
|
LLVMTypeRef ftp = lb_type(p->module, value.type);
|
|
LLVMTypeRef ft = LLVMGetElementType(ftp);
|
|
LLVMTypeRef ft = LLVMGetElementType(ftp);
|
|
LLVMValueRef fn = value.value;
|
|
LLVMValueRef fn = value.value;
|
|
@@ -7295,13 +7098,6 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
|
|
res.value = ret;
|
|
res.value = ret;
|
|
res.type = abi_rt;
|
|
res.type = abi_rt;
|
|
return res;
|
|
return res;
|
|
- } else {
|
|
|
|
-
|
|
|
|
- LLVMValueRef ret = LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(p->module, value.type)), value.value, args, arg_count, "");;
|
|
|
|
- lbValue res = {};
|
|
|
|
- res.value = ret;
|
|
|
|
- res.type = abi_rt;
|
|
|
|
- return res;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -7362,7 +7158,7 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
|
|
|
|
|
|
auto processed_args = array_make<lbValue>(permanent_allocator(), 0, args.count);
|
|
auto processed_args = array_make<lbValue>(permanent_allocator(), 0, args.count);
|
|
|
|
|
|
- if (USE_LLVM_ABI) {
|
|
|
|
|
|
+ {
|
|
lbFunctionType **ft_found = nullptr;
|
|
lbFunctionType **ft_found = nullptr;
|
|
ft_found = map_get(&m->function_type_map, hash_type(pt));
|
|
ft_found = map_get(&m->function_type_map, hash_type(pt));
|
|
if (!ft_found) {
|
|
if (!ft_found) {
|
|
@@ -7455,95 +7251,6 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
|
|
lb_emit_call_internal(p, value, {}, processed_args, nullptr, context_ptr, inlining);
|
|
lb_emit_call_internal(p, value, {}, processed_args, nullptr, context_ptr, inlining);
|
|
}
|
|
}
|
|
|
|
|
|
- } else {
|
|
|
|
- for (isize i = 0; i < param_count; i++) {
|
|
|
|
- Entity *e = pt->Proc.params->Tuple.variables[i];
|
|
|
|
- if (e->kind != Entity_Variable) {
|
|
|
|
- // array_add(&processed_args, args[i]);
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- GB_ASSERT(e->flags & EntityFlag_Param);
|
|
|
|
-
|
|
|
|
- Type *original_type = e->type;
|
|
|
|
- Type *new_type = pt->Proc.abi_compat_params[i];
|
|
|
|
- Type *arg_type = args[i].type;
|
|
|
|
-
|
|
|
|
- if (are_types_identical(arg_type, new_type)) {
|
|
|
|
- // NOTE(bill): Done
|
|
|
|
- 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)) {
|
|
|
|
- Type *av = core_type(type_deref(new_type));
|
|
|
|
- if (are_types_identical(av, core_type(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));
|
|
|
|
- }
|
|
|
|
- } 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));
|
|
|
|
- } else if (is_type_integer(new_type) || is_type_float(new_type) || is_type_boolean(new_type)) {
|
|
|
|
- array_add(&processed_args, lb_emit_transmute(p, args[i], new_type));
|
|
|
|
- } else if (is_type_simd_vector(new_type)) {
|
|
|
|
- array_add(&processed_args, lb_emit_transmute(p, args[i], new_type));
|
|
|
|
- } else if (is_type_tuple(new_type)) {
|
|
|
|
- Type *abi_type = pt->Proc.abi_compat_params[i];
|
|
|
|
- Type *st = struct_type_from_systemv_distribute_struct_fields(abi_type);
|
|
|
|
- lbValue x = {};
|
|
|
|
- i64 st_sz = type_size_of(st);
|
|
|
|
- i64 arg_sz = type_size_of(args[i].type);
|
|
|
|
- if (st_sz == arg_sz) {
|
|
|
|
- x = lb_emit_transmute(p, args[i], st);
|
|
|
|
- } else {
|
|
|
|
- // NOTE(bill): struct{f32, f32, f32} != struct{#simd[2]f32, f32}
|
|
|
|
- GB_ASSERT(st_sz > arg_sz);
|
|
|
|
- lbAddr xx = lb_add_local_generated(p, st, false);
|
|
|
|
- lbValue pp = lb_emit_conv(p, xx.addr, alloc_type_pointer(args[i].type));
|
|
|
|
- lb_emit_store(p, pp, args[i]);
|
|
|
|
- x = lb_addr_load(p, xx);
|
|
|
|
- }
|
|
|
|
- for (isize j = 0; j < new_type->Tuple.variables.count; j++) {
|
|
|
|
- lbValue xx = lb_emit_struct_ev(p, x, cast(i32)j);
|
|
|
|
- array_add(&processed_args, xx);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- lbValue x = lb_emit_conv(p, args[i], new_type);
|
|
|
|
- array_add(&processed_args, x);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (inlining == ProcInlining_none) {
|
|
|
|
- inlining = p->inlining;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- Type *abi_rt = reduce_tuple_to_single_type(pt->Proc.abi_compat_result_type);
|
|
|
|
- Type *rt = reduce_tuple_to_single_type(results);
|
|
|
|
- if (pt->Proc.return_by_pointer) {
|
|
|
|
- lbValue return_ptr = {};
|
|
|
|
- if (use_return_ptr_hint && p->return_ptr_hint_value.value != nullptr) {
|
|
|
|
- if (are_types_identical(type_deref(p->return_ptr_hint_value.type), rt)) {
|
|
|
|
- return_ptr = p->return_ptr_hint_value;
|
|
|
|
- p->return_ptr_hint_used = true;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (return_ptr.value == nullptr) {
|
|
|
|
- lbAddr r = lb_add_local_generated(p, rt, true);
|
|
|
|
- return_ptr = r.addr;
|
|
|
|
- }
|
|
|
|
- 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 {
|
|
|
|
- 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);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
Entity **found = map_get(&p->module->procedure_values, hash_pointer(value.value));
|
|
Entity **found = map_get(&p->module->procedure_values, hash_pointer(value.value));
|