URL
https://opencores.org/ocsvn/thor/thor/trunk
Subversion Repositories thor
[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [ParseExpressions.cpp] - Rev 55
Go to most recent revision | Compare with Previous | Blame | View Log
// ============================================================================ // __ // \\__/ o\ (C) 2012-2018 Robert Finch, Waterloo // \ __ / All rights reserved. // \/_// robfinch<remove>@finitron.ca // || // // CC64 - 'C' derived language compiler // - 64 bit CPU // // This source file is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This source file is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // // ============================================================================ // #include "stdafx.h" #define EXPR_DEBUG #define NUM_DIMEN 20 extern SYM *currentClass; static unsigned char sizeof_flag = 0; static TYP *ParseCastExpression(ENODE **node); static TYP *NonAssignExpression(ENODE **node); TYP *forcefit(ENODE **node1,TYP *tp1,ENODE **node2,TYP *tp2,bool); extern void backup(); extern char *inpline; extern int parsingParameterList; extern SYM *gsearch2(std::string , __int16, TypeArray *,bool); extern SYM *search2(std::string na,TABLE *tbl,TypeArray *typearray); extern int round8(int n); ENODE *pep1; TYP *ptp1; // the type just previous to the last dot int pop; // the just previous operator. // Tells subsequent levels that ParseCastExpression already fetched a token. //static unsigned char expr_flag = 0; TYP stdvoid; TYP stdint; TYP stduint; TYP stdlong; TYP stdulong; TYP stdshort; TYP stdushort; TYP stdchar; TYP stduchar; TYP stdbyte; TYP stdubyte; TYP stdstring; TYP stddbl; TYP stdtriple; TYP stdflt; TYP stddouble; TYP stdquad; TYP stdfunc; TYP stdexception; extern TYP *head; /* shared with ParseSpecifier */ extern TYP *tail; /* * expression evaluation * * this set of routines builds a parse tree for an expression. * no code is generated for the expressions during the build, * this is the job of the codegen module. for most purposes * expression() is the routine to call. it will allow all of * the C operators. for the case where the comma operator is * not valid (function parameters for instance) call NonCommaExpression(). * * each of the routines returns a pointer to a describing type * structure. each routine also takes one parameter which is a * pointer to an expression node by reference (address of pointer). * the completed expression is returned in this pointer. all * routines return either a pointer to a valid type or NULL if * the hierarchy of the next operator is too low or the next * symbol is not part of an expression. */ TYP *expression(); /* forward ParseSpecifieraration */ TYP *NonCommaExpression(); /* forward ParseSpecifieraration */ TYP *ParseUnaryExpression(); /* forward ParseSpecifieraration */ int nest_level = 0; bool isMember; void Enter(char *p) { /* int nn; for (nn = 0; nn < nest_level && nn < 60; nn++) printf(" "); printf("%s: %d\r\n", p, lineno); nest_level++; */ } void Leave(char *p, int n) { /* int nn; nest_level--; for (nn = 0; nn < nest_level; nn++) printf(" "); printf("%s (%d)\r\n", p, n); */ } int GetPtrSize() { return sizeOfPtr; } /* * build an expression node with a node type of nt and values * v1 and v2. */ ENODE *makenode(int nt, ENODE *v1, ENODE *v2) { ENODE *ep; ep = (ENODE *)xalloc(sizeof(ENODE)); ep->nodetype = (enum e_node)nt; if (v1!=nullptr && v2 != nullptr) { ep->constflag = v1->constflag && v2->constflag; ep->isUnsigned = v1->isUnsigned && v2->isUnsigned; } else if (v1 != nullptr) { ep->constflag = v1->constflag; ep->isUnsigned = v1->isUnsigned; } else if (v2 != nullptr) { ep->constflag = v2->constflag; ep->isUnsigned = v2->isUnsigned; } ep->etype = bt_void; ep->esize = -1; ep->p[0] = v1; ep->p[1] = v2; ep->p[2] = 0; return (ep); } ENODE *makefcnode(int nt, ENODE *v1, ENODE *v2, SYM *sp) { ENODE *ep; ep = (ENODE *)xalloc(sizeof(ENODE)); ep->nodetype = (enum e_node)nt; ep->sym = sp; ep->constflag = FALSE; ep->isUnsigned = FALSE; ep->etype = bt_void; ep->esize = -1; ep->p[0] = v1; ep->p[1] = v2; ep->p[2] = 0; return ep; } ENODE *makesnode(int nt, std::string *v1, std::string *v2, int64_t i) { ENODE *ep; ep = allocEnode(); ep->nodetype = (enum e_node)nt; ep->constflag = FALSE; ep->isUnsigned = FALSE; ep->etype = bt_void; ep->esize = -1; ep->sp = v1; ep->msp = v2; ep->i = i; ep->p[0] = 0; ep->p[1] = 0; ep->p[2] = 0; return ep; } ENODE *makenodei(int nt, ENODE *v1, int i) { ENODE *ep; ep = allocEnode(); ep->nodetype = (enum e_node)nt; ep->constflag = FALSE; ep->isUnsigned = FALSE; ep->etype = bt_void; ep->esize = -1; ep->i = i; ep->p[0] = v1; ep->p[1] = (ENODE *)NULL; ep->p[2] = 0; return ep; } ENODE *makeinode(int nt, int64_t v1) { ENODE *ep; ep = allocEnode(); ep->nodetype = (enum e_node)nt; ep->constflag = TRUE; ep->isUnsigned = FALSE; ep->etype = bt_void; ep->esize = -1; ep->i = v1; ep->p[1] = 0; ep->p[0] = 0; ep->p[2] = 0; return ep; } ENODE *makefnode(int nt, double v1) { ENODE *ep; ep = allocEnode(); ep->nodetype = (enum e_node)nt; ep->constflag = TRUE; ep->isUnsigned = FALSE; ep->etype = bt_void; ep->esize = -1; ep->f = v1; ep->f1 = v1; // ep->f2 = v2; ep->p[0] = 0; ep->p[1] = 0; ep->p[2] = 0; return ep; } ENODE *makefqnode(int nt, Float128 *f128) { ENODE *ep; ep = allocEnode(); ep->nodetype = (enum e_node)nt; ep->constflag = TRUE; ep->isUnsigned = FALSE; ep->etype = bt_void; ep->esize = -1; Float128::Assign(&ep->f128,f128); // ep->f2 = v2; ep->p[0] = 0; ep->p[1] = 0; ep->p[2] = 0; return ep; } void AddToList(ENODE *list, ENODE *ele) { ENODE *p, *pp; p = list; pp = nullptr; while (p) { pp = p; p = p->p[2]; } if (pp) { pp->p[2] = ele; } else list->p[2] = ele; } bool IsMemberOperator(int op) { return op==dot || op==pointsto || op==double_colon; } bool IsClassExpr() { TYP *tp; if (pep1) {// && IsMemberOperator(pop)) { if (pep1->tp) { if (pep1->tp->type==bt_class){ return true; } else if (pep1->tp->type==bt_pointer) { tp = pep1->tp->GetBtp(); if (tp==nullptr) throw new C64PException(ERR_NULLPOINTER,4); if (tp->type==bt_class) { return true; } } } } return false; } void PromoteConstFlag(ENODE *ep) { if (ep->p[0]==nullptr || ep->p[1]==nullptr) { ep->constflag = false; return; } ep->constflag = ep->p[0]->constflag && ep->p[1]->constflag; } /* * build the proper dereference operation for a node using the * type pointer tp. */ TYP *deref(ENODE **node, TYP *tp) { dfs.printf("<Deref>"); if (tp==nullptr || node==nullptr || *node==nullptr) throw new C64PException(ERR_NULLPOINTER,8); switch( tp->type ) { case bt_byte: if (tp->isUnsigned) { *node = makenode(en_ub_ref,*node,(ENODE *)NULL); (*node)->isUnsigned = TRUE; } else { *node = makenode(en_b_ref,*node,(ENODE *)NULL); } (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; if (tp->isUnsigned) tp = &stdubyte;//&stduint; else tp = &stdbyte;//&stdint; break; case bt_ubyte: *node = makenode(en_ub_ref,*node,(ENODE *)NULL); (*node)->isUnsigned = TRUE; (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; tp = &stdubyte;//&stduint; break; case bt_uchar: case bt_char: case bt_enum: if (tp->isUnsigned) { *node = makenode(en_uc_ref,*node,(ENODE *)NULL); (*node)->isUnsigned = TRUE; } else *node = makenode(en_c_ref,*node,(ENODE *)NULL); (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; if (tp->isUnsigned) tp = &stduchar; else tp = &stdchar; break; case bt_ushort: case bt_short: if (tp->isUnsigned) { *node = makenode(en_uh_ref,*node,(ENODE *)NULL); (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; (*node)->isUnsigned = TRUE; tp = &stduint; } else { *node = makenode(en_h_ref,*node,(ENODE *)NULL); (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; tp = &stdint; } break; case bt_exception: (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; (*node)->isUnsigned = TRUE; *node = makenode(en_uw_ref,*node,(ENODE *)NULL); break; case bt_ulong: case bt_long: (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; if (tp->isUnsigned) { (*node)->isUnsigned = TRUE; *node = makenode(en_uw_ref,*node,(ENODE *)NULL); } else { *node = makenode(en_w_ref,*node,(ENODE *)NULL); } break; case bt_vector: (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; *node = makenode(en_vector_ref,*node,(ENODE *)NULL); (*node)->isUnsigned = TRUE; break; case bt_vector_mask: (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; *node = makenode(en_uw_ref,*node,(ENODE *)NULL); (*node)->isUnsigned = TRUE; (*node)->vmask = (*node)->p[0]->vmask; break; // Pointers (addresses) are always unsigned case bt_pointer: (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; *node = makenode(sizeOfPtr==4 ? en_hp_ref : en_wp_ref,*node,(ENODE *)NULL); (*node)->isUnsigned = TRUE; break; case bt_unsigned: (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; *node = makenode(en_uw_ref,*node,(ENODE *)NULL); (*node)->isUnsigned = TRUE; break; case bt_triple: *node = makenode(en_triple_ref,*node,(ENODE *)NULL); (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; tp = &stdtriple; break; case bt_quad: *node = makenode(en_quad_ref,*node,(ENODE *)NULL); (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; tp = &stdquad; break; case bt_double: *node = makenode(en_dbl_ref,*node,(ENODE *)NULL); (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; tp = &stddbl; break; case bt_float: *node = makenode(en_flt_ref,*node,(ENODE *)NULL); (*node)->esize = tp->size; (*node)->etype = (enum e_bt)tp->type; tp = &stdflt; break; case bt_bitfield: if (tp->isUnsigned){ switch (tp->size) { case 1: *node = makenode(en_ubfieldref, *node, (ENODE *)NULL); break; case 2: *node = makenode(en_ucfieldref, *node, (ENODE *)NULL); break; case 4: *node = makenode(en_uhfieldref, *node, (ENODE *)NULL); break; case 8: *node = makenode(en_uwfieldref, *node, (ENODE *)NULL); break; } (*node)->isUnsigned = TRUE; } else { switch (tp->size) { case 1: *node = makenode(en_bfieldref, *node, (ENODE *)NULL); break; case 2: *node = makenode(en_cfieldref, *node, (ENODE *)NULL); break; case 4: *node = makenode(en_hfieldref, *node, (ENODE *)NULL); break; case 8: *node = makenode(en_wfieldref, *node, (ENODE *)NULL); break; } } (*node)->bit_width = tp->bit_width; (*node)->bit_offset = tp->bit_offset; /* * maybe it should be 'unsigned' */ (*node)->etype = tp->type;//(enum e_bt)stdint.type; (*node)->esize = tp->size; tp = &stdint; break; case bt_ubitfield: switch (tp->size) { case 1: *node = makenode(en_ubfieldref, *node, (ENODE *)NULL); break; case 2: *node = makenode(en_ucfieldref, *node, (ENODE *)NULL); break; case 4: *node = makenode(en_uhfieldref, *node, (ENODE *)NULL); break; case 8: *node = makenode(en_uwfieldref, *node, (ENODE *)NULL); break; } (*node)->bit_width = tp->bit_width; (*node)->bit_offset = tp->bit_offset; /* * maybe it should be 'unsigned' */ (*node)->etype = tp->type;//(enum e_bt)stdint.type; (*node)->esize = tp->size; tp = &stdint; break; //case bt_func: //case bt_ifunc: // (*node)->esize = tp->size; // (*node)->etype = tp->type; // (*node)->isUnsigned = TRUE; // *node = makenode(en_uw_ref,*node,NULL); // break; //case bt_class: //case bt_struct: //case bt_union: // dfs.printf("F"); // (*node)->esize = tp->size; // (*node)->etype = (e_bt)tp->type; // *node = makenode(en_struct_ref,*node,NULL); // (*node)->isUnsigned = TRUE; // break; default: dfs.printf("Deref :%d\n", tp->type); if ((*node)->msp) dfs.printf("%s\n",(char *)(*node)->msp->c_str()); error(ERR_DEREF); break; } (*node)->isVolatile = tp->isVolatile; (*node)->constflag = tp->isConst; dfs.printf("</Deref>"); return tp; } /* * dereference the node if val_flag is zero. If val_flag is non_zero and * tp->type is bt_pointer (array reference) set the size field to the * pointer size if this code is not executed on behalf of a sizeof * operator */ TYP *CondDeref(ENODE **node, TYP *tp) { TYP *tp1; int64_t sz; int dimen; int numele; if (tp->isArray == false) if (tp->type != bt_struct && tp->type != bt_union && tp->type != bt_class && tp->type != bt_ifunc && tp->type != bt_func) return deref(node, tp); if (tp->type == bt_pointer && sizeof_flag == 0) { sz = tp->size; dimen = tp->dimen; numele = tp->numele; tp1 = tp->GetBtp(); if (tp1==NULL) printf("DIAG: CondDeref: tp1 is NULL\r\n"); tp =(TYP *) TYP::Make(bt_pointer, sizeOfPtr); tp->isArray = true; tp->dimen = dimen; tp->numele = numele; tp->btp = tp1->GetIndex(); tp->isUnsigned = TRUE; } else if (tp->type==bt_pointer) return tp; // else if (tp->type==bt_struct || tp->type==bt_union) // return deref(node, tp); return tp; } /* TYP *CondDeref(ENODE **node, TYP *tp) { if (tp->val_flag == 0) return deref(node, tp); if (tp->type == bt_pointer && sizeof_flag == 0) tp->size = 2; return tp; } */ /* * nameref will build an expression tree that references an * identifier. if the identifier is not in the global or * local symbol table then a look-ahead to the next character * is done and if it indicates a function call the identifier * is coerced to an external function name. non-value references * generate an additional level of indirection. */ TYP *nameref2(std::string name, ENODE **node,int nt,bool alloc,TypeArray *typearray, TABLE *tbl) { SYM *sp = nullptr; Function *fn; TYP *tp; std::string stnm; dfs.puts("<nameref2>\n"); if (tbl) { dfs.printf("searching table for:%d:%s|",TABLE::matchno,(char *)name.c_str()); tbl->Find(name,bt_long,typearray,true); // gsearch2(name,bt_long,typearray,true); sp = Function::FindExactMatch(TABLE::matchno, name, bt_long, typearray)->sym; // if (sp==nullptr) { // printf("notfound\r\n"); // sp = gsearch2(name,bt_long,typearray,false); // } } else { dfs.printf("A:%d:%s",TABLE::matchno,(char *)name.c_str()); fn = Function::FindExactMatch(TABLE::matchno, name, bt_long, typearray); // If we didn't have an exact match and no (parameter) types are known // return the match if there is only a single one. if (fn==nullptr) { if (TABLE::matchno==1 && typearray==nullptr) sp = TABLE::match[0]; } else sp = fn->sym; // memset(typearray,0,sizeof(typearray)); // sp = gsearch2(name,typearray); } if (sp==nullptr && !alloc) { dfs.printf("returning nullptr"); *node = makeinode(en_labcon,9999); tp = nullptr; goto xit; } if( sp == NULL ) { while( my_isspace(lastch) ) getch(); if( lastch == '(') { sp = allocSYM(); sp->fi = allocFunction(sp->id); sp->fi->sym = sp; sp->tp = &stdfunc; sp->SetName(*(new std::string(lastid))); sp->storage_class = sc_external; sp->IsUndefined = TRUE; dfs.printf("Insert at nameref\r\n"); typearray->Print(); // gsyms[0].insert(sp); tp = &stdfunc; *node = makesnode(en_cnacon,sp->name, sp->BuildSignature(1),sp->value.i); (*node)->constflag = TRUE; (*node)->sym = sp; if (sp->tp->isUnsigned) (*node)->isUnsigned = TRUE; (*node)->esize = 8; (*node)->isPascal = sp->fi->IsPascal; } else { dfs.printf("Undefined symbol2 in nameref\r\n"); tp = (TYP *)NULL; *node = makeinode(en_labcon,9999); error(ERR_UNDEFINED); } } else { dfs.printf("sp is not null\n"); typearray->Print(); if( (tp = sp->tp) == NULL ) { error(ERR_UNDEFINED); goto xit; // guard against untyped entries } switch( sp->storage_class ) { case sc_static: if (sp->tp->type==bt_func || sp->tp->type==bt_ifunc) { //strcpy(stnm,GetNamespace()); //strcat(stnm,"_"); stnm = ""; stnm += *sp->name; *node = makesnode(en_cnacon,&stnm, sp->fi->BuildSignature(),sp->value.i); (*node)->isPascal = sp->fi->IsPascal; (*node)->constflag = TRUE; (*node)->esize = 8; //*node = makesnode(en_nacon,sp->name); //(*node)->constflag = TRUE; } else { *node = makeinode(en_labcon,sp->value.i); (*node)->constflag = TRUE; (*node)->esize = sp->tp->size;//8; (*node)->segment = dataseg; } if (sp->tp->isUnsigned) { (*node)->isUnsigned = TRUE; (*node)->esize = sp->tp->size; } (*node)->etype = bt_pointer;//sp->tp->type; break; case sc_thread: *node = makeinode(en_labcon,sp->value.i); (*node)->segment = tlsseg; (*node)->constflag = TRUE; (*node)->esize = sp->tp->size; (*node)->etype = bt_pointer;//sp->tp->type; if (sp->tp->isUnsigned) (*node)->isUnsigned = TRUE; break; case sc_global: case sc_external: if (sp->tp->type == bt_func || sp->tp->type == bt_ifunc) { *node = makesnode(en_cnacon, sp->name, sp->mangledName, sp->value.i); (*node)->isPascal = sp->fi->IsPascal; } else *node = makesnode(en_nacon,sp->name,sp->mangledName,sp->value.i); (*node)->constflag = TRUE; (*node)->esize = sp->tp->size; (*node)->etype = bt_pointer;//sp->tp->type; (*node)->isUnsigned = TRUE;// sp->tp->isUnsigned; break; case sc_const: if (sp->tp->type==bt_quad) *node = makefqnode(en_fqcon,&sp->f128); else if (sp->tp->type==bt_float || sp->tp->type==bt_double || sp->tp->type==bt_triple) *node = makefnode(en_fcon,sp->value.f); else { *node = makeinode(en_icon,sp->value.i); if (sp->tp->isUnsigned) (*node)->isUnsigned = TRUE; } (*node)->constflag = TRUE; (*node)->esize = sp->tp->size; break; default: /* auto and any errors */ if (sp->storage_class == sc_member) { // will get this for a class member // If it's a member we need to pass r25 the class pointer on // the stack. isMember = true; if ((sp->tp->type==bt_func || sp->tp->type==bt_ifunc) ||(sp->tp->type==bt_pointer && (sp->tp->GetBtp()->type == bt_func ||sp->tp->GetBtp()->type == bt_ifunc))) { *node = makesnode(en_cnacon,sp->name, sp->fi->BuildSignature(),25); (*node)->isPascal = sp->fi->IsPascal; } else { *node = makeinode(en_classcon,sp->value.i); } if (sp->tp->isUnsigned || sp->tp->type==bt_pointer) (*node)->isUnsigned = TRUE; } else { if( sp->storage_class != sc_auto) { error(ERR_ILLCLASS); } //sc_member if (sp->tp->IsVectorType()) *node = makeinode(en_autovcon,sp->value.i); else if (sp->tp->type==bt_vector_mask) *node = makeinode(en_autovmcon,sp->value.i); else if (sp->tp->IsFloatType()) *node = makeinode(en_autofcon,sp->value.i); else { *node = makeinode(en_autocon,sp->value.i); if (sp->tp->isUnsigned) (*node)->isUnsigned = TRUE; } if (sp->IsRegister) { if (sp->tp->IsFloatType()) (*node)->nodetype = en_fpregvar; else (*node)->nodetype = en_regvar; (*node)->i = sp->reg; (*node)->tp = sp->tp; //(*node)->tp->val_flag = TRUE; } } (*node)->esize = sp->tp->size; switch((*node)->nodetype) { case en_regvar: (*node)->etype = bt_long; break;//sp->tp->type; case en_fpregvar: (*node)->etype = sp->tp->type; break;//sp->tp->type; default: (*node)->etype = bt_pointer;break;//sp->tp->type; } //(*node)->etype = ((*node)->nodetype == en_regvar) ? bt_long : bt_pointer;//sp->tp->type; break; } (*node)->SetType(sp->tp); (*node)->sym = sp; dfs.printf("tp:%p ",(char *)tp); // Not sure about this if - wasn't here in the past. // if (sp->tp->type!=bt_func && sp->tp->type!=bt_ifunc) tp = CondDeref(node,tp); dfs.printf("deref tp:%p ",(char *)tp); } if (nt) NextToken(); xit: if (!tp) dfs.printf("returning nullptr2"); dfs.puts("</nameref2>\n"); return tp; } TYP *nameref(ENODE **node,int nt) { TYP *tp; bool found; dfs.puts("<Nameref>\n"); dfs.printf("GSearchfor:%s|",lastid); found = false; /* if (ptp1) { if (ptp1->type == bt_pointer) { found = ptp1->GetBtp()->lst.FindRising(lastid) > 0; } else { found = ptp1->lst.FindRising(lastid) > 0; } } if (!found) */ gsearch2(lastid,(__int16)bt_long,nullptr,false); tp = nameref2(lastid, node, nt, true, nullptr, nullptr); dfs.puts("</Nameref>\n"); return tp; } /* // Look for a function gsearch2(lastid,(__int16)bt_long,nullptr,false); while( my_isspace(lastch) ) getch(); if(lastch == '(') { NextToken(); tptr = nameref(&pnode,TRUE); tptr = ExprFunction(nullptr, &pnode); } */ // // ArgumentList will build a list of parameter expressions in // a function call and return a pointer to the last expression // parsed. since parameters are generally pushed from right // to left we get just what we asked for... // ENODE *ArgumentList(ENODE *hidden, TypeArray *typearray) { ENODE *ep1, *ep2; TYP *typ; int nn; dfs.printf("<ArgumentList>"); nn = 0; ep1 = 0; if (hidden) { ep1 = makenode(en_void,hidden,ep1); } typearray->Clear(); while( lastst != closepa) { typ = NonCommaExpression(&ep2); // evaluate a parameter if (typ) dfs.printf("%03d ", typ->typeno); else dfs.printf("%03d ", 0); if (ep2==nullptr) ep2 = makeinode(en_icon, 0); if (typ==nullptr) { error(ERR_BADARG); typearray->Add((int)bt_long,0); } else { // If a function pointer is passed, we want a pointer type if (typ->typeno==bt_func || typ->typeno == bt_ifunc) typearray->Add((int)bt_pointer,0); else typearray->Add(typ,0); } ep1 = makenode(en_void,ep2,ep1); if(lastst != comma) { dfs.printf("lastst=%d", lastst); break; } NextToken(); } NextToken(); dfs.printf("</ArgumentList>\n"); return ep1; } /* * return 1 if st in set of [ kw_char, kw_short, kw_long, kw_int, * kw_float, kw_double, kw_struct, kw_union ] */ static int IsIntrinsicType(int st) { return st == kw_byte || st==kw_char || st == kw_short || st == kw_int || st==kw_void || st == kw_int16 || st == kw_int8 || st == kw_int32 || st == kw_int16 || st == kw_long || st == kw_float || st == kw_double || st == kw_triple || st == kw_enum || st == kw_struct || st == kw_union || st== kw_unsigned || st==kw_signed || st==kw_exception || st == kw_const; } int IsBeginningOfTypecast(int st) { SYM *sp; if (st==id) { sp = tagtable.Find(lastid,false); if (sp == nullptr) sp = gsyms[0].Find(lastid,false); if (sp) return sp->storage_class==sc_typedef; return FALSE; } else return IsIntrinsicType(st) || st==kw_volatile; } SYM *makeint2(std::string name) { SYM *sp; TYP *tp; sp = allocSYM(); tp = TYP::Make(bt_long,2); tp->sname = new std::string(""); sp->SetName(name); sp->storage_class = sc_auto; sp->SetType(tp); return sp; } SYM *makeStructPtr(std::string name) { SYM *sp; TYP *tp,*tp2; sp = allocSYM(); tp = TYP::Make(bt_pointer,sizeOfPtr); tp2 = TYP::Make(bt_struct,sizeOfPtr); tp->btp = tp2->GetIndex(); tp->sname = new std::string(""); tp->isUnsigned = TRUE; sp->SetName(name); sp->storage_class = sc_auto; sp->SetType(tp); return sp; } // This function is dead code. // Create a list of dummy parameters based on argument types. // This is needed in order to add a function to the tables if // the function hasn't been encountered before. SYM *CreateDummyParameters(ENODE *ep, SYM *parent, TYP *tp) { int poffset; SYM *sp1; SYM *list; int nn; ENODE *p; static char buf[20]; list = nullptr; poffset = Compiler::GetReturnBlockSize(); // Process hidden parameter if (tp) { if (tp->GetBtp()) { if (tp->GetBtp()->type==bt_struct || tp->GetBtp()->type==bt_union || tp->GetBtp()->type==bt_class ) { sp1 = makeint2(std::string(my_strdup("_pHiddenStructPtr"))); sp1->parent = parent->GetIndex(); sp1->value.i = poffset; poffset += sizeOfWord; sp1->storage_class = sc_auto; sp1->next = 0; list = sp1; } } } nn = 0; for(p = ep; p; p = p->p[1]) { sprintf_s(buf,sizeof(buf),"_p%d", nn); sp1 = makeint2(std::string(my_strdup(buf))); if (p->p[0]==nullptr) sp1->tp =(TYP *) TYP::Make(bt_long,2); else sp1->SetType(p->p[0]->tp); sp1->parent = parent->GetIndex(); sp1->value.i = poffset; // Check for aggregate types passed as parameters. Structs // and unions use the type size. There could also be arrays // passed. poffset += round8(sp1->tp->size); // if (round8(sp1->tp->size) > 8) sp1->storage_class = sc_auto; sp1->next = 0; // record parameter list if (list == nullptr) { list = sp1; } else { sp1->SetNext(list->GetIndex()); list = sp1; } nn++; } return list; } // ---------------------------------------------------------------------------- // primary will parse a primary expression and set the node pointer // returning the type of the expression parsed. primary expressions // are any of: // id // constant // string // ( expression ) // this // ---------------------------------------------------------------------------- TYP *ParsePrimaryExpression(ENODE **node, int got_pa) { ENODE *pnode, *qnode1, *qnode2; TYP *tptr; TypeArray typearray; qnode1 = (ENODE *)NULL; qnode2 = (ENODE *)NULL; pnode = (ENODE *)NULL; *node = (ENODE *)NULL; Enter("ParsePrimary "); if (got_pa) { tptr = expression(&pnode); needpunc(closepa,7); *node = pnode; if (pnode==NULL) dfs.printf("pnode is NULL\r\n"); else (*node)->SetType(tptr); if (tptr) Leave("ParsePrimary", tptr->type); else Leave("ParsePrimary", 0); return tptr; } switch( lastst ) { case ellipsis: case id: tptr = nameref(&pnode,TRUE); /* // Try and find the symbol, if not found, assume a function // but only if it's followed by a ( if (TABLE::matchno==0) { while( my_isspace(lastch) ) getch(); if( lastch == '(') { NextToken(); tptr = ExprFunction(nullptr, &pnode); } else { tptr = nameref(&pnode,TRUE); } } else */ /* if (tptr==NULL) { tptr = allocTYP(); tptr->type = bt_long; tptr->typeno = bt_long; tptr->alignment = 8; tptr->bit_offset = 0; tptr->GetBtp() = nullptr; tptr->isArray = false; tptr->isConst = false; tptr->isIO = false; tptr->isShort = false; tptr->isUnsigned = false; tptr->size = 8; tptr->sname = my_strdup(lastid); } */ break; case cconst: tptr = &stdchar; tptr->isConst = TRUE; pnode = makeinode(en_icon,ival); pnode->constflag = TRUE; pnode->esize = 1; pnode->SetType(tptr); NextToken(); break; case iconst: tptr = &stdint; tptr->isConst = TRUE; pnode = makeinode(en_icon,ival); pnode->constflag = TRUE; if (ival >= -128 && ival < 128) pnode->esize = 1; else if (ival >= -32768 && ival < 32768) pnode->esize = 2; else if (ival >= -2147483648LL && ival < 2147483648LL) pnode->esize = 4; else pnode->esize = 2; pnode->SetType(tptr); NextToken(); break; case kw_floatmax: tptr = &stdquad; tptr->isConst = TRUE; pnode = makefnode(en_fcon,rval); pnode->constflag = TRUE; pnode->SetType(tptr); pnode->i = quadlit(Float128::FloatMax()); NextToken(); break; case rconst: pnode = makefnode(en_fcon,rval); pnode->constflag = TRUE; pnode->i = quadlit(&rval128); pnode->f128 = rval128; switch(float_precision) { case 'Q': case 'q': tptr = &stdquad; //getch(); break; case 'D': case 'd': tptr = &stddouble; //getch(); break; case 'T': case 't': tptr = &stdtriple; //getch(); break; case 'S': case 's': tptr = &stdflt; //getch(); break; default: tptr = &stddouble; break; } pnode->SetType(tptr); tptr->isConst = TRUE; NextToken(); break; case sconst: if (sizeof_flag) { tptr = (TYP *)TYP::Make(bt_pointer, 0); tptr->size = strlen(laststr) + 1; tptr->btp = stdchar.GetIndex(); tptr->GetBtp()->isConst = TRUE; tptr->val_flag = 1; tptr->isConst = TRUE; tptr->isUnsigned = TRUE; } else { tptr = &stdstring; } pnode = makenodei(en_labcon,(ENODE *)NULL,0); if (sizeof_flag == 0) pnode->i = stringlit(laststr); pnode->etype = bt_pointer; pnode->esize = 2; pnode->constflag = TRUE; pnode->segment = rodataseg; pnode->SetType(tptr); tptr->isConst = TRUE; NextToken(); break; case openpa: NextToken(); // if( !IsBeginningOfTypecast(lastst) ) { // expr_flag = 0; tptr = expression(&pnode); pnode->SetType(tptr); needpunc(closepa,8); // } //else { /* cast operator */ // ParseSpecifier(0); /* do cast ParseSpecifieraration */ // ParseDeclarationPrefix(FALSE); // tptr = head; // needpunc(closepa); // if( ParseUnaryExpression(&pnode) == NULL ) { // error(ERR_IDEXPECT); // tptr = NULL; // } //} break; case kw_this: dfs.puts("<ExprThis>"); TYP *tptr2; tptr2 = TYP::Make(bt_class,0); if (currentClass==nullptr) { error(ERR_THIS); } else { memcpy(tptr2,currentClass->tp,sizeof(TYP)); } NextToken(); tptr = TYP::Make(bt_pointer,sizeOfPtr); tptr->btp = tptr2->GetIndex(); tptr->isUnsigned = TRUE; dfs.puts((char *)tptr->GetBtp()->sname->c_str()); pnode = makeinode(en_regvar,regCLP); dfs.puts("</ExprThis>"); break; case begin: { int sz = 0; ENODE *list; NextToken(); head = tail = nullptr; list = makenode(en_list,nullptr,nullptr); while (lastst != end) { tptr = NonCommaExpression(&pnode); pnode->SetType(tptr); sz = sz + tptr->size; AddToList(list, pnode); if (lastst!=comma) break; NextToken(); } needpunc(end,9); pnode = makenode(en_aggregate,list,nullptr); pnode->SetType(tptr = TYP::Make(bt_struct,sz)); } break; default: Leave("ParsePrimary", 0); return (TYP *)NULL; } *node = pnode; if (*node) (*node)->SetType(tptr); if (tptr) Leave("ParsePrimary", tptr->type); else Leave("ParsePrimary", 0); return tptr; } /* * this function returns true if the node passed is an IsLValue. * this can be qualified by the fact that an IsLValue must have * one of the dereference operators as it's top node. */ int IsLValue(ENODE *node) { if (node==nullptr) return FALSE; switch( node->nodetype ) { case en_b_ref: case en_c_ref: case en_h_ref: case en_w_ref: case en_ub_ref: case en_uc_ref: case en_uh_ref: case en_uw_ref: case en_hp_ref: case en_wp_ref: case en_wfieldref: case en_uwfieldref: case en_bfieldref: case en_ubfieldref: case en_cfieldref: case en_ucfieldref: case en_hfieldref: case en_uhfieldref: case en_triple_ref: case en_dbl_ref: case en_quad_ref: case en_flt_ref: case en_ref32: case en_ref32u: case en_vector_ref: return TRUE; case en_cbc: case en_cbh: case en_cbw: case en_cch: case en_ccw: case en_chw: case en_cfd: case en_cubw: case en_cucw: case en_cuhw: case en_cbu: case en_ccu: case en_chu: case en_cubu: case en_cucu: case en_cuhu: case en_ccwp: case en_cucwp: return IsLValue(node->p[0]); // For an array reference there will be an add node at the top of the // expression tree. This evaluates to an address which is essentially // the same as an *_ref node. It's an LValue. case en_add: if (node->tp) return node->tp->type==bt_pointer && node->tp->isArray; else return FALSE; // A typecast will connect the types with a void node case en_void: return (node->etype == bt_pointer); } return FALSE; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- TYP *Autoincdec(TYP *tp, ENODE **node, int flag) { ENODE *ep1, *ep2; TYP *typ; int su; ep1 = *node; if( IsLValue(ep1) ) { if (tp->type == bt_pointer) { typ = tp->GetBtp(); ep2 = makeinode(en_icon,typ->size); ep2->esize = typ->size; } else { ep2 = makeinode(en_icon,1); ep2->esize = 1; } ep2->constflag = TRUE; ep2->isUnsigned = tp->isUnsigned; su = ep1->isUnsigned; ep1 = makenode(flag ? en_assub : en_asadd,ep1,ep2); ep1->isUnsigned = tp->isUnsigned; ep1->esize = tp->size; } else error(ERR_LVALUE); *node = ep1; if (*node) (*node)->SetType(tp); return tp; } void ApplyVMask(ENODE *node, ENODE *mask) { if (node==nullptr || mask==nullptr) return; if (node->p[0]) ApplyVMask(node->p[0],mask); if (node->p[1]) ApplyVMask(node->p[1],mask); if (node->p[2]) ApplyVMask(node->p[2],mask); if (node->vmask==nullptr) node->vmask = mask; return; } // ---------------------------------------------------------------------------- // A Postfix Expression is: // primary // postfix_expression[expression] // postfix_expression() // postfix_expression(argument expression list) // postfix_expression.ID // postfix_expression->ID // postfix_expression++ // postfix_expression-- // ---------------------------------------------------------------------------- TYP *ParsePostfixExpression(ENODE **node, int got_pa) { TYP *tp1, *tp2, *tp3, *tp4; ENODE *ep1, *ep2, *ep3, *ep4; ENODE *rnode, *qnode, *pnode; SYM *sp; int iu; int ii; bool classdet = false; TypeArray typearray; std::string name; int cf, uf, numdimen; int sz1, cnt, cnt2, totsz; int sa[20]; bool firstBr = true; ep1 = (ENODE *)NULL; Enter("<ParsePostfix>"); *node = (ENODE *)NULL; tp1 = ParsePrimaryExpression(&ep1, got_pa); if (ep1==NULL) { // ep1 = makeinode(en_icon, 0); // goto j1; // printf("DIAG: ParsePostFix: ep1 is NULL\r\n"); } if (tp1 == NULL) { Leave("</ParsePostfix>",0); return ((TYP *)NULL); } pep1 = nullptr; cnt = 0; while (1) { pop = lastst; switch(lastst) { case openbr: pnode = ep1; if (tp1==NULL) { error(ERR_UNDEFINED); goto j1; } NextToken(); if( tp1->type == bt_pointer ) { tp2 = expression(&rnode); tp3 = tp1; tp4 = tp1; if (rnode==nullptr) { error(ERR_EXPREXPECT); throw new C64PException(ERR_EXPREXPECT,9); } } else { tp2 = tp1; rnode = pnode; tp3 = expression(&pnode); if (tp3==NULL) { error(ERR_UNDEFINED); throw new C64PException(ERR_UNDEFINED,10); goto j1; } tp1 = tp3; tp4 = tp1; } if (cnt==0) { numdimen = tp1->dimen; cnt2 = 1; for (; tp4; tp4 = tp4->GetBtp()) { sa[cnt2] = max(tp4->numele,1); cnt2++; if (cnt2 > 19) { error(ERR_TOOMANYDIMEN); break; } } if (tp1->type==bt_pointer) sa[numdimen+1] = tp1->GetBtp()->size; else sa[numdimen+1] = tp1->size; } if (cnt==0) totsz = tp1->size; firstBr = false; if (tp1->type != bt_pointer) error(ERR_NOPOINTER); else tp1 = tp1->GetBtp(); //if (cnt==0) { // switch(numdimen) { // case 1: sz1 = sa[numdimen+1]; break; // case 2: sz1 = sa[1]*sa[numdimen+1]; break; // case 3: sz1 = sa[1]*sa[2]*sa[numdimen+1]; break; // default: // sz1 = sa[numdimen+1]; // could be a void = 0 // for (cnt2 = 1; cnt2 < numdimen; cnt2++) // sz1 = sz1 * sa[cnt2]; // } //} //else if (cnt==1) { // switch(numdimen) { // case 2: sz1 = sa[numdimen+1]; break; // case 3: sz1 = sa[1]*sa[numdimen+1]; break; // default: // sz1 = sa[numdimen+1]; // could be a void = 0 // for (cnt2 = 1; cnt2 < numdimen-1; cnt2++) // sz1 = sz1 * sa[cnt2]; // } //} //else if (cnt==2) { // switch(numdimen) { // case 3: sz1 = sa[numdimen+1]; break; // default: // sz1 = sa[numdimen+1]; // could be a void = 0 // for (cnt2 = 1; cnt2 < numdimen-2; cnt2++) // sz1 = sz1 * sa[cnt2]; // } //} //else { sz1 = sa[numdimen+1]; // could be a void = 0 for (cnt2 = 1; cnt2 < numdimen-cnt; cnt2++) sz1 = sz1 * sa[cnt2]; } qnode = makeinode(en_icon,sz1); qnode->etype = bt_ushort; qnode->esize = 8; qnode->constflag = TRUE; qnode->isUnsigned = TRUE; cf = qnode->constflag; qnode = makenode(en_mulu, qnode, rnode); qnode->etype = bt_short; qnode->esize = 8; qnode->constflag = cf & rnode->constflag; qnode->isUnsigned = rnode->isUnsigned; //(void) cast_op(&qnode, &tp_int32, tp1); cf = pnode->constflag; uf = pnode->isUnsigned; pnode = makenode(en_add, qnode, pnode); pnode->etype = bt_pointer; pnode->esize = sizeOfPtr; pnode->constflag = cf & qnode->constflag; pnode->isUnsigned = uf & qnode->isUnsigned; tp1 = CondDeref(&pnode, tp1); pnode->tp = tp1; ep1 = pnode; needpunc(closebr,9); cnt++; break; case openpa: cnt = 0; if (tp1==NULL) { error(ERR_UNDEFINED); goto j1; } tp2 = ep1->tp; if (tp2==nullptr) { error(ERR_UNDEFINED); goto j1; } if (tp2->type==bt_vector_mask) { NextToken(); tp1 = expression(&ep2); needpunc(closepa,9); ApplyVMask(ep2,ep1); ep1 = ep2; break; } if (tp2->type == bt_pointer) { dfs.printf("Got function pointer.\n"); } dfs.printf("tp2->type=%d",tp2->type); name = lastid; NextToken(); tp3 = tp1->GetBtp(); ep4 = nullptr; if (tp3) { if (tp3->type==bt_struct || tp3->type==bt_union || tp3->type==bt_class) ep4 = makenode(en_regvar,NULL,NULL); } //ep2 = ArgumentList(ep1->p[2],&typearray); ep2 = ArgumentList(ep4,&typearray); typearray.Print(); dfs.printf("Got Type: %d",tp1->type); if (tp1->type==bt_pointer) { dfs.printf("Got function pointer.\n"); ep1 = makenode(en_fcall,ep1,ep2); currentFn->IsLeaf = FALSE; break; } dfs.printf("openpa calling gsearch2"); sp = nullptr; ii = tp1->lst.FindRising(name); if (ii) { sp = Function::FindExactMatch(TABLE::matchno, name, bt_long, &typearray)->sym; } if (!sp) sp = gsearch2(name,bt_long,&typearray,true); if (sp==nullptr) { sp = allocSYM(); sp->fi = allocFunction(sp->id); sp->fi->sym = sp; sp->storage_class = sc_external; sp->SetName(name); sp->tp = TYP::Make(bt_func,0); sp->tp->btp = TYP::Make(bt_long,sizeOfWord)->GetIndex(); sp->fi->AddProto(&typearray); sp->mangledName = sp->fi->BuildSignature(); gsyms[0].insert(sp); } else if (sp->IsUndefined) { sp->tp = TYP::Make(bt_func,0); sp->tp->btp = TYP::Make(bt_long,sizeOfWord)->GetIndex(); if (!sp->fi) { sp->fi = allocFunction(sp->id); sp->fi->sym = sp; } sp->fi->AddProto(&typearray); sp->mangledName = sp->fi->BuildSignature(); gsyms[0].insert(sp); sp->IsUndefined = false; } if (sp->tp->type==bt_pointer) { dfs.printf("Got function pointer"); ep1 = makefcnode(en_fcall,ep1,ep2,sp); currentFn->IsLeaf = FALSE; } else { dfs.printf("Got direct function %s ", (char *)sp->name->c_str()); ep3 = makesnode(en_cnacon,sp->name,sp->mangledName,sp->value.i); ep1 = makefcnode(en_fcall,ep3,ep2,sp); if (!sp->fi->IsInline) currentFn->IsLeaf = FALSE; } tp1 = sp->tp->GetBtp(); // tp1 = ExprFunction(tp1, &ep1); break; case pointsto: { //int reftype = sizeOfPtr==4 ? en_h_ref : en_w_ref; int reftype = sizeOfPtr==4 ? en_hp_ref : en_wp_ref; cnt = 0; if (tp1==NULL) { error(ERR_UNDEFINED); goto j1; } if( tp1->type != bt_pointer ) { error(ERR_NOPOINTER); } else { tp1 = tp1->GetBtp(); } if( tp1->val_flag == FALSE ) { ep1 = makenode(reftype,ep1,(ENODE *)NULL); } } // fall through to dot operation case dot: cnt = 0; if (tp1==NULL) { error(ERR_UNDEFINED); goto j1; } NextToken(); /* past -> or . */ if (tp1->IsVectorType()) { NonAssignExpression(&qnode); ep2 = makenode(en_shl,qnode,makeinode(en_icon,3)); // The dot operation will deference the result below so the // old dereference operation isn't needed. It is stripped // off by using ep->p[0] rather than ep. ep1 = makenode(en_add,ep1->p[0],ep2); tp1 = tp1->GetBtp(); tp1 = CondDeref(&ep1,tp1); break; } if(lastst != id) { error(ERR_IDEXPECT); break; } dfs.printf("dot search: %p\r\n", (char *)&tp1->lst); ptp1 = tp1; pep1 = ep1; name = lastid; ii = tp1->lst.FindRising(name); if (ii==0) { dfs.printf("Nomember1"); error(ERR_NOMEMBER); break; } sp = TABLE::match[ii-1]; sp = sp->FindRisingMatch(); if( sp == NULL ) { dfs.printf("Nomember2"); error(ERR_NOMEMBER); break; } if (sp->IsPrivate && sp->parent != currentFn->sym->parent) { error(ERR_PRIVATE); break; } tp1 = sp->tp; dfs.printf("tp1->type:%d",tp1->type); if (tp1==nullptr) throw new C64PException(ERR_NULLPOINTER,5); if (tp1->type==bt_ifunc || tp1->type==bt_func) { // build the name vector and create a nacon node. dfs.printf("%s is a func\n",(char *)sp->name->c_str()); NextToken(); if (lastst==openpa) { NextToken(); ep2 = ArgumentList(pep1,&typearray); typearray.Print(); sp = Function::FindExactMatch(ii,name,bt_long,&typearray)->sym; if (sp) { // sp = TABLE::match[TABLE::matchno-1]; ep3 = makesnode(en_cnacon,sp->name,sp->mangledName,sp->value.i); ep1 = makenode(en_fcall,ep3,ep2); tp1 = sp->tp->GetBtp(); currentFn->IsLeaf = FALSE; } else { error(ERR_METHOD_NOTFOUND); goto j1; } ep1->SetType(tp1); break; } // Else: we likely wanted the addres of the function since the // function is referenced without o parameter list indicator. Goto // the regular processing code. goto j2; } else { j2: dfs.printf("tp1->type:%d",tp1->type); qnode = makeinode(en_icon,sp->value.i); qnode->constflag = TRUE; iu = ep1->isUnsigned; ep1 = makenode(en_add,ep1,qnode); ep1->constflag = ep1->p[0]->constflag; ep1->isUnsigned = iu; ep1->esize = 2; ep1->p[2] = pep1; if (tp1->type==bt_pointer && (tp1->GetBtp()->type==bt_func || tp1->GetBtp()->type==bt_ifunc)) dfs.printf("Pointer to func"); else tp1 = CondDeref(&ep1,tp1); ep1->SetType(tp1); dfs.printf("tp1->type:%d",tp1->type); } if (tp1==nullptr) getchar(); NextToken(); /* past id */ dfs.printf("B"); break; case autodec: cnt = 0; NextToken(); Autoincdec(tp1,&ep1,1); break; case autoinc: cnt = 0; NextToken(); Autoincdec(tp1,&ep1,0); break; default: goto j1; } } j1: *node = ep1; if (ep1) (*node)->SetType(tp1); if (tp1) Leave("</ParsePostfix>", tp1->type); else Leave("</ParsePostfix>", 0); return tp1; } /* * ParseUnaryExpression evaluates unary expressions and returns the type of the * expression evaluated. unary expressions are any of: * * postfix expression * ++unary * --unary * !cast_expression // not cast_expression * ~cast_expression * -cast_expression * +cast_expression * *cast_expression * &cast_expression * sizeof(typecast) * sizeof unary * typenum(typecast) // new * */ TYP *ParseUnaryExpression(ENODE **node, int got_pa) { TYP *tp, *tp1; ENODE *ep1, *ep2, *ep3; int flag2; Enter("<ParseUnary>"); ep1 = NULL; *node = (ENODE *)NULL; flag2 = FALSE; if (got_pa) { tp = ParsePostfixExpression(&ep1, got_pa); *node = ep1; if (ep1) (*node)->SetType(tp); if (tp) Leave("</ParseUnary>", tp->type); else Leave("</ParseUnary>", 0); return tp; } switch( lastst ) { case autodec: NextToken(); tp = ParseUnaryExpression(&ep1, got_pa); Autoincdec(tp,&ep1,1); break; case autoinc: NextToken(); tp = ParseUnaryExpression(&ep1, got_pa); Autoincdec(tp,&ep1,0); break; case plus: NextToken(); tp = ParseCastExpression(&ep1); if( tp == NULL ) { error(ERR_IDEXPECT); return (TYP *)NULL; } break; // Negative constants are trapped here and converted to proper form. case minus: NextToken(); tp = ParseCastExpression(&ep1); if( tp == NULL ) { error(ERR_IDEXPECT); return (TYP *)NULL; } else if (ep1->constflag && (ep1->nodetype==en_icon)) { ep1->i = -ep1->i; } else if (ep1->constflag && (ep1->nodetype==en_fcon)) { ep1->f = -ep1->f; ep1->f128.sign = !ep1->f128.sign; // A new literal label is required. ep1->i = quadlit(&ep1->f128); } else { ep1 = makenode(en_uminus,ep1,(ENODE *)NULL); ep1->constflag = ep1->p[0]->constflag; ep1->isUnsigned = ep1->p[0]->isUnsigned; ep1->esize = tp->size; ep1->etype = (e_bt)tp->type; } break; case nott: case kw_not: NextToken(); tp = ParseCastExpression(&ep1); if( tp == NULL ) { error(ERR_IDEXPECT); return (TYP *)NULL; } ep1 = makenode(en_not,ep1,(ENODE *)NULL); ep1->constflag = ep1->p[0]->constflag; ep1->isUnsigned = ep1->p[0]->isUnsigned; ep1->SetType(tp); ep1->esize = tp->size; break; case cmpl: NextToken(); tp = ParseCastExpression(&ep1); if( tp == NULL ) { error(ERR_IDEXPECT); return 0; } ep1 = makenode(en_compl,ep1,(ENODE *)NULL); ep1->constflag = ep1->p[0]->constflag; ep1->isUnsigned = ep1->p[0]->isUnsigned; ep1->SetType(tp); ep1->esize = tp->size; break; case star: NextToken(); tp = ParseCastExpression(&ep1); if( tp == NULL ) { error(ERR_IDEXPECT); return (TYP *)NULL; } if( tp->GetBtp() == NULL ) error(ERR_DEREF); else { // A star before a function pointer just means that we want to // invoke the function. We want to retain the pointer to the // function as the type. if (tp->GetBtp()->type!=bt_func && tp->GetBtp()->type!=bt_ifunc) tp = tp->GetBtp(); } tp1 = tp; //Autoincdec(tp,&ep1); tp = CondDeref(&ep1,tp); break; case bitandd: NextToken(); tp = ParseCastExpression(&ep1); if( tp == NULL ) { error(ERR_IDEXPECT); return (TYP *)NULL; } if( IsLValue(ep1)) ep1 = ep1->p[0]; ep1->esize = 8; // converted to a pointer so size is now 8 tp1 = TYP::Make(bt_pointer,8); tp1->btp = tp->GetIndex(); tp1->val_flag = FALSE; tp1->isUnsigned = TRUE; tp = tp1; // printf("tp %p: %d\r\n", tp, tp->type); /* sp = search("ta_int",&tp->GetBtp()->lst); if (sp) { printf("bitandd: ta_int\r\n"); } */ break; /* case kw_abs: NextToken(); if (lastst==openpa) { flag2 = TRUE; NextToken(); } tp = ParseCastExpression(&ep1); if( tp == NULL ) { error(ERR_IDEXPECT); return (TYP *)NULL; } ep1 = makenode(en_abs,ep1,(ENODE *)NULL); ep1->constflag = ep1->p[0]->constflag; ep1->isUnsigned = ep1->p[0]->isUnsigned; ep1->esize = tp->size; if (flag2) needpunc(closepa,2); break; case kw_max: case kw_min: { TYP *tp1, *tp2, *tp3; flag2 = lastst==kw_max; NextToken(); needpunc(comma,2); tp1 = ParseCastExpression(&ep1); if( tp1 == NULL ) { error(ERR_IDEXPECT); return (TYP *)NULL; } needpunc(comma,2); tp2 = ParseCastExpression(&ep2); if( tp1 == NULL ) { error(ERR_IDEXPECT); return (TYP *)NULL; } if (lastst==comma) { NextToken(); tp3 = ParseCastExpression(&ep3); if( tp1 == NULL ) { error(ERR_IDEXPECT); return (TYP *)NULL; } } else tp3 = nullptr; tp = forcefit(&ep2,tp2,&ep1,tp1,1); tp = forcefit(&ep3,tp3,&ep2,tp,1); ep1 = makenode(flag2 ? en_max : en_min,ep1,ep2); ep1->p[2] = ep3; ep1->constflag = ep1->p[0]->constflag & ep2->p[0]->constflag & ep3->p[0]->constflag; ep1->isUnsigned = ep1->p[0]->isUnsigned; ep1->esize = tp->size; needpunc(closepa,2); } break; */ case kw_sizeof: NextToken(); if (lastst==openpa) { flag2 = TRUE; NextToken(); } if (flag2 && IsBeginningOfTypecast(lastst)) { tp = head; tp1 = tail; Declaration::ParseSpecifier(0); Declaration::ParsePrefix(FALSE); if( head != NULL ) ep1 = makeinode(en_icon,head->size); else { error(ERR_IDEXPECT); ep1 = makeinode(en_icon,1); } head = tp; tail = tp1; } else { sizeof_flag++; tp = ParseUnaryExpression(&ep1, got_pa); sizeof_flag--; if (tp == 0) { error(ERR_SYNTAX); ep1 = makeinode(en_icon,1); } else ep1 = makeinode(en_icon, (long) tp->size); } if (flag2) needpunc(closepa,2); ep1->constflag = TRUE; ep1->esize = 2; tp = &stdint; break; case kw_new: { ENODE *ep4, *ep5; std::string *name = new std::string("__new"); currentFn->UsesNew = TRUE; currentFn->IsLeaf = FALSE; NextToken(); if (IsBeginningOfTypecast(lastst)) { tp = head; tp1 = tail; Declaration::ParseSpecifier(0); Declaration::ParsePrefix(FALSE); if( head != NULL ) ep1 = makeinode(en_icon,head->size); else { error(ERR_IDEXPECT); ep1 = makeinode(en_icon,1); } ep4 = nullptr; ep2 = makeinode(en_icon,head->GetHash()); ep3 = makenode(en_object_list,nullptr,nullptr); ep4 = makeinode(en_icon, head->typeno); //ep5 = makenode(en_void,ep1,nullptr); ep5 = nullptr; ep5 = makenode(en_void,ep2,ep5); ep5 = makenode(en_void,ep3,ep5); ep5 = makenode(en_void, ep4, ep5); ep2 = makesnode(en_cnacon, name, name, 0); ep1 = makefcnode(en_fcall, ep2, ep5, nullptr); head = tp; tail = tp1; } else { sizeof_flag++; tp = ParseUnaryExpression(&ep1, got_pa); sizeof_flag--; if (tp == 0) { error(ERR_SYNTAX); ep1 = makeinode(en_icon,1); } else ep1 = makeinode(en_icon, (long) tp->size); ep3 = makenode(en_void,ep1,nullptr); ep2 = makesnode(en_cnacon, name, name, 0); ep1 = makefcnode(en_fcall, ep2, ep3, nullptr); } } break; case kw_delete: currentFn->IsLeaf = FALSE; NextToken(); { std::string *name = new std::string("__delete"); if (lastst==openbr) { NextToken(); needpunc(closebr,50); } tp1 = ParseCastExpression(&ep1); tp1 = deref(&ep1, tp1); ep2 = makesnode(en_cnacon, name, name, 0); ep1 = makefcnode(en_fcall, ep2, ep1, nullptr); } break; case kw_typenum: NextToken(); needpunc(openpa,3); tp = head; tp1 = tail; Declaration::ParseSpecifier(0); Declaration::ParsePrefix(FALSE); if( head != NULL ) ep1 = makeinode(en_icon,head->GetHash()); else { error(ERR_IDEXPECT); ep1 = makeinode(en_icon,1); } head = tp; tail = tp1; ep1->constflag = TRUE; ep1->esize = 2; tp = &stdint; needpunc(closepa,4); break; default: tp = ParsePostfixExpression(&ep1, got_pa); break; } *node = ep1; if (ep1) (*node)->SetType(tp); if (tp) Leave("</ParseUnary>", tp->type); else Leave("</ParseUnary>", 0); return tp; } // ---------------------------------------------------------------------------- // A cast_expression is: // unary_expression // (type name)cast_expression // ---------------------------------------------------------------------------- static TYP *ParseCastExpression(ENODE **node) { TYP *tp, *tp1, *tp2; ENODE *ep1, *ep2; Enter("ParseCast "); *node = (ENODE *)NULL; switch(lastst) { /* case openpa: NextToken(); if(IsBeginningOfTypecast(lastst) ) { ParseSpecifier(0); // do cast declaration ParseDeclarationPrefix(FALSE); tp = head; tp1 = tail; needpunc(closepa); if((tp2 = ParseCastExpression(&ep1)) == NULL ) { error(ERR_IDEXPECT); tp = (TYP *)NULL; } ep2 = makenode(en_void,ep1,(ENODE *)NULL); ep2->constflag = ep1->constflag; ep2->isUnsigned = ep1->isUnsigned; ep2->etype = ep1->etype; ep2->esize = ep1->esize; forcefit(&ep2,tp2,&ep1,tp); head = tp; tail = tp1; } else { tp = ParseUnaryExpression(&ep1,1); } break; */ case openpa: NextToken(); if (IsBeginningOfTypecast(lastst)) { Declaration::ParseSpecifier(0); // do cast declaration Declaration::ParsePrefix(FALSE); tp = head; tp1 = tail; needpunc(closepa, 5); if ((tp2 = ParseCastExpression(&ep1)) == NULL) { error(ERR_IDEXPECT); tp = (TYP *)NULL; } /* if (tp2->isConst) { *node = ep1; return tp; } */ if (tp == nullptr) error(ERR_NULLPOINTER); if (tp && tp->IsFloatType()) ep2 = makenode(en_tempfpref, (ENODE *)NULL, (ENODE *)NULL); else { ep2 = makenode(en_tempref, (ENODE *)NULL, (ENODE *)NULL); ep2->SetType(tp); } ep2 = makenode(en_void,ep2,ep1); if (ep1==nullptr) error(ERR_NULLPOINTER); else { ep2->constflag = ep1->constflag; ep2->isUnsigned = ep1->isUnsigned; ep2->etype = ep1->etype; ep2->esize = ep1->esize; forcefit(&ep2,tp,&ep1,tp2,false); } // forcefit(&ep2,tp2,&ep1,tp,false); head = tp; tail = tp1; *node = ep2; (*node)->SetType(tp); return tp; } else { tp = ParseUnaryExpression(&ep1,1); } break; default: tp = ParseUnaryExpression(&ep1,0); break; } *node = ep1; if (ep1) (*node)->SetType(tp); if (tp) Leave("ParseCast", tp->type); else Leave("ParseCast", 0); return tp; } /* * multops parses the multiply priority operators. the syntax of * this group is: * * unary * unary * unary * unary / unary * unary % unary */ TYP *multops(ENODE **node) { ENODE *ep1, *ep2; TYP *tp1, *tp2; int oper; bool isScalar; Enter("Mulops"); ep1 = (ENODE *)NULL; *node = (ENODE *)NULL; tp1 = ParseCastExpression(&ep1); if( tp1 == 0 ) { Leave("Mulops NULL",0); return 0; } while( lastst == star || lastst == divide || lastst == modop) { oper = lastst; NextToken(); /* move on to next unary op */ tp2 = ParseCastExpression(&ep2); if( tp2 == 0 ) { error(ERR_IDEXPECT); *node = ep1; if (ep1) (*node)->SetType(tp1); return tp1; } isScalar = !tp2->IsVectorType(); tp1 = forcefit(&ep2,tp2,&ep1,tp1,true); switch( oper ) { case star: switch(tp1->type) { case bt_triple: ep1 = makenode(en_fmul,ep1,ep2); ep1->esize = sizeOfFPT; break; case bt_double: ep1 = makenode(en_fmul,ep1,ep2); ep1->esize = sizeOfFPD; break; case bt_quad: ep1 = makenode(en_fmul,ep1,ep2); ep1->esize = sizeOfFPQ; break; case bt_float: ep1 = makenode(en_fmul,ep1,ep2); ep1->esize = sizeOfFP; break; case bt_vector: if (isScalar) ep1 = makenode(en_vmuls,ep1,ep2); else ep1 = makenode(en_vmul,ep1,ep2); ep1->esize = 512; break; default: // place constant as second operand. if (ep1->nodetype == en_icon) { if (tp1->isUnsigned) ep1 = makenode(en_mulu, ep2, ep1); else ep1 = makenode(en_mul, ep2, ep1); } else { if (tp1->isUnsigned) ep1 = makenode(en_mulu, ep1, ep2); else ep1 = makenode(en_mul, ep1, ep2); } } ep1->esize = tp1->size; ep1->etype = (e_bt)tp1->type; break; case divide: if (tp1->type==bt_triple) { ep1 = makenode(en_fdiv,ep1,ep2); ep1->esize = sizeOfFPT; } else if (tp1->type==bt_double) { ep1 = makenode(en_fdiv,ep1,ep2); ep1->esize = sizeOfFPD; } else if (tp1->type==bt_quad) { ep1 = makenode(en_fdiv,ep1,ep2); ep1->esize = sizeOfFPQ; } else if (tp1->type==bt_float) { ep1 = makenode(en_fdiv,ep1,ep2); ep1->esize = sizeOfFP; } else if( tp1->isUnsigned ) ep1 = makenode(en_udiv,ep1,ep2); else ep1 = makenode(en_div,ep1,ep2); break; ep1->esize = tp1->size; ep1->etype = (e_bt)tp1->type; case modop: if( tp1->isUnsigned ) ep1 = makenode(en_umod,ep1,ep2); else ep1 = makenode(en_mod,ep1,ep2); ep1->esize = tp1->size; ep1->etype = tp1->type; break; } PromoteConstFlag(ep1); } *node = ep1; if (ep1) (*node)->SetType(tp1); Leave("Mulops",0); return tp1; } // ---------------------------------------------------------------------------- // Addops handles the addition and subtraction operators. // ---------------------------------------------------------------------------- static TYP *addops(ENODE **node) { ENODE *ep1, *ep2, *ep3, *ep4; TYP *tp1, *tp2; int oper; int sz1, sz2; bool isScalar = true; Enter("Addops"); ep1 = (ENODE *)NULL; *node = (ENODE *)NULL; sz1 = sz2 = 0; tp1 = multops(&ep1); if( tp1 == (TYP *)NULL ) goto xit; if (tp1->type == bt_pointer) { if (tp1->GetBtp()==NULL) { printf("DIAG: pointer to NULL type.\r\n"); goto xit; } else sz1 = tp1->GetBtp()->size; } while( lastst == plus || lastst == minus ) { oper = (lastst == plus); NextToken(); tp2 = multops(&ep2); if (tp2==nullptr) throw new C64PException(ERR_NULLPOINTER,1); isScalar = !tp2->IsVectorType(); if( tp2 == 0 ) { error(ERR_IDEXPECT); *node = ep1; goto xit; } if (tp2->type == bt_pointer) sz2 = tp2->GetBtp()->size; // Difference of two pointers to the same type of object... // Divide the result by the size of the pointed to object. if (!oper && (tp1->type == bt_pointer) && (tp2->type == bt_pointer) && (sz1==sz2)) { ep1 = makenode( en_sub,ep1,ep2); ep4 = makeinode(en_icon, sz1); ep1 = makenode(en_udiv,ep1,ep4); } else { if( tp1->type == bt_pointer ) { tp2 = forcefit(&ep2,tp2,0,&stdint,true); ep3 = makeinode(en_icon,tp1->GetBtp()->size); ep3->constflag = TRUE; ep3->esize = tp2->size; ep2 = makenode(en_mulu,ep3,ep2); ep2->constflag = ep2->p[1]->constflag; ep2->esize = tp2->size; } else if( tp2->type == bt_pointer ) { tp1 = forcefit(&ep1,tp1,0,&stdint,true); ep3 = makeinode(en_icon,tp2->GetBtp()->size); ep3->constflag = TRUE; ep3->esize = tp2->size; ep1 = makenode(en_mulu,ep3,ep1); ep1->constflag = ep1->p[1]->constflag; ep2->esize = tp2->size; } tp1 = forcefit(&ep2,tp2,&ep1,tp1,true); switch (tp1->type) { case bt_triple: ep1 = makenode( oper ? en_fadd : en_fsub,ep1,ep2); ep1->esize = sizeOfFPT; break; case bt_double: ep1 = makenode( oper ? en_fadd : en_fsub,ep1,ep2); ep1->esize = sizeOfFPD; break; case bt_quad: //tp1 = forcefit(&ep1,tp1,&ep2,tp2,true); ep1 = makenode( oper ? en_fadd : en_fsub,ep1,ep2); ep1->esize = sizeOfFPQ; break; case bt_float: ep1 = makenode( oper ? en_fadd : en_fsub,ep1,ep2); ep1->esize = sizeOfFPS; break; case bt_vector: if (isScalar) ep1 = makenode( oper ? en_vadds : en_vsubs,ep1,ep2); else ep1 = makenode( oper ? en_vadd : en_vsub,ep1,ep2); ep1->esize = 8; break; // In the case of a pointer place any constant to be added // as the second operand. This will allow the use of immediate // mode addressing rather than having to load into a register. case bt_pointer: if (ep1->nodetype==en_icon && oper) ep1 = makenode(en_add, ep2, ep1); else ep1 = makenode(oper ? en_add : en_sub, ep1, ep2); break; default: ep1 = makenode( oper ? en_add : en_sub,ep1,ep2); } } PromoteConstFlag(ep1); ep1->esize = tp1->size; ep1->etype = tp1->type; } *node = ep1; xit: if (*node) (*node)->SetType(tp1); Leave("Addops",0); return tp1; } // ---------------------------------------------------------------------------- // Shiftop handles the shift operators << and >>. // ---------------------------------------------------------------------------- TYP *shiftop(ENODE **node) { ENODE *ep1, *ep2; TYP *tp1, *tp2; int oper; Enter("Shiftop"); *node = NULL; tp1 = addops(&ep1); if( tp1 == 0) goto xit; while( lastst == lshift || lastst == rshift || lastst==lrot || lastst==rrot) { oper = (lastst == lshift); if (lastst==lrot || lastst==rrot) oper=2 + (lastst==lrot); NextToken(); tp2 = addops(&ep2); if( tp2 == 0 ) error(ERR_IDEXPECT); else { tp1 = forcefit(&ep2,tp2,&ep1,tp1,true); if (tp1->IsFloatType()) error(ERR_UNDEF_OP); else { if (tp1->isUnsigned) { switch(oper) { case 0: ep1 = makenode(en_shru,ep1,ep2); break; case 1: ep1 = makenode(en_shlu,ep1,ep2); break; case 2: ep1 = makenode(en_ror,ep1,ep2); break; case 3: ep1 = makenode(en_rol,ep1,ep2); break; } } else { switch(oper) { case 0: ep1 = makenode(en_asr,ep1,ep2); break; case 1: ep1 = makenode(en_asl,ep1,ep2); break; case 2: ep1 = makenode(en_ror,ep1,ep2); break; case 3: ep1 = makenode(en_rol,ep1,ep2); break; } } ep1->esize = tp1->size; PromoteConstFlag(ep1); } } } *node = ep1; xit: if (*node) (*node)->SetType(tp1); Leave("Shiftop",0); return tp1; } /* * relation handles the relational operators < <= > and >=. */ TYP *relation(ENODE **node) { ENODE *ep1, *ep2; TYP *tp1, *tp2; bool isVector = false; int nt; Enter("Relation"); *node = (ENODE *)NULL; tp1 = shiftop(&ep1); if( tp1 == 0 ) goto xit; for(;;) { if (tp1->IsVectorType()) isVector = true; switch( lastst ) { case lt: if (tp1->IsVectorType()) nt = en_vlt; else if (tp1->IsFloatType()) nt = en_flt; else if( tp1->isUnsigned ) nt = en_ult; else nt = en_lt; break; case gt: if (tp1->IsVectorType()) nt = en_vgt; else if (tp1->IsFloatType()) nt = en_fgt; else if( tp1->isUnsigned ) nt = en_ugt; else nt = en_gt; break; case leq: if (tp1->IsVectorType()) nt = en_vle; else if (tp1->IsFloatType()) nt = en_fle; else if( tp1->isUnsigned ) nt = en_ule; else nt = en_le; break; case geq: if (tp1->IsVectorType()) nt = en_vge; else if (tp1->IsFloatType()) nt = en_fge; else if( tp1->isUnsigned ) nt = en_uge; else nt = en_ge; break; default: goto fini; } NextToken(); tp2 = shiftop(&ep2); if( tp2 == 0 ) error(ERR_IDEXPECT); else { if (tp2->IsVectorType()) isVector = true; tp1 = forcefit(&ep2,tp2,&ep1,tp1,true); ep1 = makenode(nt,ep1,ep2); ep1->esize = 1; if (isVector) tp1 = TYP::Make(bt_vector_mask,sizeOfWord); PromoteConstFlag(ep1); } } fini: *node = ep1; xit: if (*node) (*node)->SetType(tp1); Leave("Relation",0); return tp1; } /* * equalops handles the equality and inequality operators. */ TYP *equalops(ENODE **node) { ENODE *ep1, *ep2; TYP *tp1, *tp2; int oper; bool isVector = false; Enter("EqualOps"); *node = (ENODE *)NULL; tp1 = relation(&ep1); if( tp1 == (TYP *)NULL ) goto xit; if (tp1->IsVectorType()) isVector = true; while( lastst == eq || lastst == neq ) { oper = (lastst == eq); NextToken(); tp2 = relation(&ep2); if( tp2 == NULL ) error(ERR_IDEXPECT); else { if (tp2->IsVectorType()) isVector = true; tp1 = forcefit(&ep2,tp2,&ep1,tp1,true); if (tp1->IsVectorType()) ep1 = makenode( oper ? en_veq : en_vne,ep1,ep2); else if (tp1->IsFloatType()) ep1 = makenode( oper ? en_feq : en_fne,ep1,ep2); else ep1 = makenode( oper ? en_eq : en_ne,ep1,ep2); ep1->esize = 2; if (isVector) tp1 = TYP::Make(bt_vector_mask,sizeOfWord); ep1->etype = tp1->type; PromoteConstFlag(ep1); } } *node = ep1; xit: if (*node) (*node)->SetType(tp1); Leave("EqualOps",0); return tp1; } /* * binop is a common routine to handle all of the legwork and * error checking for bitand, bitor, bitxor, andop, and orop. */ TYP *binop(ENODE **node, TYP *(*xfunc)(ENODE **),int nt, int sy) { ENODE *ep1, *ep2; TYP *tp1, *tp2; Enter("Binop"); *node = (ENODE *)NULL; tp1 = (*xfunc)(&ep1); if( tp1 == 0 ) goto xit; while( lastst == sy ) { NextToken(); tp2 = (*xfunc)(&ep2); if( tp2 == 0 ) error(ERR_IDEXPECT); else { tp1 = forcefit(&ep2,tp2,&ep1,tp1,true); ep1 = makenode(nt,ep1,ep2); ep1->esize = tp1->size; ep1->etype = tp1->type; PromoteConstFlag(ep1); } } *node = ep1; xit: if (*node) (*node)->SetType(tp1); Leave("Binop",0); return tp1; } TYP *bitwiseand(ENODE **node) /* * the bitwise and operator... */ { return binop(node,equalops,en_and,bitandd); } TYP *bitwisexor(ENODE **node) { return binop(node,bitwiseand,en_xor,uparrow); } TYP *bitwiseor(ENODE **node) { return binop(node,bitwisexor,en_or,bitorr); } TYP *andop(ENODE **node) { return binop(node,bitwiseor,en_land,land); } TYP *orop(ENODE **node) { return binop(node,andop,en_lor,lor); } /* * this routine processes the hook operator. */ TYP *conditional(ENODE **node) { TYP *tp1, *tp2, *tp3; ENODE *ep1, *ep2, *ep3; Enter("Conditional"); *node = (ENODE *)NULL; tp1 = orop(&ep1); /* get condition */ if( tp1 == (TYP *)NULL ) goto xit; if( lastst == hook ) { iflevel++; if ((iflevel > maxPn-1) && isThor) error(ERR_OUTOFPREDS); NextToken(); if( (tp2 = conditional(&ep2)) == NULL) { error(ERR_IDEXPECT); goto cexit; } needpunc(colon,6); if( (tp3 = conditional(&ep3)) == NULL) { error(ERR_IDEXPECT); goto cexit; } tp1 = forcefit(&ep3,tp3,&ep2,tp2,true); ep2 = makenode(en_void,ep2,ep3); ep2->esize = tp1->size; ep1 = makenode(en_cond,ep1,ep2); ep1->predreg = iflevel; ep1->esize = tp1->size; iflevel--; } cexit: *node = ep1; xit: if (*node) (*node)->SetType(tp1); Leave("Conditional",0); return tp1; } // ---------------------------------------------------------------------------- // asnop handles the assignment operators. currently only the // simple assignment is implemented. // ---------------------------------------------------------------------------- TYP *asnop(ENODE **node) { ENODE *ep1, *ep2, *ep3; TYP *tp1, *tp2; int op; Enter("Assignop"); *node = (ENODE *)NULL; tp1 = conditional(&ep1); if( tp1 == 0 ) goto xit; for(;;) { switch( lastst ) { case assign: op = en_assign; ascomm: NextToken(); tp2 = asnop(&ep2); ascomm2: if( tp2 == 0 || !IsLValue(ep1) ) error(ERR_LVALUE); else { tp1 = forcefit(&ep2,tp2,&ep1,tp1,false); ep1 = makenode(op,ep1,ep2); ep1->esize = tp1->size; ep1->etype = tp1->type; ep1->isUnsigned = tp1->isUnsigned; // Struct assign calls memcpy, so function is no // longer a leaf routine. if (tp1->size > 8) currentFn->IsLeaf = FALSE; } break; case asplus: op = en_asadd; ascomm3: NextToken(); tp2 = asnop(&ep2); if( tp1->type == bt_pointer ) { ep3 = makeinode(en_icon,tp1->GetBtp()->size); ep3->esize = sizeOfPtr; ep2 = makenode(en_mul,ep2,ep3); ep2->esize = sizeOfPtr; } goto ascomm2; case asminus: op = en_assub; goto ascomm3; case astimes: if (tp1->isUnsigned) op = en_asmulu; else op = en_asmul; goto ascomm; case asdivide: if (tp1->isUnsigned) op = en_asdivu; else op = en_asdiv; goto ascomm; case asmodop: if (tp1->isUnsigned) op = en_asmodu; else op = en_asmod; goto ascomm; case aslshift: op = en_aslsh; goto ascomm; case asrshift: if (tp1->isUnsigned) op = en_asrshu; else op = en_asrsh; goto ascomm; case asand: op = en_asand; goto ascomm; case asor: op = en_asor; goto ascomm; case asxor: op = en_asxor; goto ascomm; default: goto asexit; } } asexit: *node = ep1; xit: if (*node) (*node)->SetType(tp1); Leave("Assignop",0); return tp1; } // ---------------------------------------------------------------------------- // Evaluate an expression where the assignment operator is not legal. // ---------------------------------------------------------------------------- static TYP *NonAssignExpression(ENODE **node) { TYP *tp; pep1 = nullptr; Enter("NonAssignExpression"); *node = (ENODE *)NULL; tp = conditional(node); if( tp == (TYP *)NULL ) *node =(ENODE *)NULL; Leave("NonAssignExpression",tp ? tp->type : 0); if (*node) (*node)->SetType(tp); return tp; } // ---------------------------------------------------------------------------- // Evaluate an expression where the comma operator is not legal. // Externally visible entry point for GetIntegerExpression() and // ArgumentList(). // ---------------------------------------------------------------------------- TYP *NonCommaExpression(ENODE **node) { TYP *tp; pep1 = nullptr; Enter("NonCommaExpression"); *node = (ENODE *)NULL; tp = asnop(node); if( tp == (TYP *)NULL ) *node =(ENODE *)NULL; Leave("NonCommaExpression",tp ? tp->type : 0); if (*node) (*node)->SetType(tp); return tp; } /* * evaluate the comma operator. comma operators are kept as * void nodes. */ TYP *commaop(ENODE **node) { TYP *tp1,*tp2; ENODE *ep1,*ep2; *node = (ENODE *)NULL; tp1 = NonCommaExpression(&ep1); if (tp1==(TYP *)NULL) return (TYP *)NULL; while(1) { if (lastst==comma) { NextToken(); tp2 = NonCommaExpression(&ep2); ep1 = makenode(en_void,ep1,ep2); ep1->esize = tp1->size; } else break; } *node = ep1; if (*node) (*node)->SetType(tp1); return tp1; } //TYP *commaop(ENODE **node) //{ // TYP *tp1; // ENODE *ep1, *ep2; // tp1 = asnop(&ep1); // if( tp1 == NULL ) // return NULL; // if( lastst == comma ) { // NextToken(); // tp1 = commaop(&ep2); // if( tp1 == NULL ) { // error(ERR_IDEXPECT); // goto coexit; // } // ep1 = makenode(en_void,ep1,ep2); // } //coexit: *node = ep1; // return tp1; //} // ---------------------------------------------------------------------------- // Evaluate an expression where all operators are legal. // ---------------------------------------------------------------------------- TYP *expression(ENODE **node) { TYP *tp; Enter("<expression>"); pep1 = nullptr; *node = (ENODE *)NULL; tp = commaop(node); if( tp == (TYP *)NULL ) *node = (ENODE *)NULL; TRACE(printf("leave exp\r\n")); if (tp) { if (*node) (*node)->SetType(tp); Leave("Expression",tp->type); } else Leave("</Expression>",0); return tp; }
Go to most recent revision | Compare with Previous | Blame | View Log