call.c (10350B)
1 #include "cg/internal.h" 2 3 static u32 api_func_nparams(KitCg* g, KitCgTypeId fty) { 4 const CgType* ty = cg_type_get(g->c, api_unalias_type(g->c, fty)); 5 if (!ty || ty->kind != KIT_CG_TYPE_FUNC) return 0; 6 return ty->func.nparams; 7 } 8 9 CGLocal* api_alloc_call_args(KitCg* g, u32 nargs) { 10 if (!nargs) return NULL; 11 CGLocal* args = arena_array(g->c->tu, CGLocal, nargs); 12 memset(args, 0, sizeof(CGLocal) * nargs); 13 return args; 14 } 15 16 static CGLocal api_materialize_call_local(KitCg* g, ApiSValue* arg, 17 KitCgTypeId ty) { 18 if (cg_type_is_aggregate(g->c, ty)) { 19 if (api_is_lvalue_sv(arg) && arg->op.kind == OPK_LOCAL) { 20 if (api_unalias_type(g->c, arg->op.type) == api_unalias_type(g->c, ty)) 21 return arg->op.v.local; 22 } 23 CGLocal r = api_alloc_temp_local(g, ty); 24 Operand dst = api_op_local(r, ty); 25 MemAccess ma; 26 memset(&ma, 0, sizeof ma); 27 ma.type = ty; 28 ma.size = abi_cg_sizeof(g->c->abi, ty); 29 ma.align = abi_cg_alignof(g->c->abi, ty); 30 if (api_is_lvalue_sv(arg) && api_operand_can_address(&arg->op)) { 31 g->target->load(g->target, dst, arg->op, ma); 32 } else if (arg->op.kind == OPK_GLOBAL || arg->op.kind == OPK_INDIRECT) { 33 g->target->load(g->target, dst, arg->op, ma); 34 } else if (arg->op.kind == OPK_LOCAL) { 35 g->target->load(g->target, dst, api_op_indirect(arg->op.v.local, 0, ty), 36 ma); 37 } else { 38 compiler_panic(g->c, g->cur_loc, 39 "KitCg: aggregate call argument is not addressable"); 40 } 41 return r; 42 } 43 KitCgTypeId src_ty = api_sv_type(arg); 44 Operand op; 45 /* A 16-byte scalar immediate (an i128 small constant) only carries 64 bits in 46 * op.v.imm; materialize it into both sign-extended lanes so it flows as an 47 * ordinary 16-byte value rather than load_imm'ing only the low lane. */ 48 if (api_sv_op_is(arg, OPK_IMM) && api_is_wide16_scalar_type(g->c, ty)) { 49 *arg = api_make_wide16_int_const(g, arg->op.v.imm, ty); 50 } 51 /* Same for a split-lane 8-byte immediate argument: materialize it as a 52 * 2-lane memory value so the multi-part ABI path marshals both words. */ 53 if (api_sv_op_is(arg, OPK_IMM) && api_is_wide8_scalar_type(g->c, ty)) { 54 *arg = api_make_wide8_int_const(g, arg->op.v.imm, ty); 55 } 56 op = api_force_local_unless_imm(g, arg, src_ty); 57 if (op.kind == OPK_LOCAL && 58 api_unalias_type(g->c, op.type) == api_unalias_type(g->c, ty)) { 59 return op.v.local; 60 } 61 62 CGLocal r = api_alloc_temp_local(g, ty); 63 Operand dst = api_op_local(r, ty); 64 if (op.kind == OPK_IMM) { 65 g->target->load_imm(g->target, dst, op.v.imm); 66 } else if (op.kind == OPK_LOCAL) { 67 g->target->copy(g->target, dst, op); 68 } else { 69 compiler_panic(g->c, g->cur_loc, 70 "KitCg: scalar call argument is not materialized"); 71 } 72 api_release(g, arg); 73 return r; 74 } 75 76 void api_pack_call_arg(KitCg* g, CGLocal* out, KitCgTypeId fty, u32 idx) { 77 ApiSValue arg = api_pop(g); 78 u32 nfixed = api_func_nparams(g, fty); 79 KitCgTypeId aty = 80 idx >= nfixed ? api_sv_type(&arg) : cg_type_func_param_id(g->c, fty, idx); 81 if (!aty) aty = api_sv_type(&arg); 82 *out = api_materialize_call_local(g, &arg, aty); 83 } 84 85 CGLocal api_alloc_call_result(KitCg* g, KitCgTypeId ret_ty) { 86 return api_alloc_temp_local(g, ret_ty); 87 } 88 89 void api_release_call_args(KitCg* g, CGLocal* args, u32 nargs) { 90 for (u32 i = 0; i < nargs; ++i) { 91 if (args[i] != CG_LOCAL_NONE) api_release_temp_local(g, args[i]); 92 } 93 } 94 95 void api_push_call_result(KitCg* g, CGLocal result, KitCgTypeId ret_ty) { 96 Operand op = api_op_local(result, ret_ty); 97 /* An aggregate result is a PLACE (it is addressed/copied, never a scalar 98 * VALUE); i128/f128 are scalar VALUEs and flow like any other result. */ 99 if (cg_type_is_aggregate(g->c, ret_ty)) { 100 api_push(g, api_make_lv(op, ret_ty)); 101 } else { 102 api_push(g, api_make_sv(op, ret_ty)); 103 } 104 } 105 106 static void api_call_clobber_boundary(KitCg* g, const CGCallDesc* d) { 107 (void)g; 108 (void)d; 109 } 110 111 static int api_tail_ret_compatible(KitCg* g, KitCgTypeId callee_fn_type) { 112 KitCgTypeId cr = cg_type_func_result_id(g->c, callee_fn_type); 113 return api_unalias_type(g->c, g->fn_desc.result_type) == 114 api_unalias_type(g->c, cr); 115 } 116 117 static int api_tail_decide(KitCg* g, const CGCallDesc* desc, 118 KitCgTailPolicy policy) { 119 CgTarget* T = g->target; 120 const char* reason; 121 if (!api_tail_ret_compatible(g, desc->fn_type)) { 122 compiler_panic(g->c, g->cur_loc, 123 "tail call: callee return type is incompatible with the " 124 "enclosing function's return type"); 125 return 0; 126 } 127 reason = T->tail_call_unrealizable_reason 128 ? T->tail_call_unrealizable_reason(T, desc) 129 : "target does not support tail calls"; 130 if (!reason) return 1; 131 if (policy == KIT_CG_TAIL_MUST) { 132 compiler_panic(g->c, g->cur_loc, "musttail call not realizable: %s", 133 reason); 134 return 0; 135 } 136 return 0; 137 } 138 139 static void api_finish_call(KitCg* g, CGCallDesc* desc, CGLocal* args, 140 u32 nargs, Operand callee_op, ApiSValue* callee, 141 int want_tail, int emit_tail) { 142 if (emit_tail) api_temp_locals_finish(g); 143 if (!emit_tail) api_call_clobber_boundary(g, desc); 144 g->target->call(g->target, desc); 145 146 api_release_call_args(g, args, nargs); 147 if (callee && callee->op.kind != OPK_GLOBAL) { 148 api_release_temp_local(g, callee_op.v.local); 149 } 150 /* Push the single result (if any) onto the stack. */ 151 if (desc->result != CG_LOCAL_NONE) { 152 KitCgTypeId rty = cg_type_func_result_id(g->c, desc->fn_type); 153 api_push_call_result(g, desc->result, rty); 154 } 155 /* ALLOWED tail call that degraded to an ordinary call: synthesize the 156 * caller's return of the just-pushed result. */ 157 if (want_tail && !emit_tail) kit_cg_ret(g); 158 } 159 160 void kit_cg_call(KitCg* g, uint32_t nargs, KitCgTypeId fn_type, 161 KitCgCallAttrs attrs) { 162 CgTarget* T; 163 KitCgTypeId fty; 164 KitCgTypeId result_type; 165 CGLocal* args; 166 CGCallDesc desc; 167 ApiSValue callee; 168 Operand callee_op; 169 int want_tail; 170 int emit_tail; 171 if (!g) return; 172 api_local_const_memory_boundary(g); 173 want_tail = 174 attrs.tail == KIT_CG_TAIL_ALLOWED || attrs.tail == KIT_CG_TAIL_MUST; 175 T = g->target; 176 fty = resolve_type(g->c, fn_type); 177 if (!fty) return; 178 179 if (g->sp < (u32)nargs + 1u) { 180 compiler_panic(g->c, g->cur_loc, "KitCg: call stack underflow"); 181 return; 182 } 183 184 args = api_alloc_call_args(g, nargs); 185 for (u32 i = 0; i < nargs; ++i) { 186 u32 idx = nargs - 1u - i; 187 api_pack_call_arg(g, &args[idx], fty, idx); 188 } 189 190 callee = api_pop(g); 191 api_ensure_local(g, &callee); 192 callee_op = (callee.op.kind == OPK_GLOBAL) 193 ? callee.op 194 : api_force_local(g, &callee, api_sv_type(&callee)); 195 KitCgInlinePolicy inline_policy = attrs.inline_policy; 196 if (inline_policy == KIT_CG_INLINE_DEFAULT && callee_op.kind == OPK_GLOBAL && 197 callee_op.v.global.addend == 0) { 198 KitCgDecl callee_attrs = api_sym_attrs(g, (KitCgSym)callee_op.v.global.sym); 199 if (callee_attrs.kind == KIT_CG_DECL_FUNC) 200 inline_policy = callee_attrs.as.func.inline_policy; 201 } 202 203 memset(&desc, 0, sizeof desc); 204 desc.fn_type = fty; 205 desc.callee = callee_op; 206 desc.args = args; 207 desc.nargs = nargs; 208 desc.tail_policy = (u8)attrs.tail; 209 desc.inline_policy = inline_policy; 210 211 emit_tail = want_tail ? api_tail_decide(g, &desc, attrs.tail) : 0; 212 desc.flags = emit_tail ? CG_CALL_TAIL : CG_CALL_NONE; 213 result_type = emit_tail ? KIT_CG_TYPE_NONE : cg_type_func_result_id(g->c, fty); 214 if (result_type != KIT_CG_TYPE_NONE) 215 desc.result = api_alloc_call_result(g, result_type); 216 217 (void)T; 218 api_finish_call(g, &desc, args, nargs, callee_op, &callee, want_tail, 219 emit_tail); 220 } 221 222 void api_call_symbol_common(KitCg* g, KitCgSym sym, uint32_t nargs, 223 KitCgCallAttrs attrs) { 224 KitCgTypeId fty; 225 KitCgTypeId result_type; 226 CGLocal* args; 227 CGCallDesc desc; 228 Operand callee_op; 229 KitCgInlinePolicy inline_policy; 230 int want_tail; 231 int emit_tail; 232 if (!g) return; 233 api_local_const_memory_boundary(g); 234 want_tail = 235 attrs.tail == KIT_CG_TAIL_ALLOWED || attrs.tail == KIT_CG_TAIL_MUST; 236 fty = api_sym_type(g, sym); 237 if (!fty) return; 238 if (g->sp < nargs) { 239 compiler_panic(g->c, g->cur_loc, "KitCg: call stack underflow"); 240 return; 241 } 242 args = api_alloc_call_args(g, nargs); 243 for (u32 i = 0; i < nargs; ++i) { 244 u32 idx = nargs - 1u - i; 245 api_pack_call_arg(g, &args[idx], fty, idx); 246 } 247 callee_op = api_op_global((ObjSymId)sym, 0, cg_type_ptr_to(g->c, fty)); 248 inline_policy = attrs.inline_policy; 249 if (inline_policy == KIT_CG_INLINE_DEFAULT) { 250 KitCgDecl callee_attrs = api_sym_attrs(g, sym); 251 if (callee_attrs.kind == KIT_CG_DECL_FUNC) 252 inline_policy = callee_attrs.as.func.inline_policy; 253 } 254 memset(&desc, 0, sizeof desc); 255 desc.fn_type = fty; 256 desc.callee = callee_op; 257 desc.args = args; 258 desc.nargs = nargs; 259 desc.tail_policy = (u8)attrs.tail; 260 desc.inline_policy = inline_policy; 261 262 emit_tail = want_tail ? api_tail_decide(g, &desc, attrs.tail) : 0; 263 desc.flags = emit_tail ? CG_CALL_TAIL : CG_CALL_NONE; 264 result_type = emit_tail ? KIT_CG_TYPE_NONE : cg_type_func_result_id(g->c, fty); 265 if (result_type != KIT_CG_TYPE_NONE) 266 desc.result = api_alloc_call_result(g, result_type); 267 api_finish_call(g, &desc, args, nargs, callee_op, NULL, want_tail, emit_tail); 268 } 269 270 void kit_cg_call_symbol(KitCg* g, KitCgSym sym, uint32_t nargs, 271 KitCgCallAttrs attrs) { 272 api_call_symbol_common(g, sym, nargs, attrs); 273 } 274 275 void kit_cg_ret(KitCg* g) { 276 KitCgTypeId rty; 277 ApiSValue v; 278 CGLocal value; 279 if (!g) return; 280 rty = g->fn_desc.result_type; 281 if (rty == KIT_CG_TYPE_NONE) { 282 g->target->ret(g->target, CG_LOCAL_NONE); 283 return; 284 } 285 /* TOS holds the single result value. */ 286 v = api_pop(g); 287 if (cg_type_is_aggregate(g->c, rty)) { 288 value = api_materialize_call_local(g, &v, rty); 289 } else { 290 Operand ret_op = api_force_local(g, &v, rty); 291 value = ret_op.v.local; 292 } 293 g->target->ret(g->target, value); 294 api_release(g, &v); 295 } 296 297 /* ============================================================ 298 * Data definitions (stubs) 299 * ============================================================ */