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