diff options
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 67 |
1 files changed, 59 insertions, 8 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index c2739b387..9ddc182c5 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -859,6 +859,10 @@ void ir_pop_debug_location (irModule *m); irDebugInfo *ir_add_debug_info_local(irProcedure *proc, Entity *e, i32 arg_id); irDebugInfo *ir_add_debug_info_file(irModule *module, AstFile *file); irDebugInfo *ir_add_debug_info_proc(irProcedure *proc); +void ir_emit_increment(irProcedure *proc, irValue *addr); +irValue *ir_emit_array_ep(irProcedure *proc, irValue *s, irValue *index); +irValue *ir_emit_array_epi(irProcedure *proc, irValue *s, i32 index); +irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index); irValue *ir_emit_byte_swap(irProcedure *proc, irValue *value, Type *t); @@ -1274,6 +1278,17 @@ irValue *ir_emit(irProcedure *proc, irValue *instr) { return instr; } +irValue *ir_de_emit(irProcedure *proc, irValue *instr) { + GB_ASSERT(instr->kind == irValue_Instr); + irModule *m = proc->module; + irBlock *b = proc->curr_block; + GB_ASSERT(b != nullptr); + irInstr *i = ir_get_last_instr(b); + GB_ASSERT(i == &instr->Instr); + array_pop(&b->instrs); + return instr; +} + irValue *ir_const_int(i64 i) { @@ -2800,6 +2815,28 @@ irValue *ir_find_or_generate_context_ptr(irProcedure *proc) { return c; } +Array<irValue *> ir_value_to_array(irProcedure *p, irValue *value) { + Array<irValue *> array = {}; + Type *t = base_type(ir_type(value)); + if (t == nullptr) { + // Do nothing + } else if (is_type_tuple(t)) { + GB_ASSERT(t->kind == Type_Tuple); + auto *rt = &t->Tuple; + if (rt->variables.count > 0) { + array = array_make<irValue *>(ir_allocator(), rt->variables.count); + for_array(i, rt->variables) { + irValue *elem = ir_emit_struct_ev(p, value, cast(i32)i); + array[i] = elem; + } + } + } else { + array = array_make<irValue *>(ir_allocator(), 1); + array[0] = value; + } + return array; +} + irValue *ir_emit_call(irProcedure *p, irValue *value, Array<irValue *> args, ProcInlining inlining = ProcInlining_none) { Type *pt = base_type(ir_type(value)); @@ -2847,18 +2884,36 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, Array<irValue *> args, Pro inlining = p->inlining; } + irValue *result = nullptr; + Type *abi_rt = pt->Proc.abi_compat_result_type; Type *rt = reduce_tuple_to_single_type(results); if (pt->Proc.return_by_pointer) { irValue *return_ptr = ir_add_local_generated(p, rt); GB_ASSERT(is_type_pointer(ir_type(return_ptr))); ir_emit(p, ir_instr_call(p, value, return_ptr, args, nullptr, context_ptr, inlining)); - return ir_emit_load(p, return_ptr); + result = ir_emit_load(p, return_ptr); + } else { + result = ir_emit(p, ir_instr_call(p, value, nullptr, args, abi_rt, context_ptr, inlining)); + if (abi_rt != results) { + result = ir_emit_transmute(p, result, rt); + } } - irValue *result = ir_emit(p, ir_instr_call(p, value, nullptr, args, abi_rt, context_ptr, inlining)); - if (abi_rt != results) { - result = ir_emit_transmute(p, result, rt); + if (value->kind == irValue_Proc) { + irProcedure *the_proc = &value->Proc; + Entity *e = the_proc->entity; + if (entity_has_deferred_procedure(e)) { + Entity *deferred_entity = e->Procedure.deferred_procedure; + irValue **deferred_found = map_get(&p->module->values, hash_entity(deferred_entity)); + GB_ASSERT(deferred_found != nullptr); + irValue *deferred = *deferred_found; + + Array<irValue *> result_as_args = ir_value_to_array(p, result); + + irValue *deferred_call = ir_de_emit(p, ir_emit_call(p, deferred, result_as_args)); + ir_add_defer_instr(p, p->scope_index, deferred_call); + } } return result; @@ -3396,10 +3451,6 @@ irValue *ir_map_cap(irProcedure *proc, irValue *value) { } -void ir_emit_increment(irProcedure *proc, irValue *addr); -irValue *ir_emit_array_ep(irProcedure *proc, irValue *s, irValue *index); -irValue *ir_emit_array_epi(irProcedure *proc, irValue *s, i32 index); -irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index); struct irLoopData { irValue *idx_addr; |