mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 04:50:29 +00:00
Use shared partial return memory
This commit is contained in:
@@ -329,6 +329,10 @@ struct lbGlobalVariable {
|
||||
bool is_initialized;
|
||||
};
|
||||
|
||||
struct lbReturnTypeCache {
|
||||
Type * type;
|
||||
lbAddr addr;
|
||||
};
|
||||
|
||||
struct lbProcedure {
|
||||
u32 flags;
|
||||
@@ -391,6 +395,8 @@ struct lbProcedure {
|
||||
PtrMap<Ast *, lbAddr> selector_addr;
|
||||
PtrMap<LLVMValueRef, lbTupleFix> tuple_fix_map;
|
||||
|
||||
Array<lbReturnTypeCache> partial_return_type_cache;
|
||||
|
||||
Array<lbValue> asan_stack_locals;
|
||||
|
||||
void (*generate_body)(lbModule *m, lbProcedure *p);
|
||||
|
||||
@@ -540,6 +540,7 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) {
|
||||
|
||||
map_init(&p->direct_parameters);
|
||||
p->variadic_reuses.allocator = heap_allocator();
|
||||
p->partial_return_type_cache.allocator = heap_allocator();
|
||||
|
||||
GB_ASSERT(p->type != nullptr);
|
||||
|
||||
@@ -1045,6 +1046,32 @@ gb_internal lbValue lb_emit_conjugate(lbProcedure *p, lbValue val, Type *type) {
|
||||
return lb_emit_load(p, res);
|
||||
}
|
||||
|
||||
gb_internal lbValue lb_get_partial_return_local(lbProcedure *p, Type *type, Array<lbReturnTypeCache> *stack, bool use_stack) {
|
||||
if (use_stack) {
|
||||
if (stack->allocator.proc == nullptr) {
|
||||
stack->allocator = heap_allocator();
|
||||
}
|
||||
|
||||
for_array(i, p->partial_return_type_cache) {
|
||||
lbReturnTypeCache entry = p->partial_return_type_cache[i];
|
||||
if (are_types_identical(entry.type, type)) {
|
||||
array_unordered_remove(&p->partial_return_type_cache, i);
|
||||
array_add(stack, entry);
|
||||
return entry.addr.addr;
|
||||
}
|
||||
}
|
||||
|
||||
lbReturnTypeCache new_entry = {type, {}};
|
||||
new_entry.addr = lb_add_local(p, type, nullptr, true, false);
|
||||
array_add(stack, new_entry);
|
||||
return new_entry.addr.addr;
|
||||
} else {
|
||||
lbAddr addr = lb_add_local(p, type, nullptr, true, false);
|
||||
return addr.addr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, ProcInlining inlining) {
|
||||
lbModule *m = p->module;
|
||||
|
||||
@@ -1154,13 +1181,22 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> c
|
||||
}
|
||||
}
|
||||
|
||||
Array<lbReturnTypeCache> partial_return_stack = {};
|
||||
defer ({
|
||||
for (lbReturnTypeCache const &entry : partial_return_stack) {
|
||||
array_add(&p->partial_return_type_cache, entry);
|
||||
}
|
||||
array_free(&partial_return_stack);
|
||||
});
|
||||
|
||||
|
||||
Type *rt = reduce_tuple_to_single_type(results);
|
||||
Type *original_rt = rt;
|
||||
if (split_returns) {
|
||||
GB_ASSERT(rt->kind == Type_Tuple);
|
||||
for (isize j = 0; j < rt->Tuple.variables.count-1; j++) {
|
||||
Type *partial_return_type = rt->Tuple.variables[j]->type;
|
||||
lbValue partial_return_ptr = lb_add_local(p, partial_return_type, nullptr, true, false).addr;
|
||||
lbValue partial_return_ptr = lb_get_partial_return_local(p, partial_return_type, &partial_return_stack, /*use_stack*/true);
|
||||
array_add(&processed_args, partial_return_ptr);
|
||||
}
|
||||
rt = reduce_tuple_to_single_type(rt->Tuple.variables[rt->Tuple.variables.count-1]->type);
|
||||
|
||||
@@ -1146,16 +1146,19 @@ gb_internal lbValue lb_emit_tuple_ep(lbProcedure *p, lbValue ptr, i32 index) {
|
||||
GB_ASSERT(is_type_tuple(t));
|
||||
Type *result_type = t->Tuple.variables[index]->type;
|
||||
|
||||
lbValue res = {};
|
||||
lbTupleFix *tf = map_get(&p->tuple_fix_map, ptr.value);
|
||||
if (tf) {
|
||||
res = tf->values[index];
|
||||
lbValue res = tf->values[index];
|
||||
GB_ASSERT(are_types_identical(res.type, result_type));
|
||||
res = lb_address_from_load_or_generate_local(p, res);
|
||||
|
||||
// NOTE(bill): make an explicit copy because partial return values are sharing memory
|
||||
// See: lb_get_partial_return_local
|
||||
lbAddr addr = lb_add_local_generated(p, res.type, false);
|
||||
lb_addr_store(p, addr, res);
|
||||
return addr.addr;
|
||||
} else {
|
||||
res = lb_emit_struct_ep_internal(p, ptr, index, result_type);
|
||||
return lb_emit_struct_ep_internal(p, ptr, index, result_type);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user