Hi,
On 2024-04-16 01:50, Paul Moore wrote:
Writing my own backend. I am trying to understand reg_classes
On the face of it, it looks like a list of registers with flags saying
what classes they are in (int , float..)
So get_reg works down the table looking for registers of the right
class, fine, got it.
But the RC_RET function uses a register class as an index into that
table , R_RET(t) returned the class required for the return register and
RC_RET used that class as in index and then returned the value it found
as a class. So this is saying that the entries in this table are
register classes not a list of registers with their classes.
RC_RET uses a R_RET(t) which return which register is supposed to be
used as a return register for that type, it's not the class, but the
number of the register. So, RC_RET obtains that register's class and
returns it.
RC_RET(t) -> R_RET(t) (aka which register would this function use as a
return reg) -> &...
So, reg_classes is an array which index is the register number and the
value are some register flags.
I must be missing something obvious cos the existing backends work 😊
You can see that in the ARM backend for example:
/* pretty names for the registers */
enum {
TREG_R0 = 0,
TREG_R1,
TREG_R2,
TREG_R3,
TREG_R12,
TREG_F0,
TREG_F1,
TREG_F2,
TREG_F3,
#ifdef TCC_ARM_VFP
TREG_F4,
TREG_F5,
TREG_F6,
TREG_F7,
#endif
TREG_SP = 13,
TREG_LR,
};
ST_DATA const int reg_classes[NB_REGS] = {
/* r0 */ RC_INT | RC_R0,
/* r1 */ RC_INT | RC_R1,
/* r2 */ RC_INT | RC_R2,
/* r3 */ RC_INT | RC_R3,
/* r12 */ RC_INT | RC_R12,
/* f0 */ RC_FLOAT | RC_F0,
/* f1 */ RC_FLOAT | RC_F1,
/* f2 */ RC_FLOAT | RC_F2,
/* f3 */ RC_FLOAT | RC_F3,
#ifdef TCC_ARM_VFP
/* d4/s8 */ RC_FLOAT | RC_F4,
/* d5/s10 */ RC_FLOAT | RC_F5,
/* d6/s12 */ RC_FLOAT | RC_F6,
/* d7/s14 */ RC_FLOAT | RC_F7,
#endif
};
/* return registers for function */
#define REG_IRET TREG_R0 /* single word int return register */
#define REG_IRE2 TREG_R1 /* second word return register (for long long) */
#define REG_FRET TREG_F0 /* float return register */
The first registers are for int (RC_INT) operations, and the next are
for floats (RC_FLOAT). When you call R_RET() with an int it will return
REG_IRET which is defined as TREG_R0 in the enum, and has a RC_INT class
in the reg_classes.
If you call R_RET() with a float it returns REG_FRET, which is TREG_F0
(the 5th element in the enum) and has a RC_FLOAT class according to
reg_classes (see reg_classes[5]).
So, if you RC_RET() on an int, it would call R_RET on an int, obtain the
register number for the integer returns (TREG_R0) and obtain its class
=> RC_INT.
So your first sight was correct: reg_classes has a list of registers and
it says which are the classes each of the registers have. They are not
necessarily all the registers, but those available for the allocator.
I hope this helps,
Ekaitz
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel