Use shared partial return memory

This commit is contained in:
gingerBill
2025-12-27 12:28:58 +00:00
parent de761cbdd3
commit edf1e183d7
3 changed files with 51 additions and 6 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}