U8 *LexStatement2Bin(CCompCtrl *cc, I64 *_type, I64 comp_flags=0)
{//Compile one cc statement to bin code.
        I64                      size, i, j, k, *res = INVALID_PTR;
        CCodeCtrl       *tmpcbh;

        if (_type)
                *_type = RT_I64;
        Btr(&cc->flags, CCf_PASS_TRACE_PRESENT);
        if (cc->aot_depth == 2)
                COCPush(cc);
        COCInit(cc);
        if (!ParseStatement(cc,,, comp_flags))
        {
                if (cc->coc.coc_head.next != &cc->coc.coc_head)
                {
                        cc->coc.coc_head.last->ic_flags &= ~ICF_RES_NOT_USED;
                        ICAdd(cc, IC_RETURN_VAL2, 0, 0);
                        ICAdd(cc, IC_RET, 0, 0);
                        if (res = COCCompile(cc, &size, NULL, _type))
                        {
                                if (cc->flags & CCF_AOT_COMPILE)
                                {
                                        j = cc->aotc->rip;
                                        k = (size + 7) >> 3;
                                        for (i = 0; i < k; i++)
                                                AOTStoreCodeU64(cc, res[i]);
                                        Free(res);
                                        res = j;
                                }
                        }
                } //TODO: else del misc?
        }
        else //TODO: too dangerous to del Misc?
                QueueDel(&cc->coc.coc_head.next);
        if (cc->aot_depth == 2) {
                tmpcbh = COCPopNoFree(cc);
                COCAppend(cc, tmpcbh);
        }

        return res;
}

CAOT *CompJoin(CCompCtrl *cc, I64 comp_flags, U8 *map_name=NULL, U8 mapfile_drive_let=0)
{
        CAOTCtrl                                *aotc, *old_aot = cc->aotc;
        I64                                              i, j, l;
        U8                                              *buf;
        CAOTBinBlk                              *tmpbin;
        CAOTImportExport                *tmpie;
        Bool                                     okay = TRUE;
        CLexHashTableContext    *htc = MAlloc(sizeof(CLexHashTableContext));
        CAOT                                    *res = CAlloc(sizeof(CAOT)), *parent;

        if (parent = cc->aot)
        {
                res->parent_aot = parent;
                QueueInsert(res, parent->last);
        }
        else
                QueueInit(res);
        cc->aot = res;

        res->next_ie = res->last_ie = &res->next_ie;
        cc->aotc = aotc = CAlloc(sizeof(CAOTCtrl));
        cc->aot_depth++;

        aotc->bin = CAlloc(sizeof(CAOTBinBlk));
        aotc->max_align_bits = 0;
        aotc->org = INVALID_PTR;

        MemCopy(htc, &cc->htc, sizeof(CLexHashTableContext));
        if (cc->htc.fun)
                cc->htc.global_hash_table = HashTableNew(128);
        else
                cc->htc.global_hash_table = HashTableNew(1024);
        if (cc->flags & CCF_AOT_COMPILE)
        {
                cc->htc.define_hash_table = cc->htc.global_hash_table;
                if (cc->aot_depth <= 1)
                        cc->htc.global_hash_table->next = cmp.asm_hash;
                else
                        cc->htc.global_hash_table->next = htc->global_hash_table;
        }
        else
                cc->htc.global_hash_table->next = Fs->hash_table;
        cc->htc.hash_table_list = cc->htc.local_hash_table = HashTableNew(16);
        cc->htc.local_hash_table->next = cc->htc.global_hash_table;
        cc->htc.local_var_list = cc->htc.fun; //CosmiC local vars
        cc->htc.fun = NULL;
        try
        {
                if (comp_flags & CMPF_LEX_FIRST)
                        Lex(cc);
                if (!(comp_flags & CMPF_ONE_ASM_INS))
                        comp_flags |= CMPF_PRS_SEMICOLON;
                if (cc->flags & CCF_AOT_COMPILE)
                {
                        while (cc->token != TK_EOF)
                        {
                                buf = LexStatement2Bin(cc, NULL, comp_flags);
                                if (buf != INVALID_PTR)
                                {
                                        tmpie = CAlloc(sizeof(CAOTImportExport));
                                        tmpie->type = IET_MAIN;
                                        tmpie->rip = buf;
                                        QueueInsert(tmpie, res->last_ie);
                                }
                                if (comp_flags & CMPF_ASM_BLK)
                                        break;
                        }
                }
                else
                        ParseStatement(cc,,, comp_flags);
                AOTGlobalsResolve(cc, res);
        }
        catch
        {
                if (Fs->except_ch == 'Compiler' && !(comp_flags & CMPF_ASM_BLK))
                {
                        LexPutPos(cc);
                        Fs->catch_except = TRUE;
                }
                okay = FALSE;
        }
        if (!okay)
        {
                if (cc->error_count < 1)
                        cc->error_count = 1;
                cc->aot = res->parent_aot;
                Free(res);
                LinkedListDel(aotc->bin);
                res = NULL;
        }
        else
        {
                if (map_name)
                        MapFileWrite(cc->htc.global_hash_table, map_name, mapfile_drive_let);
                HashTableDel(cc->htc.local_hash_table);
                HashTableDel(cc->htc.global_hash_table);

                if (!aotc->num_bin_U8s)
                        res->buf = NULL;
                else
                {
                        if (cc->flags & CCF_AOT_COMPILE)
                                res->buf = MAlloc(aotc->num_bin_U8s);
                        else
                        {
                                if (aotc->org == INVALID_PTR)
                                        res->buf = MAlloc(aotc->num_bin_U8s, Fs->code_heap);
                                else
                                        res->buf = aotc->org;
                        }
                        res->aot_U8s = aotc->num_bin_U8s;
                        tmpbin = aotc->bin;
                        j = 0;
                        l = aotc->num_bin_U8s;
                        while (tmpbin)
                        {
                                i = l;
                                if (i > AOT_BIN_BLK_SIZE)
                                        i = AOT_BIN_BLK_SIZE;
                                MemCopy(res->buf + j, tmpbin->body, i);
                                j += i;
                                l -= i;
                                tmpbin = tmpbin->next;
                        }
                }
                LinkedListDel(aotc->bin);
                res->abss = aotc->abss;
                res->heap_globals = aotc->heap_globals;
                res->max_align_bits = aotc->max_align_bits;
                res->org = aotc->org;
        }
        cc->aot = parent;
        MemCopy(&cc->htc, htc, sizeof(CLexHashTableContext));
        Free(htc);
        Free(aotc);
        cc->aotc = old_aot;
        cc->aot_depth--;

        return res;
}

CAOT *CompBuf(U8 *buf, U8 *map_name=NULL, I64 *error_count=NULL, I64 *warning_count=NULL, U8 mapfile_drive_let=0)
{
        CCompCtrl       *cc;
        CAOT            *res = NULL;

        cc = CompCtrlNew(buf, CCF_DONT_FREE_BUF);
        cc->flags |= CCF_AOT_COMPILE;
        QueueInsert(cc, Fs->last_cc);
        res = CompJoin(cc, CMPF_LEX_FIRST, map_name, mapfile_drive_let);
        if (error_count)
                *error_count = cc->error_count;
        if (warning_count)
                *warning_count = cc->warning_count;
        QueueRemove(cc);
        if (res)
                CompCtrlDel(cc);

        return res;
}

U0 CompFixUpJITAsm(CCompCtrl *cc, CAOT *tmpaot)
{
        I64                                      i, rip2 = tmpaot->buf + tmpaot->rip, *str = NULL;
        U8                                      *ptr;
        CCodeMisc                       *g_lb;
        CAOTAbsAddr                     *tmpa, *tmpa1;
        CAOTImportExport        *tmpie, *tmpie1;
        CHashExport                     *tmpex;

        tmpa = tmpaot->abss;
        while (tmpa)
        {
                tmpa1 = tmpa->next;
                ptr = rip2 + tmpa->rip;
                switch [tmpa->type]
                {
                        case AAT_ADD_U8:        *ptr(U8  *) += rip2; break;
                        case AAT_SUB_U8:        *ptr(U8  *) -= rip2; break;
                        case AAT_ADD_U16:       *ptr(U16 *) += rip2; break;
                        case AAT_SUB_U16:       *ptr(U16 *) -= rip2; break;
                        case AAT_ADD_U32:       *ptr(U32 *) += rip2; break;
                        case AAT_SUB_U32:       *ptr(U32 *) -= rip2; break;
                        case AAT_ADD_U64:       *ptr(I64 *) += rip2; break;
                        case AAT_SUB_U64:       *ptr(I64 *) -= rip2; break;
                }
                Free(tmpa);
                tmpa = tmpa1;
        }
        tmpie = tmpaot->next_ie;
        while (tmpie != &tmpaot->next_ie)
        {
                tmpie1 = tmpie->next;
                if (tmpie->str)
                {
                        Free(str);
                        str = tmpie->str;
                }
                switch (tmpie->type)
                {
                        case IET_REL32_EXPORT:
                        case IET_IMM32_EXPORT:
                        case IET_REL64_EXPORT:
                        case IET_IMM64_EXPORT:
                                tmpex = CAlloc(sizeof(CHashExport));
                                tmpex->str = str;
                                str = NULL;
                                tmpex->type = HTT_EXPORT_SYS_SYM | HTF_IMM;
                                if (tmpie->type == IET_IMM32_EXPORT || tmpie->type == IET_IMM64_EXPORT)
                                        tmpex->val = tmpie->rip;
                                else
                                        tmpex->val = tmpie->rip + rip2;
                                tmpex->src_link = tmpie->src_link;
                                tmpie->src_link = NULL;
                                HashAdd(tmpex, Fs->hash_table);
                                SysSymImportsResolve(tmpex->str);
                                break;

                        case IET_REL_I0...IET_IMM_I64:
                                if (tmpie->str)
                                {
                                        if (tmpie->flags & IEF_GOTO_LABEL)
                                        {
                                                if (!(g_lb = COCGoToLabelFind(cc, str)))
                                                        "Unresolved Reference:%s\n", str;
                                                else
                                                {
                                                        g_lb->use_count++;
                                                        g_lb = OptLabelFwd(g_lb);
                                                        i = g_lb->addr + tmpaot->buf;
                                                }
                                                tmpex = NULL;
                                        }
                                        else
                                        {
                                                if (!(tmpex = HashFind(str, Fs->hash_table, HTG_ALL - HTT_IMPORT_SYS_SYM)))
                                                        "Unresolved Reference:%s\n", str;
                                                else
                                                {
                                                        if (tmpex->type & HTT_FUN)
                                                                i = tmpex(CHashFun *)->exe_addr;
                                                        else if (tmpex->type & HTT_GLOBAL_VAR)
                                                                i = tmpex(CHashGlobalVar *)->data_addr;
                                                        else
                                                                i = tmpex->val;
                                                }
                                                g_lb = NULL;
                                        }
                                }
                                if (tmpex || g_lb)
                                {
                                        ptr = tmpie->rip + rip2;
                                        switch [tmpie->type]
                                        {
                                                case IET_REL_I0:
                                                case IET_IMM_U0:
                                                        break;

                                                case IET_REL_I8:
                                                        if (!(I8_MIN <= i - ptr - 1 <= I8_MAX))
                                                                LexExcept(cc, "Branch out of range at ");
                                                        *ptr(U8 *) = i - ptr - 1;
                                                        break;

                                                case IET_IMM_U8:
                                                        *ptr(U8 *) = i;
                                                        break;

                                                case IET_REL_I16:
                                                        if (!(I16_MIN <= i - ptr - 2 <= I16_MAX))
                                                                LexExcept(cc, "Branch out of range at ");
                                                        *ptr(U16 *) = i - ptr - 2;
                                                        break;

                                                case IET_IMM_U16:
                                                        *ptr(U16 *) = i;
                                                        break;

                                                case IET_REL_I32:
                                                        if (!(I32_MIN <= i - ptr - 4 <= I32_MAX))
                                                                LexExcept(cc, "Branch out of range at ");
                                                        *ptr(U32 *) = i - ptr - 4;
                                                        break;

                                                case IET_IMM_U32:
                                                        *ptr(U32 *) = i;
                                                        break;

                                                case IET_REL_I64:
                                                        *ptr(I64 *) = i - ptr - 8;
                                                        break;

                                                case IET_IMM_I64:
                                                        *ptr(I64 *) = i;
                                                        break;
                                        }
                                }
                                break;
                }
                Free(tmpie->src_link);
                Free(tmpie);
                tmpie = tmpie1;
        }
        Free(str);
        if (!cc->aot_depth && Bt(&cc->opts, OPTf_TRACE))
                Un(rip2, tmpaot->aot_U8s, 64);
        QueueRemove(tmpaot);
        Free(tmpaot);
}

U0 CompFixUpAOTAsm(CCompCtrl *cc, CAOT *tmpaot)
{
        CAOTCtrl                        *aotc = cc->aotc;
        I64                                      i, rip2 = tmpaot->rip + cc->aotc->rip;
        U8                                      *ptr;
        CCodeMisc                       *g_lb = NULL;
        CAOTAbsAddr                     *tmpa, *tmpa1;
        CAOTImportExport        *tmpie, *tmpie1;

        tmpa = tmpaot->abss;
        while (tmpa)
        {
                tmpa1 = tmpa->next;
                tmpa->next = aotc->abss;
                ptr = tmpaot->buf + tmpaot->rip + tmpa->rip;
                switch [tmpa->type]
                {
                        case AAT_ADD_U8:        *ptr(U8  *) += rip2;    break;
                        case AAT_SUB_U8:        *ptr(U8  *) -= rip2;    break;
                        case AAT_ADD_U16:       *ptr(U16 *) += rip2;    break;
                        case AAT_SUB_U16:       *ptr(U16 *) -= rip2;    break;
                        case AAT_ADD_U32:       *ptr(U32 *) += rip2;    break;
                        case AAT_SUB_U32:       *ptr(U32 *) -= rip2;    break;
                        case AAT_ADD_U64:       *ptr(I64 *) += rip2;    break;
                        case AAT_SUB_U64:       *ptr(I64 *) -= rip2;    break;
                }
                aotc->abss = tmpa;
                tmpa->rip += rip2;
                tmpa = tmpa1;
        }

        tmpie = tmpaot->next_ie;
        while (tmpie != &tmpaot->next_ie)
        {
                tmpie1 = tmpie->next;
                QueueRemove(tmpie);
                if (IET_REL_I0 <= tmpie->type <= IET_IMM_I64)
                {
                        if (tmpie->str)
                        {
                                if (tmpie->flags & IEF_GOTO_LABEL)
                                {
                                        if (!(g_lb = COCGoToLabelFind(cc, tmpie->str)))
                                                "Unresolved Reference:%s\n", tmpie->str;
                                        else
                                        {
                                                g_lb->use_count++;
                                                g_lb = OptLabelFwd(g_lb);
                                        }
                                }
                                else
                                        g_lb = NULL;
                        }
                }
                else
                        g_lb = NULL;

                ptr = tmpaot->buf + tmpaot->rip + tmpie->rip;
                if (g_lb)
                {
                        i = g_lb->addr + tmpaot->buf;
                        switch [tmpie->type]
                        {
                                case IET_REL_I0:
                                case IET_IMM_U0:
                                        break;

                                case IET_REL_I8:
                                        if (!(I8_MIN <= i - ptr - 1 <= I8_MAX))
                                                LexExcept(cc, "Branch out of range at ");
                                        *ptr(U8 *) = i - ptr - 1;
                                        break;

                                case IET_IMM_U8:
                                        *ptr(U8 *) = i;
                                        break;

                                case IET_REL_I16:
                                        if (!(I16_MIN <= i - ptr - 2 <= I16_MAX))
                                                LexExcept(cc, "Branch out of range at ");
                                        *ptr(U16 *) = i - ptr - 2;
                                        break;

                                case IET_IMM_U16:
                                        *ptr(U16 *) = i;
                                        break;

                                case IET_REL_I32:
                                        if (!(I32_MIN <= i - ptr - 4 <= I32_MAX))
                                                LexExcept(cc, "Branch out of range at ");
                                        *ptr(U32 *) = i - ptr - 4;
                                        break;

                                case IET_IMM_U32:
                                        *ptr(U32 *) = i;
                                        break;

                                case IET_REL_I64:
                                        *ptr(I64 *) = i - ptr - 8;
                                        break;

                                case IET_IMM_I64:
                                        *ptr(I64 *) = i;
                                        break;
                        }
                        Free(tmpie->src_link);
                        Free(tmpie);
                }
                else
                {
                        switch (tmpie->type)
                        {
                                start:
                                        case IET_REL32_EXPORT:
                                        case IET_IMM32_EXPORT:
                                        case IET_REL64_EXPORT:
                                        case IET_IMM64_EXPORT:
                                        case IET_IMM_U0:
                                        case IET_IMM_U8:
                                        case IET_IMM_U16:
                                        case IET_IMM_U32:
                                        case IET_IMM_I64:
                                        case IET_REL_I0:
                                                break;

                                        case IET_REL_I8:        *ptr(U8  *) -= rip2;    break;
                                        case IET_REL_I16:       *ptr(U16 *) -= rip2;    break;
                                        case IET_REL_I32:       *ptr(U32 *) -= rip2;    break;
                                        case IET_REL_I64:       *ptr(I64 *) -= rip2;    break;
                                end:
                                        tmpie->rip += rip2;
                                        break;
                        }
                        tmpie->aot = NULL;
                        QueueInsert(tmpie, tmpaot->parent_aot->last_ie);
                }
                tmpie = tmpie1;
        }
}

I64 Comp(U8 *filename, U8 *map_name=NULL, U8 *out_name=NULL, U8 mapfile_drive_let=0)
{//AOT Compile CC or PRJ file a and output BIN file. Returns err_count.
        U8                                      *ptr, *fbuf = NULL, *fbuf2 = NULL, *fbuf3 = NULL, *patch_table = MAlloc(0x20000);
        CAOT                            *tmpaot;
        I64                                      i, count, size = 0, error_count = 0, warning_count = 0, aot_U8s = 0;
        CBinFile                        *bfh;
        CAOTImportExport        *tmpie, *tmpie1;
        CAOTAbsAddr                     *tmpa, *tmpa1;
        CAOTHeapGlobalRef       *tmphgr, *tmphgr1;
        CAOTHeapGlobal          *tmphg, *tmphg1;

        fbuf = ExtDefault(filename, "PRJ");
        fbuf2 = MStrPrint("#include \"%s\"", fbuf);
        if (map_name)
                fbuf3 = ExtDefault(map_name, "MAP");

        if (tmpaot = CompBuf(fbuf2, fbuf3, &error_count, &warning_count, mapfile_drive_let))
        {
                aot_U8s = tmpaot->aot_U8s;
                ptr = patch_table;
//See Load()
                count = 0;
                tmpa = tmpaot->abss;
                while (tmpa)
                {
                        if (!(tmpa->type & IEF_IMM_NOT_REL))
                                count++;
                        tmpa = tmpa->next;
                }
                if (count)
                {
                        *ptr++ = IET_ABS_ADDR;
                        *ptr(U32 *)++ = count;
                        *ptr++ = 0;
                        tmpa = tmpaot->abss;
                        while (tmpa)
                        {
                                tmpa1 = tmpa->next;
                                if (!(tmpa->type & IEF_IMM_NOT_REL))
                                        *ptr(U32 *)++ = tmpa->rip;
                                Free(tmpa);
                                tmpa = tmpa1;
                        }
                }
                tmphg = tmpaot->heap_globals;
                while (tmphg)
                {
                        tmphg1 = tmphg->next;
                        count = 0;
                        tmphgr = tmphg->references;
                        while (tmphgr)
                        {
                                count++;
                                tmphgr = tmphgr->next;
                        }
                        if (count)
                        {
                                *ptr++ = IET_DATA_HEAP;
                                *ptr(U32 *)++ = count;
                                if (tmphg->str)
                                {
                                        i = StrLen(tmphg->str);
                                        MemCopy(ptr, tmphg->str, i + 1);
                                        Free(tmphg->str);
                                        ptr += i + 1;
                                }
                                else
                                        *ptr++ = 0;
                                *ptr(I64 *)++ = tmphg->size;
                                tmphgr = tmphg->references;
                                while (tmphgr)
                                {
                                        tmphgr1 = tmphgr->next;
                                        *ptr(U32 *)++ = tmphgr->rip;
                                        Free(tmphgr);
                                        tmphgr = tmphgr1;
                                }
                        }
                        Free(tmphg);
                        tmphg = tmphg1;
                }

                //Do exports first
                tmpie = tmpaot->next_ie;
                while (tmpie != &tmpaot->next_ie)
                {
                        tmpie1 = tmpie->next;
                        if (!tmpie->type || IET_REL32_EXPORT <= tmpie->type <= IET_IMM64_EXPORT)
                        {
                                QueueRemove(tmpie);
                                *ptr++ = tmpie->type;
                                *ptr(U32 *)++ = tmpie->rip;
                                if (tmpie->str)
                                {
                                        i = StrLen(tmpie->str);
                                        MemCopy(ptr, tmpie->str, i + 1);
                                        Free(tmpie->str);
                                        ptr += i + 1;
                                }
                                else
                                        *ptr++ = 0;
                                Free(tmpie->src_link);
                                Free(tmpie);
                        }
                        tmpie = tmpie1;
                }

                //Do imports second
                tmpie = tmpaot->next_ie;
                while (tmpie != &tmpaot->next_ie)
                {
                        tmpie1 = tmpie->next;
                        QueueRemove(tmpie);
                        *ptr++ = tmpie->type;
                        if (tmpie->aot)
                                tmpie->rip += tmpie->aot->rip2;
                        *ptr(U32 *)++ = tmpie->rip;
                        if (tmpie->str)
                        {
                                i = StrLen(tmpie->str);
                                MemCopy(ptr, tmpie->str, i + 1);
                                Free(tmpie->str);
                                ptr += i + 1;
                        }
                        else
                                *ptr++ = 0;
                        Free(tmpie->src_link);
                        Free(tmpie);
                        tmpie = tmpie1;
                }

                *ptr++ = IET_END;
                MemSet(ptr, 0, 16);
                i = ptr - patch_table;
//Needs 16 ALIGN
                size = (sizeof(CBinFile) + aot_U8s + i + 15) & -16;
                bfh = MAlloc(size);
                bfh->jmp = 0xEB + 256 * (sizeof(CBinFile) - 2);
#assert sizeof(CBinFile) - 2 <= I8_MAX
                bfh->reserved = 0;
                bfh->bin_signature = BIN_SIGNATURE_VAL;
                bfh->org = tmpaot->org;
                bfh->module_align_bits = tmpaot->max_align_bits;
                bfh->patch_table_offset = sizeof(CBinFile)+aot_U8s;
                bfh->file_size = size;
                MemCopy(bfh(U8 *) + sizeof(CBinFile), tmpaot->buf, aot_U8s);
                MemCopy(bfh(U8 *) + sizeof(CBinFile) + aot_U8s, patch_table, size - aot_U8s - sizeof(CBinFile));
                Free(fbuf2);
                if (out_name)
                        fbuf2 = ExtDefault(out_name, "BIN");
                else
                        fbuf2 = ExtChange(fbuf, "BIN");
                FileWrite(fbuf2, bfh, size);
                Free(bfh);
                Free(tmpaot->buf);
                QueueDel(tmpaot);
                Free(tmpaot);
        }
        Free(patch_table);
        Free(fbuf);
        Free(fbuf2);
        Free(fbuf3);
        Print("Errs:%d Warns:%d Code:%X Size:%X\n", error_count, warning_count, aot_U8s, size);

        return error_count;
}

I64 ExePutS(U8 *buf, U8 *filename=NULL, I64 ccf_flags=0, CLexHashTableContext *htc=NULL)
{//JIT Compile and execute text from a puts("").
        I64                      res;
        Bool             okay = TRUE;
        CCompCtrl       *cc;

        if (!filename)
                filename = blkdev.tmp_filename;
        cc = CompCtrlNew(buf, ccf_flags | CCF_DONT_FREE_BUF, filename);
        if (Fs->last_cc != &Fs->next_cc)
        {
                cc->opts = Fs->last_cc->opts;
                if (htc)
                {
                        cc->flags = cc->flags & ~CCF_ASM_EXPRESSIONS | htc->old_flags & CCF_ASM_EXPRESSIONS;
                        MemCopy(&cc->htc, htc, sizeof(CLexHashTableContext));
                }
        }
        QueueInsert(cc, Fs->last_cc);
        try
        {
                Lex(cc);
                res = ExeCmdLine(cc);
        }
        catch
        {
                if (Fs->except_ch == 'Compiler' || Fs->except_ch == 'Break')
                {
                        Fs->catch_except = TRUE;
                        okay = FALSE;
                        res = 0;
                }
        }
        QueueRemove(cc);
        if (okay)
                CompCtrlDel(cc); //TODO: can crash
        return res;
}

I64 ExePrint(U8 *format, ...)
{//JIT Compile and execute text from a printf().
        I64 res;
        U8 *buf = StrPrintJoin(NULL, format, argc, argv);

        res = ExePutS(buf);
        Free(buf);

        return res;
}

I64 ExeFile(U8 *name, I64 ccf_flags=0)
{//JIT Compile and execute a file.
        I64 res;
        U8 *name2 = ExtDefault(name, "CC"), *st = MStrPrint("#include \"%s\";", name2);

        res = ExePutS(st, name, ccf_flags);
        Free(st);
        Free(name2);

        return res;
}

I64 RunFile(U8 *name, I64 ccf_flags=0, ...)
{//ExeFile() with args using LastFun().
        ExeFile(name, ccf_flags);

        return LastFun(argc, argv);
}

I64 ExePutS2(U8 *buf, U8 *filename=NULL, I64 ccf_flags=0)
{//throws exceptions
        I64                      res;
        CCompCtrl       *cc;

        if (!filename)
                filename = blkdev.tmp_filename;
        cc = CompCtrlNew(buf, ccf_flags | CCF_DONT_FREE_BUF, filename);
        if (Fs->last_cc != &Fs->next_cc)
                cc->opts = Fs->last_cc->opts;
        QueueInsert(cc, Fs->last_cc);
        Lex(cc);
        res = ExeCmdLine(cc);
        QueueRemove(cc);
        CompCtrlDel(cc);

        return res;
}

I64 ExePrint2(U8 *format, ...)
{//throws exceptions
        I64 res;
        U8 *buf = StrPrintJoin(NULL, format, argc, argv);

        res = ExePutS2(buf);
        Free(buf);

        return res;
}

I64 ExeFile2(U8 *name, I64 ccf_flags=0)
{//throws exceptions
        I64 res;
        U8 *name2 = ExtDefault(name, "CC"), *st = MStrPrint("#include \"%s\";", name2);

        res = ExePutS2(st, name, ccf_flags);
        Free(st);
        Free(name2);

        return res;
}

I64 RunFile2(U8 *name, I64 ccf_flags=0, ...)
{//ExeFile2() with args using LastFun(). throws exceptions.
        ExeFile2(name, ccf_flags);

        return LastFun(argc, argv);
}

I64 StreamExePrint(U8 *format, ...)
{//Causes value from stream to be used in an #exe{} block.
        U8                                              *buf = StrPrintJoin(NULL, format, argc, argv);
        I64                                              res = 0;
        CLexHashTableContext    *htc;
        CCompCtrl                               *cc = Fs->last_cc;

        if (cc == &Fs->next_cc)
                PrintErr("Not Compiling\n");
        else
        {
                if (!(cc->flags & CCF_EXE_BLK))
                        LexExcept(cc, "StreamExePrint only allowed in AOT compiled #exe{} mode.");
                if (htc = cc->htc.next)
                        res = ExePutS(buf,,, htc);
        }
        Free(buf);

        return res;
}

U0 CInit()
{
        CompLoadDefines;
        CompFillTables;
        QueueInit(&cmp.ic_nop);
        cmp.ic_nop.ic_class = cmp.internal_types[RT_I64];
        cmp.ic_nop.ic_code = IC_NOP1;
        AsmHashLoad;
        UAsmHashLoad;
}

CInit;