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

Reply via email to