0001 // 0002 // Binds the silly sauce from parser.c to HolyC. AIWNIOS is built so when 0003 // you write a backend,HolyC will use it too,that way you dont have to re-port 0004 // your backend again when you port to another arch 0005 // 0006 #ifdef IMPORT_AIWNIOS_SYMS 0007 import U0 __HC_SetAOTRelocBeforeRIP(U8 *,I64); //See aiwn.h(TAKES number of bytes before current RIP the symbol is located at) 0008 import U8 *__HC_CmpCtrlDel(U8 *); 0009 import U8 *__HC_ICAdd_RawBytes(U8*,U8*,I64); 0010 import U8 *__HC_ICAdd_GetVargsPtr(U8*); 0011 import U8 *__HC_ICAdd_ToF64(U8 *); 0012 import U8 *__HC_ICAdd_ToI64(U8 *); 0013 import U0 __HC_ICSetLine(U8*,I64); 0014 import U8 *__HC_ICAdd_Max_I64(U8 *); 0015 import U8 *__HC_ICAdd_Min_I64(U8 *); 0016 import U8 *__HC_ICAdd_Max_U64(U8 *); 0017 import U8 *__HC_ICAdd_Min_U64(U8 *); 0018 import U8 *__HC_ICAdd_Max_F64(U8 *); 0019 import U8 *__HC_ICAdd_Min_F64(U8 *); 0020 import U8 *__HC_ICAdd_Typecast(U8 *,I64,I64); 0021 import U8 *__HC_ICAdd_SubCall(U8 *,U8 *); 0022 import U8 *__HC_ICAdd_SubProlog(U8 *); 0023 import U8 *__HC_ICAdd_SubRet(U8 *); 0024 import U8 *__HC_ICAdd_BoundedSwitch(U8*,U8*,U8*); 0025 import U8 *__HC_ICAdd_UnboundedSwitch(U8 *,U8 *); 0026 import U8 *__HC_ICAdd_PreInc(U8 *,I64); 0027 import U8 *__HC_ICAdd_Call(U8*,I64,I64 rt,I64 ptrs); 0028 import U8 *__HC_ICAdd_F64(U8*,F64); 0029 import U8 *__HC_ICAdd_I64(U8*,I64); 0030 import U8 * __HC_ICAdd_PreDec(U8*,I64); 0031 import U8 * __HC_ICAdd_PostDec(U8*,I64); 0032 import U8 * __HC_ICAdd_PostInc(U8*,I64); 0033 import U8 * __HC_ICAdd_Pow(U8 *); 0034 import U8 * __HC_ICAdd_Lock(U8 *); 0035 import U8 * __HC_ICAdd_Eq(U8*); 0036 import U8 * __HC_ICAdd_Div(U8*); 0037 import U8 * __HC_ICAdd_Sub(U8*); 0038 import U8 * __HC_ICAdd_Mul(U8*); 0039 import U8 * __HC_ICAdd_Add(U8*); 0040 import U8 * __HC_ICAdd_Deref(U8*,I64 rt,I64 ptrs); 0041 import U8 * __HC_ICAdd_Comma(U8*); 0042 import U0 __HC_ICSetLock(U8*); 0043 import U8 * __HC_ICAdd_ToBool(U8*); 0044 import U8 * __HC_ICAdd_Addr(U8*); 0045 import U8 * __HC_ICAdd_Xor(U8*); 0046 import U8 * __HC_ICAdd_Mod(U8*); 0047 import U8 * __HC_ICAdd_Or(U8*); 0048 import U8 * __HC_ICAdd_Lt(U8*); 0049 import U8 * __HC_ICAdd_Gt(U8*); 0050 import U8 * __HC_ICAdd_Le(U8*); 0051 import U8 * __HC_ICAdd_Ge(U8*); 0052 import U8 * __HC_ICAdd_LNot(U8*); 0053 import U8 * __HC_ICAdd_BNot(U8*); 0054 import U8 * __HC_ICAdd_AndAnd(U8*); 0055 import U8 * __HC_ICAdd_And(U8*); 0056 import U8 * __HC_ICAdd_OrOr(U8*); 0057 import U8 * __HC_ICAdd_XorXor(U8*); 0058 import U8 * __HC_ICAdd_Ne(U8*); 0059 import U8 * __HC_ICAdd_EqEq(U8*); 0060 import U8 * __HC_ICAdd_Lsh(U8*); 0061 import U8 * __HC_ICAdd_Rsh(U8*); 0062 import U8 * __HC_ICAdd_AddEq(U8*); 0063 import U8 * __HC_ICAdd_SubEq(U8*); 0064 import U8 * __HC_ICAdd_MulEq(U8*); 0065 import U8 * __HC_ICAdd_DivEq(U8*); 0066 import U8 * __HC_ICAdd_LshEq(U8*); 0067 import U8 * __HC_ICAdd_RshEq(U8*); 0068 import U8 * __HC_ICAdd_AndEq(U8*); 0069 import U8 * __HC_ICAdd_OrEq(U8*); 0070 import U8 * __HC_ICAdd_XorEq(U8*); 0071 import U8 * __HC_ICAdd_ModEq(U8*); 0072 import U8 * __HC_ICAdd_FReg(U8*,I64); 0073 import U8 * __HC_ICAdd_Vargs(U8 *,I64); 0074 import U8 * __HC_ICAdd_IReg(U8*,I64 r,I64 rt,I64 ptrs); 0075 import U8 * __HC_ICAdd_Frame(U8*,I64 off,I64 rt,I64 ptrs); 0076 import U8 *__HC_CodeMiscJmpTableNew(U8 *,U8 **cmts,I64 lo,I64 hi); 0077 import U8 *__HC_CodeMiscStrNew(U8*,U8*,I64 sz); 0078 import U8 *__HC_CodeMiscLabelNew(U8*,U8**patch_addr=NULL); 0079 import U8 *__HC_CmpCtrlNew(); 0080 import U8 *__HC_CodeCtrlPush(U8*); 0081 import U0 __HC_CodeCtrlPop(U8*); 0082 import U8 *__HC_Compile(U8*,I64 *sz=NULL,U8 **dbg_info=NULL,CHeapCtrl *); 0083 import U8 *__HC_CodeMiscStrNew(U8 *,U8*,I64); 0084 import U8 *__HC_CodeMiscJmpTableNew(U8*,U8**,I64,I64); 0085 import U8 *__HC_ICAdd_Label(U8*,U8*); 0086 import U8 *__HC_ICAdd_Goto(U8*,U8*); 0087 import U8 *__HC_ICAdd_GotoIf(U8*,U8*) 0088 import U8 *__HC_ICAdd_Str(U8*,U8*); //Takes a AIWNIOS code misc 0089 import U8 *__HC_ICAdd_Neg(U8*); 0090 import U8 *__HC_ICAdd_Ret(U8*); 0091 import U8 *__HC_ICAdd_Arg(U8*,I64); 0092 import U8 *__HC_ICAdd_SetFrameSize(U8*,I64); 0093 import U8 *__HC_ICAdd_Reloc(U8 *ccmp,U8 *cc,U64*,U8 *sym,I64 rt,I64 ptrsctrl); 0094 import U8 *__HC_ICAdd_RelocUnique(U8 *ccmp,U8 *cc,U64*,U8 *sym,I64 rt,I64 ptrsctrl); 0095 import U8 *__HC_ICAdd_StaticData(U8 *ccmp,U8 *cc,I64 at,U8 *d,I64 lctrl); 0096 import U8 *__HC_ICAdd_SetStaticsSize(U8 *,I64 szctrl); 0097 import U8 *__HC_ICAdd_StaticRef(U8 *,I64 off,I64 rt,I64 ptrsctrl); 0098 import U8 *__HC_ICAdd_ShortAddr(U8 *cc,U8*cctrl,U8*,U8**); 0099 import U0 __HC_CmpCtrlSetRip(U8*,I64); 0100 import U8 * __HC_ICAdd_BT(U8*); 0101 import U8 * __HC_ICAdd_BTC(U8*); 0102 import U8 * __HC_ICAdd_BTR(U8*); 0103 import U8 * __HC_ICAdd_BTS(U8*); 0104 import U8 * __HC_ICAdd_LBTC(U8*); 0105 import U8 * __HC_ICAdd_LBTR(U8*); 0106 import U8 * __HC_ICAdd_LBTS(U8*); 0107 import U0 __HC_CodeMiscInterateThroughRefs(U8 *,U0(*fptr)(U8*addr,U8*ud),U8*user_data); 0108 import U8 * __HC_ICAdd_Fs(U8*); 0109 import U8 * __HC_ICAdd_Gs(U8*); 0110 #else 0111 extern U8 *__HC_ICAdd_Max_I64(U8 *); 0112 extern U8 *__HC_ICAdd_Min_I64(U8 *); 0113 extern U8 *__HC_ICAdd_Max_U64(U8 *); 0114 extern U8 *__HC_ICAdd_Min_U64(U8 *); 0115 extern U8 *__HC_ICAdd_Max_F64(U8 *); 0116 extern U8 *__HC_ICAdd_Min_F64(U8 *); 0117 extern U8 *__HC_ICAdd_GetVargsPtr(U8*); 0118 extern U8 *__HC_ICAdd_RawBytes(U8*,U8*,I64); 0119 extern U0 __HC_CodeMiscInterateThroughRefs(U8 *,U0(*fptr)(U8*addr,U8*ud),U8*user_data); 0120 extern U8 * __HC_ICAdd_ToF64(U8 *); 0121 extern U8 * __HC_ICAdd_ToI64(U8 *); 0122 extern U0 __HC_ICSetLine(U8*,I64); 0123 extern U8 * __HC_ICAdd_Typecast(U8 *,I64,I64); 0124 extern U8 * __HC_ICAdd_SubCall(U8 *,U8 *); 0125 extern U8 * __HC_ICAdd_SubProlog(U8 *); 0126 extern U8 * __HC_ICAdd_SubRet(U8 *); 0127 extern U8 * __HC_ICAdd_BoundedSwitch(U8*,U8*,U8*); 0128 extern U8 * __HC_ICAdd_UnboundedSwitch(U8 *,U8 *); 0129 extern U8 * __HC_ICAdd_PreInc(U8 *,I64); 0130 extern U8 * __HC_ICAdd_Call(U8*,I64,I64 rt,I64 ptrs); 0131 extern U8 * __HC_ICAdd_F64(U8*,F64); 0132 extern U8 * __HC_ICAdd_I64(U8*,I64); 0133 extern U8 * __HC_ICAdd_PreDec(U8*,I64); 0134 extern U8 * __HC_ICAdd_PostDec(U8*,I64); 0135 extern U8 * __HC_ICAdd_PostInc(U8*,I64); 0136 extern U8 * __HC_ICAdd_Pow(U8 *); 0137 extern U8 * __HC_ICAdd_Eq(U8*); 0138 extern U8 * __HC_ICAdd_Div(U8*); 0139 extern U8 * __HC_ICAdd_Sub(U8*); 0140 extern U8 * __HC_ICAdd_Mul(U8*); 0141 extern U8 * __HC_ICAdd_Add(U8*); 0142 extern U8 * __HC_ICAdd_Deref(U8*,I64 rt,I64 ptrs); 0143 extern U8 * __HC_ICAdd_Comma(U8*); 0144 extern U8 * __HC_ICAdd_Addr(U8*); 0145 extern U8 * __HC_ICAdd_Xor(U8*); 0146 extern U8 * __HC_ICAdd_Mod(U8*); 0147 extern U8 * __HC_ICAdd_Or(U8*); 0148 extern U8 * __HC_ICAdd_Lt(U8*); 0149 extern U8 * __HC_ICAdd_Gt(U8*); 0150 extern U8 * __HC_ICAdd_Le(U8*); 0151 extern U8 * __HC_ICAdd_Ge(U8*); 0152 extern U8 * __HC_ICAdd_LNot(U8*); 0153 extern U8 * __HC_ICAdd_BNot(U8*); 0154 extern U8 * __HC_ICAdd_AndAnd(U8*); 0155 extern U8 * __HC_ICAdd_And(U8*); 0156 extern U8 * __HC_ICAdd_OrOr(U8*); 0157 extern U8 * __HC_ICAdd_XorXor(U8*); 0158 extern U8 * __HC_ICAdd_Ne(U8*); 0159 extern U8 * __HC_ICAdd_EqEq(U8*); 0160 extern U8 * __HC_ICAdd_Lsh(U8*); 0161 extern U8 * __HC_ICAdd_Rsh(U8*); 0162 extern U8 * __HC_ICAdd_AddEq(U8*); 0163 extern U8 * __HC_ICAdd_SubEq(U8*); 0164 extern U8 * __HC_ICAdd_MulEq(U8*); 0165 extern U8 * __HC_ICAdd_DivEq(U8*); 0166 extern U8 * __HC_ICAdd_LshEq(U8*); 0167 extern U8 * __HC_ICAdd_RshEq(U8*); 0168 extern U8 * __HC_ICAdd_AndEq(U8*); 0169 extern U8 * __HC_ICAdd_OrEq(U8*); 0170 extern U8 * __HC_ICAdd_XorEq(U8*); 0171 extern U8 * __HC_ICAdd_ModEq(U8*); 0172 extern U8 * __HC_ICAdd_FReg(U8*,I64); 0173 extern U8 * __HC_ICAdd_Ds(U8 *,I64); 0174 extern U8 * __HC_ICAdd_IReg(U8*,I64 r,I64 rt,I64 ptrs); 0175 extern U8 * __HC_ICAdd_Frame(U8*,I64 off,I64 rt,I64 ptrs); 0176 extern U8 *__HC_CodeMiscJmpTableNew(U8 *,U8 **cmts,I64 lo,I64 hi); 0177 extern U8 *__HC_CodeMiscStrNew(U8*,U8*,I64 sz); 0178 extern U8 *__HC_CodeMiscLabelNew(U8*,U8**); 0179 extern U8 *__HC_CmpCtrlNew(); 0180 extern U8 *__HC_CodeCtrlPush(U8*); 0181 extern U0 __HC_CodeCtrlPop(U8*); 0182 extern U8 *__HC_Compile(U8*,I64 *sz=NULL,U8 **dbg_info=NULL,CHeapCtrl *c); 0183 extern U8 *__HC_CodeMiscLabelNew(U8 *,U8 **patch_addr=NULL); 0184 extern U8 *__HC_CodeMiscStrNew(U8 *,U8*,I64); 0185 extern U8 *__HC_CodeMiscJmpTableNew(U8*,U8**,I64,I64); 0186 extern U8 *__HC_ICAdd_Label(U8*,U8*); 0187 extern U8 *__HC_ICAdd_Goto(U8*,U8*); 0188 extern U8 *__HC_ICAdd_GotoIf(U8*,U8*) 0189 extern U8 *__HC_ICAdd_Str(U8*,U8*); //Takes a AIWNIOS code misc 0190 extern U8 *__HC_ICAdd_Neg(U8*); 0191 extern U8 *__HC_ICAdd_Ret(U8*); 0192 extern U8 *__HC_ICAdd_Arg(U8*,I64); 0193 extern U8 *__HC_ICAdd_SetFrameSize(U8*,I64); 0194 extern U8 *__HC_ICAdd_Reloc(U8 *ccmp,U8 *cc,U64*,U8 *sym,I64 rt,I64 ptrsctrl); 0195 extern U8 *__HC_ICAdd_StaticData(U8 *ccmp,U8 *cc,I64 at,U8 *d,I64 lctrl); 0196 extern U8 *__HC_ICAdd_SetStaticsSize(U8 *,I64 szctrl); 0197 extern U8 *__HC_ICAdd_StaticRef(U8 *,I64 off,I64 rt,I64 ptrsctrl); 0198 extern U8 *__HC_ICAdd_ShortAddr(U8 *cc,U8*cctrl,U8*,U8**); 0199 extern U0 __HC_CmpCtrlSetRip(U8*,I64); 0200 extern U8 * __HC_ICAdd_BT(U8*); 0201 extern U8 * __HC_ICAdd_BTC(U8*); 0202 extern U8 * __HC_ICAdd_BTR(U8*); 0203 extern U8 * __HC_ICAdd_BTS(U8*); 0204 extern U8 * __HC_ICAdd_LBTC(U8*); 0205 extern U8 * __HC_ICAdd_LBTR(U8*); 0206 extern U8 * __HC_ICAdd_LBTS(U8*); 0207 extern U8 * __HC_ICAdd_Fs(U8*); 0208 extern U8 * __HC_ICAdd_Gs(U8*) 0209 #endif 0210 // 0211 // See arm_backend.c 0212 // 0213 #ifdef TARGET_AARCH64 0214 #define AIWNIOS_IREG_START 19 0215 #define AIWNIOS_IREG_CNT (28 - 19 + 1) 0216 #define AIWNIOS_FREG_START 8 0217 #define AIWNIOS_FREG_CNT (15 - 8 + 1) 0218 I64 VarIRegToReg(I64 r) {return r+AIWNIOS_IREG_START;} 0219 I64 VarFRegToReg(I64 r) {return r+AIWNIOS_FREG_START;} 0220 #endif 0221 0222 #ifdef TARGET_RISCV 0223 #define AIWNIOS_IREG_START 0 0224 #define AIWNIOS_FREG_START 0 0225 #define AIWNIOS_IREG_CNT (27-18+1+1) 0226 #define AIWNIOS_FREG_CNT (27-18+1+2) 0227 I64 VarFRegToReg(I64 r) { 0228 switch(r) { 0229 case 0: 0230 return 9; 0231 case 1: 0232 return 8; 0233 case 2: 0234 return 18; 0235 case 3: 0236 return 19; 0237 case 4: 0238 return 20; 0239 case 5: 0240 return 21; 0241 case 6: 0242 return 22; 0243 case 7: 0244 return 23; 0245 case 8: 0246 return 24; 0247 case 9: 0248 return 25; 0249 case 10: 0250 return 26; 0251 case 11: 0252 return 27; 0253 } 0254 throw('Compiler'); 0255 } 0256 I64 VarIRegToReg(I64 r) { 0257 switch(r) { 0258 case 0: 0259 return 9; 0260 case 1: 0261 return 18; 0262 case 2: 0263 return 19; 0264 case 3: 0265 return 20; 0266 case 4: 0267 return 21; 0268 case 5: 0269 return 22; 0270 case 6: 0271 return 23; 0272 case 7: 0273 return 24; 0274 case 8: 0275 return 25; 0276 case 9: 0277 return 26; 0278 case 10: 0279 return 27; 0280 } 0281 throw('Compiler'); 0282 } 0283 0284 #endif 0285 0286 0287 #ifdef TARGET_X86 0288 #define REG_RAX 0 0289 #define REG_RCX 1 0290 #define REG_RDX 2 0291 #define REG_RBX 3 0292 #define REG_RSP 4 0293 #define REG_RBP 5 0294 #define REG_RSI 6 0295 #define REG_RDI 7 0296 #define REG_R8 8 0297 #define REG_R9 9 0298 #define REG_R10 10 0299 #define REG_R11 11 0300 #define REG_R12 12 0301 #define REG_R13 13 0302 #define REG_R14 14 0303 #define REG_R15 15 0304 #define REG_RIP 16 0305 #define AIWNIOS_IREG_START 9 0306 #define AIWNIOS_IREG_CNT 7 0307 #define AIWNIOS_TMP_IREG_CNT 3 0308 #define AIWNIOS_REG_FP REG_RBP 0309 #define AIWNIOS_REG_SP REG_RSP 0310 #define AIWNIOS_TMP_IREG_START 0 0311 #define AIWNIOS_FREG_START 6 0312 #define AIWNIOS_FREG_CNT (15-6+1) 0313 #define AIWNIOS_TMP_FREG_START 2 0314 #define AIWNIOS_TMP_FREG_CNT 14 0315 I64 VarFRegToReg(I64 r) { 0316 return AIWNIOS_FREG_START+r; 0317 } 0318 0319 #endif 0320 // 0321 // Replaces IC_CALL_INDIRECT(IC_ADDR_IMPORT) with Short jumps if not import 0322 // 0323 U0 AiwniosMakeShortJmps(CCmpCtrl *cc,U8 *cc2) { 0324 CRPN *head=&cc->coc.coc_head,*cur,*new; 0325 CCodeMisc *misc; 0326 for(cur=head->next;cur!=head;cur=cur->next) { 0327 if(cur->type==IC_ADDR_IMPORT) { 0328 misc=cur->ic_data; 0329 if(!(misc->h->type&HTF_IMPORT)&&(misc->flags&CMF_SHORT_ADDR)) { 0330 force: 0331 misc->addr=__HC_CodeMiscLabelNew(cc2); 0332 cur->ic_flags|=ICF_SHORT_JMP; 0333 } else { 0334 //No use imports as short addresses 0335 misc->flags&=~CMF_SHORT_ADDR; 0336 /* Nroot removed this as not all platforms have easy access to lower 32bits 0337 #ifdef TARGET_X86 0338 //In X86_64,i will put all functions in low 32bits to avoid viener wfunctions. 0339 goto force; 0340 #endif 0341 */ 0342 } 0343 } 0344 next:; 0345 } 0346 } 0347 0348 0349 0350 0351 I64 IRegIsAvail(CHashFun *fun,I64 r) { 0352 CMemberLst *mlst=fun->member_lst_and_root; 0353 while(mlst) { 0354 if(mlst->reg==r&&mlst->member_class->raw_type!=RT_F64) 0355 return FALSE; 0356 mlst=mlst->next; 0357 } 0358 return TRUE; 0359 } 0360 0361 I64 FRegIsAvail(CHashFun *fun,I64 r) { 0362 CMemberLst *mlst=fun->member_lst_and_root; 0363 while(mlst) { 0364 if(mlst->reg==r&&mlst->member_class->raw_type==RT_F64) 0365 return FALSE; 0366 mlst=mlst->next; 0367 } 0368 return TRUE; 0369 } 0370 0371 class CI64Set { 0372 I64 cnt,cap; 0373 I64 *body; 0374 }; 0375 U0 I64SetDel(CI64Set *s) { 0376 Free(s->body); 0377 Free(s); 0378 } 0379 CI64Set *I64SetNew() { 0380 CI64Set *s=CAlloc(sizeof(CI64Set)); 0381 s->cap=16; 0382 s->body=CAlloc(16*8); 0383 return s; 0384 } 0385 Bool I64SetHas(CI64Set *s,I64 v) { 0386 I64 i=s->cnt; 0387 while(--i>=0) 0388 if(s->body[i]==v) 0389 return TRUE; 0390 return FALSE; 0391 } 0392 U0 I64SetAdd(CI64Set *s,I64 v) { 0393 if(I64SetHas(s,v)) return; 0394 I64 *new; 0395 if(s->cnt+1>=s->cap) { 0396 new=CAlloc(MSize(s->body)+16*8); 0397 s->cap+=16; 0398 MemCpy(new,s->body,s->cnt*8); 0399 Free(s->body); 0400 s->body=new; 0401 } 0402 s->body[s->cnt++]=v; 0403 } 0404 U0 I64SetAddAll(CI64Set *s,CI64Set *from) { 0405 I64 idx=from->cnt; 0406 while(--idx>=0) 0407 I64SetAdd(s,from->body[idx]); 0408 } 0409 U0 I64SetRem(CI64Set *s,I64 v) { 0410 I64 idx,ptr=0,del=0; 0411 for(idx=0;idx!=s->cnt;idx++) { 0412 if(s->body[idx]!=v) 0413 s->body[ptr++]=s->body[idx]; 0414 else 0415 del++; 0416 } 0417 s->cnt-=del; 0418 } 0419 U0 I64SetRemAll(CI64Set *s,CI64Set *from) { 0420 I64 idx=from->cnt; 0421 while(--idx>=0) 0422 I64SetRem(s,from->body[idx]); 0423 } 0424 0425 #ifdef TARGET_X86 0426 I64 VarIRegToReg(I64 r) { 0427 switch(r) { 0428 break;case 0: return REG_R10; 0429 break;case 1: return REG_R11; 0430 break;case 2: return REG_R12; 0431 break;case 3: return REG_R14; 0432 break;case 4: return REG_R15; 0433 break;case 5: return REG_RDI; 0434 //AIWNIOS_IREG_CNT ends at 6,NOT 7,SEE BELOW NOTE 0435 break;case 6: return REG_RSI; 0436 //DO NOT USE THIS WITH ANYTHING RELATED TO IC_DEREF 0437 break;case 7: return REG_R13; 0438 } 0439 throw('Compile'); 0440 } 0441 #endif 0442 class CAddShortRelocData { 0443 CCmpCtrl *cc; 0444 CCodeMisc *cm; 0445 U8 *machine_code; 0446 }; 0447 Bool Globalify(U8 *addr,CAddShortRelocData *data) { 0448 CCodeMisc *cm=data->cm; 0449 CCmpCtrl *cc=data->cc; 0450 if(!(cm->h->type&HTT_GLBL_VAR)) 0451 return FALSE; 0452 CAOTHeapGlbl *glbl_gh=cc->aotc->heap_glbls; 0453 CAOTHeapGlblRef *tmpghr; 0454 while(glbl_gh&&StrCmp(glbl_gh->str,cm->h->str)) { 0455 glbl_gh=glbl_gh->next; 0456 } 0457 if(glbl_gh) { 0458 tmpghr=CAlloc(sizeof CAOTHeapGlblRef); 0459 tmpghr->next=glbl_gh->references; 0460 glbl_gh->references=tmpghr; 0461 tmpghr->offset=cm->offset; 0462 tmpghr->rip=cc->aotc->rip+(addr-data->machine_code); 0463 return TRUE; 0464 } 0465 return FALSE; 0466 } 0467 U0 AddShortReloc(U8 *addr,CAddShortRelocData *data) { 0468 CAOTImportExport *tmpaie=CAlloc(sizeof(CAOTImportExport)); 0469 #ifdef TARGET_RISCV 0470 tmpaie->type=IET_REL_RISCV; //FOR FUNCTION CALLS ONLY 0471 #else 0472 tmpaie->type=IET_REL_I32; 0473 #endif 0474 tmpaie->str=StrNew(data->cm->h->str); 0475 tmpaie->rip=data->cc->aotc->rip+(addr-data->machine_code); 0476 tmpaie->offset=data->cm->offset; 0477 tmpaie->short_jmp=TRUE; 0478 QueIns(tmpaie,data->cc->aot->last_ie); 0479 } 0480 static Bool IsTLSReloc(CCodeMisc *misc) { 0481 if(misc->h&&(!StrCmp(misc->h->str,"__Fs")||!StrCmp(misc->h->str,"__Gs"))) 0482 return TRUE; 0483 return FALSE; 0484 } 0485 static Bool IsFunArg(CHashFun *fun,CMemberLst *lst) { 0486 if(!fun) return FALSE; 0487 CMemberLst *mlst=fun->member_lst_and_root; 0488 I64 idx,off=0; 0489 if(fun->flags&(1<<Ff_DOT_DOT_DOT)) 0490 off+=2; 0491 for(idx=0;idx!=fun->arg_cnt+off;idx++) { 0492 if(lst==mlst) return TRUE; 0493 mlst=mlst->next; 0494 } 0495 return FALSE; 0496 } 0497 static I64 FunArgIdx(CHashFun *fun,CMemberLst *lst) { 0498 if(!fun) return FALSE; 0499 CMemberLst *mlst=fun->member_lst_and_root; 0500 I64 idx,off=0; 0501 if(fun->flags&(1<<Ff_DOT_DOT_DOT)) 0502 off+=2; 0503 for(idx=0;idx!=fun->arg_cnt+off;idx++) { 0504 if(lst==mlst) return idx; 0505 mlst=mlst->next; 0506 } 0507 return -1; 0508 } 0509 Bool IsKill(I64 t) { 0510 switch(t) { 0511 case IC_SHL_EQU: 0512 case IC_MUL_EQU: 0513 case IC_SHR_EQU: 0514 case IC_DIV_EQU: 0515 case IC_MOD_EQU: 0516 case IC_AND_EQU: 0517 case IC_OR_EQU: 0518 case IC_XOR_EQU: 0519 case IC_ADD_EQU: 0520 case IC_SUB_EQU: 0521 case IC_ASSIGN: 0522 case IC__PP: 0523 case IC__MM: 0524 case IC_PP_: 0525 case IC_MM_: 0526 return TRUE; 0527 } 0528 return FALSE; 0529 } 0530 CRPN *NthArgument(CRPN *r,I64 a) { 0531 r=r->next; 0532 while(--a>=0) { 0533 r=ICNext(r); 0534 } 0535 return r; 0536 } 0537 I64 FoffToMemberIdx(CCmpCtrl *cc,I64 foff) { 0538 CMemberLst *mlst=cc->htc.fun->member_lst_and_root; 0539 I64 idx=0; 0540 while(mlst) { 0541 if(mlst->offset==foff) 0542 return idx; 0543 mlst=mlst->next; 0544 idx++; 0545 } 0546 0547 return -1; 0548 } 0549 CRPN *LabelToRPN(CCmpCtrl *cc,CCodeMisc *cm) { 0550 CRPN *head=&cc->coc.coc_head,*c; 0551 for(c=head->next;c!=head;c=c->next) { 0552 if(c->type==IC_LABEL&&c->ic_data==cm) { 0553 return c; 0554 } 0555 } 0556 return NULL; 0557 } 0558 CMemberLst *NthMember(CCmpCtrl *cc,I64 i) { 0559 CMemberLst *lst=cc->htc.fun->member_lst_and_root; 0560 while(--i>=0) { 0561 if(!lst) return NULL; 0562 lst=lst->next; 0563 } 0564 return lst; 0565 } 0566 U0 DumpNthVar(CCmpCtrl *cc,I64 live) { 0567 CMemberLst *lst=cc->htc.fun->member_lst_and_root; 0568 while(--live>=0) { 0569 if(!lst) return; 0570 lst=lst->next; 0571 } 0572 if(!lst) return; 0573 DbgPrint("%s,",lst->str); 0574 } 0575 U0 DumpLiveSet(CCmpCtrl *cc,CI64Set * set) { 0576 I64 bit; 0577 for(bit=0;bit!=set->cnt;bit++) 0578 DumpNthVar(cc,set->body[bit]); 0579 } 0580 //Kind of like SSA 0581 class CVarRenumber { 0582 CI64Set *nodes; 0583 I64 idx; 0584 I64 new_foffset; 0585 }; 0586 class CVarRenumbers:CI64Set { 0587 I64 foffset; 0588 }; 0589 class CGraphColoring { 0590 I64 *colors; 0591 }; 0592 class CGraph { 0593 CI64Set **connects; //Use Bt 0594 }; 0595 //This will restore the original IC_FRAME offsets 0596 U0 VarRenumbersDel(CVarRenumbers *s) { 0597 I64 o_foff=s->foffset; 0598 I64 cnt=s->cnt,cnt2; 0599 CVarRenumber *rn; 0600 CRPN *cur,*next; 0601 while(--cnt>=0) { 0602 rn=s->body[cnt]; 0603 cnt2=rn->nodes->cnt; 0604 while(--cnt2>=0) { 0605 cur=rn->nodes->body[cnt2]; 0606 next=ICNext(cur); 0607 while(next!=cur) { 0608 if(cur->type==IC_FRAME&&cur->ic_data==rn->new_foffset) 0609 cur->ic_data=o_foff; 0610 cur=cur->next; 0611 } 0612 } 0613 I64SetDel(rn->nodes); 0614 Free(rn); 0615 } 0616 Free(s->body); 0617 Free(s); 0618 } 0619 Bool InfectAdjacent(CI64Set *add_to,CRPN *a,I64 midx,CI64Set *visited) { 0620 CI64Set *stack; 0621 CI64Set *set; 0622 I64 cnt; 0623 if(!I64SetHas(a->live_in,midx)&&!I64SetHas(a->kill_regs,midx)) 0624 return FALSE; 0625 if(I64SetHas(visited,a)) return FALSE; 0626 stack=I64SetNew; 0627 I64SetAdd(stack,a); 0628 while(stack->cnt) { 0629 a=stack->body[--stack->cnt]; 0630 I64SetAdd(visited,a); 0631 if(!I64SetHas(a->live_in,midx)&&!I64SetHas(a->kill_regs,midx)) goto skip; 0632 I64SetAdd(add_to,a); 0633 set=a->user_data; 0634 for(cnt=0;cnt!=set->cnt;cnt++) { 0635 if(!I64SetHas(visited,set->body[cnt])) 0636 I64SetAdd(stack,set->body[cnt]); 0637 } 0638 set=a->user_data2; 0639 for(cnt=0;cnt!=set->cnt;cnt++) { 0640 if(!I64SetHas(visited,set->body[cnt])) 0641 I64SetAdd(stack,set->body[cnt]); 0642 } 0643 skip:; 0644 } 0645 I64SetDel(stack); 0646 return TRUE; 0647 } 0648 I64 MakeNumberedMember(CCmpCtrl *cc,I64 from_member,I64 num,I64 tmp_off,CMemberLst **who=NULL) { 0649 I64 mc; 0650 CMemberLst *nth=NthMember(cc,from_member),*new; 0651 new=CAlloc(sizeof CMemberLst); 0652 new->str=MStrPrint("%s.%d",nth->str,num); 0653 new->member_class=nth->member_class; 0654 new->reg=REG_ALLOC; 0655 new->use_cnt=1; //Avoid "unused" var warnings 0656 new->offset=tmp_off; 0657 MemberAdd(cc,new,cc->htc.fun,PRS1B_LOCAL_VAR); 0658 if(who) *who=new; 0659 new=cc->htc.fun->member_lst_and_root; 0660 mc=0; 0661 while(new) { 0662 mc++; 0663 new=new->next; 0664 } 0665 return mc-1; 0666 } 0667 U0 DumpLive(CCmpCtrl *cc) { 0668 CRPN *cur,*head=&cc->coc.coc_head; 0669 CI64Set *set; 0670 DbgPrint("Ent:%s\n",cc->htc.fun->str); 0671 for(cur=head->next;cur!=head;cur=ICNext(cur)) { 0672 DumpRPN(cur); 0673 DbgPrint("%s(IN:",intermediate_code_table[cur->type].name); 0674 set=cur->live_in; 0675 DumpLiveSet(cc,set); 0676 DbgPrint(")OUT:"); 0677 set=cur->live_out; 0678 DumpLiveSet(cc,set); 0679 DbgPrint("\n"); 0680 } 0681 } 0682 CVarRenumbers *GenerateRenumbersForVar(CCmpCtrl *cc,I64 member,I64 *foff) { 0683 I64 new_foff=*foff,cnt=0,idx; 0684 CRPN *head=&cc->coc.coc_head,*cur; 0685 CMemberLst *mlst=NthMember(cc,member),*who; 0686 CVarRenumbers *ret=CAlloc(sizeof CVarRenumbers); 0687 CVarRenumber *renum; 0688 CI64Set *visited=I64SetNew,*tset; 0689 CRPN *cur2,*next2,cnt2; 0690 ret->body=CAlloc(16*8); 0691 ret->cap=16; 0692 ret->foffset=mlst->offset; 0693 tset=I64SetNew; 0694 for(cur=head->next;cur!=head;cur=ICNext(cur)) { 0695 if(InfectAdjacent(tset,cur,member,visited)) { 0696 *foff-=8; 0697 0698 renum=CAlloc(sizeof CVarRenumber); 0699 renum->idx=MakeNumberedMember(cc,member,cnt++,*foff,&who); 0700 renum->nodes=I64SetNew; 0701 renum->new_foffset=*foff; 0702 I64SetAddAll(renum->nodes,tset); 0703 0704 //Renumber the offsets 0705 for(cnt2=tset->cnt-1;cnt2>=0;cnt2--) { 0706 cur2=tset->body[cnt2]; 0707 next2=ICNext(cur2); 0708 0709 I64SetRem(cur2->live_in,member); 0710 I64SetRem(cur2->live_out,member); 0711 I64SetRem(cur2->kill_regs,member); 0712 0713 I64SetAdd(cur2->live_in,renum->idx); 0714 I64SetAdd(cur2->live_out,renum->idx); 0715 I64SetAdd(cur2->kill_regs,renum->idx); 0716 0717 while(next2!=cur2) { 0718 if(cur2->type==IC_FRAME&&cur2->ic_data==ret->foffset) { 0719 who->use_cnt++; 0720 cur2->ic_data=renum->new_foffset; 0721 } 0722 cur2=cur2->next; 0723 } 0724 } 0725 tset->cnt=0; 0726 I64SetAdd(ret,renum); 0727 } 0728 } 0729 I64SetDel(tset); 0730 I64SetDel(visited); 0731 return ret; 0732 } 0733 U0 GraphColoringDel(CGraphColoring *c) { 0734 Free(c->colors); 0735 Free(c); 0736 } 0737 Bool IsPtrVar(CCmpCtrl *cc,I64 foff) { 0738 CRPN *rpn,*head=&cc->coc.coc_head,*rpn2; 0739 for(rpn=head->next;rpn!=head;) { 0740 if(rpn->type==IC_DEREF) { 0741 rpn2=ICNext(rpn); 0742 while(rpn!=rpn2) { 0743 if(rpn->type==IC_FRAME&&rpn->ic_data==foff) { 0744 return TRUE; 0745 } 0746 rpn=rpn->next; 0747 } 0748 } else 0749 rpn=rpn->next; 0750 } 0751 return FALSE; 0752 } 0753 CGraphColoring *GraphColor(CCmpCtrl *cc,Bool ireg=TRUE) { 0754 CGraph *graph=CAlloc(sizeof CGraph); 0755 CGraphColoring *coloring=CAlloc(sizeof CGraphColoring); 0756 CRPN *rpn,*head=&cc->coc.coc_head; 0757 I64 bit,tmp,bit2,tmp2,mcnt=0,color; 0758 I64 reg_cnt,nth_best,penalty,best_penalty; 0759 CMemberLst *lst=cc->htc.fun->member_lst_and_root,**flat; 0760 COptMemberVar *mv; 0761 I64 foff=cc->htc.fun->size,run,adj_score; 0762 CI64Set *renumbers=I64SetNew,*adjacent; 0763 U8 *canidates; 0764 while(lst) { 0765 mcnt++; 0766 lst=lst->next; 0767 } 0768 mv=CAlloc(sizeof(COptMemberVar)*mcnt); 0769 lst=cc->htc.fun->member_lst_and_root; 0770 for(tmp=0;tmp!=mcnt;tmp++) { 0771 mv[tmp].m=lst; 0772 lst=lst->next; 0773 } 0774 tmp2=mcnt; 0775 for(tmp=0;tmp!=mcnt;tmp++) { 0776 lst=mv[tmp].m; 0777 if(!IsFunArg(cc->htc.fun,lst)) { 0778 if(!(lst->reg==REG_NONE||0<=lst->reg<REG_REGS_NUM)) { 0779 if(lst->member_class->raw_type==RT_F64&&!ireg) { 0780 re_number:; 0781 I64SetAdd(renumbers,GenerateRenumbersForVar(cc,tmp,&foff)); 0782 } else if(lst->member_class->raw_type!=RT_F64&&ireg) { 0783 goto re_number; 0784 } 0785 } 0786 } 0787 } 0788 Free(mv); 0789 //Recompute with the splits 0790 lst=cc->htc.fun->member_lst_and_root; 0791 mcnt=0; 0792 while(lst) { 0793 mcnt++; 0794 lst=lst->next; 0795 } 0796 flat=CAlloc(8*mcnt); 0797 mv=CAlloc(sizeof(COptMemberVar)*mcnt); 0798 lst=cc->htc.fun->member_lst_and_root; 0799 for(tmp=0;tmp!=mcnt;tmp++) { 0800 flat[tmp]=lst; 0801 mv[tmp].m=lst; 0802 mv[tmp].score=lst->use_cnt; 0803 lst=lst->next; 0804 } 0805 0806 for(rpn=head->next;rpn!=head;rpn=rpn->next) { 0807 if(rpn->type==IC_FRAME) { 0808 for(tmp=0;tmp!=mcnt;tmp++) { 0809 if(mv[tmp].m->offset==rpn->ic_data) { 0810 if(rpn->last(CRPN*)->type==IC_ADDR) { 0811 mv[tmp].addrof_cnt++; 0812 mv[tmp].score=0; 0813 mv[tmp].m->reg=REG_NONE; 0814 } else if(cc->flags&CCF_NO_REG_OPT) { 0815 mv[tmp].score=0; 0816 mv[tmp].m->reg=REG_NONE; 0817 } else if(!mv[tmp].addrof_cnt) 0818 mv[tmp].score++; 0819 } 0820 } 0821 } 0822 } 0823 0824 0825 coloring->colors=CAlloc(8*mcnt); 0826 canidates=MAlloc(mcnt+64); 0827 graph->connects=CAlloc(8*mcnt); 0828 for(tmp=0;tmp!=mcnt;tmp++) { 0829 graph->connects[tmp]=I64SetNew; 0830 } 0831 for(rpn=head->next;rpn!=head;rpn=rpn->next) { 0832 if(rpn->live_in&&rpn->kill_regs) { 0833 for(tmp=0;tmp!=rpn->live_in->cnt;tmp++) { 0834 bit=rpn->live_in->body[tmp]; 0835 if(!(flat[bit]->member_class->raw_type==RT_F64^^!ireg)&&flat[bit]->reg!=REG_NONE) { 0836 for(tmp2=0;tmp2!=rpn->live_in->cnt;tmp2++) { 0837 bit2=rpn->live_in->body[tmp2]; 0838 if(!(flat[bit2]->member_class->raw_type==RT_F64^^!ireg)&&flat[bit2]->reg!=REG_NONE) { 0839 I64SetAdd(graph->connects[bit],bit2); 0840 I64SetAdd(graph->connects[bit2],bit); 0841 } 0842 } 0843 //Include kill regs 0844 for(tmp2=0;tmp2!=rpn->kill_regs->cnt;tmp2++) { 0845 bit2=rpn->kill_regs->body[tmp2]; 0846 if(!(flat[bit2]->member_class->raw_type==RT_F64^^!ireg)&&flat[bit2]->reg!=REG_NONE) { 0847 I64SetAdd(graph->connects[bit],bit2); 0848 I64SetAdd(graph->connects[bit2],bit); 0849 } 0850 } 0851 } 0852 } 0853 } 0854 } 0855 if(ireg) 0856 reg_cnt=AIWNIOS_IREG_CNT; 0857 else 0858 reg_cnt=AIWNIOS_FREG_CNT; 0859 //Pre-color varaibles that are defined via "reg" keyword 0860 for(tmp=0;tmp!=mcnt;tmp++) { 0861 if(0<=mv[tmp].m->reg<REG_REGS_NUM) { 0862 coloring->colors[tmp]=mv[tmp].m->reg; 0863 } 0864 } 0865 0866 best_penalty=I64_MAX; 0867 I64 *best_colors=CAlloc(8*mcnt); 0868 0869 MemSetI64(coloring->colors,-1,mcnt); 0870 for(run=2;run>=0;--run) { 0871 for(nth_best=mcnt-1;nth_best>=0;nth_best--) { 0872 for(tmp=0;tmp!=mcnt;tmp++) { 0873 if(mv[nth_best].m==flat[tmp]) {//Unused var? 0874 if(!graph->connects[tmp]->cnt) { 0875 coloring->colors[tmp]=-1; 0876 break; 0877 } 0878 MemSet(canidates,TRUE,reg_cnt); 0879 for(tmp2=0;tmp2!=mcnt;tmp2++) { 0880 if(I64SetHas(graph->connects[tmp],tmp2)) { 0881 if(tmp!=tmp2) { 0882 color=coloring->colors[tmp2]; 0883 canidates[color]=FALSE; 0884 } 0885 } 0886 } 0887 0888 color=coloring->colors[tmp]; 0889 if(color!=-1) { 0890 if(canidates[color]) { 0891 goto skip; 0892 } 0893 } 0894 coloring->colors[tmp]=-1; 0895 for(color=0;color!=reg_cnt;color++) { 0896 if(canidates[color]) { 0897 coloring->colors[tmp]=color; 0898 break; 0899 } 0900 } 0901 #ifdef TARGET_X86 0902 //Right here our color points to R13(VarIRegToReg(color)==R13) 0903 if(ireg&&canidates[color]) { 0904 //Try register R13(has quircks with being used with SIBs) 0905 //https://wiki.osdev.org/X86-64_Instruction_Encoding 0906 if(!IsPtrVar(cc,flat[tmp]->offset)) { 0907 coloring->colors[tmp]=color; 0908 break; 0909 } 0910 } 0911 #endif 0912 skip:; 0913 } 0914 } 0915 } 0916 0917 penalty=0; 0918 for(tmp=0;tmp!=mcnt;tmp++) { 0919 if(coloring->colors[tmp]==-1&&flat[tmp]->reg!=REG_NONE) { 0920 adjacent=graph->connects[tmp]; 0921 if(adjacent->cnt) 0922 penalty+=flat[tmp]->use_cnt; 0923 } 0924 } 0925 if(penalty<best_penalty) { 0926 best_penalty=penalty; 0927 MemCpy(best_colors,coloring->colors,8*mcnt); 0928 } 0929 if(!penalty) 0930 break; 0931 0932 //Make spilled registers unspilled to check if they are good. 0933 for(tmp=0;tmp!=mcnt;tmp++) { 0934 adjacent=graph->connects[tmp]; 0935 if(!adjacent->cnt) 0936 goto skip2; 0937 if(flat[tmp]->reg!=REG_NONE&&coloring->colors[tmp]==-1) { //Not Predefined 0938 MemSet(canidates,TRUE,reg_cnt); 0939 adj_score=I16_MAX; 0940 for(tmp2=0;tmp2!=adjacent->cnt;tmp2++) { 0941 color=coloring->colors[adjacent->body[tmp2]]; 0942 if(color!=-1) { 0943 canidates[color]=FALSE; 0944 adj_score=MinI64(adj_score,flat[tmp2]->use_cnt); 0945 } 0946 } 0947 for(tmp2=0;tmp2!=reg_cnt;tmp2++) { 0948 if(canidates[tmp2]) { 0949 coloring->colors[tmp]=tmp2; 0950 goto skip2; 0951 } 0952 } 0953 for(tmp2=0;tmp2!=adjacent->cnt;tmp2++) { 0954 if(adj_score==flat[tmp2]->use_cnt) { 0955 coloring->colors[tmp2]=-1; 0956 break; 0957 } 0958 } 0959 skip2:; 0960 } 0961 } 0962 } 0963 MemCpy(coloring->colors,best_colors,8*mcnt); 0964 Free(best_colors); 0965 0966 for(tmp=0;tmp!=mcnt;tmp++) { 0967 if(!(flat[tmp]->member_class->raw_type==RT_F64^^!ireg)) 0968 if(flat[tmp]->reg==REG_ALLOC||flat[tmp]->reg==REG_UNDEF) { 0969 if(coloring->colors[tmp]==-1) 0970 flat[tmp]->reg=REG_NONE; 0971 else if(ireg) 0972 flat[tmp]->reg=VarIRegToReg(coloring->colors[tmp]); 0973 else 0974 flat[tmp]->reg=VarFRegToReg(coloring->colors[tmp]); 0975 } 0976 I64SetDel(graph->connects[tmp]); 0977 } 0978 0979 for(rpn=head->last;rpn!=head;rpn=rpn->last) { 0980 if(rpn->type==IC_FRAME) { 0981 for(tmp=0;tmp!=mcnt;tmp++) { 0982 if(rpn->ic_data==mv[tmp].m->offset) { 0983 //I hope your arhcitectue of choice has less than REG_NONE registers 0984 if(0<=mv[tmp].m->reg<REG_NONE) { //REG_NONE is 32,other buddies are larger 0985 rpn->type=IC_REG; 0986 rpn->ic_data=mv[tmp].m->reg; 0987 } 0988 break; 0989 } 0990 } 0991 } 0992 } 0993 0994 //Keep area for the poo poo tempraries for FunRep 0995 cc->htc.fun->size=foff; 0996 0997 tmp=renumbers->cnt; 0998 while(--tmp>=0) 0999 VarRenumbersDel(renumbers->body[tmp]); 1000 I64SetDel(renumbers); 1001 Free(graph->connects); 1002 Free(canidates); 1003 Free(flat); 1004 Free(graph); 1005 Free(mv); 1006 return coloring; 1007 } 1008 U0 _RPNConnect(CRPN *to,CRPN *from) { 1009 I64SetAdd(to->user_data,from); 1010 I64SetAdd(from->user_data2,to); 1011 } 1012 U0 LiveVariableAnalysis(CCmpCtrl *cc) { 1013 CRPN *rpn,*head=&cc->coc.coc_head,**flat,*end_rpn,*start_rpn,*arg,*jump_to; 1014 CCodeMisc *tab; 1015 //On first_run I generate the graph connections,no need to recompute each time 1016 Bool changed=FALSE,first_run=TRUE; 1017 I64 cnt=0,idx,idx2; 1018 I64 which; 1019 I64 *old_live,old_in,old_out; 1020 CI64Set *changed1=I64SetNew,*changed2=I64SetNew; 1021 rpn=head->next; 1022 while(rpn!=head) { 1023 rpn=ICNext(rpn); 1024 cnt++; 1025 } 1026 flat=CAlloc(cnt*8); 1027 idx=0; 1028 rpn=head->next; 1029 while(rpn!=head) { 1030 //REVERSE polish notation 1031 flat[cnt-idx-1]=rpn; 1032 idx++; 1033 rpn->user_data=I64SetNew; 1034 rpn->user_data2=I64SetNew; 1035 rpn->live_in=I64SetNew; 1036 rpn->live_out=I64SetNew; 1037 rpn->kill_regs=I64SetNew; 1038 rpn->use_regs=I64SetNew; 1039 I64SetAdd(changed1,rpn); 1040 rpn=ICNext(rpn); 1041 } 1042 do { 1043 changed=FALSE; 1044 for(idx=0;idx!=changed1->cnt;idx++) { 1045 start_rpn=changed1->body[idx]; 1046 end_rpn=ICNext(start_rpn); 1047 1048 old_in=start_rpn->live_in->cnt; 1049 old_out=start_rpn->live_out->cnt; 1050 1051 if(first_run) 1052 for(rpn=start_rpn;rpn!=end_rpn;rpn=rpn->next) { 1053 idx2=intermediate_code_table[rpn->type].arg_cnt; 1054 switch(idx2) { 1055 case IS_V_ARG: 1056 idx2=rpn->length; 1057 break; 1058 case IS_2_ARG: 1059 idx2=2; 1060 break; 1061 case IS_1_ARG: 1062 idx2=1; 1063 break; 1064 case IS_0_ARG: 1065 idx2=0; 1066 break; 1067 } 1068 if(IsKill(rpn->type)) { 1069 arg=NthArgument(rpn,--idx2); 1070 if(arg->type==IC_FRAME) { 1071 which=FoffToMemberIdx(cc,arg->ic_data); 1072 if(rpn->type==IC__MM||rpn->type==IC__PP|| 1073 rpn->type==IC_MM_||rpn->type==IC_PP_|| 1074 rpn->type==IC_SHL_EQU|| 1075 rpn->type==IC_MUL_EQU|| 1076 rpn->type==IC_SHR_EQU|| 1077 rpn->type==IC_DIV_EQU|| 1078 rpn->type==IC_MOD_EQU|| 1079 rpn->type==IC_AND_EQU|| 1080 rpn->type==IC_OR_EQU|| 1081 rpn->type==IC_XOR_EQU|| 1082 rpn->type==IC_SUB_EQU|| 1083 rpn->type==IC_ADD_EQU) 1084 I64SetAdd(start_rpn->use_regs,which); 1085 I64SetAdd(start_rpn->kill_regs,which); 1086 } 1087 } 1088 while(--idx2>=0) { 1089 arg=NthArgument(rpn,idx2); 1090 if(arg->type==IC_FRAME) { 1091 which=FoffToMemberIdx(cc,arg->ic_data); 1092 I64SetAdd(start_rpn->use_regs,which); 1093 } 1094 } 1095 } 1096 1097 rpn=start_rpn; 1098 switch(rpn->type) { 1099 case IC_BR_ZERO ... IC_BR_NOT_BTC: 1100 if(first_run) { 1101 jump_to=LabelToRPN(cc,rpn->ic_data); 1102 if(!jump_to) throw('Compiler'); 1103 _RPNConnect(jump_to,rpn); 1104 I64SetAddAll(rpn->live_out,jump_to->live_in); 1105 goto next_ic; 1106 } else { 1107 use_outgoing: 1108 for(idx2=0;idx2!=rpn->user_data2(CI64Set*)->cnt;idx2++) { 1109 jump_to=rpn->user_data2(CI64Set*)->body[idx2]; 1110 I64SetAddAll(rpn->live_out,jump_to->live_in); 1111 } 1112 break; 1113 } 1114 case IC_NOBOUND_SWITCH: 1115 case IC_SWITCH: 1116 if(first_run) { 1117 tab=rpn->ic_data; 1118 for(idx2=0;idx2!=tab->range;idx2++) { 1119 if(tab->jmp_table[idx2]) { 1120 jump_to=LabelToRPN(cc,tab->jmp_table[idx2]); 1121 if(!jump_to) throw('Compiler'); 1122 I64SetAddAll(rpn->live_out,jump_to->live_in); 1123 _RPNConnect(jump_to,rpn); 1124 } 1125 } 1126 if(tab->dft) { 1127 jump_to=LabelToRPN(cc,tab->dft); 1128 I64SetAddAll(rpn->live_out,jump_to->live_in); 1129 _RPNConnect(jump_to,rpn); 1130 } 1131 } else 1132 goto use_outgoing; 1133 break; 1134 case IC_RET: 1135 break; 1136 case IC_JMP: 1137 if(first_run) { 1138 jump_to=LabelToRPN(cc,rpn->ic_data); 1139 if(jump_to) { 1140 I64SetAddAll(rpn->live_out,jump_to->live_in); 1141 _RPNConnect(jump_to,rpn); 1142 } 1143 } else 1144 goto use_outgoing; 1145 break; 1146 case IC_SUB_CALL: 1147 //Special behavior,we are kind of linking the ends(IC_SUB_CALL/IC_SUB_RET) in a weird way 1148 //DO NOT first_run CHECK THIS 1149 jump_to=LabelToRPN(cc,rpn->ic_data); 1150 if(jump_to) { 1151 I64SetAddAll(rpn->live_out,jump_to->live_in); 1152 _RPNConnect(jump_to,rpn); 1153 //Also connect to end of SUB_CALL 1154 for(idx2=0;idx2!=cnt;idx2++) { 1155 if(flat[idx2]->type==IC_SUB_RET&&flat[idx2]->ic_data==rpn->ic_data) { 1156 jump_to=flat[idx2]; 1157 _RPNConnect(rpn,jump_to); 1158 I64SetAddAll(jump_to->live_out,rpn->live_in); 1159 } 1160 } 1161 } 1162 goto next_ic; 1163 break; 1164 case IC_SUB_RET: 1165 break; 1166 default: 1167 next_ic: 1168 if(first_run) { 1169 for(idx2=0;idx2!=cnt;idx2++) { 1170 if(flat[idx2]==rpn&&idx2+1<cnt) { 1171 I64SetAddAll(rpn->live_out,flat[idx2+1]->live_in); 1172 _RPNConnect(flat[idx2+1],rpn); 1173 break; 1174 } 1175 } 1176 } else 1177 goto use_outgoing; 1178 } 1179 rpn->live_in->cnt=0; 1180 I64SetAddAll(rpn->live_in,rpn->live_out); 1181 I64SetRemAll(rpn->live_in,rpn->kill_regs); 1182 I64SetAddAll(rpn->live_in,rpn->use_regs); 1183 1184 if(old_in!=rpn->live_in->cnt||rpn->live_out->cnt!=old_out) { 1185 changed|=TRUE; 1186 I64SetAdd(changed2,rpn); 1187 for(idx2=0;idx2!=rpn->user_data(CI64Set*)->cnt;idx2++) 1188 I64SetAdd(changed2,rpn->user_data(CI64Set*)->body[idx2]); 1189 } 1190 } 1191 first_run=FALSE; 1192 SwapI64(&changed1,&changed2); 1193 changed2->cnt=0; 1194 } while(changed); 1195 1196 Free(flat); 1197 I64SetDel(changed1); 1198 I64SetDel(changed2); 1199 } 1200 1201 // 1202 // Turns my CRPN from the parser into the IC for the C side 1203 // 1204 U8 *AiwniosCompile(CCmpCtrl *cc,I64 *res_sz=NULL,CDbgInfo **info) { 1205 CRPN *head=&cc->coc.coc_head,*cur,*new; 1206 CCodeMisc *misc,**table; 1207 CMemberLst *mlst; 1208 COptMemberVar *mv=NULL; 1209 CHashImport *h; 1210 CAOTImportExport *tmpaie; 1211 CAOTAbsAddr *tmpabs; 1212 CAOTHeapGlbl *tmpgh,*glbl_gh; 1213 CAOTHeapGlblRef *tmpghr; 1214 CAddShortRelocData fill_user_data; 1215 I64 idx,argc,member_cnt=0,ir=AIWNIOS_IREG_START,fr=AIWNIOS_FREG_START,foff,*foff_lookup=NULL,align; 1216 I64 reported_min_ln=I16_MAX,reported_max_ln=I16_MIN; 1217 U8 **aiwnios_dbg_info=NULL; 1218 U8 *acc=__HC_CmpCtrlNew(),*machine_code,*stat_nam,*dumb_crap_apple; 1219 I64 *table_ptr; 1220 U8 *cc2=__HC_CodeCtrlPush(acc); 1221 U8 *dumb_static; 1222 I64 statics_sz=0; 1223 static I64 static_cnt=0; 1224 stat_nam=MStrPrint(".STATIC_%d",static_cnt++); 1225 if(GetOption(OPTf_BOUNDS_CHECK)&&HashFind("WhineOOB",cc->htc.glbl_hash_table,HTT_FUN)) { 1226 for(cur=head->next;cur!=head;cur=cur->next) { 1227 if(cur->type==IC_DEREF) { 1228 new=CAlloc(sizeof CRPN); 1229 new->type=IC_ADDR_IMPORT; 1230 new->ic_class=cmp.internal_types[RT_I64]; 1231 new->ic_data=CodeMiscHashNew(cc,HashFind("WhineOOB",cc->htc.glbl_hash_table,HTT_FUN)); 1232 QueInsRev(new,RPNNext(cur)); 1233 new=CAlloc(sizeof CRPN); 1234 new->type=IC_CALL_INDIRECT; 1235 new->length=2; 1236 new->ic_class=cmp.internal_types[RT_I64]; 1237 QueIns(new,cur); 1238 } 1239 } 1240 } 1241 #ifdef TARGET_X86 1242 if(cc->flags&CCF_AOT_COMPILE) 1243 AiwniosMakeShortJmps(cc,acc); 1244 #endif 1245 #ifdef TARGET_RISCV 1246 if(cc->flags&CCF_AOT_COMPILE) 1247 AiwniosMakeShortJmps(cc,acc); 1248 #endif 1249 if(cc->flags&CCF_AOT_COMPILE) 1250 __HC_CmpCtrl_SetAOT(acc); 1251 if(info) { 1252 idx=cc->max_line-cc->min_line; 1253 *info=MAlloc((idx+2)*8+sizeof(CDbgInfo)); 1254 info[0]->min_line=cc->min_line; 1255 info[0]->max_line=cc->max_line; 1256 } 1257 // 1258 // Step 1,do register allocation stuff by counting the occuraces of IC_FRAME,and making 1259 // sure arent getting the address of said location 1260 // 1261 if(cc->htc.fun) { 1262 LiveVariableAnalysis(cc); 1263 GraphColoringDel(GraphColor(cc,TRUE)); 1264 GraphColoringDel(GraphColor(cc,FALSE)); 1265 member_cnt=cc->htc.fun->member_cnt; 1266 mlst=cc->htc.fun->member_lst_and_root; 1267 if(cc->htc.fun->flags&(1<<Ff_DOT_DOT_DOT)) { 1268 member_cnt+=2; 1269 } 1270 mv=CAlloc(member_cnt*sizeof(COptMemberVar)); 1271 foff_lookup=CAlloc(member_cnt*sizeof I64); 1272 for(idx=0;idx!=member_cnt;idx++) { 1273 mv[idx].m=mlst; 1274 mlst=mlst->next; 1275 } 1276 1277 //In FunRep,the function is assumes to store registers somewhere 1278 //So i "store" them at the start of the function 1279 #ifdef TARGET_RISCV 1280 //In RiscV 1281 // s0 -> TOP 1282 // s0-8 -> return_address 1283 // s0-16 -> old s0 1284 foff=16; 1285 #else 1286 foff=0; 1287 #endif 1288 for(idx=0;idx!=member_cnt;idx++) { 1289 if(mv[idx].m->reg!=REG_NONE) { 1290 mv[idx].m->offset=foff; 1291 foff+=8; 1292 } 1293 } 1294 //Assign offsets 1295 for(idx=0;idx!=member_cnt;idx++) { 1296 mlst=mv[idx].m; 1297 //idx here is the alignment 1298 align=8; 1299 if(mlst->reg==REG_NONE) { 1300 #ifdef TARGET_AARCH64 1301 foff_lookup[idx].i32[1]=foff; 1302 foff_lookup[idx].i32[0]=mlst->offset; 1303 mlst->offset=foff; 1304 foff+=mlst->member_class->size*mlst->dim.total_cnt; 1305 if(foff&(align-1)) 1306 foff+=align-(foff&(align-1)); //Align to 8 1307 #else 1308 if(IsFunArg(cc->htc.fun,mlst)&&!(mlst->flags&MLF_DOT_DOT_DOT&&!StrCmp(mlst->str,"argv"))) { 1309 //Arguments are passed on stack so no need to mode 1310 foff_lookup[idx].i32[0]=mlst->offset; 1311 //16 to offset [PC,RBP] pair at base 1312 #ifdef TARGET_RISCV 1313 //See Above TARGET_RISCV_NOTE 1314 mlst->offset=-8*FunArgIdx(cc->htc.fun,mlst); 1315 #else 1316 mlst->offset=-16-8*FunArgIdx(cc->htc.fun,mlst); 1317 #endif 1318 foff_lookup[idx].i32[1]=mlst->offset; 1319 } else { 1320 foff_lookup[idx].i32[0]=mlst->offset; 1321 //In X86_64 the stack grows down and the RBP is above the stack pointer, 1322 //SO MOVE THE OFFSETS DOWN TO THE BOTTOM 1323 //RBP 1324 //x0 1325 //x1 1326 //.... 1327 //x8 <<=offset 1328 foff+=mlst->member_class->size*mlst->dim.total_cnt; 1329 if(foff&(align-1)) 1330 foff+=align-(foff&(align-1)); //Align to 8 1331 mlst->offset=foff; 1332 foff_lookup[idx].i32[1]=foff; 1333 } 1334 #endif 1335 } else { 1336 //Assign them a spot on the stack for debugging purposes 1337 foff+=8; 1338 if(foff&7) 1339 foff+=8-(foff&7); //Align to 8 1340 mlst->offset=foff; 1341 } 1342 } 1343 if(foff&7) 1344 foff+=8-(foff&7); //Align to 8 1345 cc->htc.fun->size=foff+16; 1346 } 1347 1348 //Replace the old frame address with the new one 1349 for(cur=head->last;cur!=head;cur=cur->last) 1350 if(cur->type==IC_FRAME) 1351 for(idx=0;idx!=member_cnt;idx++) { 1352 foff=foff_lookup[idx].i32[0]; 1353 if(foff==cur->ic_data) { 1354 cur->ic_data=foff_lookup[idx].i32[1]; 1355 break; 1356 } 1357 } 1358 Free(foff_lookup); 1359 1360 // 1361 // Step 1.5,Assign the variables from the arguments 1362 // 1363 if(cc->htc.fun) { 1364 __HC_ICAdd_SetFrameSize(cc2,cc->htc.fun->size+16); 1365 mlst=cc->htc.fun->member_lst_and_root; 1366 argc=cc->htc.fun->arg_cnt; 1367 if(cc->htc.fun->flags&(1<<Ff_DOT_DOT_DOT)) 1368 argc+=2; 1369 for(idx=0;idx!=argc;idx++) { 1370 if(mlst->reg==REG_NONE) 1371 __HC_ICAdd_Frame(cc2,mlst->offset,mlst->member_class->raw_type,0); 1372 else if(mlst->member_class->raw_type!=RT_F64) { 1373 __HC_ICAdd_IReg(cc2,mlst->reg,mlst->member_class->raw_type,0); 1374 } else { 1375 __HC_ICAdd_FReg(cc2,mlst->reg); 1376 } 1377 1378 #ifdef TARGET_X86 1379 //Not yet implemented for AARCH64 1380 if(mlst->flags&MLF_DOT_DOT_DOT&&!StrCmp(mlst->str,"argv")) { 1381 __HC_ICAdd_GetVargsPtr(cc2); 1382 } else 1383 __HC_ICAdd_Arg(cc2,idx); 1384 #endif 1385 #ifdef TARGET_RISCV 1386 //Not yet implemented for AARCH64 1387 if(mlst->flags&MLF_DOT_DOT_DOT&&!StrCmp(mlst->str,"argv")) { 1388 __HC_ICAdd_GetVargsPtr(cc2); 1389 } else 1390 __HC_ICAdd_Arg(cc2,idx); 1391 #endif 1392 #ifdef TARGET_AARCH64 1393 __HC_ICAdd_Arg(cc2,idx); 1394 #endif 1395 mlst=mlst->next; 1396 } 1397 Free(mv); 1398 } else { 1399 // 1400 // Add MANDITORY room for FP/LR pair 1401 // 1402 __HC_ICAdd_SetFrameSize(cc2,16); 1403 } 1404 // 1405 // 1406 // Step 2,convert CCodeMisc's to AIWNIOS codegen CCodeMiscs 1407 // 1408 for(misc=cc->coc.coc_next_misc;misc!=&cc->coc.coc_next_misc;misc=misc->next) { 1409 switch(misc->type) { 1410 break;case CMT_HASH_ENTRY: 1411 //See spider thing for more notes 1412 break;case CMT_LABEL: 1413 misc->addr=__HC_CodeMiscLabelNew(acc,&misc->addr2); 1414 break;case CMT_GOTO_LABEL: 1415 if(!(misc->flags&CMF_DEFINED)&&misc->str) { 1416 PrintErr("Undefined reference to label \"%s\".\n",misc->str); 1417 LexExcept(cc,"Undefined label reference"); 1418 } 1419 misc->addr=__HC_CodeMiscLabelNew(acc,&misc->addr2); 1420 break;case CMT_STR_CONST: 1421 misc->addr=__HC_CodeMiscStrNew(acc,misc->str,misc->st_len); 1422 // 1423 // Skip this for now,we want to assign the labels AIWNIOS codegen CCodeMiscs to 1424 // the labels and we will pass the labels'->addr to __HC_CodeMiscJmpTableNew 1425 //break;case CMT_JMP_TABLE: 1426 // misc->addr=__HC_CodeMiscJmpTableNew(cc2); 1427 // 1428 } 1429 } 1430 //See above note 1431 for(misc=cc->coc.coc_next_misc;misc!=&cc->coc.coc_next_misc;misc=misc->next) { 1432 if(misc->type==CMT_JMP_TABLE) { 1433 table=CAlloc(misc->range*8); 1434 for(idx=0;idx!=misc->range;idx++) 1435 table[idx]=misc->jmp_table[idx]->addr; 1436 misc->addr=__HC_CodeMiscJmpTableNew(acc,table,&misc->addr2,misc->range); 1437 Free(table); 1438 } 1439 } 1440 // 1441 // Step 3,Convert static addresses to static offsets and compute statics size 1442 // 1443 if(cc->htc.fun) { 1444 // 1445 // foff_lookup will have form [orig_static_data1,offset1,...,orig_static_dataN,offsetN] 1446 // 1447 foff=0; 1448 mlst=cc->htc.fun->member_lst_and_root; 1449 for(idx=0;idx!=member_cnt;idx++) { 1450 if(mlst->flags&MLF_STATIC) { 1451 //TODO 1452 // __HC_ICAdd_StaticData(acc,cc2,foff,mlst->static_data,mlst->member_class->size*mlst->dim.total_cnt); 1453 mlst->offset=foff; 1454 foff+=mlst->member_class->size*mlst->dim.total_cnt; 1455 if(foff%8) 1456 foff+=8-foff%8; 1457 } 1458 mlst=mlst->next; 1459 } 1460 if(foff) { 1461 statics_sz=foff; 1462 } 1463 } 1464 // 1465 // Step 4,OptClassFwd the ic_class'es to reduce to I64 to I64i's etc 1466 // 1467 // Classes with base type's need to be OptClassFwd'ed to reduce down to thier base type,otherwise 1468 // it is probably an RT_I64 1469 for(cur=head->last;cur!=head;cur=cur->last) { 1470 if(cur->ic_class) 1471 cur->ic_class=OptClassFwd(cur->ic_class); 1472 } 1473 // 1474 // Step 6,convert the CRPN's into AIWNIOS rpns 1475 // 1476 for(cur=head->last;cur!=head;cur=cur->last) { 1477 switch(cur->type) { 1478 break;case IC_MAX_I64: 1479 new=__HC_ICAdd_Max_I64(cc2); 1480 break;case IC_MAX_U64: 1481 new=__HC_ICAdd_Max_U64(cc2); 1482 break;case IC_MIN_I64: 1483 new=__HC_ICAdd_Min_I64(cc2); 1484 break;case IC_MIN_U64: 1485 new=__HC_ICAdd_Min_U64(cc2); 1486 break;case IC_FS: 1487 if(!cur->ic_data) { 1488 //Unique references to the TLS offset(unlike normal functions whose pointer is stored at the end of the function and loaded from there) 1489 misc=cur->ic_data=COCMiscNew(cc,CMT_HASH_ENTRY); 1490 misc->h=HashFind("__Fs",cc->htc.glbl_hash_table,HTT_FUN); 1491 if(!misc->h) 1492 misc->h=HashFind("__Fs",Fs->hash_table,HTT_FUN); //Maybe we arent AOT Compiling 1493 } 1494 misc=cur->ic_data; 1495 misc->addr=INVALID_PTR; 1496 misc->flags&=~CMF_SHORT_ADDR; 1497 if(!(misc->h->type&HTF_IMPORT)) { 1498 new=__HC_ICAdd_I64(cc2,misc->h(CHashFun*)->exe_addr); 1499 } else 1500 new=__HC_ICAdd_RelocUnique( 1501 acc, 1502 cc2, 1503 &misc->addr, 1504 "__Fs", 1505 RT_U8, 1506 1 1507 ); 1508 new=__HC_ICAdd_Fs(cc2); 1509 break;case IC_GS: 1510 if(!cur->ic_data) { 1511 //Unique references to the TLS offset(unlike normal functions whose pointer is stored at the end of the function and loaded from there) 1512 misc=cur->ic_data=COCMiscNew(cc,CMT_HASH_ENTRY); 1513 misc->h=HashFind("__Gs",cc->htc.glbl_hash_table,HTT_FUN); 1514 if(!misc->h) 1515 misc->h=HashFind("__Gs",Fs->hash_table,HTT_FUN); //Maybe we arent AOT Compiling 1516 } 1517 misc=cur->ic_data; 1518 misc->flags&=~CMF_SHORT_ADDR; 1519 misc->addr=INVALID_PTR; 1520 if(!(misc->h->type&HTF_IMPORT)) { 1521 new=__HC_ICAdd_I64(cc2,misc->h(CHashFun*)->exe_addr); 1522 } else 1523 new=__HC_ICAdd_RelocUnique( 1524 acc, 1525 cc2, 1526 &misc->addr, 1527 "__Gs", 1528 RT_U8, 1529 1 1530 ); 1531 new=__HC_ICAdd_Gs(cc2); 1532 break;case IC_LOCK: 1533 new=__HC_ICAdd_Lock(cc2); 1534 break;case IC_FRAME: 1535 if(cur->last(CRPN*)->type==IC_ADDR) { 1536 //Our HolyC part accounts for the pointers for us 1537 new=__HC_ICAdd_Frame(cc2,cur->ic_data,RT_U8,0); 1538 } else if(cur->ic_class->ptr_stars_cnt) 1539 //All pointer arithmetic is pre-computed 1540 new=__HC_ICAdd_Frame(cc2,cur->ic_data,RT_PTR,0); 1541 else if(!cur->ic_dim) 1542 new=__HC_ICAdd_Frame(cc2,cur->ic_data,cur->ic_class->raw_type,0); 1543 else 1544 new=__HC_ICAdd_Frame(cc2,cur->ic_data,RT_I64,0); 1545 break;case IC_BR_ZERO: 1546 new=__HC_ICAdd_LNot(cc2); 1547 new=__HC_ICAdd_GotoIf(cc2,cur->ic_data(CCodeMisc*)->addr); 1548 break;case IC_BR_NOT_ZERO: 1549 new=__HC_ICAdd_GotoIf(cc2,cur->ic_data(CCodeMisc*)->addr); 1550 //break;case IC_BR_CARRY: ??? 1551 //break;case IC_BR_NOT_CARRY: ??? 1552 break;case IC_BR_EQU_EQU: 1553 new=__HC_ICAdd_EqEq(cc2); 1554 new=__HC_ICAdd_GotoIf(cc2,cur->ic_data(CCodeMisc*)->addr); 1555 break;case IC_BR_NOT_EQU: 1556 new=__HC_ICAdd_Ne(cc2); 1557 new=__HC_ICAdd_GotoIf(cc2,cur->ic_data(CCodeMisc*)->addr); 1558 break;case IC_BR_LESS: 1559 new=__HC_ICAdd_Lt(cc2); 1560 new=__HC_ICAdd_GotoIf(cc2,cur->ic_data(CCodeMisc*)->addr); 1561 break;case IC_BR_GREATER_EQU: 1562 new=__HC_ICAdd_Ge(cc2); 1563 new=__HC_ICAdd_GotoIf(cc2,cur->ic_data(CCodeMisc*)->addr); 1564 break;case IC_BR_GREATER: 1565 new=__HC_ICAdd_Gt(cc2); 1566 new=__HC_ICAdd_GotoIf(cc2,cur->ic_data(CCodeMisc*)->addr); 1567 break;case IC_BR_LESS_EQU: 1568 new=__HC_ICAdd_Le(cc2); 1569 new=__HC_ICAdd_GotoIf(cc2,cur->ic_data(CCodeMisc*)->addr); 1570 //break;case IC_BR_EQU_EQU2: ??? 1571 //break;case IC_BR_NOT_EQU2: ??? 1572 //break;case IC_BR_LESS2 ??? 1573 //break;case IC_BR_GREATER_EQU2 ??? 1574 //break;case IC_BR_GREATER2 ??? 1575 //break;case IC_BR_LESS_EQU2 ??? 1576 //break;case IC_BR_AND_ZERO ??? 1577 //break;case IC_BR_AND_NOT_ZERO ??? 1578 //break;case IC_BR_MM_ZERO ??? 1579 //break;case IC_BR_MM_NOT_ZERO ??? 1580 //break;case IC_BR_AND_AND_ZERO ??? 1581 //break;case IC_BR_AND_AND_NOT_ZERO ??? 1582 //break;case IC_BR_OR_OR_ZERO ??? 1583 //break;case IC_BR_OR_OR_NOT_ZERO ??? 1584 break;case IC_END: //This is symbolic 1585 break;case IC_NOP1: 1586 break;case IC_END_EXP: 1587 break;case IC_NOP2: 1588 break;case IC_LABEL: 1589 new=__HC_ICAdd_Label(cc2,cur->ic_data(CCodeMisc*)->addr); 1590 break;case IC_ASM: 1591 __HC_ICAdd_Label(cc2,__HC_CodeMiscLabelNew(acc,&cur->ic_data(CAiwniosAOTBlob*)->final_start_addr)); 1592 new=__HC_ICAdd_RawBytes(cc2,cur->ic_data(CAiwniosAOTBlob*)->data,cur->ic_data(CAiwniosAOTBlob*)->len); 1593 1594 //break;case IC_CALL_START: AIWNIOS DOESNT USE THESE 1595 //break;case IC_CALL_END: 1596 //break;case IC_CALL_END2: 1597 //break;case IC_RETURN_VAL: 1598 //break;case IC_RETURN_VAL2: 1599 break;case IC_IMM_I64: 1600 new=__HC_ICAdd_I64(cc2,cur->imm_i64); 1601 break;case IC_IMM_F64: 1602 new=__HC_ICAdd_F64(cc2,cur->imm_f64); 1603 break;case IC_STR_CONST: 1604 new=__HC_ICAdd_Str(cc2,cur->ic_data(CCodeMisc*)->addr); 1605 break;case IC_ABS_ADDR: 1606 misc=COCMiscNew(cc,CMT_LABEL); 1607 misc->str=MStrPrint("0x%x",cur->imm_i64); 1608 misc->flags&=~CMF_SHORT_ADDR; 1609 misc->addr=INVALID_PTR; 1610 new=__HC_ICAdd_Reloc( 1611 acc, 1612 cc2, 1613 &misc->addr, 1614 misc->str, 1615 RT_U8, 1616 1 1617 ); 1618 break;case IC_ADDR_IMPORT: 1619 // 1620 //Aiwnios ALWAYS takes 1 import misc for each IMPORTED symbol(which can 1621 // be looked up multiple times by the function) 1622 // _____ 1623 // ________/ \________ 1624 // | | /( ^___^ )\ | | 1625 // | | | /( \_/ )\ | | | 1626 // | | | | \___/ | | | | 1627 //_/_| _|_| |_|_ |_ \_ 1628 // 1629 h=cur->ic_data(CCodeMisc*)->h; 1630 if(cur->ic_flags&ICF_SHORT_JMP) { 1631 new=__HC_ICAdd_ShortAddr(acc,cc2,h->str,cur->ic_data(CCodeMisc*)->addr); 1632 break; 1633 } 1634 if(h->type&HTT_GLBL_VAR) { 1635 if((h(CHashGlblVar*)->flags&GVF_EXTERN)||cc->flags&CCF_AOT_COMPILE) { 1636 new=__HC_ICAdd_RelocUnique( 1637 acc, 1638 cc2, 1639 &cur->ic_data(CCodeMisc*)->addr, 1640 h->str, 1641 RT_U8, 1642 1 1643 ); 1644 } else { 1645 new=__HC_ICAdd_I64( 1646 cc2, 1647 h(CHashGlblVar*)->data_addr 1648 ); 1649 } 1650 } else if(h->type&HTT_FUN) { 1651 if((h(CHashFun*)->flags&(1<<Cf_EXTERN))||cc->flags&CCF_AOT_COMPILE) { 1652 new=__HC_ICAdd_Reloc( 1653 acc, 1654 cc2, 1655 &cur ->ic_data(CCodeMisc*)->addr, 1656 h->str, 1657 RT_U8, 1658 1 1659 ); 1660 } else { 1661 new=__HC_ICAdd_I64( 1662 cc2, 1663 h(CHashFun*)->exe_addr 1664 ); 1665 } 1666 } else if(!(h->type&HTF_RESOLVE)) { 1667 new=__HC_ICAdd_Reloc( 1668 acc, 1669 cc2, 1670 &cur ->ic_data(CCodeMisc*)->addr, 1671 h->str, 1672 RT_U8, 1673 1 1674 ); 1675 } else { 1676 new=__HC_ICAdd_I64( 1677 cc2, 1678 h(CHashExport*)->val 1679 ); 1680 } 1681 if(cc->flags&CCF_AOT_COMPILE) { 1682 if(h->type&HTT_GLBL_VAR&&h->type&HTF_EXPORT) { 1683 __HC_SetAOTRelocBeforeRIP(new,h(CHashGlblVar*)->data_addr_rip-cc->aotc->rip); 1684 } else if(h->type&HTT_FUN&&!Bt(&(h(CHashFun*)->flags),Cf_EXTERN)) { 1685 __HC_SetAOTRelocBeforeRIP(new,h(CHashFun*)->exe_addr-cc->aotc->rip); 1686 } 1687 } 1688 break;case IC_REG: 1689 if(cur->ic_dim) { 1690 new=__HC_ICAdd_IReg(cc2,cur->imm_i64,cmp.internal_types[RT_I64],0); 1691 } else { 1692 if(cur->ic_class->raw_type==RT_F64) { 1693 new=__HC_ICAdd_FReg(cc2,cur->imm_i64); 1694 } else { 1695 new=__HC_ICAdd_IReg(cc2,cur->imm_i64,cur->ic_class->raw_type,0); 1696 } 1697 } 1698 break;case IC_TO_I64: 1699 new=__HC_ICAdd_ToI64(cc2); 1700 break;case IC_TO_F64: 1701 new=__HC_ICAdd_ToF64(cc2); 1702 break;case IC_TO_BOOL: 1703 new=__HC_ICAdd_ToBool(cc2); 1704 break;case IC_TOUPPER: //TODO 1705 break;case IC_HOLYC_TYPECAST: 1706 new=__HC_ICAdd_Typecast(cc2,cur->ic_class->raw_type,0); 1707 break;case IC_ADDR: 1708 //Change of plans,I am making statics Relocations to be filled on the heap 1709 if(cur->next(CRPN*)->type!=IC_STATIC) 1710 new=__HC_ICAdd_Addr(cc2); 1711 break;case IC_COMMA: 1712 new=__HC_ICAdd_Comma(cc2); 1713 break;case IC_COM: 1714 new=__HC_ICAdd_BNot(cc2); 1715 break;case IC_NOT: 1716 new=__HC_ICAdd_LNot(cc2); 1717 break;case IC_UNARY_MINUS: 1718 new=__HC_ICAdd_Neg(cc2); 1719 break;case IC_DEREF: 1720 new=__HC_ICAdd_Deref(cc2,cur->ic_class->raw_type,0); 1721 //break;case IC_DEREF_PP //NOT USED BY AIWINIOS 1722 //break;case IC_DEREF_MM //DITTO 1723 break;case IC__PP: 1724 new=__HC_ICAdd_PostInc(cc2,cur->ic_data); 1725 break;case IC__MM: 1726 new=__HC_ICAdd_PostDec(cc2,cur->ic_data); 1727 break;case IC_PP_: 1728 new=__HC_ICAdd_PreInc(cc2,cur->ic_data); 1729 break;case IC_MM_: 1730 new=__HC_ICAdd_PreDec(cc2,cur->ic_data); 1731 break;case IC_SHL: 1732 new=__HC_ICAdd_Lsh(cc2); 1733 break;case IC_SHR: 1734 new=__HC_ICAdd_Rsh(cc2); 1735 //break;case IC_SHL_CONST: NOT USED BY AIWNIOS 1736 //break;case IC_SHR_CONST: NOT USED BY AIWNIOS 1737 break;case IC_POWER: 1738 throw("Compiler"); 1739 break;case IC_MUL: 1740 new=__HC_ICAdd_Mul(cc2); 1741 break;case IC_DIV: 1742 new=__HC_ICAdd_Div(cc2); 1743 break;case IC_MOD: 1744 new=__HC_ICAdd_Mod(cc2); 1745 break;case IC_AND: 1746 new=__HC_ICAdd_And(cc2); 1747 break;case IC_OR: 1748 new=__HC_ICAdd_Or(cc2); 1749 break;case IC_XOR: 1750 new=__HC_ICAdd_Xor(cc2); 1751 break;case IC_BT: 1752 new=__HC_ICAdd_BT(cc2); 1753 break;case IC_BTS: 1754 new=__HC_ICAdd_BTS(cc2); 1755 break;case IC_BTC: 1756 new=__HC_ICAdd_BTC(cc2); 1757 break;case IC_BTR: 1758 new=__HC_ICAdd_BTR(cc2); 1759 break;case IC_LBTS: 1760 new=__HC_ICAdd_LBTS(cc2); 1761 break;case IC_LBTC: 1762 new=__HC_ICAdd_LBTC(cc2); 1763 break;case IC_LBTR: 1764 new=__HC_ICAdd_LBTR(cc2); 1765 break;case IC_ADD: 1766 new=__HC_ICAdd_Add(cc2); 1767 break;case IC_SUB: 1768 new=__HC_ICAdd_Sub(cc2); 1769 //break;case IC_ADD_CONST NOT USED BY AIWNIOS 1770 //break;case IC_SUB_CONST NOT USED BY AIWNIOS 1771 break;case IC_EQU_EQU: 1772 new=__HC_ICAdd_EqEq(cc2); 1773 break;case IC_NOT_EQU: 1774 new=__HC_ICAdd_Ne(cc2); 1775 break;case IC_LESS: 1776 new=__HC_ICAdd_Lt(cc2); 1777 break;case IC_GREATER_EQU: 1778 new=__HC_ICAdd_Ge(cc2); 1779 break;case IC_GREATER: 1780 new=__HC_ICAdd_Gt(cc2); 1781 break;case IC_LESS_EQU: 1782 new=__HC_ICAdd_Le(cc2); 1783 //break;case IC_PUSH_CMP NOT USED BY AIWNIOS 1784 break;case IC_AND_AND: 1785 new=__HC_ICAdd_AndAnd(cc2); 1786 break;case IC_OR_OR: 1787 new=__HC_ICAdd_OrOr(cc2); 1788 break;case IC_XOR_XOR: 1789 new=__HC_ICAdd_XorXor(cc2); 1790 break;case IC_ASSIGN: 1791 new=__HC_ICAdd_Eq(cc2); 1792 //break;case IC_ASSIGN_PP //NOT USED BY AIWNIOS 1793 //break;case IC_ASSIGN_MM //DITTO 1794 break;case IC_SHL_EQU: 1795 new=__HC_ICAdd_LshEq(cc2); 1796 break;case IC_SHR_EQU: 1797 new=__HC_ICAdd_RshEq(cc2); 1798 break;case IC_MUL_EQU: 1799 new=__HC_ICAdd_MulEq(cc2); 1800 break;case IC_DIV_EQU: 1801 new=__HC_ICAdd_DivEq(cc2); 1802 break;case IC_MOD_EQU: 1803 new=__HC_ICAdd_ModEq(cc2); 1804 break;case IC_AND_EQU: 1805 new=__HC_ICAdd_AndEq(cc2); 1806 break;case IC_OR_EQU: 1807 new=__HC_ICAdd_OrEq(cc2); 1808 break;case IC_XOR_EQU: 1809 new=__HC_ICAdd_XorEq(cc2); 1810 break;case IC_ADD_EQU: 1811 new=__HC_ICAdd_AddEq(cc2); 1812 break;case IC_SUB_EQU: 1813 new=__HC_ICAdd_SubEq(cc2); 1814 break;case IC_JMP: 1815 new=__HC_ICAdd_Goto(cc2,cur->ic_data(CCodeMisc*)->addr); 1816 break;case IC_SUB_RET: 1817 new=__HC_ICAdd_SubRet(cc2); 1818 break;case IC_SUB_CALL: 1819 new=__HC_ICAdd_SubCall(cc2,cur->ic_data(CCodeMisc*)->addr); 1820 break;case IC_SWITCH: 1821 misc=cur->ic_data(CCodeMisc*); 1822 __HC_ICAdd_BoundedSwitch(cc2,misc->addr,misc->dft->addr); 1823 break;case IC_NOBOUND_SWITCH: 1824 __HC_ICAdd_UnboundedSwitch(cc2,cur->ic_data(CCodeMisc*)->addr); 1825 break;case IC_RET: 1826 new=__HC_ICAdd_Ret(cc2); 1827 break;case IC_CALL_INDIRECT: 1828 new=__HC_ICAdd_Call( 1829 cc2, 1830 cur->length-1, 1831 cur->ic_class->raw_type, 1832 0); 1833 /*TODO 1834 IC_CALL 1835 IC_CALL_INDIRECT2 1836 IC_CALL_IMPORT 1837 IC_CALL_EXTERN 1838 */ 1839 break;case IC_VARGS: 1840 new=__HC_ICAdd_Vargs(cc2,cur->ic_data); 1841 break;case IC_STATIC: 1842 //HolyC side accounts for the ptr arithmetic for us 1843 new=__HC_ICAdd_Reloc( 1844 acc, 1845 cc2, 1846 &cur->ic_data(CCodeMisc*)->addr, 1847 stat_nam, 1848 RT_I64, 1849 0 1850 ); 1851 if(cur->ic_data(CCodeMisc*)->offset) { 1852 misc=cur->ic_data; 1853 mlst=misc->offset; //See AIWNIOS_PrsExp.HC 1854 __HC_ICAdd_I64(cc2,mlst->offset); 1855 __HC_ICAdd_Add(cc2); 1856 } 1857 if(cur->last(CRPN*)->type!=IC_ADDR) { 1858 __HC_ICAdd_Deref(cc2,cur->ic_class->raw_type,0); 1859 } 1860 } 1861 if(cur->ic_line&&cur->ic_line>=cc->min_line) { //check for oddities(maybe includes accross a file boundary) 1862 reported_max_ln=MaxI64(reported_max_ln,cur->ic_line); 1863 reported_min_ln=MinI64(reported_min_ln,cur->ic_line); 1864 __HC_ICSetLine(new,cur->ic_line); 1865 } 1866 if(cur->ic_flags&ICF_LOCK) 1867 __HC_ICSetLock(new); 1868 } 1869 if(reported_min_ln!=I16_MAX) { 1870 aiwnios_dbg_info=CAlloc(8*(reported_max_ln-reported_min_ln+2)); 1871 } else 1872 aiwnios_dbg_info=NULL; 1873 machine_code=__HC_Compile(acc,&idx,aiwnios_dbg_info,Fs->code_heap); 1874 if(res_sz) *res_sz=idx; 1875 if(info&&aiwnios_dbg_info) { 1876 if(reported_min_ln!=I16_MAX&&reported_min_ln>=cc->min_line) { 1877 foff=reported_min_ln-cc->min_line+1; 1878 MemCpy(info[0]->body+foff,aiwnios_dbg_info,8*ClampI64(reported_max_ln-reported_min_ln-foff+1,0,MaxI64(cc->max_line-cc->min_line-foff-1,0))); 1879 } 1880 info[0]->body[0]=machine_code; 1881 info[0]->body[cc->max_line-cc->min_line+1]=idx+machine_code; 1882 } 1883 Free(aiwnios_dbg_info); 1884 1885 // 1886 //Turn the CMT_HASH_ENTRY to CMT_LABEL to avoid freeing the CHash. 1887 //Things work different in AIWNIOS 1888 // 1889 // Also be sure to turn the relocations to CHashImport's 1890 // 1891 if(statics_sz&&!(cc->flags&CCF_AOT_COMPILE)) { 1892 dumb_static=CAlloc(statics_sz); 1893 mlst=cc->htc.fun->member_lst_and_root; 1894 for(idx=0;idx!=member_cnt;idx++) { 1895 if(mlst->flags&MLF_STATIC) { 1896 if(mlst->static_data) { 1897 MemCpy(dumb_static+mlst->offset,mlst->static_data,mlst->member_class->size*mlst->dim.total_cnt); 1898 } 1899 } 1900 mlst=mlst->next; 1901 } 1902 } 1903 tmpgh=NULL; 1904 for(misc=cc->coc.coc_next_misc;misc!=&cc->coc.coc_next_misc;misc=misc->next) { 1905 if(misc->flags&CMF_STATIC) { 1906 if(misc->addr!=INVALID_PTR) { 1907 if(cc->flags&CCF_AOT_COMPILE) { 1908 if(!tmpgh) { 1909 tmpgh=CAlloc(sizeof CAOTHeapGlbl); 1910 tmpgh->size=statics_sz; 1911 tmpgh->str=StrNew(stat_nam); 1912 tmpgh->next=cc->aotc->heap_glbls; 1913 tmpgh->data=CAlloc(statics_sz); 1914 cc->aotc->heap_glbls=tmpgh; 1915 mlst=cc->htc.fun->member_lst_and_root; 1916 for(idx=0;idx!=member_cnt;idx++) { 1917 if(mlst->flags&MLF_STATIC) { 1918 if(mlst->static_data) { 1919 MemCpy(tmpgh->data+mlst->offset,mlst->static_data,mlst->member_class->size*mlst->dim.total_cnt); 1920 } 1921 } 1922 mlst=mlst->next; 1923 } 1924 } 1925 tmpghr=CAlloc(sizeof CAOTHeapGlblRef); 1926 tmpghr->next=tmpgh->references; 1927 tmpgh->references=tmpghr; 1928 //tmpghr->offset=misc->offset; 1929 tmpghr->rip=cc->aotc->rip+(misc->addr(U8*)-machine_code); 1930 } else { 1931 WriteProtectMemCpy(misc->addr,&dumb_static,8); 1932 } 1933 } 1934 } else if(misc->type==CMT_HASH_ENTRY) { 1935 misc->type=CMT_LABEL; 1936 // 1937 // AIWNIOS will always use IC_ADDR_IMPORT,but if we find a existing symbol 1938 // to bind we use it's address (instead of a relocation). 1939 // So if we have relocations that aren't used (have an ->addr of INVALID_PTR) 1940 // dont add a "fill-in-later" for it 1941 // 1942 if(cc->flags&CCF_AOT_COMPILE) { 1943 if(misc->addr!=INVALID_PTR) { 1944 //All non-imported functions are short calls 1945 if(misc->flags&CMF_SHORT_ADDR) { 1946 fill_user_data.cc=cc; 1947 fill_user_data.cm=misc; 1948 fill_user_data.machine_code=machine_code; 1949 __HC_CodeMiscInterateThroughRefs(misc->addr,&AddShortReloc,&fill_user_data); 1950 }else if(IsTLSReloc(misc)) { 1951 tmpaie=CAlloc(sizeof(CAOTImportExport)); 1952 tmpaie->type=IET_IMM_I64; 1953 tmpaie->str=StrNew(misc->h->str); 1954 tmpaie->rip=cc->aotc->rip+(misc->addr(U8*)-machine_code); 1955 tmpaie->offset=misc->offset; 1956 QueIns(tmpaie,cc->aot->last_ie); 1957 } else if(misc->h->type&HTT_GLBL_VAR){ 1958 fill_user_data.cc=cc; 1959 fill_user_data.cm=misc; 1960 fill_user_data.machine_code=machine_code; 1961 if(!Globalify(misc->addr,&fill_user_data)) 1962 goto norm_reloc; 1963 } else { 1964 norm_reloc: 1965 tmpaie=CAlloc(sizeof(CAOTImportExport)); 1966 tmpaie->type=IET_IMM_I64; 1967 tmpaie->str=StrNew(misc->h->str); 1968 tmpaie->rip=cc->aotc->rip+(misc->addr(U8*)-machine_code); 1969 tmpaie->offset=misc->offset; 1970 QueIns(tmpaie,cc->aot->last_ie); 1971 } 1972 } 1973 } else { 1974 if(misc->addr!=INVALID_PTR) { 1975 h=CAlloc(sizeof CHashImport); 1976 h->type=HTT_IMPORT_SYS_SYM; 1977 h->str=StrNew(misc->h->str); 1978 h->module_base=machine_code; 1979 //[reloc type 1][reloc offset 4][name?]NULL] 1980 //Nroot adds an aditional byte to specify NULL after we load the silly sauce 1981 h->module_header_entry=CAlloc(StrLen(h->str)+5+1+1); 1982 if(IsTLSReloc(misc)) 1983 h->module_header_entry[0]=IET_IMM_I64; 1984 else 1985 h->module_header_entry[0]=IET_IMM_I64; 1986 h->module_header_entry[1](U32)=misc->addr(U8*)-machine_code; 1987 StrCpy(h->module_header_entry+5,h->str); 1988 HashAdd(h,Fs->hash_table); 1989 } 1990 } 1991 } else if(misc->addr!=INVALID_PTR&&misc->type==CMT_LABEL&&misc->str&&!StrNCmp("0x",misc->str,2)) { 1992 tmpabs=CAlloc(sizeof(CAOTAbsAddr)); 1993 tmpabs->next=cc->aotc->abss; 1994 tmpabs->type=AAT_ADD_U64; 1995 tmpabs->rip=cc->aotc->rip+(misc->addr(U8*)-machine_code); 1996 cc->aotc->abss=tmpabs; 1997 misc->addr(U64*)[0]=Str2I64(misc->str); 1998 } else if(misc->addr!=INVALID_PTR&&misc->type==CMT_JMP_TABLE&&cc->flags&CCF_AOT_COMPILE) { 1999 for(idx=0;idx<misc->range;idx++) { 2000 tmpabs=CAlloc(sizeof(CAOTAbsAddr)); 2001 tmpabs->next=cc->aotc->abss; 2002 tmpabs->type=AAT_ADD_U64; 2003 table_ptr=misc->addr2(U8*)+8*idx; 2004 foff=cc->aotc->rip+(*table_ptr-machine_code(I64)); 2005 WriteProtectMemCpy(table_ptr,&foff,8); 2006 tmpabs->rip=cc->aotc->rip+((misc->addr2(U8*)+8*idx)-machine_code); 2007 cc->aotc->abss=tmpabs; 2008 } 2009 } 2010 } 2011 2012 Free(stat_nam); 2013 __HC_CodeCtrlPop(acc); 2014 2015 // 2016 // For CAiwniosAOTBlob,Fill in the relocations 2017 // 2018 for(cur=head->last;cur!=head;cur=cur->last) { 2019 if(cur->live_in) I64SetDel(cur->live_in); 2020 if(cur->live_out) I64SetDel(cur->live_out); 2021 if(cur->use_regs) I64SetDel(cur->use_regs); 2022 if(cur->kill_regs) I64SetDel(cur->kill_regs); 2023 if(cur->user_data) I64SetDel(cur->user_data); 2024 if(cur->user_data2) I64SetDel(cur->user_data2); 2025 if(cur->type==IC_ASM) { 2026 //TODO AOT 2027 JITFixupAiwniosAOTBlob(cc,cur->ic_data,cur->ic_data(CAiwniosAOTBlob*)->final_start_addr); 2028 AiwniosAOTBlobDel(cur->ic_data); 2029 } 2030 } 2031 __HC_CmpCtrlDel(acc); 2032 COCDel(cc,&cc->coc); 2033 return machine_code; 2034 } 2035 2036 U8 *COCCompile(CCmpCtrl *cc,I64 *_code_size,CDbgInfo **_dbg,I64 *_type) { 2037 CRPN *rpn=cc->coc.coc_head.next; 2038 if(rpn->type==IC_RET&&_type) 2039 *_type=AssignRawTypeToNode(rpn->next)->raw_type; 2040 U8 *mc=AiwniosCompile(cc,_code_size,_dbg); 2041 return mc; 2042 } 2043 2044 /** 2045 * Has format 2046 * if(HTT_FUN) 2047 * FUNC_NAME(U8[]) 2048 * FUNC_FILE(U8[]) 2049 * FUNC_HELP_IDX(U8[]) 2050 * U32 s,e; 2051 * U32 line_offsets[] 2052 * U32 stk_size 2053 * U32 var_cnt 2054 * VAR_NAME(U8[]) 2055 * VAR_TYPE(U8[]) 2056 * U32 reg 2057 * U32 offset 2058 * U32 star_cnt 2059 * U32 total_dim //I64 array[3][4] would have total_dim of 12 2060 * 2061 * if(HTT_HELP_FILE) 2062 * POINTS_TO_FILE(U8[]) 2063 * HELP_IDX(U8[]) 2064 * ... 2065 */ 2066 I64 __DbgInfoWrite(CHashTable *h,U8 *to) { 2067 I64 i,ln,size=0,min,max; 2068 CHashSrcSym *tmph; 2069 CHashFun *,*pub_tmph; 2070 CHashClass *tmpc; 2071 CMemberLst *fun_mem; 2072 CDbgInfo *dbg_info; 2073 U32 start_ptr,cnt; 2074 U8 *src_link,buffer[1024],*bptr=&buffer; 2075 for (i=0;i<=h->mask;i++) { 2076 for(tmph=h->body[i];tmph;tmph=tmph->next) { 2077 if (tmph->src_link && !(tmph->type & (HTF_IMPORT | HTF_PRIVATE)) && (dbg_info=tmph->dbg_info)) { 2078 if((tmph->type&HTT_FUN)&&!(tmph(CHashFun*)->flags&(1<<Cf_EXTERN))) { 2079 if(to) (to+size)(I64*)[0]=tmph->type&(HTT_FUN|HTF_PUBLIC); 2080 size+=sizeof(I64); 2081 StrScan(tmph->src_link,"FL:%s,%d",&bptr,&ln); 2082 if(to) StrCpy(to+size,tmph->str); 2083 size+=StrLen(tmph->str)+1; 2084 if(to) StrCpy(to+size,buffer); 2085 size+=StrLen(buffer)+1; 2086 pub_tmph=HashFind(tmph->str,h,HTF_PUBLIC); 2087 if(pub_tmph) { 2088 if(pub_tmph->idx) { 2089 if(to) StrCpy(to+size,pub_tmph->idx); 2090 size+=StrLen(pub_tmph->idx)+1; 2091 goto wrote_help_idx; 2092 } 2093 } 2094 if(tmph->idx) { 2095 if(to) StrCpy(to+size,tmph->idx); 2096 size+=StrLen(tmph->idx)+1; 2097 } else { 2098 if(to) StrCpy(to+size,""); 2099 size+=StrLen("")+1; 2100 } 2101 wrote_help_idx: 2102 min=dbg_info->min_line; 2103 max=dbg_info->max_line; 2104 if(to) (to+size)(U32*)[0]=min; 2105 if(to) (to+size)(U32*)[1]=max; 2106 size+=2*sizeof(U32); 2107 max-=min; 2108 min-=min; 2109 start_ptr=dbg_info->body[0]; 2110 for(ln=0;ln<=max+1;ln++) { 2111 if(dbg_info->body[ln]) { 2112 if(to) (to+size)(U32*)[0]=dbg_info->body[ln]-start_ptr; 2113 } else { 2114 if(to) (to+size)(U32*)[0]=0; 2115 } 2116 size+=4; 2117 } 2118 if(to) (to+size)(U32*)[0]=tmph(CHashFun*)->size; 2119 size+=4; 2120 fun_mem=tmph(CHashFun*)->member_lst_and_root; 2121 for(cnt=0;fun_mem;fun_mem=fun_mem->next) 2122 cnt++; 2123 if(to) (to+size)(U32*)[0]=cnt; 2124 size+=4; 2125 fun_mem=tmph(CHashFun*)->member_lst_and_root; 2126 for(;fun_mem;fun_mem=fun_mem->next) { 2127 if(to) StrCpy(to+size,fun_mem->str); 2128 size+=StrLen(fun_mem->str)+1; 2129 tmpc=fun_mem->member_class; 2130 tmpc-=tmpc->ptr_stars_cnt; 2131 if(tmpc->str) { 2132 if(to) StrCpy(to+size,tmpc->str); 2133 size+=StrLen(tmpc->str)+1; 2134 } else { 2135 if(to) to[size]=0; 2136 size++; 2137 } 2138 if(to) (to+size)(U32*)[0]=fun_mem->reg; 2139 size+=4; 2140 if(to) (to+size)(U32*)[0]=fun_mem->offset; 2141 size+=4; 2142 if(to) (to+size)(U32*)[0]=fun_mem->member_class->ptr_stars_cnt; 2143 size+=4; 2144 if(to) (to+size)(U32*)[0]=fun_mem->dim.total_cnt; 2145 size+=4; 2146 } 2147 } 2148 } else if(tmph->type&HTT_HELP_FILE){ 2149 if(to) (to+size)(I64*)[0]=HTT_HELP_FILE; 2150 size+=sizeof(I64); 2151 if(to) StrCpy(to+size,tmph->str); 2152 size+=StrLen(tmph->str)+1; 2153 if(to) StrCpy(to+size,tmph->idx); 2154 size+=StrLen(tmph->idx)+1; 2155 } 2156 } 2157 } 2158 return size; 2159 } 2160 U0 DbgInfoWrite(CHashTable *h,U8 *name) { 2161 I64 len=__DbgInfoWrite(h,NULL); 2162 U8 *buf=MAlloc(len); 2163 __DbgInfoWrite(h,buf); 2164 FileWrite(name,buf,len); 2165 Free(buf); 2166 } 2167 U0 DbgInfoRead(U8 *file) { 2168 I64 min,max,ln,type,len; 2169 CHashSrcSym *tmph; 2170 CMemberLst *tmpm=NULL,*tmpm2=NULL,*tmpm_start; 2171 CDbgInfo *dbg_info; 2172 CHashClass *tmpc; 2173 U8 *body=FileRead(file,&len),*ptr=body,*fn,*idx; 2174 while(ptr<body+len) { 2175 type=ptr(I64*)[0]; 2176 ptr+=8; 2177 if(type&HTT_FUN) { 2178 tmph=HashFind(ptr,Fs->hash_table,HTT_FUN); 2179 ptr+=StrLen(ptr)+1; 2180 fn=ptr; 2181 ptr+=StrLen(ptr)+1; 2182 idx=ptr; 2183 ptr+=StrLen(ptr)+1; 2184 min=ptr(U32*)[0]; 2185 max=ptr(U32*)[1]; 2186 ptr+=2*sizeof(U32); 2187 if(tmph&&tmph->type&HTT_FUN) { 2188 tmph->type|=type; //type may include HTF_PUBLIC 2189 Free(tmph->src_link); 2190 Free(tmph->idx); 2191 if(StrLen(idx)) 2192 tmph->idx=StrNew(idx); 2193 else 2194 tmph->idx=NULL; 2195 tmph->src_link=MStrPrint("FL:%s,%d",fn,min); 2196 tmph->dbg_info=CAlloc(sizeof(CDbgInfo)+sizeof(I64)*(max-min+1)); 2197 tmph->dbg_info->min_line=min; 2198 tmph->dbg_info->max_line=max; 2199 for(ln=min;ln<=max+1;ln++) { 2200 tmph->dbg_info->body[ln-min]=tmph(CHashFun*)->exe_addr(U8*)+ptr(U32*)[ln-min]; 2201 if(ln-min&&tmph->dbg_info->body[ln-min]==tmph(CHashFun*)->exe_addr) 2202 tmph->dbg_info->body[ln-min]=NULL; 2203 } 2204 } 2205 ptr+=sizeof(U32)*(max-min+1+1); 2206 if(tmph) tmph(CHashFun*)->size=ptr(I32*)[0]; 2207 ptr+=sizeof(U32); 2208 max=ptr(U32*)[0]; 2209 ptr+=sizeof(U32); 2210 tmpm=NULL; 2211 tmpm2=NULL; 2212 tmpm_start=NULL; 2213 for(min=0;min!=max;min++) { 2214 if(tmph) tmpm=CAlloc(sizeof(CMemberLst)); 2215 if(tmph) tmpm->str=StrNew(ptr); 2216 ptr+=StrLen(ptr)+1; 2217 tmpc=HashFind(ptr,Fs->hash_table,HTT_CLASS|HTT_INTERNAL_TYPE); 2218 if(tmph) tmpm->member_class=tmpc; 2219 ptr+=StrLen(ptr)+1; 2220 //If we couldn't find a class,continue 2221 if(!tmpc) { 2222 if(tmpm) Free(tmpm->str); 2223 Free(tmpm); 2224 ptr+=16; 2225 goto next; 2226 } 2227 if(tmph) tmpm->reg=ptr(U32*)[0]; 2228 ptr+=4; 2229 if(tmph) tmpm->offset=ptr(I32*)[0]; 2230 ptr+=4; 2231 if(tmpm) tmpm->member_class+=ptr(U32*)[0]; //In TempleOS,the next class is a "pointer star" 2232 ptr+=4; 2233 if(tmpm) tmpm->dim.total_cnt=tmpm->dim.cnt=ptr(U32*)[0]; 2234 ptr+=4; 2235 if(!tmpm_start) tmpm_start=tmpm; 2236 if(tmpm2) tmpm2->next=tmpm; 2237 tmpm2=tmpm; 2238 next:; 2239 } 2240 if(tmph) { 2241 tmpm=tmph(CHashFun*)->member_lst_and_root; 2242 for(;tmpm&&tmpm->next;tmpm=tmpm->next); 2243 if(tmpm) 2244 tmpm->next=tmpm_start; 2245 else 2246 tmph(CHashFun*)->member_lst_and_root=tmpm_start; 2247 } 2248 } else if(type&HTT_HELP_FILE) { 2249 tmph=CAlloc(sizeof(CHashSrcSym)); 2250 tmph->type=HTF_PUBLIC|HTT_HELP_FILE; 2251 tmph->str=StrNew(ptr); 2252 ptr+=StrLen(ptr)+1; 2253 tmph->idx=StrNew(ptr); 2254 ptr+=StrLen(ptr)+1; 2255 HashAdd(tmph,Fs->hash_table); 2256 } 2257 } 2258 }