3 typedef struct Class_ Class
;
4 typedef struct Insl Insl
;
5 typedef struct Params Params
;
8 Cstk
= 1, /* pass on the stack */
9 Cptr
= 2, /* replaced by a pointer */
39 static int gpreg
[12] = {R0
, R1
, R2
, R3
, R4
, R5
, R6
, R7
};
40 static int fpreg
[12] = {V0
, V1
, V2
, V3
, V4
, V5
, V6
, V7
};
42 /* layout of call's second argument (RCall)
45 * |0.00|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)
54 isfloatv(Typ
*t
, char *cls
)
59 for (n
=0; n
<t
->nunion
; n
++)
60 for (f
=t
->fields
[n
]; f
->type
!= FEnd
; f
++)
73 if (isfloatv(&typ
[f
->len
], cls
))
83 typclass(Class
*c
, Typ
*t
, int *gp
, int *fp
)
88 sz
= (t
->size
+ 7) & -8;
95 err("alignments larger than 16 are not supported");
97 if (t
->dark
|| sz
> 16 || sz
== 0) {
98 /* large structs are replaced by a
99 * pointer to some caller-allocated
108 c
->ishfa
= isfloatv(t
, &c
->hfa
.base
);
109 c
->hfa
.size
= t
->size
/(KWIDE(c
->hfa
.base
) ? 8 : 4);
112 for (n
=0; n
<c
->hfa
.size
; n
++, c
->nfp
++) {
114 c
->cls
[n
] = c
->hfa
.base
;
117 for (n
=0; n
<sz
/8; n
++, c
->ngp
++) {
126 sttmps(Ref tmp
[], int cls
[], uint nreg
, Ref mem
, Fn
*fn
)
129 [Kw
] = Ostorew
, [Kl
] = Ostorel
,
130 [Ks
] = Ostores
, [Kd
] = Ostored
138 for (n
=0; n
<nreg
; n
++) {
139 tmp
[n
] = newtmp("abi", cls
[n
], fn
);
140 r
= newtmp("abi", Kl
, fn
);
141 emit(st
[cls
[n
]], 0, R
, tmp
[n
], r
);
142 emit(Oadd
, Kl
, r
, mem
, getcon(off
, fn
));
143 off
+= KWIDE(cls
[n
]) ? 8 : 4;
148 ldregs(int reg
[], int cls
[], int n
, Ref mem
, Fn
*fn
)
155 for (i
=0; i
<n
; i
++) {
156 r
= newtmp("abi", Kl
, fn
);
157 emit(Oload
, cls
[i
], TMP(reg
[i
]), r
, R
);
158 emit(Oadd
, Kl
, r
, mem
, getcon(off
, fn
));
159 off
+= KWIDE(cls
[i
]) ? 8 : 4;
164 selret(Blk
*b
, Fn
*fn
)
172 if (!isret(j
) || j
== Jret0
)
179 typclass(&cr
, &typ
[fn
->retty
], gpreg
, fpreg
);
180 cty
= (cr
.nfp
<< 2) | cr
.ngp
;
181 if (cr
.class & Cptr
) {
182 assert(rtype(fn
->retr
) == RTmp
);
183 blit(fn
->retr
, 0, r
, cr
.t
->size
, fn
);
185 ldregs(cr
.reg
, cr
.cls
, cr
.nreg
, r
, fn
);
189 emit(Ocopy
, k
, TMP(R0
), r
, R
);
192 emit(Ocopy
, k
, TMP(V0
), r
, R
);
197 b
->jmp
.arg
= CALL(cty
);
201 argsclass(Ins
*i0
, Ins
*i1
, Class
*carg
, Ref
*env
)
203 int ngp
, nfp
, *gp
, *fp
;
211 for (i
=i0
, c
=carg
; i
<i1
; i
++, c
++)
217 if (KBASE(i
->cls
) == 0 && ngp
> 0) {
222 if (KBASE(i
->cls
) == 1 && nfp
> 0) {
231 typclass(c
, &typ
[i
->arg
[0].val
], gp
, fp
);
232 if (c
->class & Cptr
) {
239 } else if (c
->ngp
<= ngp
) {
260 return ((gp
-gpreg
) << 5) | ((fp
-fpreg
) << 9);
264 arm64_retregs(Ref r
, int p
[2])
269 assert(rtype(r
) == RCall
);
271 nfp
= (r
.val
>> 2) & 7;
285 arm64_argregs(Ref r
, int p
[2])
290 assert(rtype(r
) == RCall
);
291 ngp
= (r
.val
>> 5) & 15;
292 nfp
= (r
.val
>> 9) & 15;
293 x8
= (r
.val
>> 13) & 1;
303 return b
| ((bits
)x8
<< R8
);
307 stkblob(Ref r
, Class
*c
, Fn
*fn
, Insl
**ilp
)
312 il
= alloc(sizeof *il
);
313 al
= c
->t
->align
- 2; /* NAlign == 3 */
316 il
->i
= (Ins
){Oalloc
+al
, Kl
, r
, {getcon(c
->t
->size
, fn
)}};
322 selcall(Fn
*fn
, Ins
*i0
, Ins
*i1
, Insl
**ilp
)
329 Ref r
, rstk
, env
, tmp
[4];
332 ca
= alloc((i1
-i0
) * sizeof ca
[0]);
333 cty
= argsclass(i0
, i1
, ca
, &env
);
336 for (i
=i0
, c
=ca
; i
<i1
; i
++, c
++) {
337 if (c
->class & Cptr
) {
338 i
->arg
[0] = newtmp("abi", Kl
, fn
);
339 stkblob(i
->arg
[0], c
, fn
, ilp
);
346 rstk
= getcon(stk
, fn
);
348 emit(Oadd
, Kl
, TMP(SP
), TMP(SP
), rstk
);
350 if (!req(i1
->arg
[1], R
)) {
351 typclass(&cr
, &typ
[i1
->arg
[1].val
], gpreg
, fpreg
);
352 stkblob(i1
->to
, &cr
, fn
, ilp
);
353 cty
|= (cr
.nfp
<< 2) | cr
.ngp
;
354 if (cr
.class & Cptr
) {
356 emit(Ocopy
, Kw
, R
, TMP(R0
), R
);
358 sttmps(tmp
, cr
.cls
, cr
.nreg
, i1
->to
, fn
);
359 for (n
=0; n
<cr
.nreg
; n
++) {
361 emit(Ocopy
, cr
.cls
[n
], tmp
[n
], r
, R
);
365 if (KBASE(i1
->cls
) == 0) {
366 emit(Ocopy
, i1
->cls
, i1
->to
, TMP(R0
), R
);
369 emit(Ocopy
, i1
->cls
, i1
->to
, TMP(V0
), R
);
376 die("todo (arm abi): env calls");
377 emit(Ocall
, 0, R
, i1
->arg
[0], CALL(cty
));
380 /* struct return argument */
381 emit(Ocopy
, Kl
, TMP(R8
), i1
->to
, R
);
383 for (i
=i0
, c
=ca
; i
<i1
; i
++, c
++) {
384 if ((c
->class & Cstk
) != 0)
387 emit(Ocopy
, *c
->cls
, TMP(*c
->reg
), i
->arg
[0], R
);
389 ldregs(c
->reg
, c
->cls
, c
->nreg
, i
->arg
[1], fn
);
393 for (i
=i0
, c
=ca
; i
<i1
; i
++, c
++) {
394 if ((c
->class & Cstk
) == 0)
396 if (i
->op
!= Oargc
) {
397 r
= newtmp("abi", Kl
, fn
);
398 emit(Ostorel
, 0, R
, i
->arg
[0], r
);
399 emit(Oadd
, Kl
, r
, TMP(SP
), getcon(off
, fn
));
401 blit(TMP(SP
), off
, i
->arg
[1], c
->size
, fn
);
405 emit(Osub
, Kl
, TMP(SP
), TMP(SP
), rstk
);
407 for (i
=i0
, c
=ca
; i
<i1
; i
++, c
++)
409 blit(i
->arg
[0], 0, i
->arg
[1], c
->t
->size
, fn
);
413 selpar(Fn
*fn
, Ins
*i0
, Ins
*i1
)
419 Ref r
, env
, tmp
[16], *t
;
422 ca
= alloc((i1
-i0
) * sizeof ca
[0]);
425 cty
= argsclass(i0
, i1
, ca
, &env
);
429 for (i
=i0
, c
=ca
; i
<i1
; i
++, c
++) {
430 if (i
->op
!= Oparc
|| (c
->class & (Cptr
|Cstk
)))
432 sttmps(t
, c
->cls
, c
->nreg
, i
->to
, fn
);
433 stkblob(i
->to
, c
, fn
, &il
);
436 for (; il
; il
=il
->link
)
439 if (fn
->retty
>= 0) {
440 typclass(&cr
, &typ
[fn
->retty
], gpreg
, fpreg
);
441 if (cr
.class & Cptr
) {
442 fn
->retr
= newtmp("abi", Kl
, fn
);
443 emit(Ocopy
, Kl
, fn
->retr
, TMP(R8
), R
);
448 for (i
=i0
, c
=ca
, s
=2; i
<i1
; i
++, c
++) {
450 && (c
->class & Cptr
) == 0) {
451 if (c
->class & Cstk
) {
452 fn
->tmp
[i
->to
.val
].slot
= -s
;
455 for (n
=0; n
<c
->nreg
; n
++) {
457 emit(Ocopy
, c
->cls
[n
], *t
++, r
, R
);
459 } else if (c
->class & Cstk
) {
460 r
= newtmp("abi", Kl
, fn
);
461 emit(Oload
, *c
->cls
, i
->to
, r
, R
);
462 emit(Oaddr
, Kl
, r
, SLOT(-s
), R
);
466 emit(Ocopy
, *c
->cls
, i
->to
, r
, R
);
471 die("todo (arm abi): env calls");
475 .ngp
= (cty
>> 5) & 15,
476 .nfp
= (cty
>> 9) & 15
481 split(Fn
*fn
, Blk
*b
)
487 bn
->nins
= &insb
[NIns
] - curi
;
488 idup(&bn
->ins
, curi
, bn
->nins
);
490 bn
->visit
= ++b
->visit
;
491 (void)!snprintf(bn
->name
, NString
, "%s.%d", b
->name
, b
->visit
);
499 chpred(Blk
*b
, Blk
*bp
, Blk
*bp1
)
504 for (p
=b
->phi
; p
; p
=p
->link
) {
505 for (a
=0; p
->blk
[a
]!=bp
; a
++)
512 selvaarg(Fn
*fn
, Blk
*b
, Ins
*i
)
514 Ref loc
, lreg
, lstk
, nr
, r0
, r1
, c8
, c16
, c24
, c28
, ap
;
515 Blk
*b0
, *bstk
, *breg
;
519 c16
= getcon(16, fn
);
520 c24
= getcon(24, fn
);
521 c28
= getcon(28, fn
);
523 isgp
= KBASE(i
->cls
) == 0;
526 r0 =l add ap, (24 or 28)
531 r0 =l add ap, (8 or 16)
534 r0 =w add nr, (8 or 16)
535 r1 =l add ap, (24 or 28)
542 %loc =l phi @breg %lreg, @bstk %lstk
543 i->to =(i->cls) load %loc
546 loc
= newtmp("abi", Kl
, fn
);
547 emit(Oload
, i
->cls
, i
->to
, loc
, R
);
553 chpred(b
->s1
, b
, b0
);
554 if (b
->s2
&& b
->s2
!= b
->s1
)
555 chpred(b
->s2
, b
, b0
);
557 lreg
= newtmp("abi", Kl
, fn
);
558 nr
= newtmp("abi", Kl
, fn
);
559 r0
= newtmp("abi", Kw
, fn
);
560 r1
= newtmp("abi", Kl
, fn
);
561 emit(Ostorew
, Kw
, R
, r0
, r1
);
562 emit(Oadd
, Kl
, r1
, ap
, isgp
? c24
: c28
);
563 emit(Oadd
, Kw
, r0
, nr
, isgp
? c8
: c16
);
564 r0
= newtmp("abi", Kl
, fn
);
565 r1
= newtmp("abi", Kl
, fn
);
566 emit(Oadd
, Kl
, lreg
, r1
, nr
);
567 emit(Oload
, Kl
, r1
, r0
, R
);
568 emit(Oadd
, Kl
, r0
, ap
, isgp
? c8
: c16
);
570 breg
->jmp
.type
= Jjmp
;
573 lstk
= newtmp("abi", Kl
, fn
);
574 r0
= newtmp("abi", Kl
, fn
);
575 emit(Ostorel
, Kw
, R
, r0
, ap
);
576 emit(Oadd
, Kl
, r0
, lstk
, c8
);
577 emit(Oload
, Kl
, lstk
, ap
, R
);
579 bstk
->jmp
.type
= Jjmp
;
582 b0
->phi
= alloc(sizeof *b0
->phi
);
584 .cls
= Kl
, .to
= loc
,
589 r0
= newtmp("abi", Kl
, fn
);
590 r1
= newtmp("abi", Kw
, fn
);
595 emit(Ocmpw
+Cislt
, Kw
, r1
, nr
, CON_Z
);
596 emit(Oloadsw
, Kl
, nr
, r0
, R
);
597 emit(Oadd
, Kl
, r0
, ap
, isgp
? c24
: c28
);
601 selvastart(Fn
*fn
, Params p
, Ref ap
)
605 rsave
= newtmp("abi", Kl
, fn
);
607 r0
= newtmp("abi", Kl
, fn
);
608 emit(Ostorel
, Kw
, R
, r0
, ap
);
609 emit(Oadd
, Kl
, r0
, rsave
, getcon(p
.nstk
*8 + 192, fn
));
611 r0
= newtmp("abi", Kl
, fn
);
612 r1
= newtmp("abi", Kl
, fn
);
613 emit(Ostorel
, Kw
, R
, r1
, r0
);
614 emit(Oadd
, Kl
, r1
, rsave
, getcon(64, fn
));
615 emit(Oadd
, Kl
, r0
, ap
, getcon(8, fn
));
617 r0
= newtmp("abi", Kl
, fn
);
618 r1
= newtmp("abi", Kl
, fn
);
619 emit(Ostorel
, Kw
, R
, r1
, r0
);
620 emit(Oadd
, Kl
, r1
, rsave
, getcon(192, fn
));
621 emit(Oaddr
, Kl
, rsave
, SLOT(-1), R
);
622 emit(Oadd
, Kl
, r0
, ap
, getcon(16, fn
));
624 r0
= newtmp("abi", Kl
, fn
);
625 emit(Ostorew
, Kw
, R
, getcon((p
.ngp
-8)*8, fn
), r0
);
626 emit(Oadd
, Kl
, r0
, ap
, getcon(24, fn
));
628 r0
= newtmp("abi", Kl
, fn
);
629 emit(Ostorew
, Kw
, R
, getcon((p
.nfp
-8)*16, fn
), r0
);
630 emit(Oadd
, Kl
, r0
, ap
, getcon(28, fn
));
642 for (b
=fn
->start
; b
; b
=b
->link
)
645 /* lower parameters */
646 for (b
=fn
->start
, i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++)
649 p
= selpar(fn
, b
->ins
, i
);
650 n
= b
->nins
- (i
- b
->ins
) + (&insb
[NIns
] - curi
);
651 i0
= alloc(n
* sizeof(Ins
));
652 ip
= icpy(ip
= i0
, curi
, &insb
[NIns
] - curi
);
653 ip
= icpy(ip
, i
, &b
->ins
[b
->nins
] - i
);
657 /* lower calls, returns, and vararg instructions */
662 b
= fn
->start
; /* do it last */
667 for (i
=&b
->ins
[b
->nins
]; i
!=b
->ins
;)
674 for (i0
=i
; i0
>b
->ins
; i0
--)
675 if (!isarg((i0
-1)->op
))
677 selcall(fn
, i0
, i
, &il
);
681 selvastart(fn
, p
, i
->arg
[0]);
691 for (; il
; il
=il
->link
)
693 b
->nins
= &insb
[NIns
] - curi
;
694 idup(&b
->ins
, curi
, b
->nins
);
695 } while (b
!= fn
->start
);
698 fprintf(stderr
, "\n> After ABI lowering:\n");