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[]={
18 {_SC("_OP_TAILCALL")},
20 {_SC("_OP_PREPCALL")},
21 {_SC("_OP_PREPCALLK")},
33 {_SC("_OP_LOADNULLS")},
34 {_SC("_OP_LOADROOTTABLE")},
35 {_SC("_OP_LOADBOOL")},
40 {_SC("_OP_LOADFREEVAR")},
42 {_SC("_OP_GETVARGV")},
43 {_SC("_OP_NEWTABLE")},
44 {_SC("_OP_NEWARRAY")},
45 {_SC("_OP_APPENDARRAY")},
46 {_SC("_OP_GETPARENT")},
47 {_SC("_OP_COMPARITH")},
48 {_SC("_OP_COMPARITHL")},
55 {_SC("_OP_INSTANCEOF")},
65 {_SC("_OP_DELEGATE")},
68 {_SC("_OP_PUSHTRAP")},
75 void DumpLiteral(SQObjectPtr &o)
78 case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;
79 case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
80 case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break;
81 default: assert(0); break; //shut up compiler
85 SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
88 _literals = SQTable::Create(ss,0);
89 _strings = SQTable::Create(ss,0);
104 void SQFuncState::Error(const SQChar *err)
106 _errfunc(_errtarget,err);
110 void SQFuncState::Dump(SQFunctionProto *func)
112 SQUnsignedInteger n=0,i;
113 scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
114 scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
115 scprintf(_SC("--------------------------------------------------------------------\n"));
116 scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
117 scprintf(_SC("-----LITERALS\n"));
118 SQObjectPtr refidx,key,val;
120 SQObjectPtrVec templiterals;
121 templiterals.resize(_nliterals);
122 while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
124 templiterals[_integer(val)]=key;
126 for(i=0;i<templiterals.size();i++){
127 scprintf(_SC("[%d] "),n);
128 DumpLiteral(templiterals[i]);
132 scprintf(_SC("-----PARAMS\n"));
134 scprintf(_SC("<<VARPARAMS>>\n"));
136 for(i=0;i<_parameters.size();i++){
137 scprintf(_SC("[%d] "),n);
138 DumpLiteral(_parameters[i]);
142 scprintf(_SC("-----LOCALS\n"));
143 for(i=0;i<func->_localvarinfos.size();i++){
144 SQLocalVarInfo lvi=func->_localvarinfos[i];
145 scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
148 scprintf(_SC("-----LINE INFO\n"));
149 for(i=0;i<_lineinfos.size();i++){
150 SQLineInfo li=_lineinfos[i];
151 scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
154 scprintf(_SC("-----dump\n"));
156 for(i=0;i<_instructions.size();i++){
157 SQInstruction &inst=_instructions[i];
158 if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
160 SQInteger lidx = inst._arg1;
161 scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
162 if(lidx >= 0xFFFFFFFF)
163 scprintf(_SC("null"));
166 SQObjectPtr val,key,refo;
167 while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
172 if(inst.op != _OP_DLOAD) {
173 scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
176 scprintf(_SC(" %d "),inst._arg2);
178 if(lidx >= 0xFFFFFFFF)
179 scprintf(_SC("null"));
182 SQObjectPtr val,key,refo;
183 while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
191 else if(inst.op==_OP_ARITH){
192 scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
195 scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
198 scprintf(_SC("-----\n"));
199 scprintf(_SC("stack size[%d]\n"),func->_stacksize);
200 scprintf(_SC("--------------------------------------------------------------------\n\n"));
204 SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
206 return GetConstant(SQObjectPtr(cons));
209 SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
211 return GetConstant(SQObjectPtr(cons));
214 SQInteger SQFuncState::GetConstant(const SQObject &cons)
217 if(!_table(_literals)->Get(cons,val))
220 _table(_literals)->NewSlot(cons,val);
222 if(_nliterals > MAX_LITERALS) {
224 Error(_SC("internal compiler error: too many literals"));
227 return _integer(val);
230 void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
232 _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
233 _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
234 _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
235 _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
238 void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
241 case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
242 case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
243 case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
244 case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
248 SQInteger SQFuncState::AllocStackPos()
250 SQInteger npos=_vlocals.size();
251 _vlocals.push_back(SQLocalVarInfo());
252 if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
253 if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
254 _stacksize=_vlocals.size();
259 SQInteger SQFuncState::PushTarget(SQInteger n)
262 _targetstack.push_back(n);
266 _targetstack.push_back(n);
270 SQInteger SQFuncState::GetUpTarget(SQInteger n){
271 return _targetstack[((_targetstack.size()-1)-n)];
274 SQInteger SQFuncState::TopTarget(){
275 return _targetstack.back();
277 SQInteger SQFuncState::PopTarget()
279 SQInteger npos=_targetstack.back();
280 SQLocalVarInfo t=_vlocals[_targetstack.back()];
281 if(type(t._name)==OT_NULL){
284 _targetstack.pop_back();
288 SQInteger SQFuncState::GetStackSize()
290 return _vlocals.size();
293 void SQFuncState::SetStackSize(SQInteger n)
295 SQInteger size=_vlocals.size();
298 SQLocalVarInfo lvi=_vlocals.back();
299 if(type(lvi._name)!=OT_NULL){
300 lvi._end_op=GetCurrentPos();
301 _localvarinfos.push_back(lvi);
307 bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
309 if(stkpos>=_vlocals.size())return false;
310 else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
314 SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
316 SQInteger pos=_vlocals.size();
319 lvi._start_op=GetCurrentPos()+1;
320 lvi._pos=_vlocals.size();
321 _vlocals.push_back(lvi);
322 if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
327 SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
329 SQInteger locals=_vlocals.size();
331 if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){
339 SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
341 SQInteger outers = _outervalues.size();
342 for(SQInteger i = 0; i<outers; i++) {
343 if(_string(_outervalues[i]._name) == _string(name))
349 void SQFuncState::AddOuterValue(const SQObject &name)
353 pos = _parent->GetLocalVariable(name);
355 pos = _parent->GetOuterVariable(name);
357 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
362 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
366 _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global
369 void SQFuncState::AddParameter(const SQObject &name)
371 PushLocalVariable(name);
372 _parameters.push_back(name);
375 void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
377 if(_lastline!=line || force){
379 li._line=line;li._op=(GetCurrentPos()+1);
380 if(lineop)AddInstruction(_OP_LINE,0,line);
381 _lineinfos.push_back(li);
386 void SQFuncState::AddInstruction(SQInstruction &i)
388 SQInteger size = _instructions.size();
389 if(size > 0 && _optimization){ //simple optimizer
390 SQInstruction &pi = _instructions[size-1];//previous instruction
393 if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
394 pi.op = _OP_TAILCALL;
398 if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
400 pi._arg2 = (unsigned char)i._arg1;
408 if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
409 pi.op = _OP_PREPCALLK;
417 case _OP_APPENDARRAY:
418 if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
419 pi.op = _OP_APPENDARRAY;
422 pi._arg2 = MAX_FUNC_STACKSIZE;
423 pi._arg3 = MAX_FUNC_STACKSIZE;
428 if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))
431 _optimization = false;
435 if(pi.op == _OP_MOVE)
439 pi._arg3 = (unsigned char)i._arg1;
444 if(pi.op == _OP_LOAD && i._arg1 < 256) {
447 pi._arg3 = (unsigned char)i._arg1;
451 case _OP_EQ:case _OP_NE:
452 if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
458 pi._arg3 = MAX_FUNC_STACKSIZE;
463 if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
465 pi._arg1 = pi._arg1 + 1;
466 pi.op = _OP_LOADNULLS;
471 if(pi.op == _OP_LINE) {
472 _instructions.pop_back();
473 _lineinfos.pop_back();
478 _optimization = true;
479 _instructions.push_back(i);
482 SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
484 SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
485 _table(_strings)->NewSlot(ns,(SQInteger)1);
489 SQFunctionProto *SQFuncState::BuildProto()
491 SQFunctionProto *f=SQFunctionProto::Create();
492 f->_literals.resize(_nliterals);
493 SQObjectPtr refidx,key,val;
496 f->_stacksize = _stacksize;
497 f->_sourcename = _sourcename;
498 f->_bgenerator = _bgenerator;
501 while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
502 f->_literals[_integer(val)]=key;
506 f->_functions.resize(_functions.size());
507 f->_functions.copy(_functions);
508 f->_parameters.resize(_parameters.size());
509 f->_parameters.copy(_parameters);
510 f->_outervalues.resize(_outervalues.size());
511 f->_outervalues.copy(_outervalues);
512 f->_instructions.resize(_instructions.size());
513 f->_instructions.copy(_instructions);
514 f->_localvarinfos.resize(_localvarinfos.size());
515 f->_localvarinfos.copy(_localvarinfos);
516 f->_lineinfos.resize(_lineinfos.size());
517 f->_lineinfos.copy(_lineinfos);
518 f->_varparams = _varparams;
523 SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
525 SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
526 new (child) SQFuncState(ss,this,_errfunc,_errtarget);
527 _childstates.push_back(child);
531 void SQFuncState::PopChildState()
533 SQFuncState *child = _childstates.back();
534 sq_delete(child,SQFuncState);
535 _childstates.pop_back();
538 SQFuncState::~SQFuncState()
540 while(_childstates.size() > 0)