#define PE_UNARY_TERM1 0 #define PE_UNARY_TERM2 1 #define PE_MAYBE_MODIFIERS 2 #define PE_UNARY_MODIFIERS 3 #define PE_DEREFERENCE 4 #define PE_CHECK_BINARY_OPS1 5 #define PE_CHECK_BINARY_OPS2 6 #define PE_DO_UNARY_OP 7 #define PE_DO_BINARY_OP 8 #define PE_POP_HIGHER 9 #define PE_PUSH_LOWER 10 #define PE_POP_ALL1 11 #define PE_POP_ALL2 12 CIntermediateCode *PrsAddOp(CCmpCtrl *cc,I64 stk_op,CHashClass *tmpc) { CIntermediateCode *tmpi=cc->coc.coc_head.last; Bool div_sizeof=FALSE; switch (stk_op.u16[0]) { case IC_ADD: if (tmpc->ptr_stars_cnt && !tmpi->ic_class->ptr_stars_cnt && tmpi->ic_class->raw_type!=RT_F64) { ICAdd(cc,IC_SIZEOF,1,cmp.internal_types[RT_I64]); ICAdd(cc,IC_MUL,0,cmp.internal_types[RT_I64]); } break; case IC_SUB: if (tmpc->ptr_stars_cnt && tmpi->ic_class->raw_type!=RT_F64) { if (!tmpi->ic_class->ptr_stars_cnt) { ICAdd(cc,IC_SIZEOF,1,cmp.internal_types[RT_I64]); ICAdd(cc,IC_MUL,0,cmp.internal_types[RT_I64]); } else div_sizeof=TRUE; } break; case IC_AND_AND: case IC_OR_OR: ICAdd(cc,IC_NOP1,0,cmp.internal_types[RT_I64]); break; case IC_ADD_EQU: case IC_SUB_EQU: if (tmpc->ptr_stars_cnt) { ICAdd(cc,IC_SIZEOF,1,cmp.internal_types[RT_I64]); ICAdd(cc,IC_MUL,0,cmp.internal_types[RT_I64]); } break; } tmpi=ICAdd(cc,stk_op,0,tmpc); if (stk_op.u8[3]&ECF_HAS_PUSH_CMP) { tmpi->ic_flags|=ICF_POP_CMP; ICAdd(cc,IC_NOP1,0,cmp.internal_types[RT_I64]); ICAdd(cc,IC_AND_AND,0,cmp.internal_types[RT_I64],ICF_POP_CMP); } if (div_sizeof) { tmpc--; if (tmpc->size!=1) { ICAdd(cc,IC_IMM_I64,tmpc->size,cmp.internal_types[RT_I64]); ICAdd(cc,IC_DIV,0,cmp.internal_types[RT_I64]); tmpc=cmp.internal_types[RT_I64]; } } return tmpi; } U0 PrsExpression2(CCmpCtrl *cc,I64 *_max_prec,CPrsStk *ps) { I64 i,cur_op,stk_op,state,max_prec=PREC_NULL,unary_pre_prec,paren_prec, unary_post_prec,left_prec=PREC_MAX; CIntermediateCode *tmpi; CHashClass *tmpc; CMemberLst *local_var; CArrayDim *tmpad=NULL; goto pe_unary_term1; while (TRUE) { switch [state] { case PE_UNARY_TERM1: pe_unary_term1: unary_pre_prec=PREC_NULL; unary_post_prec=PREC_NULL; cc->flags&=~(CCF_PAREN+CCF_PREINC+CCF_PREDEC+CCF_POSTINC+ CCF_POSTDEC+CCF_FUN_EXP); case PE_UNARY_TERM2: state=PrsUnaryTerm(cc,ps,&local_var,&tmpad, &max_prec,&unary_pre_prec,&paren_prec); break; case PE_UNARY_MODIFIERS: state=PrsUnaryModifier(cc,ps,&local_var,&tmpad,&unary_post_prec); break; case PE_MAYBE_MODIFIERS: if (cc->token=='(') //Typecast or fun_ptr { cc->flags|=CCF_RAX; state=PrsUnaryModifier(cc,ps,&local_var,&tmpad,&unary_post_prec); } else goto pe_check_binary_ops1; break; case PE_DEREFERENCE: if (!(cc->flags&(CCF_PREINC|CCF_PREDEC|CCF_POSTINC|CCF_POSTDEC))) i=IC_DEREF+PREC_UNARY_PRE<<16; else { if (cc->flags & CCF_POSTINC) i=IC__PP+PREC_UNARY_POST<<16; else if (cc->flags & CCF_POSTDEC) i=IC__MM+PREC_UNARY_POST<<16; else if (cc->flags & CCF_PREDEC) i=IC_MM_+PREC_UNARY_PRE<<16; else i=IC_PP_+PREC_UNARY_PRE<<16; cc->flags&=~(CCF_PREINC|CCF_PREDEC|CCF_POSTINC|CCF_POSTDEC); } tmpi=cc->coc.coc_head.last; if (cc->flags & (CCF_RAX|CCF_ARRAY)) { if (tmpi->ic_code==IC_DEREF) tmpi->ic_code=i; } else { tmpc=OptClassFwd(tmpi->ic_class-1); ICAdd(cc,i,0,tmpc); } case PE_CHECK_BINARY_OPS1: pe_check_binary_ops1: if (paren_prec) { if (unary_pre_prec || unary_post_prec) { if (paren_prec<=unary_pre_prec && !unary_post_prec) ParenWarning(cc); paren_prec=PREC_NULL; } else if (paren_prec<=PREC_UNARY_PRE+ASSOC_MASK) ParenWarning(cc); } cur_op=cmp.binary_ops[cc->token]; case PE_CHECK_BINARY_OPS2: pe_check_binary_ops2: stk_op=PrsPop(ps); tmpc=PrsPop(ps); if (!(0<stk_op.u8[2]<=PREC_UNARY_PRE+ASSOC_MASK)) goto pe_do_binary_op; case PE_DO_UNARY_OP: if (cur_op.u16[0]==IC_POWER && stk_op.u16[0]==IC_UNARY_MINUS) { Lex(cc); //skip ` op left_prec=cur_op.i8[2]; PrsPush(ps,tmpc); PrsPush(ps,stk_op); PrsPush(ps,cc->coc.coc_head.last->ic_class); PrsPush(ps,cur_op); goto pe_unary_term1; } else { tmpi=cc->coc.coc_head.last; tmpc=tmpi->ic_class; if (stk_op.u16[0]==IC_DEREF && tmpc->ptr_stars_cnt) tmpc--; else if (stk_op.u16[0]==IC_ADDR) { cc->abs_cnts.c_addres++; if (intermediate_code_table[tmpi->ic_code].type==IST_DEREF) OptFree(tmpi); tmpc++; } tmpc=OptClassFwd(tmpc); if (stk_op) ICAdd(cc,stk_op,0,tmpc); goto pe_check_binary_ops2; } case PE_DO_BINARY_OP: pe_do_binary_op: PrsPush(ps,tmpc); PrsPush(ps,stk_op); if (!cur_op) goto pe_pop_all1; switch (cur_op.u16[0]) { case IC_ADD: case IC_SUB: tmpi=cc->coc.coc_head.last; if (!tmpi->ic_class->ptr_stars_cnt && tmpi->ic_class->raw_type!=RT_F64) { ICAdd(cc,IC_SIZEOF,1,cmp.internal_types[RT_I64]); ICAdd(cc,IC_MUL,0,cmp.internal_types[RT_I64]); } break; case IC_AND_AND: case IC_OR_OR: ICAdd(cc,IC_NOP1,0,cmp.internal_types[RT_I64]); break; } if (cc->flags & CCF_FUN_EXP) { ps->ptr2--; cc->flags&=~CCF_FUN_EXP; } Lex(cc); //skip op if (paren_prec>PREC_UNARY_PRE+ASSOC_MASK && paren_prec&~ASSOC_MASK<left_prec&~ASSOC_MASK+ paren_prec&ASSOCF_RIGHT && paren_prec&~ASSOC_MASK<cur_op.u8[2]&~ASSOC_MASK+ !(paren_prec&ASSOCF_RIGHT)) ParenWarning(cc); if (cur_op.u8[2]>max_prec) max_prec=cur_op.u8[2]; left_prec=cur_op.u8[2]; if (intermediate_code_table[cur_op.u16[0]].type==IST_ASSIGN) { tmpi=cc->coc.coc_head.last; tmpc=OptClassFwd(tmpi->ic_class); if (intermediate_code_table[tmpi->ic_code].type!=IST_DEREF || !tmpc->ptr_stars_cnt && !Bt(&tmpc->flags,Cf_INTERNAL_TYPE)) LexExcept(cc,"Invalid lval at "); tmpi->ic_code=IC_NOP1; //Important for setting class (pretty sure) cur_op.u8[2]=PREC_ASSIGN|ASSOCF_RIGHT; } case PE_POP_HIGHER: pe_pop_higher: stk_op=PrsPop(ps); //pop ops of higher prec tmpc=PrsPop(ps); if (!stk_op) goto pe_push_lower; else if (cur_op.u8[2]&~ASSOC_MASK==stk_op.u8[2]&~ASSOC_MASK) { if (cur_op.u8[2]&ASSOCF_RIGHT) goto pe_push_lower; } else if (cur_op.u8[2]&~ASSOC_MASK<=stk_op.u8[2]&~ASSOC_MASK) goto pe_push_lower; tmpi=PrsAddOp(cc,stk_op,tmpc); if (intermediate_code_table[cur_op.u16[0]].type==IST_CMP && intermediate_code_table[stk_op.u16[0]].type==IST_CMP) { tmpi->ic_flags|=ICF_PUSH_CMP; ICAdd(cc,IC_NOP1,0,cmp.internal_types[RT_I64]); ICAdd(cc,IC_PUSH_CMP,0,tmpc); cur_op.u8[3]|=ECF_HAS_PUSH_CMP; } else if (cur_op.u16[0]==IC_AND_AND || cur_op.u16[0]==IC_OR_OR) ICAdd(cc,IC_NOP1,0,cmp.internal_types[RT_I64]); goto pe_pop_higher; case PE_PUSH_LOWER: pe_push_lower: PrsPush(ps,tmpc); PrsPush(ps,stk_op); PrsPush(ps,cc->coc.coc_head.last->ic_class); PrsPush(ps,cur_op); goto pe_unary_term1; case PE_POP_ALL1: pe_pop_all1: if (paren_prec>PREC_UNARY_PRE+ASSOC_MASK && paren_prec&~ASSOC_MASK<=left_prec&~ASSOC_MASK- paren_prec&ASSOCF_LEFT-left_prec&ASSOCF_LEFT) ParenWarning(cc); case PE_POP_ALL2: pe_pop_all2: stk_op=PrsPop(ps); tmpc=PrsPop(ps); if (!stk_op.u16[0]) goto pe_done; PrsAddOp(cc,stk_op,tmpc); goto pe_pop_all2; } } pe_done: if (_max_prec) *_max_prec=max_prec; } Bool PrsExpression(CCmpCtrl *cc,I64 *_max_prec,Bool end_exp,CPrsStk *_ps=NULL) { Bool res=TRUE; I64 old_flags=cc->flags; CPrsStk *ps; if (_ps) ps=_ps; else { ps=MAlloc(sizeof(CPrsStk)); ps->ptr=0; ps->ptr2=0; } PrsPush(ps,0); //terminate PrsPush(ps,0); //terminate try //try catch causes noreg vars in function PrsExpression2(cc,_max_prec,ps); catch { if (Fs->except_ch=='Compiler') { res=FALSE; Fs->catch_except=TRUE; } } if (!_ps) { if (ps->ptr) LexExcept(cc,"Compiler Parse Error at "); Free(ps); } if (res) { if (end_exp) ICAdd(cc,IC_END_EXP,0,0,ICF_RES_NOT_USED); if (cc->coc.coc_head.last->ic_class== cmp.internal_types[RT_U0]) LexWarn(cc,"U0 Expression "); } cc->flags|=old_flags&(CCF_PREINC|CCF_PREDEC); return res; } U0 PrsSizeOf(CCmpCtrl *cc) { CHashClass *tmpc; CMemberLst *tmpm; CDbgInfo *dbg_info; I64 i; if (cc->token!=TK_IDENT) LexExcept(cc,"Invalid class at "); if (tmpm=cc->local_var_entry) { tmpc=tmpm->member_class; i=tmpc->size*tmpm->dim.total_cnt; if (Lex(cc)=='.') goto pu_sizeof_member; } else { if (!(tmpc=cc->hash_entry) || !(tmpc->type & (HTT_CLASS|HTT_INTERNAL_TYPE|HTT_GLBL_VAR| HTT_FUN|HTT_EXPORT_SYS_SYM))) LexExcept(cc,"Invalid class at "); if (tmpc->type&(HTT_FUN|HTT_EXPORT_SYS_SYM)) { if (!(dbg_info=tmpc(CHashFun *)->dbg_info)) LexExcept(cc,"Size not defined at "); i=dbg_info->body[dbg_info->max_line+1-dbg_info->min_line] -dbg_info->body[0]; Lex(cc); } else { i=tmpc->size; while (Lex(cc)=='.') { pu_sizeof_member: if (!(tmpc->type & (HTT_CLASS|HTT_GLBL_VAR))) LexExcept(cc,"Invalid class at "); else if (tmpc->type & HTT_GLBL_VAR) tmpc=tmpc(CHashGlblVar *)->var_class; if (Lex(cc)!=TK_IDENT || !(tmpm=MemberFind(cc->cur_str,tmpc))) LexExcept(cc,"Invalid member at "); else if (cc->local_var_entry) cc->local_var_entry->use_cnt--; tmpc=tmpm->member_class; //Probably others like this: #assert offset(CHashClass.size)==offset(CHashGlblVar.size) i=tmpc->size*tmpm->dim.total_cnt; } } } if (cc->token=='*') { while (Lex(cc)=='*'); i=sizeof(U8 *); } ICAdd(cc,IC_IMM_I64,i,cmp.internal_types[RT_I64]); } U0 PrsOffsetOf(CCmpCtrl *cc) { CHashClass *tmpc; CMemberLst *tmpm; I64 i; if (cc->token!=TK_IDENT) LexExcept(cc,"Invalid class at "); if (tmpm=cc->local_var_entry) tmpc=tmpm->member_class; else { tmpc=cc->hash_entry; if (!tmpc || !(tmpc->type & (HTT_CLASS|HTT_GLBL_VAR))) LexExcept(cc,"Invalid class at "); else if (tmpc->type & HTT_GLBL_VAR) tmpc=tmpc(CHashGlblVar *)->var_class; } if (Lex(cc)!='.') LexExcept(cc,"Expecting '.' at "); i=0; do { if (Lex(cc)!=TK_IDENT || !(tmpm=MemberFind(cc->cur_str,tmpc))) LexExcept(cc,"Invalid member at "); else if (cc->local_var_entry) cc->local_var_entry->use_cnt--; i+=tmpm->offset; tmpc=tmpm->member_class; } while (Lex(cc)=='.'); ICAdd(cc,IC_IMM_I64,i,cmp.internal_types[RT_I64]); } I64 PrsFunCall(CCmpCtrl *cc,CPrsStk *ps,Bool indirect,CHashFun *tmpf) { I64 i,argc_cnt,dft_val; Bool is_first_arg=TRUE,needs_right_paren,is_print,is_putchars, is_template_fun; CHashClass *tmpc2,*last_class=NULL; CMemberLst *tmpm; CCodeCtrl *tmpcbh,*tmpcbh1; CCodeMisc *cm; CIntermediateCode *tmpi; if (!tmpf) { if (cc->token==TK_CHAR_CONST) { if (!(tmpf=HashFind("PutChars",cc->htc.hash_table_lst,HTT_FUN))) LexExcept(cc,"Missing header for Print() and PutChars() at "); if (!cc->cur_i64) //empty char signals PutChars with variable Lex(cc); is_print=FALSE; is_putchars=TRUE; } else { if (!(tmpf=HashFind("Print",cc->htc.hash_table_lst,HTT_FUN))) LexExcept(cc,"Missing header for Print() and PutChars() at "); if (!*cc->cur_str) //empty string signals Print with variable fmt_str Lex(cc); is_putchars=FALSE; is_print=TRUE; } } else { is_print=FALSE; is_putchars=FALSE; } if (Bt(&tmpf->flags,Ff_INTERNAL)&& IC_SQR<=tmpf->exe_addr<=IC_ATAN) is_template_fun=TRUE; else is_template_fun=FALSE; if (indirect) { if (!(cc->flags & (CCF_RAX | CCF_ARRAY))) ICAdd(cc,IC_DEREF,0,cmp.internal_types[RT_PTR]); cc->coc.coc_head.last->ic_class=cmp.internal_types[RT_PTR]; ICAdd(cc,IC_SET_RAX,0,cmp.internal_types[RT_PTR]); ICAdd(cc,IC_NOP2,1,cmp.internal_types[RT_PTR]); //balance the books } COCPush(cc); tmpcbh=cc->coc.coc_next; cc->coc.coc_next=NULL; i=tmpf->arg_cnt; tmpm=tmpf->member_lst_and_root; argc_cnt=0; if (cc->token=='(') { Lex(cc); needs_right_paren=TRUE; } else needs_right_paren=FALSE; while (i--) { COCInit(cc); if (!is_first_arg) { if (is_print) { if (cc->token==',') Lex(cc); else if (cc->token!=';') LexExcept(cc,"Expecting ',' at "); } else { if (needs_right_paren) { if (cc->token==',') Lex(cc); else if (cc->token!=')') LexExcept(cc,"Expecting ',' at "); } } } if (tmpm->flags & MLF_DFT_AVAILABLE && (cc->token==')' || cc->token==',' || !needs_right_paren)) { dft_val=tmpm->dft_val; if (tmpm->flags & MLF_LASTCLASS && last_class) dft_val=(last_class-last_class->ptr_stars_cnt)->str; if (tmpm->flags & (MLF_STR_DFT_AVAILABLE|MLF_LASTCLASS) && cc->flags&CCF_AOT_COMPILE) { cm=COCMiscNew(cc,CMT_STR_CONST); ICAdd(cc,IC_STR_CONST,cm,cmp.internal_types[RT_U8]+1); cm->st_len=StrLen(dft_val)+1; cm->str=StrNew(dft_val); cc->flags|=CCF_HAS_MISC_DATA; } else ICAdd(cc,IC_IMM_I64,dft_val,tmpm->member_class); } else { if (!PrsExpression(cc,NULL,FALSE,ps)) throw('Compiler'); else { COCPush(cc); cc->pass=0; OptPass012(cc); cc->pass=1; tmpi=OptPass012(cc); COCPop(cc); last_class=OptClassFwd(tmpi->ic_class); tmpc2=OptClassFwd(tmpm->member_class); if (tmpc2->raw_type==RT_F64 && !tmpm->dim.next && last_class->raw_type!=RT_F64) tmpi->ic_flags|=ICF_RES_TO_F64; else if (tmpc2->raw_type!=RT_F64 && last_class->raw_type==RT_F64) tmpi->ic_flags|=ICF_RES_TO_INT; } } COCPush(cc); is_first_arg=FALSE; tmpm=tmpm->next; } if (tmpm && tmpm->flags & MLF_DOT_DOT_DOT) { COCInit(cc); tmpi=ICAdd(cc,IC_IMM_I64,0,tmpm->member_class); COCPush(cc); if (is_print) { if (cc->token!=';') { do { if (!is_first_arg) { if (cc->token==',') Lex(cc); else LexExcept(cc,"Expecting ',' at "); } COCInit(cc); if (!PrsExpression(cc,NULL,FALSE,ps)) throw('Compiler'); COCPush(cc); is_first_arg=FALSE; argc_cnt++; } while (cc->token==','); } } else if (needs_right_paren) { if (cc->token!=')') { do { if (!is_first_arg) { if (cc->token==',') Lex(cc); else LexExcept(cc,"Expecting ',' at "); } COCInit(cc); if (!PrsExpression(cc,NULL,FALSE,ps)) throw('Compiler'); COCPush(cc); is_first_arg=FALSE; argc_cnt++; } while (cc->token==','); } } tmpi->ic_data=argc_cnt++; //++ so add_esp latter works } if (needs_right_paren) { if (cc->token==')') Lex(cc); else LexExcept(cc,"Missing ')' at "); } tmpcbh1=tmpcbh->coc_next; tmpcbh->coc_next=cc->coc.coc_next; cc->coc.coc_next=tmpcbh; COCPop(cc); tmpcbh=cc->coc.coc_next; cc->coc.coc_next=tmpcbh1; if (!is_template_fun) ICAdd(cc,IC_CALL_START,tmpf,0); if (indirect) ICAdd(cc,IC_PUSH_REGS,1<<REG_RAX,tmpf->return_class); while (tmpcbh) { tmpcbh1=tmpcbh->coc_next; COCAppend(cc,tmpcbh); if (!Bt(&tmpf->flags,Ff_INTERNAL)) cc->coc.coc_head.last->ic_flags|=ICF_PUSH_RES; tmpcbh=tmpcbh1; } if (Bt(&tmpf->flags,Ff_INTERNAL)) ICAdd(cc,tmpf->exe_addr,0,tmpf->return_class); else { if (indirect) ICAdd(cc,IC_CALL_INDIRECT, (argc_cnt+tmpf->arg_cnt)<<3,tmpf->return_class); else if (Bt(&tmpf->flags,Cf_EXTERN)) { cc->abs_cnts.externs++; if (cc->flags&CCF_AOT_COMPILE) { if (tmpf->type&HTF_IMPORT) ICAdd(cc,IC_CALL_IMPORT,tmpf,tmpf->return_class); else ICAdd(cc,IC_CALL_EXTERN,tmpf,tmpf->return_class); } else ICAdd(cc,IC_CALL_INDIRECT2,&tmpf->exe_addr,tmpf->return_class); } else ICAdd(cc,IC_CALL,tmpf->exe_addr,tmpf->return_class); if ((Bt(&tmpf->flags,Ff_RET1) || Bt(&tmpf->flags,Ff_ARGPOP)) && !Bt(&tmpf->flags,Ff_NOARGPOP)) { if (indirect) { ICAdd(cc,IC_ADD_RSP1,(argc_cnt+tmpf->arg_cnt)<<3,tmpf->return_class); ICAdd(cc,IC_ADD_RSP,8,tmpf->return_class); } else ICAdd(cc,IC_ADD_RSP1,(argc_cnt+tmpf->arg_cnt)<<3,tmpf->return_class); } else { if (indirect) argc_cnt++; ICAdd(cc,IC_ADD_RSP,(argc_cnt+tmpf->arg_cnt)<<3,tmpf->return_class); } } if (!is_template_fun) ICAdd(cc,IC_CALL_END,tmpf,tmpf->return_class); if (is_print||is_putchars) ICAdd(cc,IC_END_EXP,0,0,ICF_RES_NOT_USED); cc->flags=(cc->flags|CCF_RAX) & ~(CCF_ARRAY|CCF_FUN_EXP); return PE_UNARY_MODIFIERS; } I64 PrsUnaryTerm(CCmpCtrl *cc,CPrsStk *ps,CMemberLst **_local_var, CArrayDim **_tmpad,I64 *max_prec,I64 *unary_pre_prec,I64 *paren_prec) { I64 i,j; CHashExport *tmpex; CHashClass *tmpc; CHashFun *tmpf; CHashGlblVar *tmpg; CMemberLst *tmpm; CAsmUndefHash *tmpauh; CCodeMisc *cm; Bool paren_warn; *_local_var=NULL; *paren_prec=PREC_NULL; switch (cc->token) { start: if (PREC_UNARY_PRE>*max_prec) *max_prec=PREC_UNARY_PRE; *unary_pre_prec=PREC_UNARY_PRE; start: case '~': i=IC_COM; break; case '!': i=IC_NOT; break; case '-': i=IC_UNARY_MINUS; break; case '*': i=IC_DEREF; break; end: Lex(cc); //Skip op break; case '&': if (Lex(cc)==TK_IDENT) { if (tmpc=cc->hash_entry) { if (tmpc->type & HTT_FUN) { tmpf=tmpc; if (!Bt(&tmpf->flags,Ff_INTERNAL)) { if (Bt(&tmpf->flags,Cf_EXTERN)) { if (cc->flags&CCF_AOT_COMPILE) { if (cc->flags&CCF_ASM_EXPRESSIONS) { if (tmpex=HashFind(tmpf->str,cc->htc.hash_table_lst, HTT_EXPORT_SYS_SYM)) goto pu_export_sys_sym; else goto pu_new_sys_sym; } LexExcept(cc,"Can't take addr of extern fun"); } cc->abs_cnts.externs++; ICAdd(cc,IC_IMM_I64, &tmpf->exe_addr,cmp.internal_types[RT_PTR]); ICAdd(cc,IC_DEREF,0,cmp.internal_types[RT_PTR]); } else { if (cc->flags&CCF_AOT_COMPILE) { ICAdd(cc,IC_ABS_ADDR, tmpf->exe_addr,cmp.internal_types[RT_PTR]); if (cc->flags&CCF_ASM_EXPRESSIONS) cc->abs_cnts.abs_addres++; } else ICAdd(cc,IC_IMM_I64, tmpf->exe_addr,cmp.internal_types[RT_PTR]); } cc->abs_cnts.c_addres++; Lex(cc); return PE_MAYBE_MODIFIERS; } } else if (tmpc->type & HTT_EXPORT_SYS_SYM) { tmpex=tmpc; if (cc->flags&CCF_ASM_EXPRESSIONS && !(cc->flags&CCF_AOT_COMPILE) && tmpex->type&HTF_IMM) { cc->abs_cnts.c_addres++; ICAdd(cc,IC_IMM_I64, tmpex->val,cmp.internal_types[RT_PTR]); Lex(cc); return PE_MAYBE_MODIFIERS; } else goto pu_export_sys_sym; } } else if (cc->flags&CCF_ASM_EXPRESSIONS && !cc->local_var_entry) goto pu_ident_but_not_local_var; } i=IC_ADDR; break; end: PrsPush(ps,tmpc); PrsPush(ps,PREC_UNARY_PRE<<16+i); return PE_UNARY_TERM2; start: case TK_I64: case TK_CHAR_CONST: case TK_INS_BIN_SIZE: if (cc->cur_i64<0) ICAdd(cc,IC_IMM_I64,cc->cur_i64,cmp.internal_types[RT_U64]); else ICAdd(cc,IC_IMM_I64,cc->cur_i64,cmp.internal_types[RT_I64]); Lex(cc); break; case TK_F64: ICAdd(cc,IC_IMM_F64,cc->cur_f64(I64),cmp.internal_types[RT_F64]); Lex(cc); break; case TK_STR: cm=COCMiscNew(cc,CMT_STR_CONST); ICAdd(cc,IC_STR_CONST,cm,cmp.internal_types[RT_U8]+1); cm->str=LexExtStr(cc,&cm->st_len); cc->flags|=CCF_HAS_MISC_DATA; break; case TK_INS_BIN: cm=COCMiscNew(cc,CMT_STR_CONST); ICAdd(cc,IC_STR_CONST,cm,cmp.internal_types[RT_U8]+1); cm->str=cc->cur_str; cm->st_len=cc->cur_str_len; cc->cur_str=NULL; cc->flags|=CCF_HAS_MISC_DATA; Lex(cc); break; case '$': if (cc->flags & CCF_ASM_EXPRESSIONS) { cc->abs_cnts.abs_addres++; if (cc->flags&CCF_AOT_COMPILE) ICAdd(cc,IC_ABS_ADDR,cc->aotc->rip,cmp.internal_types[RT_PTR]); else ICAdd(cc,IC_IMM_I64,cc->aotc->rip,cmp.internal_types[RT_PTR]); } else { if (cc->flags&CCF_CLASS_DOL_OFFSET) ICAdd(cc,IC_IMM_I64,cc->class_dol_offset, cmp.internal_types[RT_I64]); else ICAdd(cc,IC_RIP,0,cmp.internal_types[RT_PTR]); } Lex(cc); break; end: if (PREC_TERM>*max_prec) *max_prec=PREC_TERM; return PE_MAYBE_MODIFIERS; case '(': if (Lex(cc)==TK_IDENT && cc->hash_entry && cc->hash_entry->type & (HTT_CLASS|HTT_INTERNAL_TYPE)) LexExcept(cc,"Use TempleOS postfix typecasting at "); else { if (PREC_TERM>*max_prec) *max_prec=PREC_TERM; if (cc->lex_include_stk->flags&LFSF_DEFINE) paren_warn=FALSE; else paren_warn=TRUE; if (!PrsExpression(cc,paren_prec,FALSE,ps)) throw('Compiler'); if (!paren_warn) *paren_prec=PREC_NULL; if (cc->token!=')') LexExcept(cc,"Missing ')' at "); Lex(cc); //skip ) cc->flags= cc->flags & ~CCF_ARRAY | CCF_RAX | CCF_PAREN; return PE_UNARY_MODIFIERS; } start: case '+': break; case TK_PLUS_PLUS: cc->flags|=CCF_PREINC; break; case TK_MINUS_MINUS: cc->flags|=CCF_PREDEC; break; end: if (PREC_UNARY_PRE>*max_prec) *max_prec=PREC_UNARY_PRE; *unary_pre_prec=PREC_UNARY_PRE; Lex(cc); return PE_UNARY_TERM2; case TK_IDENT: if (tmpm=cc->local_var_entry) { if (PREC_TERM>*max_prec) *max_prec=PREC_TERM; cc->flags&=~(CCF_RAX|CCF_ARRAY|CCF_FUN_EXP); tmpc=tmpm->member_class+1; if (tmpm->flags & MLF_FUN && !(cc->flags&CCF_ASM_EXPRESSIONS)) { PrsPopDeref(ps); cc->flags|=CCF_FUN_EXP; PrsPush2(ps,tmpm->fun_ptr-tmpm->fun_ptr->ptr_stars_cnt); } if (tmpm->dim.next) { *_tmpad=tmpm->dim.next; cc->flags|=CCF_ARRAY; } if (tmpm->flags&MLF_STATIC) { if (cc->flags&CCF_AOT_COMPILE) { // if (tmpg->flags&GVF_DATA_HEAP) //TODO // ICAdd(cc,IC_HEAP_GLBL,tmpm->static_data,tmpc); // else ICAdd(cc,IC_ABS_ADDR,tmpm->static_data_rip,tmpc); } else ICAdd(cc,IC_IMM_I64,tmpm->static_data,tmpc); } else { if (cc->flags&CCF_ASM_EXPRESSIONS) { i=PrsPop(ps); ps->ptr--; if (i.u16[0]!=IC_ADDR) LexExcept(cc,"Expecting '&' at "); ICAdd(cc,IC_IMM_I64,tmpm->offset,cmp.internal_types[RT_PTR]); *_local_var=tmpm; Lex(cc); return PE_MAYBE_MODIFIERS; } else { if (tmpm->dim.next && tmpm->offset>0 && StrCmp(tmpm->str,"argv")) { tmpc++; cc->flags&=~CCF_ARRAY; } ICAdd(cc,IC_RBP,0,tmpc); ICAdd(cc,IC_IMM_I64,tmpm->offset,tmpc); ICAdd(cc,IC_ADD,0,tmpc); } } Lex(cc); //skip var name *_local_var=tmpm; return PE_UNARY_MODIFIERS; } pu_ident_but_not_local_var: if (!(tmpex=cc->hash_entry)) { if (!(cc->flags & CCF_ASM_EXPRESSIONS)) LexExcept(cc,"Invalid lval at "); tmpc=NULL; pu_new_sys_sym: tmpex=CAlloc(sizeof(CHashExport),Fs->code_heap); tmpex->str=cc->cur_str; cc->cur_str=NULL; if (!cc->htc.local_var_lst && *tmpex->str=='@' && tmpex->str[1]=='@') { tmpex->type=HTT_EXPORT_SYS_SYM | HTF_UNRESOLVED | HTF_LOCAL; HashAdd(tmpex,cc->htc.local_hash_table); } else { tmpex->type=HTT_EXPORT_SYS_SYM | HTF_UNRESOLVED; if (tmpc) HashAddAfter(tmpex,tmpc,cc->htc.glbl_hash_table); else HashAdd(tmpex,cc->htc.glbl_hash_table); } } switch (Bsf(tmpex->type)) { case HTt_EXPORT_SYS_SYM: pu_export_sys_sym: if (PREC_TERM>*max_prec) *max_prec=PREC_TERM; if (!(tmpex->type & (HTF_IMM|HTF_IMPORT))) cc->abs_cnts.abs_addres++; if (tmpex->type & HTF_UNRESOLVED) { if (!(cc->flags&CCF_ASM_EXPRESSIONS)) LexExcept(cc,"Illegal fwd ref at "); tmpauh=MAlloc(sizeof(CAsmUndefHash)); tmpauh->hash=tmpex; tmpauh->next=cc->asm_undef_hash; cc->asm_undef_hash=tmpauh; if (tmpex->type & HTF_LOCAL) cc->flags|=CCF_UNRESOLVED|CCF_LOCAL; else cc->flags|=CCF_UNRESOLVED; ICAdd(cc,IC_IMM_I64, &tmpex->val,cmp.internal_types[RT_PTR],ICF_NO_RIP); ICAdd(cc,IC_DEREF,0,cmp.internal_types[RT_PTR]); } else { if (cc->flags&CCF_AOT_COMPILE && !(tmpex->type & HTF_IMM)) ICAdd(cc,IC_ABS_ADDR,tmpex->val,cmp.internal_types[RT_PTR]); else { if (tmpex->type&HTF_IMM) cc->abs_cnts.c_addres++; ICAdd(cc,IC_IMM_I64,tmpex->val,cmp.internal_types[RT_PTR]); } } Lex(cc); return PE_MAYBE_MODIFIERS; case HTt_FUN: if (PREC_TERM>*max_prec) *max_prec=PREC_TERM; Lex(cc); //skip fun name return PrsFunCall(cc,ps,FALSE,tmpex); case HTt_GLBL_VAR: if (PREC_TERM>*max_prec) *max_prec=PREC_TERM; tmpg=tmpex; tmpc=tmpg->var_class+1; cc->flags&=~(CCF_RAX|CCF_ARRAY|CCF_FUN_EXP); if (tmpg->flags&GVF_ARRAY) { *_tmpad=tmpg->dim.next; cc->flags|=CCF_ARRAY; } if (cc->flags&CCF_AOT_COMPILE) { if (tmpg->flags & GVF_EXTERN) //TODO LexExcept(cc,"Feature not implemented "); else { if (tmpg->flags & GVF_IMPORT) ICAdd(cc,IC_ADDR_IMPORT,tmpg,tmpc); else { if (tmpg->flags&GVF_DATA_HEAP) ICAdd(cc,IC_HEAP_GLBL,tmpg->heap_glbl,tmpc); else ICAdd(cc,IC_ABS_ADDR,tmpg->data_addr_rip,tmpc); } } } else { if (tmpg->flags & GVF_EXTERN) { cc->abs_cnts.externs++; ICAdd(cc,IC_IMM_I64,&tmpg->data_addr,tmpc); ICAdd(cc,IC_DEREF,0,tmpc); } else ICAdd(cc,IC_IMM_I64,tmpg->data_addr,tmpc); } Lex(cc); if (tmpg->flags & GVF_FUN) { PrsPopDeref(ps); cc->flags|=CCF_FUN_EXP; PrsPush2(ps,tmpg->fun_ptr-tmpg->fun_ptr->ptr_stars_cnt); } return PE_UNARY_MODIFIERS; case HTt_CLASS: PrsOffsetOf(cc); return PE_MAYBE_MODIFIERS; case HTt_KEYWORD: switch (tmpex(CHashGeneric *)->user_data0) { case KW_SIZEOF: if (PREC_TERM>*max_prec) *max_prec=PREC_TERM; j=0; while (Lex(cc)=='(') j++; PrsSizeOf(cc); while (j--) { if (cc->token!=')') LexExcept(cc,"Missing ')' at "); Lex(cc); } return PE_MAYBE_MODIFIERS; case KW_OFFSET: if (PREC_TERM>*max_prec) *max_prec=PREC_TERM; j=0; while (Lex(cc)=='(') j++; PrsOffsetOf(cc); while (j--) { if (cc->token!=')') LexExcept(cc,"Missing ')' at "); Lex(cc); } return PE_MAYBE_MODIFIERS; case KW_DEFINED: if (PREC_TERM>*max_prec) *max_prec=PREC_TERM; j=0; while (Lex(cc)=='(') j++; if (cc->token==TK_IDENT && (cc->hash_entry || cc->local_var_entry)) ICAdd(cc,IC_IMM_I64,TRUE,cmp.internal_types[RT_I64]); else ICAdd(cc,IC_IMM_I64,FALSE,cmp.internal_types[RT_I64]); Lex(cc); while (j--) { if (cc->token!=')') LexExcept(cc,"Missing ')' at "); Lex(cc); } return PE_MAYBE_MODIFIERS; } } } LexExcept(cc,"Missing expression at "); } I64 PrsUnaryModifier(CCmpCtrl *cc,CPrsStk *ps,CMemberLst **_local_var, CArrayDim **_tmpad,I64 *unary_post_prec) { CHashClass *tmpc,*tmpc1; CHashFun *fun_ptr; CMemberLst *tmpm=*_local_var; CIntermediateCode *tmpi,*tmpi1; CArrayDim *tmpad1,tmpad2; CCodeMisc *cm; I64 mode,old_flags; Bool was_paren=Btr(&cc->flags,CCf_PAREN); *_local_var=NULL; switch (cc->token) { case '.': if (tmpm) tmpm->reg=REG_NONE; goto um_join; case TK_DEREFERENCE: tmpi=cc->coc.coc_head.last; if (!(cc->flags & (CCF_RAX | CCF_ARRAY))) ICAdd(cc,IC_DEREF+PREC_UNARY_PRE<<16,0,tmpi->ic_class-1); else tmpi->ic_class--; um_join: if (!*unary_post_prec) *unary_post_prec=PREC_TERM; tmpc=cc->coc.coc_head.last->ic_class; if ((!tmpc->ptr_stars_cnt || cc->flags & CCF_ARRAY) && cc->token=='.') LexExcept(cc,"Must be address, not value "); if (!(cc->flags & CCF_RAX)) tmpc--; if (!(tmpc->type & HTT_CLASS)) LexExcept(cc,"Invalid class at "); if (Lex(cc)!=TK_IDENT || !(tmpm=MemberFind(cc->cur_str,tmpc))) LexExcept(cc,"Invalid member at "); else if (cc->local_var_entry) cc->local_var_entry->use_cnt--; Lex(cc); //skip member name tmpc1=tmpm->member_class+1; ICAdd(cc,IC_IMM_I64,tmpm->offset,tmpc1); cc->flags&=~(CCF_RAX|CCF_ARRAY|CCF_FUN_EXP); if (tmpm->dim.next) { *_tmpad=tmpm->dim.next; cc->flags|=CCF_ARRAY; } if(tmpm->flags & MLF_FUN) { PrsPopDeref(ps); PrsPush2(ps,tmpm->fun_ptr-tmpm->fun_ptr->ptr_stars_cnt); cc->flags|=CCF_FUN_EXP; } ICAdd(cc,IC_ADD,0,tmpc1); return PE_UNARY_MODIFIERS; case '(': if (cc->flags & CCF_FUN_EXP) { if (!*unary_post_prec) *unary_post_prec=PREC_TERM; return PrsFunCall(cc,ps,TRUE,PrsPop2(ps)); } if (!*unary_post_prec) *unary_post_prec=PREC_TERM; if (Lex(cc)!=TK_IDENT) LexExcept(cc,"Invalid class at "); if (Btr(&cc->flags,CCf_FUN_EXP)) ps->ptr2--; cc->flags&=~CCF_ARRAY; tmpc=cc->hash_entry; Lex(cc); mode=PRS0_TYPECAST|PRS1_NULL; tmpc=PrsType(cc,&tmpc,&mode,NULL,NULL,&fun_ptr,NULL,&tmpad2,0); if (fun_ptr) { PrsPopDeref(ps); Bts(&cc->flags,CCf_FUN_EXP); PrsPush2(ps,fun_ptr); cm=COCMiscNew(cc,CMT_HASH_ENTRY); cm->h=fun_ptr; } if (*_tmpad=tmpad2.next) { cc->flags|=CCF_ARRAY; tmpc++; cm=COCMiscNew(cc,CMT_ARRAY_DIM); cm->dim=*_tmpad; } if (!(cc->flags&(CCF_RAX|CCF_ARRAY))) tmpc++; tmpi=cc->coc.coc_head.last; tmpi->ic_class=tmpc; ICAdd(cc,IC_HOLYC_TYPECAST,was_paren,tmpc); if (cc->token!=')') LexExcept(cc,"Missing ')' at "); Lex(cc); return PE_UNARY_MODIFIERS; case '[': if (!*unary_post_prec) *unary_post_prec=PREC_TERM; Lex(cc); tmpc=OptClassFwd(cc->coc.coc_head.last->ic_class); if (!tmpc->ptr_stars_cnt) LexExcept(cc,"Not array or ptr "); if (!(cc->flags & (CCF_ARRAY | CCF_RAX))) { tmpc=OptClassFwd(tmpc-1); if (!tmpc->ptr_stars_cnt) LexExcept(cc,"Not array or ptr "); ICAdd(cc,IC_DEREF+PREC_UNARY_PRE<<16,0,tmpc); } tmpc1=tmpc-1; if (tmpad1=*_tmpad) { ICAdd(cc,IC_IMM_I64,tmpad1->total_cnt*tmpc1->size,tmpc); if (*_tmpad=tmpad1->next) { old_flags=cc->flags; if (!PrsExpression(cc,NULL,FALSE,ps)) throw('Compiler'); cc->flags=cc->flags&~CCF_FUN_EXP|old_flags&CCF_FUN_EXP; if (cc->token!=']') LexExcept(cc,"Missing ']' at "); Lex(cc); //skip ] tmpi1=cc->coc.coc_head.last; tmpi1->ic_flags|=ICF_RES_TO_INT; ICAdd(cc,IC_MUL,0,tmpc); ICAdd(cc,IC_ADD,0,tmpc); cc->flags|=CCF_RAX; return PE_UNARY_MODIFIERS; } } else ICAdd(cc,IC_IMM_I64,tmpc1->size,tmpc); old_flags=cc->flags; if (!PrsExpression(cc,NULL,FALSE,ps)) throw('Compiler'); cc->flags=cc->flags&~CCF_FUN_EXP|old_flags&CCF_FUN_EXP; if (cc->token!=']') LexExcept(cc,"Missing ']' at "); Lex(cc); //skip ] tmpi1=cc->coc.coc_head.last; tmpi1->ic_flags|=ICF_RES_TO_INT; ICAdd(cc,IC_MUL,0,tmpc); ICAdd(cc,IC_ADD,0,tmpc); cc->flags&=~(CCF_RAX|CCF_ARRAY); return PE_UNARY_MODIFIERS; start: case TK_PLUS_PLUS: cc->flags|=CCF_POSTINC; break; case TK_MINUS_MINUS: cc->flags|=CCF_POSTDEC; break; end: if (!*unary_post_prec) *unary_post_prec=PREC_UNARY_POST; Lex(cc); return PE_DEREFERENCE; } return PE_DEREFERENCE; } U8 *LexExpression2Bin(CCmpCtrl *cc,I64 *_type=NULL) {//Compile cc expression. You call the code. U8 *res; I64 size; Bool old_trace=Btr(&cc->flags,CCf_PASS_TRACE_PRESENT); COCPush(cc); COCInit(cc); if (PrsExpression(cc,NULL,FALSE)) { ICAdd(cc,IC_RETURN_VAL,0,0); ICAdd(cc,IC_RET,0,0); res=COCCompile(cc,&size,NULL,_type); } else res=NULL; COCPop(cc); BEqu(&cc->flags,CCf_PASS_TRACE_PRESENT,old_trace); return res; } Bool IsLexExpression2Bin(CCmpCtrl *cc,U8 **_machine_code) {//Compile cc expression to bin. Return err status. return ToBool(*_machine_code=LexExpression2Bin(cc)); } I64 LexExpressionI64(CCmpCtrl *cc) {//Compile cc expression, forcing to I64 and eval. U8 *machine_code; I64 res,type; if (machine_code=LexExpression2Bin(cc,&type)) { res=Call(machine_code); Free(machine_code); if (type==RT_F64) res=ToI64(res(F64)); } else res=0; return res; } F64 LexExpressionF64(CCmpCtrl *cc) {//Compile cc expression, forcing to F64 and eval. U8 *machine_code; I64 res,type; if (machine_code=LexExpression2Bin(cc,&type)) { res=Call(machine_code); Free(machine_code); if (type!=RT_F64) res(F64)=ToF64(res); } else res=0; return res(F64); } I64 LexExpression(CCmpCtrl *cc) {//Compile cc expression and eval. Might be I64 or F64. U8 *machine_code; I64 res; if (machine_code=LexExpression2Bin(cc)) { res=Call(machine_code); Free(machine_code); } else res=0; return res; }