2 see copyright notice in squirrel.h
\r
4 #include "sqpcheader.h"
\r
5 #include "sqcompiler.h"
\r
6 #include "sqfuncproto.h"
\r
7 #include "sqstring.h"
\r
9 #include "sqopcodes.h"
\r
10 #include "sqfuncstate.h"
\r
13 SQInstructionDesc g_InstrDesc[]={
\r
16 {_SC("_OP_TAILCALL")},
\r
18 {_SC("_OP_PREPCALL")},
\r
19 {_SC("_OP_PREPCALLK")},
\r
22 {_SC("_OP_NEWSLOT")},
\r
23 {_SC("_OP_DELETE")},
\r
30 {_SC("_OP_RETURN")},
\r
31 {_SC("_OP_LOADNULLS")},
\r
32 {_SC("_OP_LOADROOTTABLE")},
\r
37 {_SC("_OP_LOADFREEVAR")},
\r
39 {_SC("_OP_GETVARGV")},
\r
40 {_SC("_OP_NEWTABLE")},
\r
41 {_SC("_OP_NEWARRAY")},
\r
42 {_SC("_OP_APPENDARRAY")},
\r
43 {_SC("_OP_GETPARENT")},
\r
44 {_SC("_OP_COMPARITH")},
\r
45 {_SC("_OP_COMPARITHL")},
\r
51 {_SC("_OP_EXISTS")},
\r
52 {_SC("_OP_INSTANCEOF")},
\r
58 {_SC("_OP_CLOSURE")},
\r
60 {_SC("_OP_RESUME")},
\r
61 {_SC("_OP_FOREACH")},
\r
62 {_SC("_OP_DELEGATE")},
\r
64 {_SC("_OP_TYPEOF")},
\r
65 {_SC("_OP_PUSHTRAP")},
\r
66 {_SC("_OP_POPTRAP")},
\r
69 {_SC("_OP_NEWSLOTA")},
\r
70 {_SC("_OP_LOADBOOL")}
\r
73 void DumpLiteral(SQObjectPtr &o)
\r
76 case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;
\r
77 case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
\r
78 case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break;
\r
82 SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent)
\r
85 _literals = SQTable::Create(ss,0);
\r
88 _optimization = true;
\r
98 void SQFuncState::Dump()
\r
100 unsigned int n=0,i;
\r
101 SQFunctionProto *func=_funcproto(_func);
\r
102 scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
\r
103 scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
\r
104 scprintf(_SC("--------------------------------------------------------------------\n"));
\r
105 scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
\r
106 scprintf(_SC("-----LITERALS\n"));
\r
107 SQObjectPtr refidx,key,val;
\r
109 SQObjectPtrVec templiterals;
\r
110 templiterals.resize(_nliterals);
\r
111 while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {
\r
113 templiterals[_integer(val)]=key;
\r
115 for(i=0;i<templiterals.size();i++){
\r
116 scprintf(_SC("[%d] "),n);
\r
117 DumpLiteral(templiterals[i]);
\r
118 scprintf(_SC("\n"));
\r
121 scprintf(_SC("-----PARAMS\n"));
\r
123 scprintf(_SC("<<VARPARAMS>>\n"));
\r
125 for(i=0;i<_parameters.size();i++){
\r
126 scprintf(_SC("[%d] "),n);
\r
127 DumpLiteral(_parameters[i]);
\r
128 scprintf(_SC("\n"));
\r
131 scprintf(_SC("-----LOCALS\n"));
\r
132 for(i=0;i<func->_localvarinfos.size();i++){
\r
133 SQLocalVarInfo lvi=func->_localvarinfos[i];
\r
134 scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
\r
137 scprintf(_SC("-----LINE INFO\n"));
\r
138 for(i=0;i<_lineinfos.size();i++){
\r
139 SQLineInfo li=_lineinfos[i];
\r
140 scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
\r
143 scprintf(_SC("-----dump\n"));
\r
145 for(i=0;i<_instructions.size();i++){
\r
146 SQInstruction &inst=_instructions[i];
\r
147 if(inst.op==_OP_LOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
\r
149 int lidx = inst._arg1;
\r
150 scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
\r
151 if(lidx >= 0xFFFFFFFF)
\r
152 scprintf(_SC("null"));
\r
155 SQObjectPtr val,key,refo;
\r
156 while(((refidx=_table(_literals)->Next(refo,key,val))!= -1) && (_integer(val) != lidx)) {
\r
161 scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
\r
163 else if(inst.op==_OP_ARITH){
\r
164 scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
\r
167 scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
\r
170 scprintf(_SC("-----\n"));
\r
171 scprintf(_SC("stack size[%d]\n"),func->_stacksize);
\r
172 scprintf(_SC("--------------------------------------------------------------------\n\n"));
\r
175 int SQFuncState::GetStringConstant(const SQChar *cons)
\r
177 return GetConstant(SQString::Create(_sharedstate,cons));
\r
180 int SQFuncState::GetNumericConstant(const SQInteger cons)
\r
182 return GetConstant(cons);
\r
185 int SQFuncState::GetNumericConstant(const SQFloat cons)
\r
187 return GetConstant(cons);
\r
190 int SQFuncState::GetConstant(SQObjectPtr cons)
\r
194 if(!_table(_literals)->Get(cons,val))
\r
197 _table(_literals)->NewSlot(cons,val);
\r
199 if(_nliterals > MAX_LITERALS) throw ParserException(_SC("internal compiler error: too many literals"));
\r
201 return _integer(val);
\r
204 void SQFuncState::SetIntructionParams(int pos,int arg0,int arg1,int arg2,int arg3)
\r
206 _instructions[pos]._arg0=*((unsigned int *)&arg0);
\r
207 _instructions[pos]._arg1=*((unsigned int *)&arg1);
\r
208 _instructions[pos]._arg2=*((unsigned int *)&arg2);
\r
209 _instructions[pos]._arg3=*((unsigned int *)&arg3);
\r
212 void SQFuncState::SetIntructionParam(int pos,int arg,int val)
\r
215 case 0:_instructions[pos]._arg0=*((unsigned int *)&val);break;
\r
216 case 1:_instructions[pos]._arg1=*((unsigned int *)&val);break;
\r
217 case 2:_instructions[pos]._arg2=*((unsigned int *)&val);break;
\r
218 case 3:_instructions[pos]._arg3=*((unsigned int *)&val);break;
\r
219 case 4:_instructions[pos]._arg1=*((unsigned int *)&val);break;
\r
223 int SQFuncState::AllocStackPos()
\r
225 int npos=_vlocals.size();
\r
226 _vlocals.push_back(SQLocalVarInfo());
\r
227 if(_vlocals.size()>((unsigned int)_stacksize)) {
\r
228 if(_stacksize>MAX_FUNC_STACKSIZE) throw ParserException(_SC("internal compiler error: too many locals"));
\r
229 _stacksize=_vlocals.size();
\r
234 int SQFuncState::PushTarget(int n)
\r
237 _targetstack.push_back(n);
\r
241 _targetstack.push_back(n);
\r
245 int SQFuncState::GetUpTarget(int n){
\r
246 return _targetstack[((_targetstack.size()-1)-n)];
\r
249 int SQFuncState::TopTarget(){
\r
250 return _targetstack.back();
\r
252 int SQFuncState::PopTarget()
\r
254 int npos=_targetstack.back();
\r
255 SQLocalVarInfo t=_vlocals[_targetstack.back()];
\r
256 if(type(t._name)==OT_NULL){
\r
257 _vlocals.pop_back();
\r
259 _targetstack.pop_back();
\r
263 int SQFuncState::GetStackSize()
\r
265 return _vlocals.size();
\r
268 void SQFuncState::SetStackSize(int n)
\r
270 int size=_vlocals.size();
\r
273 SQLocalVarInfo lvi=_vlocals.back();
\r
274 if(type(lvi._name)!=OT_NULL){
\r
275 lvi._end_op=GetCurrentPos();
\r
276 _localvarinfos.push_back(lvi);
\r
278 _vlocals.pop_back();
\r
282 bool SQFuncState::IsLocal(unsigned int stkpos)
\r
284 if(stkpos>=_vlocals.size())return false;
\r
285 else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
\r
289 int SQFuncState::PushLocalVariable(const SQObjectPtr &name)
\r
291 int pos=_vlocals.size();
\r
292 SQLocalVarInfo lvi;
\r
294 lvi._start_op=GetCurrentPos()+1;
\r
295 lvi._pos=_vlocals.size();
\r
296 _vlocals.push_back(lvi);
\r
297 if(_vlocals.size()>((unsigned int)_stacksize))_stacksize=_vlocals.size();
\r
302 int SQFuncState::GetLocalVariable(const SQObjectPtr &name)
\r
304 int locals=_vlocals.size();
\r
306 if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){
\r
314 int SQFuncState::GetOuterVariable(const SQObjectPtr &name)
\r
316 int outers = _outervalues.size();
\r
317 for(int i = 0; i<outers; i++) {
\r
318 if(_string(_outervalues[i]._name) == _string(name))
\r
324 void SQFuncState::AddOuterValue(const SQObjectPtr &name)
\r
326 //AddParameter(name);
\r
329 pos = _parent->GetLocalVariable(name);
\r
331 pos = _parent->GetOuterVariable(name);
\r
333 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
\r
338 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
\r
342 _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global
\r
345 void SQFuncState::AddParameter(const SQObjectPtr &name)
\r
347 PushLocalVariable(name);
\r
348 _parameters.push_back(name);
\r
351 void SQFuncState::AddLineInfos(int line,bool lineop,bool force)
\r
353 if(_lastline!=line || force){
\r
355 li._line=line;li._op=(GetCurrentPos()+1);
\r
356 if(lineop)AddInstruction(_OP_LINE,0,line);
\r
357 _lineinfos.push_back(li);
\r
362 void SQFuncState::AddInstruction(SQInstruction &i)
\r
364 int size = _instructions.size();
\r
365 if(size > 0 && _optimization){ //simple optimizer
\r
366 SQInstruction &pi = _instructions[size-1];//previous instruction
\r
369 if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
\r
370 pi.op = _OP_TAILCALL;
\r
374 if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
\r
375 pi._arg1 = pi._arg1;
\r
376 pi._arg2 = (unsigned char)i._arg1;
\r
378 pi._arg0 = i._arg0;
\r
384 if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
\r
385 pi.op = _OP_PREPCALLK;
\r
386 pi._arg0 = i._arg0;
\r
387 pi._arg1 = pi._arg1;
\r
388 pi._arg2 = i._arg2;
\r
389 pi._arg3 = i._arg3;
\r
393 case _OP_APPENDARRAY:
\r
394 if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
\r
395 pi.op = _OP_APPENDARRAY;
\r
396 pi._arg0 = i._arg0;
\r
397 pi._arg1 = pi._arg1;
\r
398 pi._arg2 = MAX_FUNC_STACKSIZE;
\r
399 pi._arg3 = MAX_FUNC_STACKSIZE;
\r
404 if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))
\r
406 pi._arg0 = i._arg0;
\r
407 _optimization = false;
\r
411 if(pi.op == _OP_MOVE)
\r
414 pi._arg2 = i._arg0;
\r
415 pi._arg3 = (unsigned char)i._arg1;
\r
420 case _OP_EQ:case _OP_NE:
\r
421 if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
\r
424 pi._arg0 = i._arg0;
\r
425 pi._arg1 = pi._arg1;
\r
426 pi._arg2 = i._arg2;
\r
427 pi._arg3 = MAX_FUNC_STACKSIZE;
\r
431 case _OP_LOADNULLS:
\r
432 //case _OP_LOADNULL:
\r
433 if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
\r
435 pi._arg1 = pi._arg1 + 1;
\r
436 pi.op = _OP_LOADNULLS;
\r
441 if(pi.op == _OP_LINE) {
\r
442 _instructions.pop_back();
\r
443 _lineinfos.pop_back();
\r
448 _optimization = true;
\r
449 _instructions.push_back(i);
\r
452 SQObject SQFuncState::CreateString(const SQChar *s)
\r
454 SQObjectPtr ns(SQString::Create(_sharedstate,s));
\r
455 _stringrefs.push_back(ns);
\r
459 void SQFuncState::Finalize()
\r
461 SQFunctionProto *f=_funcproto(_func);
\r
462 f->_literals.resize(_nliterals);
\r
463 SQObjectPtr refidx,key,val;
\r
465 while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {
\r
466 f->_literals[_integer(val)]=key;
\r
469 f->_functions.resize(_functions.size());
\r
470 f->_functions.copy(_functions);
\r
471 f->_parameters.resize(_parameters.size());
\r
472 f->_parameters.copy(_parameters);
\r
473 f->_outervalues.resize(_outervalues.size());
\r
474 f->_outervalues.copy(_outervalues);
\r
475 f->_instructions.resize(_instructions.size());
\r
476 f->_instructions.copy(_instructions);
\r
477 f->_localvarinfos.resize(_localvarinfos.size());
\r
478 f->_localvarinfos.copy(_localvarinfos);
\r
479 f->_lineinfos.resize(_lineinfos.size());
\r
480 f->_lineinfos.copy(_lineinfos);
\r
481 f->_varparams = _varparams;
\r