mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-14 15:23:15 +00:00
Make USE_NEW_LLVM_ABI_SYSTEM the actual behaviour and remove the previous approach
This commit is contained in:
@@ -1,12 +1,6 @@
|
||||
#include "llvm_backend.hpp"
|
||||
#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_member_types = {};
|
||||
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);
|
||||
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) {
|
||||
@@ -1280,146 +1270,85 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
param_count += 1;
|
||||
}
|
||||
} else {
|
||||
LLVMTypeRef old_abi_fn_type = nullptr;
|
||||
}
|
||||
m->internal_type_level += 1;
|
||||
defer (m->internal_type_level -= 1);
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
Type *e_type = reduce_tuple_to_single_type(e->type);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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 {
|
||||
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;
|
||||
@@ -1467,7 +1396,7 @@ LLVMTypeRef lb_type(lbModule *m, Type *type) {
|
||||
m->internal_type_level += 1;
|
||||
llvm_type = lb_type_internal(m, type);
|
||||
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);
|
||||
if (is_type_named(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) {
|
||||
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);
|
||||
|
||||
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;
|
||||
// TODO(bill): Clean up this logic
|
||||
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
|
||||
isize offset = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
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;
|
||||
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) {
|
||||
lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias");
|
||||
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);
|
||||
|
||||
if (p->abi_function_type) {
|
||||
lb_ensure_abi_function_type(p->module, p);
|
||||
{
|
||||
lbFunctionType *ft = p->abi_function_type;
|
||||
|
||||
unsigned param_offset = 0;
|
||||
@@ -2602,80 +2503,6 @@ void lb_begin_procedure_body(lbProcedure *p) {
|
||||
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) {
|
||||
lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos);
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
||||
|
||||
LLVMBuildRetVoid(p->builder);
|
||||
} 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));
|
||||
|
||||
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);
|
||||
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_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);
|
||||
GB_ASSERT(curr_block != p->decl_block->block);
|
||||
|
||||
if (USE_LLVM_ABI) {
|
||||
|
||||
{
|
||||
LLVMTypeRef ftp = lb_type(p->module, value.type);
|
||||
LLVMTypeRef ft = LLVMGetElementType(ftp);
|
||||
LLVMValueRef fn = value.value;
|
||||
@@ -7295,13 +7098,6 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
|
||||
res.value = ret;
|
||||
res.type = abi_rt;
|
||||
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);
|
||||
|
||||
if (USE_LLVM_ABI) {
|
||||
{
|
||||
lbFunctionType **ft_found = nullptr;
|
||||
ft_found = map_get(&m->function_type_map, hash_type(pt));
|
||||
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);
|
||||
}
|
||||
|
||||
} 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));
|
||||
|
||||
@@ -31,7 +31,7 @@ gb_global Timings global_timings = {0};
|
||||
|
||||
#if defined(GB_SYSTEM_OSX)
|
||||
#include <llvm/Config/llvm-config.h>
|
||||
#if LLVM_VERSION_MAJOR < 11
|
||||
#if LLVM_VERSION_MAJOR < 11
|
||||
#error LLVM Version 11+ is required => "brew install llvm@11"
|
||||
#endif
|
||||
#endif
|
||||
@@ -1844,9 +1844,7 @@ void print_show_unused(Checker *c) {
|
||||
|
||||
void enforce_platform_settings(void) {
|
||||
#if defined(GB_SYSTEM_OSX) && defined(GB_CPU_ARM)
|
||||
#if defined(USE_NEW_LLVM_ABI_SYSTEM)
|
||||
build_context.use_llvm_api = true;
|
||||
#endif
|
||||
build_context.use_llvm_api = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user