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[]={
17 {_SC("_OP_LOADFLOAT")},
19 {_SC("_OP_TAILCALL")},
21 {_SC("_OP_PREPCALL")},
22 {_SC("_OP_PREPCALLK")},
34 {_SC("_OP_LOADNULLS")},
35 {_SC("_OP_LOADROOTTABLE")},
36 {_SC("_OP_LOADBOOL")},
41 {_SC("_OP_LOADFREEVAR")},
43 {_SC("_OP_GETVARGV")},
44 {_SC("_OP_NEWTABLE")},
45 {_SC("_OP_NEWARRAY")},
46 {_SC("_OP_APPENDARRAY")},
47 {_SC("_OP_GETPARENT")},
48 {_SC("_OP_COMPARITH")},
49 {_SC("_OP_COMPARITHL")},
56 {_SC("_OP_INSTANCEOF")},
66 {_SC("_OP_POSTFOREACH")},
67 {_SC("_OP_DELEGATE")},
70 {_SC("_OP_PUSHTRAP")},
77 void DumpLiteral(SQObjectPtr &o)
80 case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;
81 case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
82 case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break;
83 default: assert(0); break; //shut up compiler
87 SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
90 _literals = SQTable::Create(ss,0);
91 _strings = SQTable::Create(ss,0);
106 void SQFuncState::Error(const SQChar *err)
108 _errfunc(_errtarget,err);
112 void SQFuncState::Dump(SQFunctionProto *func)
114 SQUnsignedInteger n=0,i;
116 scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
117 scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
118 scprintf(_SC("--------------------------------------------------------------------\n"));
119 scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
120 scprintf(_SC("-----LITERALS\n"));
121 SQObjectPtr refidx,key,val;
123 SQObjectPtrVec templiterals;
124 templiterals.resize(_nliterals);
125 while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
127 templiterals[_integer(val)]=key;
129 for(i=0;i<templiterals.size();i++){
130 scprintf(_SC("[%d] "),n);
131 DumpLiteral(templiterals[i]);
135 scprintf(_SC("-----PARAMS\n"));
137 scprintf(_SC("<<VARPARAMS>>\n"));
139 for(i=0;i<_parameters.size();i++){
140 scprintf(_SC("[%d] "),n);
141 DumpLiteral(_parameters[i]);
145 scprintf(_SC("-----LOCALS\n"));
146 for(si=0;si<func->_nlocalvarinfos;si++){
147 SQLocalVarInfo lvi=func->_localvarinfos[si];
148 scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
151 scprintf(_SC("-----LINE INFO\n"));
152 for(i=0;i<_lineinfos.size();i++){
153 SQLineInfo li=_lineinfos[i];
154 scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
157 scprintf(_SC("-----dump\n"));
159 for(i=0;i<_instructions.size();i++){
160 SQInstruction &inst=_instructions[i];
161 if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
163 SQInteger lidx = inst._arg1;
164 scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
165 if(lidx >= 0xFFFFFFFF)
166 scprintf(_SC("null"));
169 SQObjectPtr val,key,refo;
170 while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
175 if(inst.op != _OP_DLOAD) {
176 scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
179 scprintf(_SC(" %d "),inst._arg2);
181 if(lidx >= 0xFFFFFFFF)
182 scprintf(_SC("null"));
185 SQObjectPtr val,key,refo;
186 while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
194 else if(inst.op==_OP_LOADFLOAT) {
195 scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);
197 else if(inst.op==_OP_ARITH){
198 scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
201 scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
204 scprintf(_SC("-----\n"));
205 scprintf(_SC("stack size[%d]\n"),func->_stacksize);
206 scprintf(_SC("--------------------------------------------------------------------\n\n"));
210 SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
212 return GetConstant(SQObjectPtr(cons));
215 SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
217 return GetConstant(SQObjectPtr(cons));
220 SQInteger SQFuncState::GetConstant(const SQObject &cons)
223 if(!_table(_literals)->Get(cons,val))
226 _table(_literals)->NewSlot(cons,val);
228 if(_nliterals > MAX_LITERALS) {
230 Error(_SC("internal compiler error: too many literals"));
233 return _integer(val);
236 void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
238 _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
239 _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
240 _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
241 _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
244 void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
247 case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
248 case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
249 case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
250 case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
254 SQInteger SQFuncState::AllocStackPos()
256 SQInteger npos=_vlocals.size();
257 _vlocals.push_back(SQLocalVarInfo());
258 if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
259 if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
260 _stacksize=_vlocals.size();
265 SQInteger SQFuncState::PushTarget(SQInteger n)
268 _targetstack.push_back(n);
272 _targetstack.push_back(n);
276 SQInteger SQFuncState::GetUpTarget(SQInteger n){
277 return _targetstack[((_targetstack.size()-1)-n)];
280 SQInteger SQFuncState::TopTarget(){
281 return _targetstack.back();
283 SQInteger SQFuncState::PopTarget()
285 SQInteger npos=_targetstack.back();
286 SQLocalVarInfo t=_vlocals[_targetstack.back()];
287 if(type(t._name)==OT_NULL){
290 _targetstack.pop_back();
294 SQInteger SQFuncState::GetStackSize()
296 return _vlocals.size();
299 void SQFuncState::SetStackSize(SQInteger n)
301 SQInteger size=_vlocals.size();
304 SQLocalVarInfo lvi=_vlocals.back();
305 if(type(lvi._name)!=OT_NULL){
306 lvi._end_op=GetCurrentPos();
307 _localvarinfos.push_back(lvi);
313 bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
315 if(stkpos>=_vlocals.size())return false;
316 else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
320 SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
322 SQInteger pos=_vlocals.size();
325 lvi._start_op=GetCurrentPos()+1;
326 lvi._pos=_vlocals.size();
327 _vlocals.push_back(lvi);
328 if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
333 SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
335 SQInteger locals=_vlocals.size();
337 if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){
345 SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
347 SQInteger outers = _outervalues.size();
348 for(SQInteger i = 0; i<outers; i++) {
349 if(_string(_outervalues[i]._name) == _string(name))
355 void SQFuncState::AddOuterValue(const SQObject &name)
359 pos = _parent->GetLocalVariable(name);
361 pos = _parent->GetOuterVariable(name);
363 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
368 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
372 _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global
375 void SQFuncState::AddParameter(const SQObject &name)
377 PushLocalVariable(name);
378 _parameters.push_back(name);
381 void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
383 if(_lastline!=line || force){
385 li._line=line;li._op=(GetCurrentPos()+1);
386 if(lineop)AddInstruction(_OP_LINE,0,line);
387 _lineinfos.push_back(li);
392 void SQFuncState::AddInstruction(SQInstruction &i)
394 SQInteger size = _instructions.size();
395 if(size > 0 && _optimization){ //simple optimizer
396 SQInstruction &pi = _instructions[size-1];//previous instruction
399 if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
400 pi.op = _OP_TAILCALL;
404 if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
406 pi._arg2 = (unsigned char)i._arg1;
414 if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
415 pi.op = _OP_PREPCALLK;
423 case _OP_APPENDARRAY:
424 if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
425 pi.op = _OP_APPENDARRAY;
428 pi._arg2 = MAX_FUNC_STACKSIZE;
429 pi._arg3 = MAX_FUNC_STACKSIZE;
434 if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))
437 _optimization = false;
441 if(pi.op == _OP_MOVE)
445 pi._arg3 = (unsigned char)i._arg1;
450 if(pi.op == _OP_LOAD && i._arg1 < 256) {
453 pi._arg3 = (unsigned char)i._arg1;
457 case _OP_EQ:case _OP_NE:
458 if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
464 pi._arg3 = MAX_FUNC_STACKSIZE;
469 if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
471 pi._arg1 = pi._arg1 + 1;
472 pi.op = _OP_LOADNULLS;
477 if(pi.op == _OP_LINE) {
478 _instructions.pop_back();
479 _lineinfos.pop_back();
484 _optimization = true;
485 _instructions.push_back(i);
488 SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
490 SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
491 _table(_strings)->NewSlot(ns,(SQInteger)1);
495 SQFunctionProto *SQFuncState::BuildProto()
497 SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(),
498 _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
499 _lineinfos.size(),_localvarinfos.size());
501 SQObjectPtr refidx,key,val;
504 f->_stacksize = _stacksize;
505 f->_sourcename = _sourcename;
506 f->_bgenerator = _bgenerator;
509 while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
510 f->_literals[_integer(val)]=key;
514 for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
515 for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
516 for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
517 for(SQUnsignedInteger no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no];
518 for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no];
520 memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
522 f->_varparams = _varparams;
527 SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
529 SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
530 new (child) SQFuncState(ss,this,_errfunc,_errtarget);
531 _childstates.push_back(child);
535 void SQFuncState::PopChildState()
537 SQFuncState *child = _childstates.back();
538 sq_delete(child,SQFuncState);
539 _childstates.pop_back();
542 SQFuncState::~SQFuncState()
544 while(_childstates.size() > 0)