kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

native_target.c (7039B)


      1 #include "arch/native_target.h"
      2 
      3 static const NativePhysRegInfo* native_class_phys_reg(
      4     const NativeAllocClassInfo* ci, Reg reg) {
      5   for (u32 i = 0; ci && i < ci->nphys; ++i)
      6     if (ci->phys[i].reg == reg) return &ci->phys[i];
      7   return NULL;
      8 }
      9 
     10 const NativeAllocClassInfo* native_reg_info_class_info(
     11     const NativeRegInfo* ri, NativeAllocClass cls) {
     12   if (!ri || cls >= NATIVE_REG_CLASS_COUNT) return NULL;
     13   for (u32 i = 0; i < ri->nclasses; ++i) {
     14     const NativeAllocClassInfo* ci = &ri->classes[i];
     15     if ((NativeAllocClass)ci->cls == cls) return ci;
     16   }
     17   return NULL;
     18 }
     19 
     20 u32 native_reg_info_flag_mask(const NativeRegInfo* ri, NativeAllocClass cls,
     21                               u16 flag) {
     22   const NativeAllocClassInfo* ci = native_reg_info_class_info(ri, cls);
     23   u32 mask = 0;
     24   for (u32 i = 0; ci && i < ci->nphys; ++i)
     25     if ((ci->phys[i].flags & flag) != 0 &&
     26         ci->phys[i].reg < NATIVE_MAX_HARD_REGS)
     27       mask |= 1u << ci->phys[i].reg;
     28   return mask;
     29 }
     30 
     31 static u32 native_validate_reg_list(Compiler* c,
     32                                     const NativeAllocClassInfo* ci,
     33                                     const Reg* regs, u32 nregs,
     34                                     const char* list_name) {
     35   u32 mask = 0;
     36   if ((nregs != 0u) != (regs != NULL))
     37     compiler_panic(c, (SrcLoc){0, 0, 0},
     38                    "native register model: class %u has inconsistent %s list",
     39                    (unsigned)ci->cls, list_name);
     40   if (nregs > NATIVE_MAX_HARD_REGS)
     41     compiler_panic(c, (SrcLoc){0, 0, 0},
     42                    "native register model: class %u has too many %s registers "
     43                    "(%u)",
     44                    (unsigned)ci->cls, list_name, (unsigned)nregs);
     45   for (u32 i = 0; i < nregs; ++i) {
     46     Reg reg = regs[i];
     47     const NativePhysRegInfo* phys;
     48     if (reg >= NATIVE_MAX_HARD_REGS || (mask & (1u << reg)))
     49       compiler_panic(c, (SrcLoc){0, 0, 0},
     50                      "native register model: class %u has invalid/duplicate "
     51                      "%s register %u",
     52                      (unsigned)ci->cls, list_name, (unsigned)reg);
     53     phys = native_class_phys_reg(ci, reg);
     54     if (!phys || phys->cls != ci->cls)
     55       compiler_panic(c, (SrcLoc){0, 0, 0},
     56                      "native register model: class %u %s register %u is not a "
     57                      "matching physical register",
     58                      (unsigned)ci->cls, list_name, (unsigned)reg);
     59     mask |= 1u << reg;
     60   }
     61   return mask;
     62 }
     63 
     64 void native_reg_info_validate(Compiler* c, const NativeRegInfo* ri) {
     65   u32 seen = 0;
     66   if (!ri) return;
     67   if (ri->nclasses > NATIVE_REG_CLASS_COUNT ||
     68       (ri->nclasses != 0u) != (ri->classes != NULL))
     69     compiler_panic(c, (SrcLoc){0, 0, 0},
     70                    "native register model: invalid register class table");
     71   for (u32 n = 0; n < ri->nclasses; ++n) {
     72     const NativeAllocClassInfo* ci = &ri->classes[n];
     73     u32 cls = ci->cls;
     74     u32 known_mask = 0;
     75     u32 emit_mask;
     76     u32 asm_mask;
     77     if (cls >= NATIVE_REG_CLASS_COUNT || (seen & (1u << cls)))
     78       compiler_panic(c, (SrcLoc){0, 0, 0},
     79                      "native register model: duplicate/invalid register class "
     80                      "%u",
     81                      (unsigned)cls);
     82     seen |= 1u << cls;
     83     if ((ci->nphys != 0u) != (ci->phys != NULL) ||
     84         ci->nphys > NATIVE_MAX_HARD_REGS)
     85       compiler_panic(c, (SrcLoc){0, 0, 0},
     86                      "native register model: class %u has invalid physical "
     87                      "table size %u",
     88                      (unsigned)cls, (unsigned)ci->nphys);
     89     for (u32 i = 0; i < ci->nphys; ++i) {
     90       const NativePhysRegInfo* phys = &ci->phys[i];
     91       if (phys->reg >= NATIVE_MAX_HARD_REGS || phys->cls != cls ||
     92           (known_mask & (1u << phys->reg)))
     93         compiler_panic(c, (SrcLoc){0, 0, 0},
     94                        "native register model: class %u has invalid physical "
     95                        "register %u",
     96                        (unsigned)cls, (unsigned)phys->reg);
     97       if ((phys->flags & NATIVE_REG_CALLER_SAVED) &&
     98           (phys->flags & NATIVE_REG_CALLEE_SAVED))
     99         compiler_panic(c, (SrcLoc){0, 0, 0},
    100                        "native register model: class %u register %u is both "
    101                        "caller- and callee-saved",
    102                        (unsigned)cls, (unsigned)phys->reg);
    103       if ((phys->flags & NATIVE_REG_ALLOCABLE) &&
    104           (phys->flags & NATIVE_REG_RESERVED))
    105         compiler_panic(c, (SrcLoc){0, 0, 0},
    106                        "native register model: class %u register %u is both "
    107                        "allocable and reserved",
    108                        (unsigned)cls, (unsigned)phys->reg);
    109       known_mask |= 1u << phys->reg;
    110     }
    111     (void)native_validate_reg_list(c, ci, ci->ndt_allocable,
    112                                    ci->ndt_allocable_count, "O0 allocable");
    113     (void)native_validate_reg_list(c, ci, ci->scratch, ci->nscratch,
    114                                    "O0 scratch");
    115     emit_mask = native_validate_reg_list(c, ci, ci->emit_temps,
    116                                          ci->nemit_temps, "emit temp");
    117     asm_mask = native_validate_reg_list(c, ci, ci->asm_temps, ci->nasm_temps,
    118                                         "asm-internal temp");
    119     (void)native_validate_reg_list(c, ci, ci->direct_asm_allocable,
    120                                    ci->ndirect_asm_allocable,
    121                                    "direct-asm allocable");
    122     if (emit_mask & asm_mask)
    123       compiler_panic(c, (SrcLoc){0, 0, 0},
    124                      "native register model: class %u emit and asm temp banks "
    125                      "overlap",
    126                      (unsigned)cls);
    127     if (asm_mask &
    128         ~native_reg_info_flag_mask(ri, (NativeAllocClass)cls,
    129                                    NATIVE_REG_RESERVED))
    130       compiler_panic(c, (SrcLoc){0, 0, 0},
    131                      "native register model: class %u asm temp bank is not "
    132                      "reserved",
    133                      (unsigned)cls);
    134     if (ci->emit_cache_mask & ~emit_mask)
    135       compiler_panic(c, (SrcLoc){0, 0, 0},
    136                      "native register model: class %u cache mask escapes emit "
    137                      "temp bank",
    138                      (unsigned)cls);
    139     for (u32 i = 0; i < ci->nemit_temps; ++i) {
    140       const NativePhysRegInfo* phys =
    141           native_class_phys_reg(ci, ci->emit_temps[i]);
    142       if (phys && (phys->flags & NATIVE_REG_ALLOCABLE))
    143         compiler_panic(c, (SrcLoc){0, 0, 0},
    144                        "native register model: class %u emit temp %u is "
    145                        "allocable",
    146                        (unsigned)cls, (unsigned)ci->emit_temps[i]);
    147     }
    148     for (u32 i = 0; i < ci->nasm_temps; ++i) {
    149       const NativePhysRegInfo* phys =
    150           native_class_phys_reg(ci, ci->asm_temps[i]);
    151       if (phys && (phys->flags & NATIVE_REG_ALLOCABLE))
    152         compiler_panic(c, (SrcLoc){0, 0, 0},
    153                        "native register model: class %u asm temp %u is "
    154                        "allocable",
    155                        (unsigned)cls, (unsigned)ci->asm_temps[i]);
    156     }
    157   }
    158 }