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 case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
84 default: scprintf(_SC("(%s %p)"),GetTypeName(o),_rawval(o));break; break; //shut up compiler
88 SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
91 _literals = SQTable::Create(ss,0);
92 _strings = SQTable::Create(ss,0);
107 void SQFuncState::Error(const SQChar *err)
109 _errfunc(_errtarget,err);
113 void SQFuncState::Dump(SQFunctionProto *func)
115 SQUnsignedInteger n=0,i;
117 scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
118 scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
119 scprintf(_SC("--------------------------------------------------------------------\n"));
120 scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
121 scprintf(_SC("-----LITERALS\n"));
122 SQObjectPtr refidx,key,val;
124 SQObjectPtrVec templiterals;
125 templiterals.resize(_nliterals);
126 while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
128 templiterals[_integer(val)]=key;
130 for(i=0;i<templiterals.size();i++){
131 scprintf(_SC("[%d] "),n);
132 DumpLiteral(templiterals[i]);
136 scprintf(_SC("-----PARAMS\n"));
138 scprintf(_SC("<<VARPARAMS>>\n"));
140 for(i=0;i<_parameters.size();i++){
141 scprintf(_SC("[%d] "),n);
142 DumpLiteral(_parameters[i]);
146 scprintf(_SC("-----LOCALS\n"));
147 for(si=0;si<func->_nlocalvarinfos;si++){
148 SQLocalVarInfo lvi=func->_localvarinfos[si];
149 scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
152 scprintf(_SC("-----LINE INFO\n"));
153 for(i=0;i<_lineinfos.size();i++){
154 SQLineInfo li=_lineinfos[i];
155 scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
158 scprintf(_SC("-----dump\n"));
160 for(i=0;i<_instructions.size();i++){
161 SQInstruction &inst=_instructions[i];
162 if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
164 SQInteger lidx = inst._arg1;
165 scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
166 if(lidx >= 0xFFFFFFFF)
167 scprintf(_SC("null"));
170 SQObjectPtr val,key,refo;
171 while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
176 if(inst.op != _OP_DLOAD) {
177 scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
180 scprintf(_SC(" %d "),inst._arg2);
182 if(lidx >= 0xFFFFFFFF)
183 scprintf(_SC("null"));
186 SQObjectPtr val,key,refo;
187 while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
195 else if(inst.op==_OP_LOADFLOAT) {
196 scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);
198 else if(inst.op==_OP_ARITH){
199 scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
202 scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
205 scprintf(_SC("-----\n"));
206 scprintf(_SC("stack size[%d]\n"),func->_stacksize);
207 scprintf(_SC("--------------------------------------------------------------------\n\n"));
211 SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
213 return GetConstant(SQObjectPtr(cons));
216 SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
218 return GetConstant(SQObjectPtr(cons));
221 SQInteger SQFuncState::GetConstant(const SQObject &cons)
224 if(!_table(_literals)->Get(cons,val))
227 _table(_literals)->NewSlot(cons,val);
229 if(_nliterals > MAX_LITERALS) {
231 Error(_SC("internal compiler error: too many literals"));
234 return _integer(val);
237 void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
239 _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
240 _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
241 _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
242 _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
245 void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
248 case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
249 case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
250 case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
251 case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
255 SQInteger SQFuncState::AllocStackPos()
257 SQInteger npos=_vlocals.size();
258 _vlocals.push_back(SQLocalVarInfo());
259 if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
260 if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
261 _stacksize=_vlocals.size();
266 SQInteger SQFuncState::PushTarget(SQInteger n)
269 _targetstack.push_back(n);
273 _targetstack.push_back(n);
277 SQInteger SQFuncState::GetUpTarget(SQInteger n){
278 return _targetstack[((_targetstack.size()-1)-n)];
281 SQInteger SQFuncState::TopTarget(){
282 return _targetstack.back();
284 SQInteger SQFuncState::PopTarget()
286 SQInteger npos=_targetstack.back();
287 SQLocalVarInfo t=_vlocals[_targetstack.back()];
288 if(type(t._name)==OT_NULL){
291 _targetstack.pop_back();
295 SQInteger SQFuncState::GetStackSize()
297 return _vlocals.size();
300 void SQFuncState::SetStackSize(SQInteger n)
302 SQInteger size=_vlocals.size();
305 SQLocalVarInfo lvi=_vlocals.back();
306 if(type(lvi._name)!=OT_NULL){
307 lvi._end_op=GetCurrentPos();
308 _localvarinfos.push_back(lvi);
314 bool SQFuncState::IsConstant(const SQObject &name,SQObject &e)
317 if(_table(_sharedstate->_consts)->Get(name,val)) {
324 bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
326 if(stkpos>=_vlocals.size())return false;
327 else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
331 SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
333 SQInteger pos=_vlocals.size();
336 lvi._start_op=GetCurrentPos()+1;
337 lvi._pos=_vlocals.size();
338 _vlocals.push_back(lvi);
339 if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
344 SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
346 SQInteger locals=_vlocals.size();
348 if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){
356 SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
358 SQInteger outers = _outervalues.size();
359 for(SQInteger i = 0; i<outers; i++) {
360 if(_string(_outervalues[i]._name) == _string(name))
366 void SQFuncState::AddOuterValue(const SQObject &name)
370 pos = _parent->GetLocalVariable(name);
372 pos = _parent->GetOuterVariable(name);
374 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
379 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
383 _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global
386 void SQFuncState::AddParameter(const SQObject &name)
388 PushLocalVariable(name);
389 _parameters.push_back(name);
392 void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
394 if(_lastline!=line || force){
396 li._line=line;li._op=(GetCurrentPos()+1);
397 if(lineop)AddInstruction(_OP_LINE,0,line);
398 _lineinfos.push_back(li);
403 void SQFuncState::AddInstruction(SQInstruction &i)
405 SQInteger size = _instructions.size();
406 if(size > 0 && _optimization){ //simple optimizer
407 SQInstruction &pi = _instructions[size-1];//previous instruction
410 if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
411 pi.op = _OP_TAILCALL;
415 if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
417 pi._arg2 = (unsigned char)i._arg1;
425 if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
426 pi.op = _OP_PREPCALLK;
434 case _OP_APPENDARRAY:
435 if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
436 pi.op = _OP_APPENDARRAY;
439 pi._arg2 = MAX_FUNC_STACKSIZE;
440 pi._arg3 = MAX_FUNC_STACKSIZE;
445 if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))
448 _optimization = false;
452 if(pi.op == _OP_MOVE)
456 pi._arg3 = (unsigned char)i._arg1;
461 if(pi.op == _OP_LOAD && i._arg1 < 256) {
464 pi._arg3 = (unsigned char)i._arg1;
468 case _OP_EQ:case _OP_NE:
469 if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
475 pi._arg3 = MAX_FUNC_STACKSIZE;
480 if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
482 pi._arg1 = pi._arg1 + 1;
483 pi.op = _OP_LOADNULLS;
488 if(pi.op == _OP_LINE) {
489 _instructions.pop_back();
490 _lineinfos.pop_back();
495 _optimization = true;
496 _instructions.push_back(i);
499 SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
501 SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
502 _table(_strings)->NewSlot(ns,(SQInteger)1);
506 SQObject SQFuncState::CreateTable()
508 SQObjectPtr nt(SQTable::Create(_sharedstate,0));
509 _table(_strings)->NewSlot(nt,(SQInteger)1);
513 SQFunctionProto *SQFuncState::BuildProto()
515 SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(),
516 _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
517 _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
519 SQObjectPtr refidx,key,val;
522 f->_stacksize = _stacksize;
523 f->_sourcename = _sourcename;
524 f->_bgenerator = _bgenerator;
527 while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
528 f->_literals[_integer(val)]=key;
532 for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
533 for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
534 for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
535 for(SQUnsignedInteger no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no];
536 for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no];
537 for(SQUnsignedInteger no = 0; no < _defaultparams.size(); no++) f->_defaultparams[no] = _defaultparams[no];
539 memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
541 f->_varparams = _varparams;
546 SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
548 SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
549 new (child) SQFuncState(ss,this,_errfunc,_errtarget);
550 _childstates.push_back(child);
554 void SQFuncState::PopChildState()
556 SQFuncState *child = _childstates.back();
557 sq_delete(child,SQFuncState);
558 _childstates.pop_back();
561 SQFuncState::~SQFuncState()
563 while(_childstates.size() > 0)