sqfuncstate.cpp

00001 /*
00002   see copyright notice in squirrel.h
00003 */
00004 #include "sqpcheader.h"
00005 #include "sqcompiler.h"
00006 #include "sqfuncproto.h"
00007 #include "sqstring.h"
00008 #include "sqtable.h"
00009 #include "sqopcodes.h"
00010 #include "sqfuncstate.h"
00011 
00012 #ifdef _DEBUG_DUMP
00013 SQInstructionDesc g_InstrDesc[]={
00014   {_SC("_OP_LINE")},
00015   {_SC("_OP_LOAD")},
00016   {_SC("_OP_LOADINT")},
00017   {_SC("_OP_LOADFLOAT")},
00018   {_SC("_OP_DLOAD")},
00019   {_SC("_OP_TAILCALL")},
00020   {_SC("_OP_CALL")},
00021   {_SC("_OP_PREPCALL")},
00022   {_SC("_OP_PREPCALLK")},
00023   {_SC("_OP_GETK")},
00024   {_SC("_OP_MOVE")},
00025   {_SC("_OP_NEWSLOT")},
00026   {_SC("_OP_DELETE")},
00027   {_SC("_OP_SET")},
00028   {_SC("_OP_GET")},
00029   {_SC("_OP_EQ")},
00030   {_SC("_OP_NE")},
00031   {_SC("_OP_ARITH")},
00032   {_SC("_OP_BITW")},
00033   {_SC("_OP_RETURN")},
00034   {_SC("_OP_LOADNULLS")},
00035   {_SC("_OP_LOADROOTTABLE")},
00036   {_SC("_OP_LOADBOOL")},
00037   {_SC("_OP_DMOVE")},
00038   {_SC("_OP_JMP")},
00039   {_SC("_OP_JNZ")},
00040   {_SC("_OP_JZ")},
00041   {_SC("_OP_LOADFREEVAR")},
00042   {_SC("_OP_VARGC")},
00043   {_SC("_OP_GETVARGV")},
00044   {_SC("_OP_NEWTABLE")},
00045   {_SC("_OP_NEWARRAY")},
00046   {_SC("_OP_APPENDARRAY")},
00047   {_SC("_OP_GETPARENT")},
00048   {_SC("_OP_COMPARITH")},
00049   {_SC("_OP_COMPARITHL")},
00050   {_SC("_OP_INC")},
00051   {_SC("_OP_INCL")},
00052   {_SC("_OP_PINC")},
00053   {_SC("_OP_PINCL")},
00054   {_SC("_OP_CMP")},
00055   {_SC("_OP_EXISTS")},
00056   {_SC("_OP_INSTANCEOF")},
00057   {_SC("_OP_AND")},
00058   {_SC("_OP_OR")},
00059   {_SC("_OP_NEG")},
00060   {_SC("_OP_NOT")},
00061   {_SC("_OP_BWNOT")},
00062   {_SC("_OP_CLOSURE")},
00063   {_SC("_OP_YIELD")},
00064   {_SC("_OP_RESUME")},
00065   {_SC("_OP_FOREACH")},
00066   {_SC("_OP_POSTFOREACH")},
00067   {_SC("_OP_DELEGATE")},
00068   {_SC("_OP_CLONE")},
00069   {_SC("_OP_TYPEOF")},
00070   {_SC("_OP_PUSHTRAP")},
00071   {_SC("_OP_POPTRAP")},
00072   {_SC("_OP_THROW")},
00073   {_SC("_OP_CLASS")},
00074   {_SC("_OP_NEWSLOTA")},
00075   {_SC("_OP_SCOPE_END")}
00076 };
00077 #endif
00078 void DumpLiteral(SQObjectPtr &o)
00079 {
00080   switch(type(o)){
00081     case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;
00082     case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
00083 #if defined(_SQ64)
00084     case OT_INTEGER: scprintf(_SC("{%ld}"),_integer(o));break;
00085 #else
00086     case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break;
00087 #endif
00088     case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
00089     default: scprintf(_SC("(%s %p)"),GetTypeName(o),_rawval(o));break; break; //shut up compiler
00090   }
00091 }
00092 
00093 SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
00094 {
00095     _nliterals = 0;
00096     _literals = SQTable::Create(ss,0);
00097     _strings =  SQTable::Create(ss,0);
00098     _sharedstate = ss;
00099     _lastline = 0;
00100     _optimization = true;
00101     _parent = parent;
00102     _stacksize = 0;
00103     _traps = 0;
00104     _returnexp = 0;
00105     _varparams = false;
00106     _errfunc = efunc;
00107     _errtarget = ed;
00108     _bgenerator = false;
00109 
00110 }
00111 
00112 void SQFuncState::Error(const SQChar *err)
00113 {
00114   _errfunc(_errtarget,err);
00115 }
00116 
00117 #ifdef _DEBUG_DUMP
00118 void SQFuncState::Dump(SQFunctionProto *func)
00119 {
00120   SQUnsignedInteger n=0,i;
00121   SQInteger si;
00122   scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
00123   scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
00124   scprintf(_SC("--------------------------------------------------------------------\n"));
00125   scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
00126   scprintf(_SC("-----LITERALS\n"));
00127   SQObjectPtr refidx,key,val;
00128   SQInteger idx;
00129   SQObjectPtrVec templiterals;
00130   templiterals.resize(_nliterals);
00131   while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
00132     refidx=idx;
00133     templiterals[_integer(val)]=key;
00134   }
00135   for(i=0;i<templiterals.size();i++){
00136     scprintf(_SC("[%d] "),n);
00137     DumpLiteral(templiterals[i]);
00138     scprintf(_SC("\n"));
00139     n++;
00140   }
00141   scprintf(_SC("-----PARAMS\n"));
00142   if(_varparams)
00143     scprintf(_SC("<<VARPARAMS>>\n"));
00144   n=0;
00145   for(i=0;i<_parameters.size();i++){
00146     scprintf(_SC("[%d] "),n);
00147     DumpLiteral(_parameters[i]);
00148     scprintf(_SC("\n"));
00149     n++;
00150   }
00151   scprintf(_SC("-----LOCALS\n"));
00152   for(si=0;si<func->_nlocalvarinfos;si++){
00153     SQLocalVarInfo lvi=func->_localvarinfos[si];
00154     scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
00155     n++;
00156   }
00157   scprintf(_SC("-----LINE INFO\n"));
00158   for(i=0;i<_lineinfos.size();i++){
00159     SQLineInfo li=_lineinfos[i];
00160     scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
00161     n++;
00162   }
00163   scprintf(_SC("-----dump\n"));
00164   n=0;
00165   for(i=0;i<_instructions.size();i++){
00166     SQInstruction &inst=_instructions[i];
00167     if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
00168 
00169       SQInteger lidx = inst._arg1;
00170       scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
00171       if(lidx >= 0xFFFFFFFF)
00172         scprintf(_SC("null"));
00173       else {
00174         SQInteger refidx;
00175         SQObjectPtr val,key,refo;
00176         while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
00177           refo = refidx;
00178         }
00179         DumpLiteral(key);
00180       }
00181       if(inst.op != _OP_DLOAD) {
00182         scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
00183       }
00184       else {
00185         scprintf(_SC(" %d "),inst._arg2);
00186         lidx = inst._arg3;
00187         if(lidx >= 0xFFFFFFFF)
00188           scprintf(_SC("null"));
00189         else {
00190           SQInteger refidx;
00191           SQObjectPtr val,key,refo;
00192           while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
00193             refo = refidx;
00194         }
00195         DumpLiteral(key);
00196         scprintf(_SC("\n"));
00197       }
00198       }
00199     }
00200     else if(inst.op==_OP_LOADFLOAT) {
00201       scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);
00202     }
00203     else if(inst.op==_OP_ARITH){
00204       scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
00205     }
00206     else
00207       scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
00208     n++;
00209   }
00210   scprintf(_SC("-----\n"));
00211   scprintf(_SC("stack size[%d]\n"),func->_stacksize);
00212   scprintf(_SC("--------------------------------------------------------------------\n\n"));
00213 }
00214 #endif
00215 
00216 SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
00217 {
00218   return GetConstant(SQObjectPtr(cons));
00219 }
00220 
00221 SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
00222 {
00223   return GetConstant(SQObjectPtr(cons));
00224 }
00225 
00226 SQInteger SQFuncState::GetConstant(const SQObject &cons)
00227 {
00228   SQObjectPtr val;
00229   if(!_table(_literals)->Get(cons,val))
00230   {
00231     val = _nliterals;
00232     _table(_literals)->NewSlot(cons,val);
00233     _nliterals++;
00234     if(_nliterals > MAX_LITERALS) {
00235       val.Null();
00236       Error(_SC("internal compiler error: too many literals"));
00237     }
00238   }
00239   return _integer(val);
00240 }
00241 
00242 void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
00243 {
00244   _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
00245   _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
00246   _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
00247   _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
00248 }
00249 
00250 void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
00251 {
00252   switch(arg){
00253     case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
00254     case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
00255     case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
00256     case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
00257   };
00258 }
00259 
00260 SQInteger SQFuncState::AllocStackPos()
00261 {
00262   SQInteger npos=_vlocals.size();
00263   _vlocals.push_back(SQLocalVarInfo());
00264   if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
00265     if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
00266     _stacksize=_vlocals.size();
00267   }
00268   return npos;
00269 }
00270 
00271 SQInteger SQFuncState::PushTarget(SQInteger n)
00272 {
00273   if(n!=-1){
00274     _targetstack.push_back(n);
00275     return n;
00276   }
00277   n=AllocStackPos();
00278   _targetstack.push_back(n);
00279   return n;
00280 }
00281 
00282 SQInteger SQFuncState::GetUpTarget(SQInteger n){
00283   return _targetstack[((_targetstack.size()-1)-n)];
00284 }
00285 
00286 SQInteger SQFuncState::TopTarget(){
00287   return _targetstack.back();
00288 }
00289 SQInteger SQFuncState::PopTarget()
00290 {
00291   SQInteger npos=_targetstack.back();
00292   SQLocalVarInfo t=_vlocals[_targetstack.back()];
00293   if(type(t._name)==OT_NULL){
00294     _vlocals.pop_back();
00295   }
00296   _targetstack.pop_back();
00297   return npos;
00298 }
00299 
00300 SQInteger SQFuncState::GetStackSize()
00301 {
00302   return _vlocals.size();
00303 }
00304 
00305 void SQFuncState::SetStackSize(SQInteger n)
00306 {
00307   SQInteger size=_vlocals.size();
00308   while(size>n){
00309     size--;
00310     SQLocalVarInfo lvi=_vlocals.back();
00311     if(type(lvi._name)!=OT_NULL){
00312       lvi._end_op=GetCurrentPos();
00313       _localvarinfos.push_back(lvi);
00314     }
00315     _vlocals.pop_back();
00316   }
00317 }
00318 
00319 bool SQFuncState::IsConstant(const SQObject &name,SQObject &e)
00320 {
00321   SQObjectPtr val;
00322   if(_table(_sharedstate->_consts)->Get(name,val)) {
00323     e = val;
00324     return true;
00325   }
00326   return false;
00327 }
00328 
00329 bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
00330 {
00331   if(stkpos>=_vlocals.size())return false;
00332   else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
00333   return false;
00334 }
00335 
00336 SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
00337 {
00338   SQInteger pos=_vlocals.size();
00339   SQLocalVarInfo lvi;
00340   lvi._name=name;
00341   lvi._start_op=GetCurrentPos()+1;
00342   lvi._pos=_vlocals.size();
00343   _vlocals.push_back(lvi);
00344   if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
00345 
00346   return pos;
00347 }
00348 
00349 SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
00350 {
00351   SQInteger locals=_vlocals.size();
00352   while(locals>=1){
00353     if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){
00354       return locals-1;
00355     }
00356     locals--;
00357   }
00358   return -1;
00359 }
00360 
00361 SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
00362 {
00363   SQInteger outers = _outervalues.size();
00364   for(SQInteger i = 0; i<outers; i++) {
00365     if(_string(_outervalues[i]._name) == _string(name))
00366       return i;
00367   }
00368   return -1;
00369 }
00370 
00371 void SQFuncState::AddOuterValue(const SQObject &name)
00372 {
00373   SQInteger pos=-1;
00374   if(_parent) {
00375     pos = _parent->GetLocalVariable(name);
00376     if(pos == -1) {
00377       pos = _parent->GetOuterVariable(name);
00378       if(pos != -1) {
00379         _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
00380         return;
00381       }
00382     }
00383     else {
00384       _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
00385       return;
00386     }
00387   }
00388   _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global
00389 }
00390 
00391 void SQFuncState::AddParameter(const SQObject &name)
00392 {
00393   PushLocalVariable(name);
00394   _parameters.push_back(name);
00395 }
00396 
00397 void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
00398 {
00399   if(_lastline!=line || force){
00400     SQLineInfo li;
00401     li._line=line;li._op=(GetCurrentPos()+1);
00402     if(lineop)AddInstruction(_OP_LINE,0,line);
00403     _lineinfos.push_back(li);
00404     _lastline=line;
00405   }
00406 }
00407 
00408 void SQFuncState::AddInstruction(SQInstruction &i)
00409 {
00410   SQInteger size = _instructions.size();
00411   if(size > 0 && _optimization){ //simple optimizer
00412     SQInstruction &pi = _instructions[size-1];//previous instruction
00413     switch(i.op) {
00414     case _OP_RETURN:
00415       if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
00416         pi.op = _OP_TAILCALL;
00417       }
00418     break;
00419     case _OP_GET:
00420       if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
00421         pi._arg1 = pi._arg1;
00422         pi._arg2 = (unsigned char)i._arg1;
00423         pi.op = _OP_GETK;
00424         pi._arg0 = i._arg0;
00425 
00426         return;
00427       }
00428     break;
00429     case _OP_PREPCALL:
00430       if( pi.op == _OP_LOAD  && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
00431         pi.op = _OP_PREPCALLK;
00432         pi._arg0 = i._arg0;
00433         pi._arg1 = pi._arg1;
00434         pi._arg2 = i._arg2;
00435         pi._arg3 = i._arg3;
00436         return;
00437       }
00438       break;
00439     case _OP_APPENDARRAY:
00440       if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
00441         pi.op = _OP_APPENDARRAY;
00442         pi._arg0 = i._arg0;
00443         pi._arg1 = pi._arg1;
00444         pi._arg2 = MAX_FUNC_STACKSIZE;
00445         pi._arg3 = MAX_FUNC_STACKSIZE;
00446         return;
00447       }
00448       break;
00449     case _OP_MOVE:
00450       if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))
00451       {
00452         pi._arg0 = i._arg0;
00453         _optimization = false;
00454         return;
00455       }
00456 
00457       if(pi.op == _OP_MOVE)
00458       {
00459         pi.op = _OP_DMOVE;
00460         pi._arg2 = i._arg0;
00461         pi._arg3 = (unsigned char)i._arg1;
00462         return;
00463       }
00464       break;
00465     case _OP_LOAD:
00466       if(pi.op == _OP_LOAD && i._arg1 < 256) {
00467         pi.op = _OP_DLOAD;
00468         pi._arg2 = i._arg0;
00469         pi._arg3 = (unsigned char)i._arg1;
00470         return;
00471       }
00472       break;
00473     case _OP_EQ:case _OP_NE:
00474       if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
00475       {
00476         pi.op = i.op;
00477         pi._arg0 = i._arg0;
00478         pi._arg1 = pi._arg1;
00479         pi._arg2 = i._arg2;
00480         pi._arg3 = MAX_FUNC_STACKSIZE;
00481         return;
00482       }
00483       break;
00484     case _OP_LOADNULLS:
00485       if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
00486 
00487         pi._arg1 = pi._arg1 + 1;
00488         pi.op = _OP_LOADNULLS;
00489         return;
00490       }
00491             break;
00492     case _OP_LINE:
00493       if(pi.op == _OP_LINE) {
00494         _instructions.pop_back();
00495         _lineinfos.pop_back();
00496       }
00497       break;
00498     }
00499   }
00500   _optimization = true;
00501   _instructions.push_back(i);
00502 }
00503 
00504 SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
00505 {
00506   SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
00507   _table(_strings)->NewSlot(ns,(SQInteger)1);
00508   return ns;
00509 }
00510 
00511 SQObject SQFuncState::CreateTable()
00512 {
00513   SQObjectPtr nt(SQTable::Create(_sharedstate,0));
00514   _table(_strings)->NewSlot(nt,(SQInteger)1);
00515   return nt;
00516 }
00517 
00518 SQFunctionProto *SQFuncState::BuildProto()
00519 {
00520   SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(),
00521     _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
00522     _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
00523 
00524   SQObjectPtr refidx,key,val;
00525   SQInteger idx;
00526 
00527   f->_stacksize = _stacksize;
00528   f->_sourcename = _sourcename;
00529   f->_bgenerator = _bgenerator;
00530   f->_name = _name;
00531 
00532   while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
00533     f->_literals[_integer(val)]=key;
00534     refidx=idx;
00535   }
00536 
00537   for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
00538   for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
00539   for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
00540   for(SQUnsignedInteger no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no];
00541   for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no];
00542   for(SQUnsignedInteger no = 0; no < _defaultparams.size(); no++) f->_defaultparams[no] = _defaultparams[no];
00543 
00544   memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
00545 
00546   f->_varparams = _varparams;
00547 
00548   return f;
00549 }
00550 
00551 SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
00552 {
00553   SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
00554   new (child) SQFuncState(ss,this,_errfunc,_errtarget);
00555   _childstates.push_back(child);
00556   return child;
00557 }
00558 
00559 void SQFuncState::PopChildState()
00560 {
00561   SQFuncState *child = _childstates.back();
00562   sq_delete(child,SQFuncState);
00563   _childstates.pop_back();
00564 }
00565 
00566 SQFuncState::~SQFuncState()
00567 {
00568   while(_childstates.size() > 0)
00569   {
00570     PopChildState();
00571   }
00572 }

Generated on Thu Oct 1 11:03:11 2009 for OpenTTD by  doxygen 1.5.6