2 see copyright notice in squirrel.h
4 #include "sqpcheader.h"
5 #include "sqcompiler.h"
6 #include "sqfuncproto.h"
10 #include "sqfuncstate.h"
13 SQInstructionDesc g_InstrDesc[]={
16 {_SC("_OP_TAILCALL")},
18 {_SC("_OP_PREPCALL")},
19 {_SC("_OP_PREPCALLK")},
31 {_SC("_OP_LOADNULLS")},
32 {_SC("_OP_LOADROOTTABLE")},
37 {_SC("_OP_LOADFREEVAR")},
39 {_SC("_OP_GETVARGV")},
40 {_SC("_OP_NEWTABLE")},
41 {_SC("_OP_NEWARRAY")},
42 {_SC("_OP_APPENDARRAY")},
43 {_SC("_OP_GETPARENT")},
44 {_SC("_OP_COMPARITH")},
45 {_SC("_OP_COMPARITHL")},
52 {_SC("_OP_INSTANCEOF")},
62 {_SC("_OP_DELEGATE")},
65 {_SC("_OP_PUSHTRAP")},
69 {_SC("_OP_NEWSLOTA")},
73 void DumpLiteral(SQObjectPtr &o)
76 case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;
77 case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
78 case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break;
82 SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
85 _literals = SQTable::Create(ss,0);
86 _strings = SQTable::Create(ss,0);
101 void SQFuncState::Error(const SQChar *err)
103 _errfunc(_errtarget,err);
107 void SQFuncState::Dump()
110 SQFunctionProto *func=_funcproto(_func);
111 scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
112 scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
113 scprintf(_SC("--------------------------------------------------------------------\n"));
114 scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
115 scprintf(_SC("-----LITERALS\n"));
116 SQObjectPtr refidx,key,val;
118 SQObjectPtrVec templiterals;
119 templiterals.resize(_nliterals);
120 while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {
122 templiterals[_integer(val)]=key;
124 for(i=0;i<templiterals.size();i++){
125 scprintf(_SC("[%d] "),n);
126 DumpLiteral(templiterals[i]);
130 scprintf(_SC("-----PARAMS\n"));
132 scprintf(_SC("<<VARPARAMS>>\n"));
134 for(i=0;i<_parameters.size();i++){
135 scprintf(_SC("[%d] "),n);
136 DumpLiteral(_parameters[i]);
140 scprintf(_SC("-----LOCALS\n"));
141 for(i=0;i<func->_localvarinfos.size();i++){
142 SQLocalVarInfo lvi=func->_localvarinfos[i];
143 scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
146 scprintf(_SC("-----LINE INFO\n"));
147 for(i=0;i<_lineinfos.size();i++){
148 SQLineInfo li=_lineinfos[i];
149 scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
152 scprintf(_SC("-----dump\n"));
154 for(i=0;i<_instructions.size();i++){
155 SQInstruction &inst=_instructions[i];
156 if(inst.op==_OP_LOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
158 int lidx = inst._arg1;
159 scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
160 if(lidx >= 0xFFFFFFFF)
161 scprintf(_SC("null"));
164 SQObjectPtr val,key,refo;
165 while(((refidx=_table(_literals)->Next(refo,key,val))!= -1) && (_integer(val) != lidx)) {
170 scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
172 else if(inst.op==_OP_ARITH){
173 scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
176 scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
179 scprintf(_SC("-----\n"));
180 scprintf(_SC("stack size[%d]\n"),func->_stacksize);
181 scprintf(_SC("--------------------------------------------------------------------\n\n"));
184 /*int SQFuncState::GetStringConstant(SQObjectPtr &cons)
186 return GetConstant(cons);
189 int SQFuncState::GetNumericConstant(const SQInteger cons)
191 return GetConstant(SQObjectPtr(cons));
194 int SQFuncState::GetNumericConstant(const SQFloat cons)
196 return GetConstant(SQObjectPtr(cons));
199 int SQFuncState::GetConstant(const SQObject &cons)
203 if(!_table(_literals)->Get(cons,val))
206 _table(_literals)->NewSlot(cons,val);
208 if(_nliterals > MAX_LITERALS) {
210 Error(_SC("internal compiler error: too many literals"));
213 return _integer(val);
216 void SQFuncState::SetIntructionParams(int pos,int arg0,int arg1,int arg2,int arg3)
218 _instructions[pos]._arg0=*((unsigned int *)&arg0);
219 _instructions[pos]._arg1=*((unsigned int *)&arg1);
220 _instructions[pos]._arg2=*((unsigned int *)&arg2);
221 _instructions[pos]._arg3=*((unsigned int *)&arg3);
224 void SQFuncState::SetIntructionParam(int pos,int arg,int val)
227 case 0:_instructions[pos]._arg0=*((unsigned int *)&val);break;
228 case 1:_instructions[pos]._arg1=*((unsigned int *)&val);break;
229 case 2:_instructions[pos]._arg2=*((unsigned int *)&val);break;
230 case 3:_instructions[pos]._arg3=*((unsigned int *)&val);break;
231 case 4:_instructions[pos]._arg1=*((unsigned int *)&val);break;
235 int SQFuncState::AllocStackPos()
237 int npos=_vlocals.size();
238 _vlocals.push_back(SQLocalVarInfo());
239 if(_vlocals.size()>((unsigned int)_stacksize)) {
240 if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
241 _stacksize=_vlocals.size();
246 int SQFuncState::PushTarget(int n)
249 _targetstack.push_back(n);
253 _targetstack.push_back(n);
257 int SQFuncState::GetUpTarget(int n){
258 return _targetstack[((_targetstack.size()-1)-n)];
261 int SQFuncState::TopTarget(){
262 return _targetstack.back();
264 int SQFuncState::PopTarget()
266 int npos=_targetstack.back();
267 SQLocalVarInfo t=_vlocals[_targetstack.back()];
268 if(type(t._name)==OT_NULL){
271 _targetstack.pop_back();
275 int SQFuncState::GetStackSize()
277 return _vlocals.size();
280 void SQFuncState::SetStackSize(int n)
282 int size=_vlocals.size();
285 SQLocalVarInfo lvi=_vlocals.back();
286 if(type(lvi._name)!=OT_NULL){
287 lvi._end_op=GetCurrentPos();
288 _localvarinfos.push_back(lvi);
294 bool SQFuncState::IsLocal(unsigned int stkpos)
296 if(stkpos>=_vlocals.size())return false;
297 else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
301 int SQFuncState::PushLocalVariable(const SQObject &name)
303 int pos=_vlocals.size();
306 lvi._start_op=GetCurrentPos()+1;
307 lvi._pos=_vlocals.size();
308 _vlocals.push_back(lvi);
309 if(_vlocals.size()>((unsigned int)_stacksize))_stacksize=_vlocals.size();
314 int SQFuncState::GetLocalVariable(const SQObject &name)
316 int locals=_vlocals.size();
318 if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){
326 int SQFuncState::GetOuterVariable(const SQObject &name)
328 int outers = _outervalues.size();
329 for(int i = 0; i<outers; i++) {
330 if(_string(_outervalues[i]._name) == _string(name))
336 void SQFuncState::AddOuterValue(const SQObject &name)
338 //AddParameter(name);
341 pos = _parent->GetLocalVariable(name);
343 pos = _parent->GetOuterVariable(name);
345 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
350 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
354 _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global
357 void SQFuncState::AddParameter(const SQObject &name)
359 PushLocalVariable(name);
360 _parameters.push_back(name);
363 void SQFuncState::AddLineInfos(int line,bool lineop,bool force)
365 if(_lastline!=line || force){
367 li._line=line;li._op=(GetCurrentPos()+1);
368 if(lineop)AddInstruction(_OP_LINE,0,line);
369 _lineinfos.push_back(li);
374 void SQFuncState::AddInstruction(SQInstruction &i)
376 int size = _instructions.size();
377 if(size > 0 && _optimization){ //simple optimizer
378 SQInstruction &pi = _instructions[size-1];//previous instruction
381 if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
382 pi.op = _OP_TAILCALL;
386 if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
388 pi._arg2 = (unsigned char)i._arg1;
396 if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
397 pi.op = _OP_PREPCALLK;
405 case _OP_APPENDARRAY:
406 if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
407 pi.op = _OP_APPENDARRAY;
410 pi._arg2 = MAX_FUNC_STACKSIZE;
411 pi._arg3 = MAX_FUNC_STACKSIZE;
416 if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))
419 _optimization = false;
423 if(pi.op == _OP_MOVE)
427 pi._arg3 = (unsigned char)i._arg1;
432 case _OP_EQ:case _OP_NE:
433 if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
439 pi._arg3 = MAX_FUNC_STACKSIZE;
445 if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
447 pi._arg1 = pi._arg1 + 1;
448 pi.op = _OP_LOADNULLS;
453 if(pi.op == _OP_LINE) {
454 _instructions.pop_back();
455 _lineinfos.pop_back();
460 _optimization = true;
461 _instructions.push_back(i);
464 SQObject SQFuncState::CreateString(const SQChar *s,int len)
466 SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
467 _table(_strings)->NewSlot(ns,1);
471 void SQFuncState::Finalize()
473 SQFunctionProto *f=_funcproto(_func);
474 f->_literals.resize(_nliterals);
475 SQObjectPtr refidx,key,val;
477 while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {
478 f->_literals[_integer(val)]=key;
481 f->_functions.resize(_functions.size());
482 f->_functions.copy(_functions);
483 f->_parameters.resize(_parameters.size());
484 f->_parameters.copy(_parameters);
485 f->_outervalues.resize(_outervalues.size());
486 f->_outervalues.copy(_outervalues);
487 f->_instructions.resize(_instructions.size());
488 f->_instructions.copy(_instructions);
489 f->_localvarinfos.resize(_localvarinfos.size());
490 f->_localvarinfos.copy(_localvarinfos);
491 f->_lineinfos.resize(_lineinfos.size());
492 f->_lineinfos.copy(_lineinfos);
493 f->_varparams = _varparams;
496 SQFuncState *SQFuncState::PushChildState(SQSharedState *ss,SQFunctionProto *func)
498 SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
499 new (child) SQFuncState(ss,func,this,_errfunc,_errtarget);
500 _childstates.push_back(child);
504 void SQFuncState::PopChildState()
506 SQFuncState *child = _childstates.back();
507 sq_delete(child,SQFuncState);
508 _childstates.pop_back();
511 SQFuncState::~SQFuncState()
513 while(_childstates.size() > 0)