U0 ParsePush(CParseStack *ps,I64 val) { ps->stack[++ps->ptr] = val; } I64 ParsePop(CParseStack *ps) { return ps->stack[ps->ptr--]; } U0 ParsePush2(CParseStack *ps, I64 val) { ps->stack2[++ps->ptr2] = val; } I64 ParsePop2(CParseStack *ps) { return ps->stack2[ps->ptr2--]; } U0 ParsePopDeref(CParseStack *ps) { I64 i = ParsePop(ps); CHashClass *tmpc = ParsePop(ps); if (i.u16[0] != IC_DEREF) { ParsePush(ps, tmpc); ParsePush(ps, i); } } I64 ParseKeyWord(CCompCtrl *cc) {//Convert cur token to KEYWORD or -1. CHashGeneric *tmph; if (cc->token == TK_IDENT &&(tmph = cc->hash_entry) && tmph->type & HTT_KEYWORD) return tmph->user_data0; else return -1; } CHashClass *ParseClassNew() {/*Pointers to classes are handled by allocating 5 structures for each new class and representing a pointer to a class by advancing 1 struct forward for one * and two forward for two **. */ I64 i; CHashClass *res = CAlloc(sizeof(CHashClass) * (PTR_STARS_NUM + 1), Fs->code_heap), *tmpc = res; for (i = 0; i <= PTR_STARS_NUM; i++) { tmpc->type = HTT_CLASS; tmpc->raw_type = RT_PTR; tmpc->size = sizeof(U8 *); tmpc->ptr_stars_count = i; tmpc++; } res->last_in_member_list = &res->member_list_and_root; res->size = 0; return res; } CHashFun *ParseFunNew() { I64 i; CHashFun *res = CAlloc(sizeof(CHashFun) * (PTR_STARS_NUM + 1), Fs->code_heap), *tmpf = res; for (i = 0; i <= PTR_STARS_NUM; i++) { tmpf->type = HTT_FUN; tmpf->raw_type = RT_PTR; tmpf->size = sizeof(U8 *); tmpf->ptr_stars_count = i; tmpf++; } res->last_in_member_list = &res->member_list_and_root; res->size = 0; return res; } CIntermediateCode *ICAdd(CCompCtrl *cc, I64 opcode_and_precedence, I64 arg, CHashClass *c, I64 flags=0) { CIntermediateCode *tmpi = MAlloc(sizeof(CIntermediateCode)); tmpi->ic_code = opcode_and_precedence.u16[0]; tmpi->ic_precedence = opcode_and_precedence.u16[1]; tmpi->ic_data = arg; tmpi->ic_class = c; if (cc->pass_trace) { Bts(&cc->flags, CCf_PASS_TRACE_PRESENT); flags |= ICF_PASS_TRACE; } if (cc->lock_count) flags |= ICF_LOCK; tmpi->ic_flags = flags; tmpi->ic_line = cc->last_line_num; QueueInsert(tmpi, cc->coc.coc_head.last); return tmpi; } U0 COCInit(CCompCtrl *cc) { CCodeCtrl *tmpcbh = &cc->coc; QueueInit(&tmpcbh->coc_head.next); QueueInit(&tmpcbh->coc_next_misc); tmpcbh->coc_head.ic_code = IC_END; } U0 COCPush(CCompCtrl *cc) { CCodeCtrl *tmpcbh = MAlloc(sizeof(CCodeCtrl)); MemCopy(tmpcbh, &cc->coc, sizeof(CCodeCtrl)); cc->coc.coc_next = tmpcbh; } CCompCtrl *COCPopNoFree(CCompCtrl *cc) { CCodeCtrl *tmpcbh = cc->coc.coc_next; MemCopy(&cc->coc, tmpcbh, sizeof(CCodeCtrl)); return tmpcbh; } U0 COCPop(CCompCtrl *cc) { Free(COCPopNoFree(cc)); } U0 COCAppend(CCompCtrl *cc, CCodeCtrl *tmpcbh) { if (tmpcbh->coc_head.next != &cc->coc.coc_head.next) { cc->coc.coc_head.last->next = tmpcbh->coc_head.next; tmpcbh->coc_head.next->last = cc->coc.coc_head.last; cc->coc.coc_head.last = tmpcbh->coc_head.last; tmpcbh->coc_head.last->next = &cc->coc.coc_head.next; } if (tmpcbh->coc_next_misc != &cc->coc.coc_next_misc) { cc->coc.coc_last_misc->next = tmpcbh->coc_next_misc; tmpcbh->coc_next_misc->last = cc->coc.coc_last_misc; cc->coc.coc_last_misc = tmpcbh->coc_last_misc; tmpcbh->coc_last_misc->next = &cc->coc.coc_next_misc; } Free(tmpcbh); } CCodeMisc *COCMiscNew(CCompCtrl *cc, I64 ty) { CCodeMisc *res = CAlloc(sizeof(CCodeMisc)); res->addr = INVALID_PTR; res->type = ty; QueueInsert(res, cc->coc.coc_last_misc); return res; } CCodeMisc *COCGoToLabelFind(CCompCtrl *cc, U8 *name) { CCodeMisc *cm = cc->coc.coc_next_misc; while (cm != &cc->coc.coc_next_misc) { if ((cm->type == CMT_GOTO_LABEL || cm->type == CMT_ASM_LABEL) && !StrCompare(cm->str, name)) return cm; cm = cm->next; } return NULL; } I64 COCFloatConstFind(CCompCtrl *cc, F64 d) { I64 i; CCodeMisc *cm = cc->coc.coc_next_misc; while (cm != &cc->coc.coc_next_misc) { if (cm->type == CMT_FLOAT_CONSTS) { for (i = 0; i < cm->num_consts; i++) if (cm->float_consts[i] == d) return cm->addr + i * sizeof(F64); if (cm->num_consts < CM_CONSTS_NUM) { cm->float_consts[cm->num_consts++] = d; return cm->addr + i * sizeof(F64); } } cm = cm->next; } cm = COCMiscNew(cc, CMT_FLOAT_CONSTS); cm->float_consts = MAlloc(CM_CONSTS_NUM * sizeof(F64)); cm->float_consts[cm->num_consts++] = d; return cm->addr; } U0 COCDel(CCompCtrl *cc, CCodeCtrl *coc) { CCodeMisc *cm, *cm1; U8 *undef = NULL; QueueDel(&coc->coc_head.next); cm = coc->coc_next_misc; while (cm != &coc->coc_next_misc) { cm1 = cm->next; switch (cm->type) { case CMT_GOTO_LABEL: case CMT_ASM_LABEL: if (!(cm->flags & CMF_DEFINED)) { undef = cm->str; cm->str = NULL; } else if (!cm->use_count) { PrintWarn("Unused label %s\n", cm->str); LexWarn(cc, "Unused label at "); } break; case CMT_JMP_TABLE: Free(cm->jmp_table); break; case CMT_FLOAT_CONSTS: Free(cm->float_consts); break; case CMT_ARRAY_DIM: LinkedListDel(cm->dim); break; case CMT_HASH_ENTRY: HashDel(cm->h); break; } Free(cm->str); Free(cm); cm = cm1; } if (undef) { PrintErr("Undefined goto label %s\n", undef); Free(undef); LexExcept(cc, "Undefined goto label at "); } } U0 COCHeaderPut(CCompCtrl *cc, I64 pass, Bool put) { CIntermediateCode *tmpi; if (Bt(&cc->flags, CCf_PASS_TRACE_PRESENT)) { if (put) { if (Bt(&cc->saved_pass_trace, pass - 1)) { "$IV,1$Pass %d:$IV,0$\n", pass - 1; tmpi = cc->coc.coc_head.next; while (tmpi->ic_code) { if (tmpi->ic_flags & ICF_PASS_TRACE) ICPut(cc, tmpi); tmpi = tmpi->next; } } } else if (Bt(&cc->saved_pass_trace, pass)) "$IV,1$Pass %d:$IV,0$\n", pass; } cc->pass = pass; } U8 *COCCompile(CCompCtrl *cc, I64 *_code_size, CDebugInfo **_debug, I64 *_type) { U8 *res; CCodeMisc *lb; I64 i, code_size, last_code_size; COptReg reg_offsets[REG_REGS_NUM]; if (_debug) *_debug = NULL; cc->pass = 0; COCHeaderPut(cc, 1, TRUE); OptPass012(cc); COCHeaderPut(cc, 2, TRUE); OptPass012(cc); COCHeaderPut(cc, 3, TRUE); OptPass3(cc, reg_offsets); COCHeaderPut(cc, 4, TRUE); OptPass4(cc, reg_offsets, _type); COCHeaderPut(cc, 5, TRUE); OptPass5(cc); COCHeaderPut(cc, 6, TRUE); OptPass6(cc); COCHeaderPut(cc, 7, TRUE); lb = cc->coc.coc_next_misc; while (lb != &cc->coc.coc_next_misc) { if (lb->type == CMT_JMP_TABLE) { for (i = 0; i < lb->range; i++) lb->jmp_table[i] = OptLabelFwd(lb->jmp_table[i]); lb->default = OptLabelFwd(lb->default); } lb = lb->next; } COCHeaderPut(cc, 7, FALSE); OptPass789A(cc, reg_offsets, NULL, NULL); COCHeaderPut(cc, 8, FALSE); OptPass789A(cc, reg_offsets, NULL, NULL); COCHeaderPut(cc, 9, FALSE); code_size = OptPass789A(cc, reg_offsets, NULL, NULL); do { last_code_size = code_size; COCHeaderPut(cc, 9, FALSE); code_size = OptPass789A(cc, reg_offsets, NULL, NULL); if (code_size > last_code_size) { "Pass:9 Code Size\n"; LexExcept(cc, "Compiler Optimization Error at "); } } while (code_size < last_code_size); if (cc->flags & CCF_AOT_COMPILE) res = MAlloc(code_size); else { res = MAlloc(code_size, Fs->code_heap); if (cc->htc.fun) Fs->last_fun = cc->htc.fun; } COCHeaderPut(cc, 10, FALSE); code_size = OptPass789A(cc, reg_offsets, res, _debug); COCDel(cc, &cc->coc); if (Bt(&cc->opts, OPTf_TRACE)) { if (cc->flags & CCF_AOT_COMPILE) { if (cc->aotc->seg_size == 16) Un(res, code_size, 16); else if (cc->aotc->seg_size == 64) Un(res, code_size, 64); else Un(res, code_size, 32); } else Un(res,code_size, 64); } if (_code_size) *_code_size = code_size; cc->saved_pass_trace = cc->pass_trace; return res; }