U0 ParseVarInit(CCompCtrl *cc, U8 **_dst, CHashClass *tmpc, CArrayDim *tmpad, U8 *data_addr_rip, U8 **_base, Bool data_heap, I64 pass) { U8 *dst = *_dst, *machine_code; I64 i, j, r, old_flags, type, size; CMemberList *tmpm; CIntermediateCode *tmpi; CAOTCtrl *aotc = cc->aotc; CAOTAbsAddr *tmpa; CAOTImportExport *tmpie; Bool is_str; tmpc = OptClassFwd(tmpc); if (tmpm = tmpc->member_list_and_root) { if (cc->token != '{') LexExcept(cc, "Expecting '{' at "); LexPopNoRestore(cc); LexPush(cc); Lex(cc); while (tmpm) { ParseVarInit2(cc, &dst, tmpm->member_class, &tmpm->dim, data_addr_rip, _base, data_heap, pass); if (cc->token == ',') Lex(cc); tmpm = tmpm->next; } LexPopNoRestore(cc); if (cc->token != '}') LexExcept(cc, "Missing '}' at "); Lex(cc); } else { if (tmpc->ptr_stars_count == 1 && ((tmpc - 1)->raw_type == RT_I8 || (tmpc - 1)->raw_type == RT_U8) && !tmpad && cc->token == TK_STR) is_str = TRUE; else is_str = FALSE; if (cc->flags & CCF_AOT_COMPILE && is_str) { LexPopNoRestore(cc); machine_code = LexExtStr(cc, &i); if (pass == 2) { tmpa = CAlloc(sizeof(CAOTAbsAddr)); tmpa->next = aotc->abss; tmpa->type = AAT_ADD_U64; aotc->abss = tmpa; tmpa->rip = data_addr_rip + dst - *_base; *dst(I64 *) = aotc->rip; for (j = 0; j < i; j++) AOTStoreCodeU8(cc, machine_code[j]); } Free(machine_code); } else { old_flags = cc->flags; cc->flags = CCF_NO_ABSS | cc->flags & ~(CCF_AOT_COMPILE | CCF_HAS_MISC_DATA | CCF_NOT_CONST); machine_code = LexExpression2Bin(cc, &type); if (old_flags & CCF_AOT_COMPILE && cc->flags & CCF_NOT_CONST && !Bt(&cc->opts, OPTf_GLOBALS_ON_DATA_HEAP)) { cc->flags = cc->flags & ~CCF_NO_ABSS | CCF_AOT_COMPILE; Free(machine_code); if (pass == 2) { MemSet(dst, 0, tmpc->size); LexPopRestore(cc); Lex(cc); COCPush(cc); COCInit(cc); ICAdd(cc, IC_ABS_ADDR, data_addr_rip, tmpc + 1); ICAdd(cc, IC_IMM_I64, dst - *_base, tmpc + 1); ICAdd(cc, IC_ADD, 0, tmpc + 1); if (!ParseExpression(cc, NULL, TRUE)) throw('Compiler'); tmpi = cc->coc.coc_head.last; if (tmpi->ic_code == IC_END_EXP) { tmpi->ic_code = IC_NOP1; tmpi->ic_flags = 0; } ICAdd(cc, IC_ASSIGN, 0, tmpc); ICAdd(cc, IC_END_EXP, 0, tmpc, ICF_RES_NOT_USED); ICAdd(cc, IC_RET, 0, 0); if (machine_code = COCCompile(cc, &size, NULL, NULL)) { tmpie = CAlloc(sizeof(CAOTImportExport)); tmpie->type = IET_MAIN; tmpie->rip = cc->aotc->rip; QueueInsert(tmpie, cc->aot->last_ie); for (i = 0; i < size; i++) AOTStoreCodeU8(cc, machine_code[i]); Free(machine_code); } COCPop(cc); } else LexPopNoRestore(cc); } else { LexPopNoRestore(cc); if (!machine_code) throw('Compiler'); r = Call(machine_code); if (!(cc->flags & CCF_HAS_MISC_DATA) || pass == 1) Free(machine_code); if (type == RT_F64 && tmpc->raw_type != RT_F64) r = r(F64); else if (type != RT_F64 && tmpc->raw_type == RT_F64) r(F64) = r; MemCopy(dst, &r, tmpc->size); } } dst += tmpc->size; cc->flags = cc->flags & ~CCF_NO_ABSS | old_flags & (CCF_HAS_MISC_DATA | CCF_AOT_COMPILE); } *_dst = dst; } class CVI2 { CVI2 *next, *last; U0 base; }; U0 ParseVarInit2(CCompCtrl *cc, U8 **_dst, CHashClass *tmpc, CArrayDim *tmpad, U8 *data_addr_rip, U8 **_base, Bool data_heap, I64 pass) { I64 i, j, count; U8 *st, *_b; CVI2 head, *tmpvi, *tmpvi1; CArrayDim *tmpad1; tmpc = OptClassFwd(tmpc); if (tmpad1 = tmpad->next) { if (!tmpc->ptr_stars_count && (tmpc->raw_type == RT_I8 || tmpc->raw_type == RT_U8) && cc->token == TK_STR) { LexPopNoRestore(cc); st = LexExtStr(cc,&i); if (tmpad1->count < 0) {//[] tmpad1->count = i; tmpad->total_count = i * tmpad1->total_count; Free(*_base); if (data_heap) *_base = MAlloc(i); else *_base = MAlloc(i, Fs->code_heap); MemCopy(*_base, st, i); *_dst = *_base + i; } else { MemCopy(*_dst, st, tmpad1->count); *_dst += tmpad1->count; } Free(st); LexPush(cc); } else { if (cc->token == '{') { LexPopNoRestore(cc); LexPush(cc); Lex(cc); } if (tmpad1->count < 0) {//[] QueueInit(&head); count = 0; while (cc->token != '}') { tmpvi = MAlloc(offset(CVI2.base) + tmpad1->total_count * tmpc->size); _b = &tmpvi->base; ParseVarInit2(cc, &_b, tmpc, tmpad1, data_addr_rip, _base, data_heap, pass); QueueInsert(tmpvi, head.last); if (cc->token == ',') Lex(cc); count++; } Lex(cc); //skip '}' tmpad1->count = count; tmpad->total_count = count * tmpad1->total_count; j = tmpad1->total_count * tmpc->size; i = count * j; Free(*_base); if (data_heap) *_base = _b = MAlloc(i); else *_base = _b = MAlloc(i, Fs->code_heap); tmpvi = head.next; while (tmpvi != &head) { tmpvi1 = tmpvi->next; MemCopy(_b, &tmpvi->base, j); _b += j; Free(tmpvi); tmpvi = tmpvi1; } *_dst = _b; } else { for (i = 0; i < tmpad1->count; i++) { ParseVarInit2(cc, _dst, tmpc, tmpad1, data_addr_rip, _base, data_heap, pass); if (tmpad1->count > 1 && cc->token == ',') Lex(cc); } if (cc->token == '}') Lex(cc); } } } else { ParseVarInit(cc, _dst, tmpc, tmpad1, data_addr_rip, _base, data_heap, pass); LexPush(cc); } } U0 ParseGlobalInit(CCompCtrl *cc, CHashGlobalVar *tmpg, I64 pass) { U8 *dst = tmpg->data_addr; ParseVarInit2(cc, &dst, tmpg->var_class, &tmpg->dim, tmpg->data_addr_rip, &tmpg->data_addr, Bt(&cc->opts, OPTf_GLOBALS_ON_DATA_HEAP) || Bt(&cc->flags, CCf_AOT_COMPILE), pass); } U0 ParseStaticInit(CCompCtrl *cc, CMemberList *tmpm, I64 pass) { U8 *machine_code, *dst = tmpm->static_data; CHashClass *tmpc = tmpm->member_class; I64 i, size; CAOTImportExport *tmpie; if (cc->flags & CCF_AOT_COMPILE && pass == 2) { COCPush(cc); COCInit(cc); } ParseVarInit2(cc, &dst, tmpc, &tmpm->dim, tmpm->static_data_rip, &tmpm->static_data, Bt(&cc->flags, CCf_AOT_COMPILE), pass); if (cc->flags & CCF_AOT_COMPILE && pass == 2) { if (cc->coc.coc_head.next != &cc->coc.coc_head) { ICAdd(cc, IC_RET, 0, 0); if (machine_code = COCCompile(cc, &size, NULL, NULL)) { if (pass == 2) { tmpie = CAlloc(sizeof(CAOTImportExport)); tmpie->type = IET_MAIN; tmpie->rip = cc->aotc->rip; QueueInsert(tmpie, cc->aot->last_ie); for (i = 0; i < size; i++) AOTStoreCodeU8(cc, machine_code[i]); } Free(machine_code); } } //TODO: else del misc? COCPop(cc); } } U0 ParseArrayDims(CCompCtrl *cc, I64 mode, CArrayDim *dim) {//dim->next!=0 for array CArrayDim *tmpad, *tmpad1; I64 j; dim->next = NULL; dim->count = 0; dim->total_count = 1; tmpad1 = &dim->next; if (cc->token == '[') { if (mode.u8[1] == PRS1B_FUN_ARG) LexExcept(cc, "No arrays in fun args at "); do { if (Lex(cc) == ']' && !dim->next) j = 0; else { if ((j = LexExpressionI64(cc)) < 0) LexExcept(cc, "Invalid array size at "); } tmpad = MAlloc(sizeof(CArrayDim)); tmpad->next = NULL; tmpad1 = &dim; do { tmpad1->total_count *= j; if (!tmpad1->next) { tmpad1->next = tmpad; break; } tmpad1 = tmpad1->next; } while (tmpad1); tmpad1 = tmpad; tmpad->count = j; tmpad->total_count = 1; if (cc->token != ']') LexExcept(cc, "Missing ']' at "); } while (Lex(cc) == '['); } } CHashClass *ParseType(CCompCtrl *cc, CHashClass **_tmpc1, I64 *_mode, CMemberList *tmpm, U8 **_ident, CHashFun **_fun_ptr, CHashExport **_tmpex, CArrayDim *tmpad, I64 fsp_flags) { I64 k, ptr_stars_count, mode = *_mode; CHashClass *tmpc1 = *_tmpc1, *tmpc2; CHashFun *fun_ptr = NULL; CHashExport *tmpex = NULL; pt_start: if (!tmpc1 || !(tmpc1->type & (HTT_CLASS | HTT_INTERNAL_TYPE))) LexExcept(cc, "Invalid class at "); ptr_stars_count = 0; while (cc->token == '*') { if (mode.u8[1]) { LexPopNoRestore(cc); LexPush(cc); } Lex(cc); tmpc1++; if (++ptr_stars_count > PTR_STARS_NUM) LexExcept(cc, "Too many *'s at "); } k = ParseKeyWord(cc); if (k == KW_UNION || k == KW_CLASS) { Lex(cc); tmpc2 = ParseClass(cc, k, fsp_flags, mode & 255 == PRS0_EXTERN); tmpc2->fwd_class = tmpc1; tmpc1 = tmpc2; if (_tmpc1) *_tmpc1 = tmpc1; mode = PRS0_NULL|PRS1_NULL; goto pt_start; } if (cc->token == '(') { if (Lex(cc) != '*') LexExcept(cc, "Expecting '*' at "); ptr_stars_count = 1; //fun_ptr while (Lex(cc) == '*') ptr_stars_count++; //fun_ptr if (ptr_stars_count > PTR_STARS_NUM) LexExcept(cc, "Too many *'s at "); } else ptr_stars_count = -1; //fun_ptr if (_ident) { if (cc->token == TK_IDENT) { tmpex = cc->hash_entry; *_ident = cc->cur_str; cc->cur_str = NULL; Lex(cc); } else { if (!mode.u8[1]) *_ident = NULL; else if (cc->token == ',' || cc->token == ';' || cc->token == ')') { tmpex = NULL; *_ident = StrNew("_anon_"); tmpm->flags |= MLF_NO_UNUSED_WARN; } else LexExcept(cc, "Expecting identifier at "); } } if (ptr_stars_count >= 0) { //fun_ptr if (cc->token != ')') LexExcept(cc, "Missing ')' at "); if (Lex(cc) != '(') LexExcept(cc, "Expecting '(' at "); fun_ptr = ParseFunJoin(cc, tmpc1, NULL, fsp_flags) + ptr_stars_count; tmpc1 = cmp.internal_types[RT_PTR] + ptr_stars_count; } ParseArrayDims(cc, mode, tmpad); tmpc2 = OptClassFwd(tmpc1); if (tmpc2->ptr_stars_count) { tmpc2 -= tmpc2->ptr_stars_count; if (tmpc2->type & HTT_INTERNAL_TYPE && !tmpc2->size) LexWarn(cc, "use \"U8 *\" instead of \"U0 *\" at "); } if (_mode) *_mode = mode; if (_fun_ptr) *_fun_ptr = fun_ptr; if (_tmpex) *_tmpex = tmpex; return tmpc1; } U0 ParseDotDotDot(CCompCtrl *cc, CHashFun *tmpf, I64 _reg) { CMemberList *tmpm; CArrayDim *tmpad; Bts(&tmpf->flags, Ff_DOT_DOT_DOT); Lex(cc); tmpm = MemberListNew(_reg); tmpm->flags = MLF_DOT_DOT_DOT; tmpm->member_class = cmp.internal_types[RT_I64]; tmpm->str = StrNew("argc"); tmpm->offset = tmpf->size; tmpm->size = 8; tmpf->size += 8; MemberAdd(cc, tmpm, tmpf, PRS1B_FUN_ARG); tmpm = MemberListNew(_reg); tmpm->flags = MLF_DOT_DOT_DOT; tmpm->member_class = cmp.internal_types[RT_I64]; tmpm->str = StrNew("argv"); tmpm->dim.total_count = 127; //arbitrary tmpm->dim.next = tmpad = MAlloc(sizeof(CArrayDim)); tmpad->next = NULL; tmpad->count = 127; //arbitrary tmpad->total_count = 1; tmpm->offset = tmpf->size; tmpm->size = 8; //Close enough tmpf->size += 8;//Close enough MemberAdd(cc, tmpm, tmpf, PRS1B_FUN_ARG); if (cc->token == ')') Lex(cc); } U0 ParseVarList(CCompCtrl *cc, CHashClass *tmpc, I64 mode, I64 union_base=0) { I64 i, k, old_flags = cc->flags, old_flags2, type, _reg; CHashClass *tmpc1, *tmpc2; CHash *tmph; CMemberList *tmpm; CMemberListMeta *tmp_meta; U8 *machine_code; Bool undef_array_size, first; cc->flags |= CCF_DONT_MAKE_RES; if (mode.u8[1] == PRS1B_CLASS) cc->flags |= CCF_CLASS_DOL_OFFSET; if ((mode.u8[1] != PRS1B_LOCAL_VAR && mode.u8[1] != PRS1B_STATIC_LOCAL_VAR || mode & PRSF_UNION) && (cc->token == '(' || cc->token == '{')) Lex(cc); while (TRUE) { if (mode & PRSF_UNION) cc->class_dol_offset = union_base; else cc->class_dol_offset = tmpc->size; while (cc->token == ';') Lex(cc); while (cc->token == '$') { if (Lex(cc) != '=') //skip $ LexExcept(cc, "Expecting '=' at "); Lex(cc); //skip = cc->class_dol_offset = LexExpression(cc); if (-cc->class_dol_offset > tmpc->neg_offset) tmpc->neg_offset = -cc->class_dol_offset; if (mode & PRSF_UNION) union_base = cc->class_dol_offset; else tmpc->size = cc->class_dol_offset; if (cc->token != ';') LexExcept(cc, "Missing ';' at"); Lex(cc); //skip ; } if (cc->token == ')' || cc->token == '}') { Lex(cc); goto pvl_done; } _reg = REG_UNDEF; pvl_restart1: switch (ParseKeyWord(cc)) { case KW_REG: _reg = REG_ALLOC; if (Lex(cc) == TK_IDENT) { k = DefineMatch(cc->cur_str, "ST_U64_REGS"); if (k >= 0) { _reg = k; Lex(cc); } } goto pvl_restart1; case KW_NOREG: _reg = REG_NONE; Lex(cc); goto pvl_restart1; } if (cc->token == TK_ELLIPSIS && mode.u8[1] == PRS1B_FUN_ARG) { ParseDotDotDot(cc, tmpc, _reg); goto pvl_done; } if (cc->token == TK_IDENT) tmph = cc->hash_entry; else tmph = NULL; if (!tmph) LexExcept(cc, "Expecting type at "); k = ParseKeyWord(cc); if (k == KW_UNION) { Lex(cc); ParseVarList(cc, tmpc, mode | PRSF_UNION, tmpc->size); } else { if (!(tmph->type & (HTT_CLASS | HTT_INTERNAL_TYPE))) LexExcept(cc, "Expecting type at "); first = TRUE; pvl_restart2: tmpc1 = tmph; LexPush(cc); Lex(cc); //skip type or ',' tmpm = MemberListNew(_reg); _reg = REG_UNDEF; if (mode.u8[1] == PRS1B_STATIC_LOCAL_VAR) { tmpm->flags |= MLF_STATIC; tmpm->reg = REG_NONE; } if (mode.u8[1] == PRS1B_FUN_ARG || mode.u8[1] == PRS1B_LOCAL_VAR) { pvl_restart3: switch (ParseKeyWord(cc)) { case KW_REG: tmpm->reg = REG_ALLOC; LexPopNoRestore(cc); LexPush(cc); if (Lex(cc) == TK_IDENT) { k = DefineMatch(cc->cur_str, "ST_U64_REGS"); if (k >= 0) { tmpm->reg = k; LexPopNoRestore(cc); LexPush(cc); Lex(cc); } } goto pvl_restart3; case KW_NOREG: tmpm->reg = REG_NONE; LexPopNoRestore(cc); LexPush(cc); Lex(cc); goto pvl_restart3; } } tmpm->member_class = ParseType(cc, &tmpc1, &mode, tmpm, &tmpm->str, &tmpm->fun_ptr, NULL, &tmpm->dim, 0); if (tmpm->fun_ptr) tmpm->flags |= MLF_FUN; if (first) MemberAdd(cc, tmpm, tmpc, mode.u8[1]); else MemberAdd(cc, tmpm, tmpc, PRS1B_NULL); tmpc->member_count++; tmpc2 = tmpm->member_class; i = tmpc2->size * tmpm->dim.total_count; switch (mode.u8[1]) { case PRS1B_STATIC_LOCAL_VAR: if (i < 0) { i = 0; undef_array_size = TRUE; } else undef_array_size = FALSE; if (mode & PRSF_UNION) LexExcept(cc, "Static unions are not implemented "); k = (i + 7) & ~7; if (cc->flags & CCF_AOT_COMPILE) tmpm->static_data = MAlloc(k); else tmpm->static_data = MAlloc(k, Fs->code_heap); if (cc->flags & CCF_AOT_COMPILE) { tmpm->static_data_rip = cc->aotc->rip; k >>= 3; while (k--) AOTStoreCodeU64(cc, 0); } else if (sys_var_init_flag) MemSet(tmpm->static_data, sys_var_init_val, k); LexPopNoRestore(cc); if (cc->token == '=') { cc->flags = cc->flags & ~CCF_DONT_MAKE_RES | old_flags & CCF_DONT_MAKE_RES; if (undef_array_size) { LexPush(cc); LexPush(cc); Lex(cc); //skip = ParseStaticInit(cc, tmpm, 1); LexPopNoRestore(cc); i = tmpc2->size * tmpm->dim.total_count; k = (i + 7) & ~7; if (cc->flags & CCF_AOT_COMPILE) { k >>= 3; while (k--) AOTStoreCodeU64(cc, 0); } else if (sys_var_init_flag) MemSet(tmpm->static_data, sys_var_init_val, k); LexPopRestore(cc); } LexPush(cc); Lex(cc); //skip = ParseStaticInit(cc, tmpm, 2); LexPopNoRestore(cc); if (cc->flags & CCF_AOT_COMPILE) for (k = 0; k < i; k++) AOTStoreCodeU8At(cc, tmpm->static_data_rip + k, tmpm->static_data[k]); tmpm->use_count = 0; cc->flags |= CCF_DONT_MAKE_RES; } if (cc->flags & CCF_AOT_COMPILE) Free(tmpm->static_data); break; case PRS1B_LOCAL_VAR: if (mode & PRSF_UNION) { if (union_base - tmpc->size<i) i = union_base - i - tmpc->size; else i = 0; } if (i >= 8) tmpc->size = (tmpc->size - i) & ~7; else if (i >= 4) tmpc->size = (tmpc->size - i) & ~3; else if (i >= 2) tmpc->size = (tmpc->size - i) & ~1; else tmpc->size -= i; tmpm->offset = tmpc->size; tmpm->size = i; if (cc->token == '=') { cc->flags = cc->flags & ~CCF_DONT_MAKE_RES | old_flags & CCF_DONT_MAKE_RES; LexPopRestore(cc); Lex(cc); if (!ParseExpression(cc, NULL, TRUE)) throw('Compiler'); tmpm->use_count = 0; cc->flags |= CCF_DONT_MAKE_RES; } else LexPopNoRestore(cc); break; case PRS1B_FUN_ARG: if (mode & PRSF_UNION) { tmpm->offset = union_base; if (tmpc->size - union_base < 8) tmpc->size = 8 + union_base; } else { tmpm->offset = tmpc->size; tmpc->size += 8; } tmpm->size = 8; if (cc->token == '=') { Lex(cc); if (ParseKeyWord(cc) == KW_LASTCLASS) { tmpm->flags |= MLF_LASTCLASS; Lex(cc); } else { old_flags2 = cc->flags; cc->flags &= ~CCF_HAS_MISC_DATA; machine_code = LexExpression2Bin(cc, &type); if (!machine_code) throw('Compiler'); tmpm->default_val = Call(machine_code); tmpc2 = OptClassFwd(tmpc2); if (tmpc2->raw_type == RT_F64) { if (type != RT_F64) tmpm->default_val(F64) = tmpm->default_val; } else { if (type == RT_F64) tmpm->default_val = tmpm->default_val(F64); } if (cc->flags & CCF_HAS_MISC_DATA) { tmpm->default_val = StrNew(tmpm->default_val); tmpm->flags |= MLF_STR_DEFAULT_AVAILABLE; } Free(machine_code); cc->flags |= old_flags2 & CCF_HAS_MISC_DATA; } tmpm->flags |= MLF_DEFAULT_AVAILABLE; } LexPopNoRestore(cc); break; case PRS1B_CLASS: if (mode & PRSF_UNION) { tmpm->offset = union_base; if (tmpc->size - union_base < i) tmpc->size = i + union_base; } else { tmpm->offset = tmpc->size; tmpc->size += i; } tmpm->size = i; if (mode & PRSF_UNION) cc->class_dol_offset = union_base; else cc->class_dol_offset = tmpc->size; while (cc->token == TK_IDENT) { tmp_meta = MAlloc(sizeof(CMemberListMeta)); tmp_meta->next = tmpm->meta; tmpm->meta = tmp_meta; tmp_meta->str = cc->cur_str; tmp_meta->flags = 0; cc->cur_str = NULL; if (Lex(cc) == TK_STR) { tmp_meta->user_data = LexExtStr(cc); tmp_meta->flags |= MLMF_IS_STR; } else tmp_meta->user_data = LexExpression(cc); } LexPopNoRestore(cc); break; } switch (cc->token) { case ',': if (mode.u8[1] == PRS1B_FUN_ARG && !(mode & PRSF_UNION)) Lex(cc); else { first = FALSE; goto pvl_restart2; } break; case ')': case '}': Lex(cc); goto pvl_done; case ';': cc->flags = cc->flags & ~CCF_DONT_MAKE_RES | old_flags & CCF_DONT_MAKE_RES; Lex(cc); cc->flags |= CCF_DONT_MAKE_RES; if ((mode.u8[1] == PRS1B_LOCAL_VAR || mode.u8[1] == PRS1B_STATIC_LOCAL_VAR) && !(mode & PRSF_UNION)) goto pvl_done; break; default: LexExcept(cc, "Missing ';' at"); } } } pvl_done: cc->flags = cc->flags & ~(CCF_CLASS_DOL_OFFSET | CCF_DONT_MAKE_RES) | old_flags & (CCF_CLASS_DOL_OFFSET | CCF_DONT_MAKE_RES); }