00001
00002
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;
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));
00380 return;
00381 }
00382 }
00383 else {
00384 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL));
00385 return;
00386 }
00387 }
00388 _outervalues.push_back(SQOuterVar(name,name,otSYMBOL));
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){
00412 SQInstruction &pi = _instructions[size-1];
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 }