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 }