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 }