abi.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. #include "all.h"
  2. typedef struct Abi Abi;
  3. typedef struct Class Class;
  4. typedef struct Insl Insl;
  5. typedef struct Params Params;
  6. enum {
  7. Cstk = 1, /* pass on the stack */
  8. Cptr = 2, /* replaced by a pointer */
  9. };
  10. struct Class {
  11. char class;
  12. char ishfa;
  13. struct {
  14. char base;
  15. uchar size;
  16. } hfa;
  17. uint size;
  18. uint align;
  19. Typ *t;
  20. uchar nreg;
  21. uchar ngp;
  22. uchar nfp;
  23. int reg[4];
  24. int cls[4];
  25. };
  26. struct Insl {
  27. Ins i;
  28. Insl *link;
  29. };
  30. struct Params {
  31. uint ngp;
  32. uint nfp;
  33. uint stk;
  34. };
  35. static int gpreg[12] = {R0, R1, R2, R3, R4, R5, R6, R7};
  36. static int fpreg[12] = {V0, V1, V2, V3, V4, V5, V6, V7};
  37. static int store[] = {
  38. [Kw] = Ostorew, [Kl] = Ostorel,
  39. [Ks] = Ostores, [Kd] = Ostored
  40. };
  41. /* layout of call's second argument (RCall)
  42. *
  43. * 13
  44. * 29 14 | 9 5 2 0
  45. * |0.00|x|x|xxxx|xxxx|xxx|xx| range
  46. * | | | | | ` gp regs returned (0..2)
  47. * | | | | ` fp regs returned (0..4)
  48. * | | | ` gp regs passed (0..8)
  49. * | | ` fp regs passed (0..8)
  50. * | ` indirect result register x8 used (0..1)
  51. * ` env pointer passed in x9 (0..1)
  52. */
  53. static int
  54. isfloatv(Typ *t, char *cls)
  55. {
  56. Field *f;
  57. uint n;
  58. for (n=0; n<t->nunion; n++)
  59. for (f=t->fields[n]; f->type != FEnd; f++)
  60. switch (f->type) {
  61. case Fs:
  62. if (*cls == Kd)
  63. return 0;
  64. *cls = Ks;
  65. break;
  66. case Fd:
  67. if (*cls == Ks)
  68. return 0;
  69. *cls = Kd;
  70. break;
  71. case FTyp:
  72. if (isfloatv(&typ[f->len], cls))
  73. break;
  74. /* fall through */
  75. default:
  76. return 0;
  77. }
  78. return 1;
  79. }
  80. static void
  81. typclass(Class *c, Typ *t, int *gp, int *fp)
  82. {
  83. uint64_t sz, hfasz;
  84. uint n;
  85. sz = (t->size + 7) & -8;
  86. c->t = t;
  87. c->class = 0;
  88. c->ngp = 0;
  89. c->nfp = 0;
  90. c->align = 8;
  91. if (t->align > 3)
  92. err("alignments larger than 8 are not supported");
  93. c->size = sz;
  94. c->hfa.base = Kx;
  95. c->ishfa = isfloatv(t, &c->hfa.base);
  96. hfasz = t->size/(KWIDE(c->hfa.base) ? 8 : 4);
  97. c->ishfa &= !t->isdark && hfasz <= 4;
  98. c->hfa.size = hfasz;
  99. if (c->ishfa) {
  100. for (n=0; n<hfasz; n++, c->nfp++) {
  101. c->reg[n] = *fp++;
  102. c->cls[n] = c->hfa.base;
  103. }
  104. c->nreg = n;
  105. }
  106. else if (t->isdark || sz > 16 || sz == 0) {
  107. /* large structs are replaced by a
  108. * pointer to some caller-allocated
  109. * memory */
  110. c->class |= Cptr;
  111. c->size = 8;
  112. c->ngp = 1;
  113. *c->reg = *gp;
  114. *c->cls = Kl;
  115. }
  116. else {
  117. for (n=0; n<sz/8; n++, c->ngp++) {
  118. c->reg[n] = *gp++;
  119. c->cls[n] = Kl;
  120. }
  121. c->nreg = n;
  122. }
  123. }
  124. static void
  125. sttmps(Ref tmp[], int cls[], uint nreg, Ref mem, Fn *fn)
  126. {
  127. uint n;
  128. uint64_t off;
  129. Ref r;
  130. assert(nreg <= 4);
  131. off = 0;
  132. for (n=0; n<nreg; n++) {
  133. tmp[n] = newtmp("abi", cls[n], fn);
  134. r = newtmp("abi", Kl, fn);
  135. emit(store[cls[n]], 0, R, tmp[n], r);
  136. emit(Oadd, Kl, r, mem, getcon(off, fn));
  137. off += KWIDE(cls[n]) ? 8 : 4;
  138. }
  139. }
  140. /* todo, may read out of bounds */
  141. static void
  142. ldregs(int reg[], int cls[], int n, Ref mem, Fn *fn)
  143. {
  144. int i;
  145. uint64_t off;
  146. Ref r;
  147. off = 0;
  148. for (i=0; i<n; i++) {
  149. r = newtmp("abi", Kl, fn);
  150. emit(Oload, cls[i], TMP(reg[i]), r, R);
  151. emit(Oadd, Kl, r, mem, getcon(off, fn));
  152. off += KWIDE(cls[i]) ? 8 : 4;
  153. }
  154. }
  155. static void
  156. selret(Blk *b, Fn *fn)
  157. {
  158. int j, k, cty;
  159. Ref r;
  160. Class cr;
  161. j = b->jmp.type;
  162. if (!isret(j) || j == Jret0)
  163. return;
  164. r = b->jmp.arg;
  165. b->jmp.type = Jret0;
  166. if (j == Jretc) {
  167. typclass(&cr, &typ[fn->retty], gpreg, fpreg);
  168. if (cr.class & Cptr) {
  169. assert(rtype(fn->retr) == RTmp);
  170. emit(Oblit1, 0, R, INT(cr.t->size), R);
  171. emit(Oblit0, 0, R, r, fn->retr);
  172. cty = 0;
  173. } else {
  174. ldregs(cr.reg, cr.cls, cr.nreg, r, fn);
  175. cty = (cr.nfp << 2) | cr.ngp;
  176. }
  177. } else {
  178. k = j - Jretw;
  179. if (KBASE(k) == 0) {
  180. emit(Ocopy, k, TMP(R0), r, R);
  181. cty = 1;
  182. } else {
  183. emit(Ocopy, k, TMP(V0), r, R);
  184. cty = 1 << 2;
  185. }
  186. }
  187. b->jmp.arg = CALL(cty);
  188. }
  189. static int
  190. argsclass(Ins *i0, Ins *i1, Class *carg)
  191. {
  192. int va, envc, ngp, nfp, *gp, *fp;
  193. Class *c;
  194. Ins *i;
  195. va = 0;
  196. envc = 0;
  197. gp = gpreg;
  198. fp = fpreg;
  199. ngp = 8;
  200. nfp = 8;
  201. for (i=i0, c=carg; i<i1; i++, c++)
  202. switch (i->op) {
  203. case Oargsb:
  204. case Oargub:
  205. case Oparsb:
  206. case Oparub:
  207. c->size = 1;
  208. goto Scalar;
  209. case Oargsh:
  210. case Oarguh:
  211. case Oparsh:
  212. case Oparuh:
  213. c->size = 2;
  214. goto Scalar;
  215. case Opar:
  216. case Oarg:
  217. c->size = 8;
  218. if (T.apple && !KWIDE(i->cls))
  219. c->size = 4;
  220. Scalar:
  221. c->align = c->size;
  222. *c->cls = i->cls;
  223. if (va) {
  224. c->class |= Cstk;
  225. c->size = 8;
  226. c->align = 8;
  227. break;
  228. }
  229. if (KBASE(i->cls) == 0 && ngp > 0) {
  230. ngp--;
  231. *c->reg = *gp++;
  232. break;
  233. }
  234. if (KBASE(i->cls) == 1 && nfp > 0) {
  235. nfp--;
  236. *c->reg = *fp++;
  237. break;
  238. }
  239. c->class |= Cstk;
  240. break;
  241. case Oparc:
  242. case Oargc:
  243. typclass(c, &typ[i->arg[0].val], gp, fp);
  244. if (c->ngp <= ngp) {
  245. if (c->nfp <= nfp) {
  246. ngp -= c->ngp;
  247. nfp -= c->nfp;
  248. gp += c->ngp;
  249. fp += c->nfp;
  250. break;
  251. } else
  252. nfp = 0;
  253. } else
  254. ngp = 0;
  255. c->class |= Cstk;
  256. break;
  257. case Opare:
  258. case Oarge:
  259. *c->reg = R9;
  260. *c->cls = Kl;
  261. envc = 1;
  262. break;
  263. case Oargv:
  264. va = T.apple != 0;
  265. break;
  266. default:
  267. die("unreachable");
  268. }
  269. return envc << 14 | (gp-gpreg) << 5 | (fp-fpreg) << 9;
  270. }
  271. bits
  272. arm64_retregs(Ref r, int p[2])
  273. {
  274. bits b;
  275. int ngp, nfp;
  276. assert(rtype(r) == RCall);
  277. ngp = r.val & 3;
  278. nfp = (r.val >> 2) & 7;
  279. if (p) {
  280. p[0] = ngp;
  281. p[1] = nfp;
  282. }
  283. b = 0;
  284. while (ngp--)
  285. b |= BIT(R0+ngp);
  286. while (nfp--)
  287. b |= BIT(V0+nfp);
  288. return b;
  289. }
  290. bits
  291. arm64_argregs(Ref r, int p[2])
  292. {
  293. bits b;
  294. int ngp, nfp, x8, x9;
  295. assert(rtype(r) == RCall);
  296. ngp = (r.val >> 5) & 15;
  297. nfp = (r.val >> 9) & 15;
  298. x8 = (r.val >> 13) & 1;
  299. x9 = (r.val >> 14) & 1;
  300. if (p) {
  301. p[0] = ngp + x8 + x9;
  302. p[1] = nfp;
  303. }
  304. b = 0;
  305. while (ngp--)
  306. b |= BIT(R0+ngp);
  307. while (nfp--)
  308. b |= BIT(V0+nfp);
  309. return b | ((bits)x8 << R8) | ((bits)x9 << R9);
  310. }
  311. static void
  312. stkblob(Ref r, Class *c, Fn *fn, Insl **ilp)
  313. {
  314. Insl *il;
  315. int al;
  316. uint64_t sz;
  317. il = alloc(sizeof *il);
  318. al = c->t->align - 2; /* NAlign == 3 */
  319. if (al < 0)
  320. al = 0;
  321. sz = c->class & Cptr ? c->t->size : c->size;
  322. il->i = (Ins){Oalloc+al, Kl, r, {getcon(sz, fn)}};
  323. il->link = *ilp;
  324. *ilp = il;
  325. }
  326. static uint
  327. align(uint x, uint al)
  328. {
  329. return (x + al-1) & -al;
  330. }
  331. static void
  332. selcall(Fn *fn, Ins *i0, Ins *i1, Insl **ilp)
  333. {
  334. Ins *i;
  335. Class *ca, *c, cr;
  336. int op, cty;
  337. uint n, stk, off;;
  338. Ref r, rstk, tmp[4];
  339. ca = alloc((i1-i0) * sizeof ca[0]);
  340. cty = argsclass(i0, i1, ca);
  341. stk = 0;
  342. for (i=i0, c=ca; i<i1; i++, c++) {
  343. if (c->class & Cptr) {
  344. i->arg[0] = newtmp("abi", Kl, fn);
  345. stkblob(i->arg[0], c, fn, ilp);
  346. i->op = Oarg;
  347. }
  348. if (c->class & Cstk) {
  349. stk = align(stk, c->align);
  350. stk += c->size;
  351. }
  352. }
  353. stk = align(stk, 16);
  354. rstk = getcon(stk, fn);
  355. if (stk)
  356. emit(Oadd, Kl, TMP(SP), TMP(SP), rstk);
  357. if (!req(i1->arg[1], R)) {
  358. typclass(&cr, &typ[i1->arg[1].val], gpreg, fpreg);
  359. stkblob(i1->to, &cr, fn, ilp);
  360. cty |= (cr.nfp << 2) | cr.ngp;
  361. if (cr.class & Cptr) {
  362. /* spill & rega expect calls to be
  363. * followed by copies from regs,
  364. * so we emit a dummy
  365. */
  366. cty |= 1 << 13 | 1;
  367. emit(Ocopy, Kw, R, TMP(R0), R);
  368. } else {
  369. sttmps(tmp, cr.cls, cr.nreg, i1->to, fn);
  370. for (n=0; n<cr.nreg; n++) {
  371. r = TMP(cr.reg[n]);
  372. emit(Ocopy, cr.cls[n], tmp[n], r, R);
  373. }
  374. }
  375. } else {
  376. if (KBASE(i1->cls) == 0) {
  377. emit(Ocopy, i1->cls, i1->to, TMP(R0), R);
  378. cty |= 1;
  379. } else {
  380. emit(Ocopy, i1->cls, i1->to, TMP(V0), R);
  381. cty |= 1 << 2;
  382. }
  383. }
  384. emit(Ocall, 0, R, i1->arg[0], CALL(cty));
  385. if (cty & (1 << 13))
  386. /* struct return argument */
  387. emit(Ocopy, Kl, TMP(R8), i1->to, R);
  388. for (i=i0, c=ca; i<i1; i++, c++) {
  389. if ((c->class & Cstk) != 0)
  390. continue;
  391. if (i->op == Oarg || i->op == Oarge)
  392. emit(Ocopy, *c->cls, TMP(*c->reg), i->arg[0], R);
  393. if (i->op == Oargc)
  394. ldregs(c->reg, c->cls, c->nreg, i->arg[1], fn);
  395. }
  396. /* populate the stack */
  397. off = 0;
  398. for (i=i0, c=ca; i<i1; i++, c++) {
  399. if ((c->class & Cstk) == 0)
  400. continue;
  401. off = align(off, c->align);
  402. r = newtmp("abi", Kl, fn);
  403. if (i->op == Oarg || isargbh(i->op)) {
  404. switch (c->size) {
  405. case 1: op = Ostoreb; break;
  406. case 2: op = Ostoreh; break;
  407. case 4:
  408. case 8: op = store[*c->cls]; break;
  409. default: die("unreachable");
  410. }
  411. emit(op, 0, R, i->arg[0], r);
  412. } else {
  413. assert(i->op == Oargc);
  414. emit(Oblit1, 0, R, INT(c->size), R);
  415. emit(Oblit0, 0, R, i->arg[1], r);
  416. }
  417. emit(Oadd, Kl, r, TMP(SP), getcon(off, fn));
  418. off += c->size;
  419. }
  420. if (stk)
  421. emit(Osub, Kl, TMP(SP), TMP(SP), rstk);
  422. for (i=i0, c=ca; i<i1; i++, c++)
  423. if (c->class & Cptr) {
  424. emit(Oblit1, 0, R, INT(c->t->size), R);
  425. emit(Oblit0, 0, R, i->arg[1], i->arg[0]);
  426. }
  427. }
  428. static Params
  429. selpar(Fn *fn, Ins *i0, Ins *i1)
  430. {
  431. Class *ca, *c, cr;
  432. Insl *il;
  433. Ins *i;
  434. int op, n, cty;
  435. uint off;
  436. Ref r, tmp[16], *t;
  437. ca = alloc((i1-i0) * sizeof ca[0]);
  438. curi = &insb[NIns];
  439. cty = argsclass(i0, i1, ca);
  440. fn->reg = arm64_argregs(CALL(cty), 0);
  441. il = 0;
  442. t = tmp;
  443. for (i=i0, c=ca; i<i1; i++, c++) {
  444. if (i->op != Oparc || (c->class & (Cptr|Cstk)))
  445. continue;
  446. sttmps(t, c->cls, c->nreg, i->to, fn);
  447. stkblob(i->to, c, fn, &il);
  448. t += c->nreg;
  449. }
  450. for (; il; il=il->link)
  451. emiti(il->i);
  452. if (fn->retty >= 0) {
  453. typclass(&cr, &typ[fn->retty], gpreg, fpreg);
  454. if (cr.class & Cptr) {
  455. fn->retr = newtmp("abi", Kl, fn);
  456. emit(Ocopy, Kl, fn->retr, TMP(R8), R);
  457. fn->reg |= BIT(R8);
  458. }
  459. }
  460. t = tmp;
  461. off = 0;
  462. for (i=i0, c=ca; i<i1; i++, c++)
  463. if (i->op == Oparc && !(c->class & Cptr)) {
  464. if (c->class & Cstk) {
  465. off = align(off, c->align);
  466. fn->tmp[i->to.val].slot = -(off+2);
  467. off += c->size;
  468. } else
  469. for (n=0; n<c->nreg; n++) {
  470. r = TMP(c->reg[n]);
  471. emit(Ocopy, c->cls[n], *t++, r, R);
  472. }
  473. } else if (c->class & Cstk) {
  474. off = align(off, c->align);
  475. if (isparbh(i->op))
  476. op = Oloadsb + (i->op - Oparsb);
  477. else
  478. op = Oload;
  479. emit(op, *c->cls, i->to, SLOT(-(off+2)), R);
  480. off += c->size;
  481. } else {
  482. emit(Ocopy, *c->cls, i->to, TMP(*c->reg), R);
  483. }
  484. return (Params){
  485. .stk = align(off, 8),
  486. .ngp = (cty >> 5) & 15,
  487. .nfp = (cty >> 9) & 15
  488. };
  489. }
  490. static Blk *
  491. split(Fn *fn, Blk *b)
  492. {
  493. Blk *bn;
  494. ++fn->nblk;
  495. bn = newblk();
  496. idup(bn, curi, &insb[NIns]-curi);
  497. curi = &insb[NIns];
  498. bn->visit = ++b->visit;
  499. strf(bn->name, "%s.%d", b->name, b->visit);
  500. bn->loop = b->loop;
  501. bn->link = b->link;
  502. b->link = bn;
  503. return bn;
  504. }
  505. static void
  506. chpred(Blk *b, Blk *bp, Blk *bp1)
  507. {
  508. Phi *p;
  509. uint a;
  510. for (p=b->phi; p; p=p->link) {
  511. for (a=0; p->blk[a]!=bp; a++)
  512. assert(a+1<p->narg);
  513. p->blk[a] = bp1;
  514. }
  515. }
  516. static void
  517. apple_selvaarg(Fn *fn, Blk *b, Ins *i)
  518. {
  519. Ref ap, stk, stk8, c8;
  520. (void)b;
  521. c8 = getcon(8, fn);
  522. ap = i->arg[0];
  523. stk8 = newtmp("abi", Kl, fn);
  524. stk = newtmp("abi", Kl, fn);
  525. emit(Ostorel, 0, R, stk8, ap);
  526. emit(Oadd, Kl, stk8, stk, c8);
  527. emit(Oload, i->cls, i->to, stk, R);
  528. emit(Oload, Kl, stk, ap, R);
  529. }
  530. static void
  531. arm64_selvaarg(Fn *fn, Blk *b, Ins *i)
  532. {
  533. Ref loc, lreg, lstk, nr, r0, r1, c8, c16, c24, c28, ap;
  534. Blk *b0, *bstk, *breg;
  535. int isgp;
  536. c8 = getcon(8, fn);
  537. c16 = getcon(16, fn);
  538. c24 = getcon(24, fn);
  539. c28 = getcon(28, fn);
  540. ap = i->arg[0];
  541. isgp = KBASE(i->cls) == 0;
  542. /* @b [...]
  543. r0 =l add ap, (24 or 28)
  544. nr =l loadsw r0
  545. r1 =w csltw nr, 0
  546. jnz r1, @breg, @bstk
  547. @breg
  548. r0 =l add ap, (8 or 16)
  549. r1 =l loadl r0
  550. lreg =l add r1, nr
  551. r0 =w add nr, (8 or 16)
  552. r1 =l add ap, (24 or 28)
  553. storew r0, r1
  554. @bstk
  555. lstk =l loadl ap
  556. r0 =l add lstk, 8
  557. storel r0, ap
  558. @b0
  559. %loc =l phi @breg %lreg, @bstk %lstk
  560. i->to =(i->cls) load %loc
  561. */
  562. loc = newtmp("abi", Kl, fn);
  563. emit(Oload, i->cls, i->to, loc, R);
  564. b0 = split(fn, b);
  565. b0->jmp = b->jmp;
  566. b0->s1 = b->s1;
  567. b0->s2 = b->s2;
  568. if (b->s1)
  569. chpred(b->s1, b, b0);
  570. if (b->s2 && b->s2 != b->s1)
  571. chpred(b->s2, b, b0);
  572. lreg = newtmp("abi", Kl, fn);
  573. nr = newtmp("abi", Kl, fn);
  574. r0 = newtmp("abi", Kw, fn);
  575. r1 = newtmp("abi", Kl, fn);
  576. emit(Ostorew, Kw, R, r0, r1);
  577. emit(Oadd, Kl, r1, ap, isgp ? c24 : c28);
  578. emit(Oadd, Kw, r0, nr, isgp ? c8 : c16);
  579. r0 = newtmp("abi", Kl, fn);
  580. r1 = newtmp("abi", Kl, fn);
  581. emit(Oadd, Kl, lreg, r1, nr);
  582. emit(Oload, Kl, r1, r0, R);
  583. emit(Oadd, Kl, r0, ap, isgp ? c8 : c16);
  584. breg = split(fn, b);
  585. breg->jmp.type = Jjmp;
  586. breg->s1 = b0;
  587. lstk = newtmp("abi", Kl, fn);
  588. r0 = newtmp("abi", Kl, fn);
  589. emit(Ostorel, Kw, R, r0, ap);
  590. emit(Oadd, Kl, r0, lstk, c8);
  591. emit(Oload, Kl, lstk, ap, R);
  592. bstk = split(fn, b);
  593. bstk->jmp.type = Jjmp;
  594. bstk->s1 = b0;
  595. b0->phi = alloc(sizeof *b0->phi);
  596. *b0->phi = (Phi){
  597. .cls = Kl, .to = loc,
  598. .narg = 2,
  599. .blk = vnew(2, sizeof b0->phi->blk[0], PFn),
  600. .arg = vnew(2, sizeof b0->phi->arg[0], PFn),
  601. };
  602. b0->phi->blk[0] = bstk;
  603. b0->phi->blk[1] = breg;
  604. b0->phi->arg[0] = lstk;
  605. b0->phi->arg[1] = lreg;
  606. r0 = newtmp("abi", Kl, fn);
  607. r1 = newtmp("abi", Kw, fn);
  608. b->jmp.type = Jjnz;
  609. b->jmp.arg = r1;
  610. b->s1 = breg;
  611. b->s2 = bstk;
  612. emit(Ocmpw+Cislt, Kw, r1, nr, CON_Z);
  613. emit(Oloadsw, Kl, nr, r0, R);
  614. emit(Oadd, Kl, r0, ap, isgp ? c24 : c28);
  615. }
  616. static void
  617. apple_selvastart(Fn *fn, Params p, Ref ap)
  618. {
  619. Ref off, stk, arg;
  620. off = getcon(p.stk, fn);
  621. stk = newtmp("abi", Kl, fn);
  622. arg = newtmp("abi", Kl, fn);
  623. emit(Ostorel, 0, R, arg, ap);
  624. emit(Oadd, Kl, arg, stk, off);
  625. emit(Oaddr, Kl, stk, SLOT(-1), R);
  626. }
  627. static void
  628. arm64_selvastart(Fn *fn, Params p, Ref ap)
  629. {
  630. Ref r0, r1, rsave;
  631. rsave = newtmp("abi", Kl, fn);
  632. r0 = newtmp("abi", Kl, fn);
  633. emit(Ostorel, Kw, R, r0, ap);
  634. emit(Oadd, Kl, r0, rsave, getcon(p.stk + 192, fn));
  635. r0 = newtmp("abi", Kl, fn);
  636. r1 = newtmp("abi", Kl, fn);
  637. emit(Ostorel, Kw, R, r1, r0);
  638. emit(Oadd, Kl, r1, rsave, getcon(64, fn));
  639. emit(Oadd, Kl, r0, ap, getcon(8, fn));
  640. r0 = newtmp("abi", Kl, fn);
  641. r1 = newtmp("abi", Kl, fn);
  642. emit(Ostorel, Kw, R, r1, r0);
  643. emit(Oadd, Kl, r1, rsave, getcon(192, fn));
  644. emit(Oaddr, Kl, rsave, SLOT(-1), R);
  645. emit(Oadd, Kl, r0, ap, getcon(16, fn));
  646. r0 = newtmp("abi", Kl, fn);
  647. emit(Ostorew, Kw, R, getcon((p.ngp-8)*8, fn), r0);
  648. emit(Oadd, Kl, r0, ap, getcon(24, fn));
  649. r0 = newtmp("abi", Kl, fn);
  650. emit(Ostorew, Kw, R, getcon((p.nfp-8)*16, fn), r0);
  651. emit(Oadd, Kl, r0, ap, getcon(28, fn));
  652. }
  653. void
  654. arm64_abi(Fn *fn)
  655. {
  656. Blk *b;
  657. Ins *i, *i0;
  658. Insl *il;
  659. int n0, n1, ioff;
  660. Params p;
  661. for (b=fn->start; b; b=b->link)
  662. b->visit = 0;
  663. /* lower parameters */
  664. for (b=fn->start, i=b->ins; i<&b->ins[b->nins]; i++)
  665. if (!ispar(i->op))
  666. break;
  667. p = selpar(fn, b->ins, i);
  668. n0 = &insb[NIns] - curi;
  669. ioff = i - b->ins;
  670. n1 = b->nins - ioff;
  671. vgrow(&b->ins, n0+n1);
  672. icpy(b->ins+n0, b->ins+ioff, n1);
  673. icpy(b->ins, curi, n0);
  674. b->nins = n0+n1;
  675. /* lower calls, returns, and vararg instructions */
  676. il = 0;
  677. b = fn->start;
  678. do {
  679. if (!(b = b->link))
  680. b = fn->start; /* do it last */
  681. if (b->visit)
  682. continue;
  683. curi = &insb[NIns];
  684. selret(b, fn);
  685. for (i=&b->ins[b->nins]; i!=b->ins;)
  686. switch ((--i)->op) {
  687. default:
  688. emiti(*i);
  689. break;
  690. case Ocall:
  691. for (i0=i; i0>b->ins; i0--)
  692. if (!isarg((i0-1)->op))
  693. break;
  694. selcall(fn, i0, i, &il);
  695. i = i0;
  696. break;
  697. case Ovastart:
  698. if (T.apple)
  699. apple_selvastart(fn, p, i->arg[0]);
  700. else
  701. arm64_selvastart(fn, p, i->arg[0]);
  702. break;
  703. case Ovaarg:
  704. if (T.apple)
  705. apple_selvaarg(fn, b, i);
  706. else
  707. arm64_selvaarg(fn, b, i);
  708. break;
  709. case Oarg:
  710. case Oargc:
  711. die("unreachable");
  712. }
  713. if (b == fn->start)
  714. for (; il; il=il->link)
  715. emiti(il->i);
  716. idup(b, curi, &insb[NIns]-curi);
  717. } while (b != fn->start);
  718. if (debug['A']) {
  719. fprintf(stderr, "\n> After ABI lowering:\n");
  720. printfn(fn, stderr);
  721. }
  722. }
  723. /* abi0 for apple target; introduces
  724. * necessary sign extensions in calls
  725. * and returns
  726. */
  727. void
  728. apple_extsb(Fn *fn)
  729. {
  730. Blk *b;
  731. Ins *i0, *i1, *i;
  732. int j, op;
  733. Ref r;
  734. for (b=fn->start; b; b=b->link) {
  735. curi = &insb[NIns];
  736. j = b->jmp.type;
  737. if (isretbh(j)) {
  738. r = newtmp("abi", Kw, fn);
  739. op = Oextsb + (j - Jretsb);
  740. emit(op, Kw, r, b->jmp.arg, R);
  741. b->jmp.arg = r;
  742. b->jmp.type = Jretw;
  743. }
  744. for (i=&b->ins[b->nins]; i>b->ins;) {
  745. emiti(*--i);
  746. if (i->op != Ocall)
  747. continue;
  748. for (i0=i1=i; i0>b->ins; i0--)
  749. if (!isarg((i0-1)->op))
  750. break;
  751. for (i=i1; i>i0;) {
  752. emiti(*--i);
  753. if (isargbh(i->op)) {
  754. i->to = newtmp("abi", Kl, fn);
  755. curi->arg[0] = i->to;
  756. }
  757. }
  758. for (i=i1; i>i0;)
  759. if (isargbh((--i)->op)) {
  760. op = Oextsb + (i->op - Oargsb);
  761. emit(op, Kw, i->to, i->arg[0], R);
  762. }
  763. }
  764. idup(b, curi, &insb[NIns]-curi);
  765. }
  766. if (debug['A']) {
  767. fprintf(stderr, "\n> After Apple pre-ABI:\n");
  768. printfn(fn, stderr);
  769. }
  770. }