as_restore.cpp 132 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2015 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. //
  24. // as_restore.cpp
  25. //
  26. // Functions for saving and restoring module bytecode
  27. // asCRestore was originally written by Dennis Bollyn, [email protected]
  28. #include "as_config.h"
  29. #include "as_restore.h"
  30. #include "as_bytecode.h"
  31. #include "as_scriptobject.h"
  32. #include "as_texts.h"
  33. BEGIN_AS_NAMESPACE
  34. asCReader::asCReader(asCModule* _module, asIBinaryStream* _stream, asCScriptEngine* _engine)
  35. : module(_module), stream(_stream), engine(_engine)
  36. {
  37. error = false;
  38. bytesRead = 0;
  39. }
  40. void asCReader::ReadData(void *data, asUINT size)
  41. {
  42. asASSERT(size == 1 || size == 2 || size == 4 || size == 8);
  43. #if defined(AS_BIG_ENDIAN)
  44. for( asUINT n = 0; n < size; n++ )
  45. stream->Read(((asBYTE*)data)+n, 1);
  46. #else
  47. for( int n = size-1; n >= 0; n-- )
  48. stream->Read(((asBYTE*)data)+n, 1);
  49. #endif
  50. bytesRead += size;
  51. }
  52. int asCReader::Read(bool *wasDebugInfoStripped)
  53. {
  54. // Before starting the load, make sure that
  55. // any existing resources have been freed
  56. module->InternalReset();
  57. // Call the inner method to do the actual loading
  58. int r = ReadInner();
  59. if( r < 0 )
  60. {
  61. // Something went wrong while loading the bytecode, so we need
  62. // to clean-up whatever has been created during the process.
  63. // Make sure none of the loaded functions attempt to release
  64. // references that have not yet been increased
  65. asUINT i;
  66. for( i = 0; i < module->scriptFunctions.GetLength(); i++ )
  67. if( !dontTranslate.MoveTo(0, module->scriptFunctions[i]) )
  68. if( module->scriptFunctions[i]->scriptData )
  69. module->scriptFunctions[i]->scriptData->byteCode.SetLength(0);
  70. asCSymbolTable<asCGlobalProperty>::iterator it = module->scriptGlobals.List();
  71. for( ; it; it++ )
  72. if( (*it)->GetInitFunc() )
  73. if( (*it)->GetInitFunc()->scriptData )
  74. (*it)->GetInitFunc()->scriptData->byteCode.SetLength(0);
  75. module->InternalReset();
  76. }
  77. else
  78. {
  79. // Init system functions properly
  80. engine->PrepareEngine();
  81. // Initialize the global variables (unless requested not to)
  82. if( engine->ep.initGlobalVarsAfterBuild )
  83. r = module->ResetGlobalVars(0);
  84. if( wasDebugInfoStripped )
  85. *wasDebugInfoStripped = noDebugInfo;
  86. }
  87. return r;
  88. }
  89. int asCReader::Error(const char *msg)
  90. {
  91. // Don't write if it has already been reported an error earlier
  92. if( !error )
  93. {
  94. asCString str;
  95. str.Format(msg, bytesRead);
  96. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  97. error = true;
  98. }
  99. return asERROR;
  100. }
  101. int asCReader::ReadInner()
  102. {
  103. // This function will load each entity one by one from the stream.
  104. // If any error occurs, it will return to the caller who is
  105. // responsible for cleaning up the partially loaded entities.
  106. engine->deferValidationOfTemplateTypes = true;
  107. unsigned long i, count;
  108. asCScriptFunction* func;
  109. ReadData(&noDebugInfo, 1);
  110. // Read enums
  111. count = ReadEncodedUInt();
  112. module->enumTypes.Allocate(count, false);
  113. for( i = 0; i < count && !error; i++ )
  114. {
  115. asCObjectType *ot = asNEW(asCObjectType)(engine);
  116. if( ot == 0 )
  117. {
  118. error = true;
  119. return asOUT_OF_MEMORY;
  120. }
  121. ReadObjectTypeDeclaration(ot, 1);
  122. // If the type is shared then we should use the original if it exists
  123. bool sharedExists = false;
  124. if( ot->IsShared() )
  125. {
  126. for( asUINT n = 0; n < engine->sharedScriptTypes.GetLength(); n++ )
  127. {
  128. asCObjectType *t = engine->sharedScriptTypes[n];
  129. if( t &&
  130. t->IsShared() &&
  131. t->name == ot->name &&
  132. t->nameSpace == ot->nameSpace &&
  133. (t->flags & asOBJ_ENUM) )
  134. {
  135. asDELETE(ot, asCObjectType);
  136. ot = t;
  137. sharedExists = true;
  138. break;
  139. }
  140. }
  141. }
  142. if( sharedExists )
  143. {
  144. existingShared.Insert(ot, true);
  145. ot->AddRefInternal();
  146. }
  147. else
  148. {
  149. if( ot->IsShared() )
  150. {
  151. engine->sharedScriptTypes.PushLast(ot);
  152. ot->AddRefInternal();
  153. }
  154. // Set this module as the owner
  155. ot->module = module;
  156. }
  157. module->enumTypes.PushLast(ot);
  158. ReadObjectTypeDeclaration(ot, 2);
  159. }
  160. if( error ) return asERROR;
  161. // classTypes[]
  162. // First restore the structure names, then the properties
  163. count = ReadEncodedUInt();
  164. module->classTypes.Allocate(count, false);
  165. for( i = 0; i < count && !error; ++i )
  166. {
  167. asCObjectType *ot = asNEW(asCObjectType)(engine);
  168. if( ot == 0 )
  169. {
  170. error = true;
  171. return asOUT_OF_MEMORY;
  172. }
  173. ReadObjectTypeDeclaration(ot, 1);
  174. // If the type is shared, then we should use the original if it exists
  175. bool sharedExists = false;
  176. if( ot->IsShared() )
  177. {
  178. for( asUINT n = 0; n < engine->sharedScriptTypes.GetLength(); n++ )
  179. {
  180. asCObjectType *t = engine->sharedScriptTypes[n];
  181. if( t &&
  182. t->IsShared() &&
  183. t->name == ot->name &&
  184. t->nameSpace == ot->nameSpace &&
  185. t->IsInterface() == ot->IsInterface() )
  186. {
  187. asDELETE(ot, asCObjectType);
  188. ot = t;
  189. sharedExists = true;
  190. break;
  191. }
  192. }
  193. }
  194. if( sharedExists )
  195. {
  196. existingShared.Insert(ot, true);
  197. ot->AddRefInternal();
  198. }
  199. else
  200. {
  201. if( ot->IsShared() )
  202. {
  203. engine->sharedScriptTypes.PushLast(ot);
  204. ot->AddRefInternal();
  205. }
  206. // Set this module as the owner
  207. ot->module = module;
  208. }
  209. module->classTypes.PushLast(ot);
  210. }
  211. if( error ) return asERROR;
  212. // Read func defs
  213. count = ReadEncodedUInt();
  214. module->funcDefs.Allocate(count, false);
  215. for( i = 0; i < count && !error; i++ )
  216. {
  217. bool isNew;
  218. asCScriptFunction *func = ReadFunction(isNew, false, true);
  219. if( func )
  220. {
  221. module->funcDefs.PushLast(func);
  222. engine->funcDefs.PushLast(func);
  223. // TODO: clean up: This is also done by the builder. It should probably be moved to a method in the module
  224. // Check if there is another identical funcdef from another module and if so reuse that instead
  225. for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
  226. {
  227. asCScriptFunction *f2 = engine->funcDefs[n];
  228. if( f2 == 0 || func == f2 )
  229. continue;
  230. if( f2->name == func->name &&
  231. f2->nameSpace == func->nameSpace &&
  232. f2->IsSignatureExceptNameEqual(func) )
  233. {
  234. // Replace our funcdef for the existing one
  235. module->funcDefs[module->funcDefs.IndexOf(func)] = f2;
  236. f2->AddRefInternal();
  237. engine->funcDefs.RemoveValue(func);
  238. savedFunctions[savedFunctions.IndexOf(func)] = f2;
  239. func->ReleaseInternal();
  240. break;
  241. }
  242. }
  243. }
  244. else
  245. Error(TXT_INVALID_BYTECODE_d);
  246. }
  247. // Read interface methods
  248. for( i = 0; i < module->classTypes.GetLength() && !error; i++ )
  249. {
  250. if( module->classTypes[i]->IsInterface() )
  251. ReadObjectTypeDeclaration(module->classTypes[i], 2);
  252. }
  253. // Read class methods and behaviours
  254. for( i = 0; i < module->classTypes.GetLength() && !error; ++i )
  255. {
  256. if( !module->classTypes[i]->IsInterface() )
  257. ReadObjectTypeDeclaration(module->classTypes[i], 2);
  258. }
  259. // Read class properties
  260. for( i = 0; i < module->classTypes.GetLength() && !error; ++i )
  261. {
  262. if( !module->classTypes[i]->IsInterface() )
  263. ReadObjectTypeDeclaration(module->classTypes[i], 3);
  264. }
  265. if( error ) return asERROR;
  266. // Read typedefs
  267. count = ReadEncodedUInt();
  268. module->typeDefs.Allocate(count, false);
  269. for( i = 0; i < count && !error; i++ )
  270. {
  271. asCObjectType *ot = asNEW(asCObjectType)(engine);
  272. if( ot == 0 )
  273. {
  274. error = true;
  275. return asOUT_OF_MEMORY;
  276. }
  277. ReadObjectTypeDeclaration(ot, 1);
  278. ot->module = module;
  279. module->typeDefs.PushLast(ot);
  280. ReadObjectTypeDeclaration(ot, 2);
  281. }
  282. if( error ) return asERROR;
  283. // scriptGlobals[]
  284. count = ReadEncodedUInt();
  285. if( count && engine->ep.disallowGlobalVars )
  286. {
  287. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_GLOBAL_VARS_NOT_ALLOWED);
  288. Error(TXT_INVALID_BYTECODE_d);
  289. }
  290. module->scriptGlobals.Allocate(count, false);
  291. for( i = 0; i < count && !error; ++i )
  292. {
  293. ReadGlobalProperty();
  294. }
  295. // scriptFunctions[]
  296. count = ReadEncodedUInt();
  297. for( i = 0; i < count && !error; ++i )
  298. {
  299. size_t len = module->scriptFunctions.GetLength();
  300. bool isNew;
  301. func = ReadFunction(isNew);
  302. if( func == 0 )
  303. {
  304. Error(TXT_INVALID_BYTECODE_d);
  305. break;
  306. }
  307. // Is the function shared and was it created now?
  308. if( func->isShared && len != module->scriptFunctions.GetLength() )
  309. {
  310. // If the function already existed in another module, then
  311. // we need to replace it with previously existing one
  312. for( asUINT n = 0; n < engine->scriptFunctions.GetLength() && !error; n++ )
  313. {
  314. asCScriptFunction *realFunc = engine->scriptFunctions[n];
  315. if( realFunc &&
  316. realFunc != func &&
  317. realFunc->IsShared() &&
  318. realFunc->IsSignatureEqual(func) )
  319. {
  320. // Replace the recently created function with the pre-existing function
  321. module->scriptFunctions[module->scriptFunctions.GetLength()-1] = realFunc;
  322. realFunc->AddRefInternal();
  323. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  324. engine->RemoveScriptFunction(func);
  325. // Insert the function in the dontTranslate array
  326. dontTranslate.Insert(realFunc, true);
  327. // Release the function, but make sure nothing else is released
  328. func->id = 0;
  329. func->scriptData->byteCode.SetLength(0);
  330. func->ReleaseInternal();
  331. break;
  332. }
  333. }
  334. }
  335. }
  336. // globalFunctions[]
  337. count = ReadEncodedUInt();
  338. for( i = 0; i < count && !error; ++i )
  339. {
  340. bool isNew;
  341. func = ReadFunction(isNew, false, false);
  342. if( func )
  343. {
  344. // All the global functions were already loaded while loading the scriptFunctions, here
  345. // we're just re-reading the references to know which goes into the globalFunctions array
  346. asASSERT( !isNew );
  347. module->globalFunctions.Put(func);
  348. }
  349. else
  350. Error(TXT_INVALID_BYTECODE_d);
  351. }
  352. if( error ) return asERROR;
  353. // bindInformations[]
  354. count = ReadEncodedUInt();
  355. module->bindInformations.Allocate(count, false);
  356. for( i = 0; i < count && !error; ++i )
  357. {
  358. sBindInfo *info = asNEW(sBindInfo);
  359. if( info == 0 )
  360. {
  361. error = true;
  362. return asOUT_OF_MEMORY;
  363. }
  364. bool isNew;
  365. info->importedFunctionSignature = ReadFunction(isNew, false, false);
  366. if( info->importedFunctionSignature == 0 )
  367. {
  368. Error(TXT_INVALID_BYTECODE_d);
  369. break;
  370. }
  371. if( engine->freeImportedFunctionIdxs.GetLength() )
  372. {
  373. int id = engine->freeImportedFunctionIdxs.PopLast();
  374. info->importedFunctionSignature->id = int(FUNC_IMPORTED + id);
  375. engine->importedFunctions[id] = info;
  376. }
  377. else
  378. {
  379. info->importedFunctionSignature->id = int(FUNC_IMPORTED + engine->importedFunctions.GetLength());
  380. engine->importedFunctions.PushLast(info);
  381. }
  382. ReadString(&info->importFromModule);
  383. info->boundFunctionId = -1;
  384. module->bindInformations.PushLast(info);
  385. }
  386. if( error ) return asERROR;
  387. // usedTypes[]
  388. count = ReadEncodedUInt();
  389. usedTypes.Allocate(count, false);
  390. for( i = 0; i < count && !error; ++i )
  391. {
  392. asCObjectType *ot = ReadObjectType();
  393. usedTypes.PushLast(ot);
  394. }
  395. // usedTypeIds[]
  396. if( !error )
  397. ReadUsedTypeIds();
  398. // usedFunctions[]
  399. if( !error )
  400. ReadUsedFunctions();
  401. // usedGlobalProperties[]
  402. if( !error )
  403. ReadUsedGlobalProps();
  404. // usedStringConstants[]
  405. if( !error )
  406. ReadUsedStringConstants();
  407. // usedObjectProperties
  408. if( !error )
  409. ReadUsedObjectProps();
  410. // Validate the template types
  411. if( !error )
  412. {
  413. for( i = 0; i < usedTypes.GetLength() && !error; i++ )
  414. {
  415. if( !(usedTypes[i]->flags & asOBJ_TEMPLATE) ||
  416. !usedTypes[i]->beh.templateCallback )
  417. continue;
  418. bool dontGarbageCollect = false;
  419. asCScriptFunction *callback = engine->scriptFunctions[usedTypes[i]->beh.templateCallback];
  420. if( !engine->CallGlobalFunctionRetBool(usedTypes[i], &dontGarbageCollect, callback->sysFuncIntf, callback) )
  421. {
  422. asCString sub = usedTypes[i]->templateSubTypes[0].Format(usedTypes[i]->nameSpace);
  423. for( asUINT n = 1; n < usedTypes[i]->templateSubTypes.GetLength(); n++ )
  424. {
  425. sub += ",";
  426. sub += usedTypes[i]->templateSubTypes[n].Format(usedTypes[i]->nameSpace);
  427. }
  428. asCString str;
  429. str.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, usedTypes[i]->name.AddressOf(), sub.AddressOf());
  430. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  431. Error(TXT_INVALID_BYTECODE_d);
  432. }
  433. else
  434. {
  435. // If the callback said this template instance won't be garbage collected then remove the flag
  436. if( dontGarbageCollect )
  437. usedTypes[i]->flags &= ~asOBJ_GC;
  438. }
  439. }
  440. }
  441. engine->deferValidationOfTemplateTypes = false;
  442. if( error ) return asERROR;
  443. // Update the loaded bytecode to point to the correct types, property offsets,
  444. // function ids, etc. This is basically a linking stage.
  445. for( i = 0; i < module->scriptFunctions.GetLength() && !error; i++ )
  446. if( module->scriptFunctions[i]->funcType == asFUNC_SCRIPT )
  447. TranslateFunction(module->scriptFunctions[i]);
  448. asCSymbolTable<asCGlobalProperty>::iterator globIt = module->scriptGlobals.List();
  449. while( globIt && !error )
  450. {
  451. asCScriptFunction *initFunc = (*globIt)->GetInitFunc();
  452. if( initFunc )
  453. TranslateFunction(initFunc);
  454. globIt++;
  455. }
  456. if( error ) return asERROR;
  457. // Add references for all functions (except for the pre-existing shared code)
  458. for( i = 0; i < module->scriptFunctions.GetLength(); i++ )
  459. if( !dontTranslate.MoveTo(0, module->scriptFunctions[i]) )
  460. module->scriptFunctions[i]->AddReferences();
  461. globIt = module->scriptGlobals.List();
  462. while( globIt )
  463. {
  464. asCScriptFunction *initFunc = (*globIt)->GetInitFunc();
  465. if( initFunc )
  466. initFunc->AddReferences();
  467. globIt++;
  468. }
  469. return error ? asERROR : asSUCCESS;
  470. }
  471. void asCReader::ReadUsedStringConstants()
  472. {
  473. asCString str;
  474. asUINT count;
  475. count = ReadEncodedUInt();
  476. usedStringConstants.Allocate(count, false);
  477. for( asUINT i = 0; i < count; ++i )
  478. {
  479. ReadString(&str);
  480. usedStringConstants.PushLast(engine->AddConstantString(str.AddressOf(), str.GetLength()));
  481. }
  482. }
  483. void asCReader::ReadUsedFunctions()
  484. {
  485. asUINT count;
  486. count = ReadEncodedUInt();
  487. usedFunctions.SetLength(count);
  488. if( usedFunctions.GetLength() != count )
  489. {
  490. // Out of memory
  491. error = true;
  492. return;
  493. }
  494. memset(usedFunctions.AddressOf(), 0, sizeof(asCScriptFunction *)*count);
  495. for( asUINT n = 0; n < usedFunctions.GetLength(); n++ )
  496. {
  497. char c;
  498. // Read the data to be able to uniquely identify the function
  499. // Is the function from the module or the application?
  500. ReadData(&c, 1);
  501. if( c == 'n' )
  502. {
  503. // Null function pointer
  504. usedFunctions[n] = 0;
  505. }
  506. else
  507. {
  508. asCScriptFunction func(engine, c == 'm' ? module : 0, asFUNC_DUMMY);
  509. ReadFunctionSignature(&func);
  510. if( error )
  511. {
  512. func.funcType = asFUNC_DUMMY;
  513. return;
  514. }
  515. // Find the correct function
  516. if( c == 'm' )
  517. {
  518. if( func.funcType == asFUNC_IMPORTED )
  519. {
  520. for( asUINT i = 0; i < module->bindInformations.GetLength(); i++ )
  521. {
  522. asCScriptFunction *f = module->bindInformations[i]->importedFunctionSignature;
  523. if( !func.IsSignatureEqual(f) ||
  524. func.objectType != f->objectType ||
  525. func.funcType != f->funcType ||
  526. func.nameSpace != f->nameSpace )
  527. continue;
  528. usedFunctions[n] = f;
  529. break;
  530. }
  531. }
  532. else
  533. {
  534. for( asUINT i = 0; i < module->scriptFunctions.GetLength(); i++ )
  535. {
  536. asCScriptFunction *f = module->scriptFunctions[i];
  537. if( !func.IsSignatureEqual(f) ||
  538. func.objectType != f->objectType ||
  539. func.funcType != f->funcType ||
  540. func.nameSpace != f->nameSpace )
  541. continue;
  542. usedFunctions[n] = f;
  543. break;
  544. }
  545. }
  546. }
  547. else
  548. {
  549. for( asUINT i = 0; i < engine->scriptFunctions.GetLength(); i++ )
  550. {
  551. asCScriptFunction *f = engine->scriptFunctions[i];
  552. if( f == 0 ||
  553. !func.IsSignatureEqual(f) ||
  554. func.objectType != f->objectType ||
  555. func.nameSpace != f->nameSpace )
  556. continue;
  557. usedFunctions[n] = f;
  558. break;
  559. }
  560. }
  561. // Set the type to dummy so it won't try to release the id
  562. func.funcType = asFUNC_DUMMY;
  563. if( usedFunctions[n] == 0 )
  564. {
  565. Error(TXT_INVALID_BYTECODE_d);
  566. return;
  567. }
  568. }
  569. }
  570. }
  571. void asCReader::ReadFunctionSignature(asCScriptFunction *func)
  572. {
  573. asUINT i, count;
  574. asCDataType dt;
  575. int num;
  576. ReadString(&func->name);
  577. if( func->name == DELEGATE_FACTORY )
  578. {
  579. // It's not necessary to read anymore, everything is known
  580. asCScriptFunction *f = engine->registeredGlobalFuncs.GetFirst(engine->nameSpaces[0], DELEGATE_FACTORY);
  581. asASSERT( f );
  582. func->returnType = f->returnType;
  583. func->parameterTypes = f->parameterTypes;
  584. func->inOutFlags = f->inOutFlags;
  585. func->funcType = f->funcType;
  586. func->defaultArgs = f->defaultArgs;
  587. func->nameSpace = f->nameSpace;
  588. return;
  589. }
  590. ReadDataType(&func->returnType);
  591. count = ReadEncodedUInt();
  592. if( count > 256 )
  593. {
  594. // Too many arguments, must be something wrong in the file
  595. Error(TXT_INVALID_BYTECODE_d);
  596. return;
  597. }
  598. func->parameterTypes.Allocate(count, false);
  599. for( i = 0; i < count; ++i )
  600. {
  601. ReadDataType(&dt);
  602. func->parameterTypes.PushLast(dt);
  603. }
  604. func->inOutFlags.SetLength(func->parameterTypes.GetLength());
  605. if( func->inOutFlags.GetLength() != func->parameterTypes.GetLength() )
  606. {
  607. // Out of memory
  608. error = true;
  609. return;
  610. }
  611. memset(func->inOutFlags.AddressOf(), 0, sizeof(asETypeModifiers)*func->inOutFlags.GetLength());
  612. count = ReadEncodedUInt();
  613. if( count > func->parameterTypes.GetLength() )
  614. {
  615. // Cannot be more than the number of arguments
  616. Error(TXT_INVALID_BYTECODE_d);
  617. return;
  618. }
  619. for( i = 0; i < count; ++i )
  620. {
  621. num = ReadEncodedUInt();
  622. func->inOutFlags[i] = static_cast<asETypeModifiers>(num);
  623. }
  624. func->funcType = (asEFuncType)ReadEncodedUInt();
  625. // Read the default args, from last to first
  626. count = ReadEncodedUInt();
  627. if( count > func->parameterTypes.GetLength() )
  628. {
  629. // Cannot be more than the number of arguments
  630. Error(TXT_INVALID_BYTECODE_d);
  631. return;
  632. }
  633. if( count )
  634. {
  635. func->defaultArgs.SetLength(func->parameterTypes.GetLength());
  636. if( func->defaultArgs.GetLength() != func->parameterTypes.GetLength() )
  637. {
  638. // Out of memory
  639. error = true;
  640. return;
  641. }
  642. memset(func->defaultArgs.AddressOf(), 0, sizeof(asCString*)*func->defaultArgs.GetLength());
  643. for( i = 0; i < count; i++ )
  644. {
  645. asCString *str = asNEW(asCString);
  646. if( str == 0 )
  647. {
  648. // Out of memory
  649. error = true;
  650. return;
  651. }
  652. func->defaultArgs[func->defaultArgs.GetLength()-1-i] = str;
  653. ReadString(str);
  654. }
  655. }
  656. func->objectType = ReadObjectType();
  657. if( func->objectType )
  658. {
  659. func->objectType->AddRefInternal();
  660. asBYTE b;
  661. ReadData(&b, 1);
  662. func->isReadOnly = (b & 1) ? true : false;
  663. func->isPrivate = (b & 2) ? true : false;
  664. func->isProtected = (b & 4) ? true : false;
  665. func->nameSpace = engine->nameSpaces[0];
  666. }
  667. else
  668. {
  669. asCString ns;
  670. ReadString(&ns);
  671. func->nameSpace = engine->AddNameSpace(ns.AddressOf());
  672. }
  673. }
  674. asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool addToEngine, bool addToGC)
  675. {
  676. isNew = false;
  677. if( error ) return 0;
  678. char c;
  679. ReadData(&c, 1);
  680. if( c == '\0' )
  681. {
  682. // There is no function, so return a null pointer
  683. return 0;
  684. }
  685. if( c == 'r' )
  686. {
  687. // This is a reference to a previously saved function
  688. asUINT index = ReadEncodedUInt();
  689. if( index < savedFunctions.GetLength() )
  690. return savedFunctions[index];
  691. else
  692. {
  693. Error(TXT_INVALID_BYTECODE_d);
  694. return 0;
  695. }
  696. }
  697. // Load the new function
  698. isNew = true;
  699. asCScriptFunction *func = asNEW(asCScriptFunction)(engine,0,asFUNC_DUMMY);
  700. if( func == 0 )
  701. {
  702. // Out of memory
  703. error = true;
  704. return 0;
  705. }
  706. savedFunctions.PushLast(func);
  707. int i, count;
  708. asCDataType dt;
  709. int num;
  710. ReadFunctionSignature(func);
  711. if( error )
  712. {
  713. func->DestroyHalfCreated();
  714. return 0;
  715. }
  716. if( func->funcType == asFUNC_SCRIPT )
  717. {
  718. func->AllocateScriptFunctionData();
  719. if( func->scriptData == 0 )
  720. {
  721. // Out of memory
  722. error = true;
  723. func->DestroyHalfCreated();
  724. return 0;
  725. }
  726. if( addToGC && !addToModule )
  727. engine->gc.AddScriptObjectToGC(func, &engine->functionBehaviours);
  728. ReadByteCode(func);
  729. func->scriptData->variableSpace = ReadEncodedUInt();
  730. count = ReadEncodedUInt();
  731. func->scriptData->objVariablePos.Allocate(count, false);
  732. func->scriptData->objVariableTypes.Allocate(count, false);
  733. func->scriptData->funcVariableTypes.Allocate(count, false);
  734. for( i = 0; i < count; ++i )
  735. {
  736. func->scriptData->objVariableTypes.PushLast(ReadObjectType());
  737. asUINT idx = ReadEncodedUInt();
  738. func->scriptData->funcVariableTypes.PushLast((asCScriptFunction*)(asPWORD)idx);
  739. num = ReadEncodedUInt();
  740. func->scriptData->objVariablePos.PushLast(num);
  741. if( error )
  742. {
  743. // No need to continue (the error has already been reported before)
  744. func->DestroyHalfCreated();
  745. return 0;
  746. }
  747. }
  748. if( count > 0 )
  749. func->scriptData->objVariablesOnHeap = ReadEncodedUInt();
  750. else
  751. func->scriptData->objVariablesOnHeap = 0;
  752. int length = ReadEncodedUInt();
  753. func->scriptData->objVariableInfo.SetLength(length);
  754. for( i = 0; i < length; ++i )
  755. {
  756. func->scriptData->objVariableInfo[i].programPos = ReadEncodedUInt();
  757. func->scriptData->objVariableInfo[i].variableOffset = ReadEncodedUInt();
  758. func->scriptData->objVariableInfo[i].option = ReadEncodedUInt();
  759. }
  760. if( !noDebugInfo )
  761. {
  762. length = ReadEncodedUInt();
  763. func->scriptData->lineNumbers.SetLength(length);
  764. if( int(func->scriptData->lineNumbers.GetLength()) != length )
  765. {
  766. // Out of memory
  767. error = true;
  768. func->DestroyHalfCreated();
  769. return 0;
  770. }
  771. for( i = 0; i < length; ++i )
  772. func->scriptData->lineNumbers[i] = ReadEncodedUInt();
  773. // Read the array of script sections
  774. length = ReadEncodedUInt();
  775. func->scriptData->sectionIdxs.SetLength(length);
  776. if( int(func->scriptData->sectionIdxs.GetLength()) != length )
  777. {
  778. // Out of memory
  779. error = true;
  780. func->DestroyHalfCreated();
  781. return 0;
  782. }
  783. for( i = 0; i < length; ++i )
  784. {
  785. if( (i & 1) == 0 )
  786. func->scriptData->sectionIdxs[i] = ReadEncodedUInt();
  787. else
  788. {
  789. asCString str;
  790. ReadString(&str);
  791. func->scriptData->sectionIdxs[i] = engine->GetScriptSectionNameIndex(str.AddressOf());
  792. }
  793. }
  794. }
  795. // Read the variable information
  796. if( !noDebugInfo )
  797. {
  798. length = ReadEncodedUInt();
  799. func->scriptData->variables.Allocate(length, false);
  800. for( i = 0; i < length; i++ )
  801. {
  802. asSScriptVariable *var = asNEW(asSScriptVariable);
  803. if( var == 0 )
  804. {
  805. // Out of memory
  806. error = true;
  807. func->DestroyHalfCreated();
  808. return 0;
  809. }
  810. func->scriptData->variables.PushLast(var);
  811. var->declaredAtProgramPos = ReadEncodedUInt();
  812. var->stackOffset = ReadEncodedUInt();
  813. ReadString(&var->name);
  814. ReadDataType(&var->type);
  815. if( error )
  816. {
  817. // No need to continue (the error has already been reported before)
  818. func->DestroyHalfCreated();
  819. return 0;
  820. }
  821. }
  822. }
  823. char bits;
  824. ReadData(&bits, 1);
  825. func->isShared = bits & 1 ? true : false;
  826. func->dontCleanUpOnException = bits & 2 ? true : false;
  827. // Read script section name
  828. if( !noDebugInfo )
  829. {
  830. asCString name;
  831. ReadString(&name);
  832. func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(name.AddressOf());
  833. func->scriptData->declaredAt = ReadEncodedUInt();
  834. }
  835. // Read parameter names
  836. if( !noDebugInfo )
  837. {
  838. asUINT count = asUINT(ReadEncodedUInt64());
  839. if( count > func->parameterTypes.GetLength() )
  840. {
  841. error = true;
  842. func->DestroyHalfCreated();
  843. return 0;
  844. }
  845. func->parameterNames.SetLength(count);
  846. for( asUINT n = 0; n < count; n++ )
  847. ReadString(&func->parameterNames[n]);
  848. }
  849. }
  850. else if( func->funcType == asFUNC_VIRTUAL || func->funcType == asFUNC_INTERFACE )
  851. {
  852. func->vfTableIdx = ReadEncodedUInt();
  853. }
  854. if( addToModule )
  855. {
  856. // The refCount is already 1
  857. module->scriptFunctions.PushLast(func);
  858. func->module = module;
  859. }
  860. if( addToEngine )
  861. {
  862. func->id = engine->GetNextScriptFunctionId();
  863. engine->AddScriptFunction(func);
  864. }
  865. if( func->objectType )
  866. func->ComputeSignatureId();
  867. return func;
  868. }
  869. void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase)
  870. {
  871. if( phase == 1 )
  872. {
  873. // Read the initial attributes
  874. ReadString(&ot->name);
  875. ReadData(&ot->flags, 4);
  876. ot->size = ReadEncodedUInt();
  877. asCString ns;
  878. ReadString(&ns);
  879. ot->nameSpace = engine->AddNameSpace(ns.AddressOf());
  880. // Reset the size of script classes, since it will be recalculated as properties are added
  881. if( (ot->flags & asOBJ_SCRIPT_OBJECT) && ot->size != 0 )
  882. ot->size = sizeof(asCScriptObject);
  883. // Use the default script class behaviours
  884. ot->beh = engine->scriptTypeBehaviours.beh;
  885. ot->beh.construct = 0;
  886. ot->beh.factory = 0;
  887. ot->beh.constructors.PopLast(); // These will be read from the file
  888. ot->beh.factories.PopLast(); // These will be read from the file
  889. engine->scriptFunctions[ot->beh.addref]->AddRefInternal();
  890. engine->scriptFunctions[ot->beh.release]->AddRefInternal();
  891. engine->scriptFunctions[ot->beh.gcEnumReferences]->AddRefInternal();
  892. engine->scriptFunctions[ot->beh.gcGetFlag]->AddRefInternal();
  893. engine->scriptFunctions[ot->beh.gcGetRefCount]->AddRefInternal();
  894. engine->scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRefInternal();
  895. engine->scriptFunctions[ot->beh.gcSetFlag]->AddRefInternal();
  896. engine->scriptFunctions[ot->beh.copy]->AddRefInternal();
  897. // TODO: weak: Should not do this if the class has been declared with 'noweak'
  898. engine->scriptFunctions[ot->beh.getWeakRefFlag]->AddRefInternal();
  899. }
  900. else if( phase == 2 )
  901. {
  902. if( ot->flags & asOBJ_ENUM )
  903. {
  904. int count = ReadEncodedUInt();
  905. bool sharedExists = existingShared.MoveTo(0, ot);
  906. if( !sharedExists )
  907. {
  908. ot->enumValues.Allocate(count, false);
  909. for( int n = 0; n < count; n++ )
  910. {
  911. asSEnumValue *e = asNEW(asSEnumValue);
  912. if( e == 0 )
  913. {
  914. // Out of memory
  915. error = true;
  916. return;
  917. }
  918. ReadString(&e->name);
  919. ReadData(&e->value, 4); // TODO: Should be encoded
  920. ot->enumValues.PushLast(e);
  921. }
  922. }
  923. else
  924. {
  925. // Verify that the enum values exists in the original
  926. asCString name;
  927. int value;
  928. for( int n = 0; n < count; n++ )
  929. {
  930. ReadString(&name);
  931. ReadData(&value, 4); // TODO: Should be encoded
  932. bool found = false;
  933. for( asUINT e = 0; e < ot->enumValues.GetLength(); e++ )
  934. {
  935. if( ot->enumValues[e]->name == name &&
  936. ot->enumValues[e]->value == value )
  937. {
  938. found = true;
  939. break;
  940. }
  941. }
  942. if( !found )
  943. {
  944. asCString str;
  945. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  946. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  947. Error(TXT_INVALID_BYTECODE_d);
  948. }
  949. }
  950. }
  951. }
  952. else if( ot->flags & asOBJ_TYPEDEF )
  953. {
  954. eTokenType t = (eTokenType)ReadEncodedUInt();
  955. ot->templateSubTypes.PushLast(asCDataType::CreatePrimitive(t, false));
  956. }
  957. else
  958. {
  959. // If the type is shared and pre-existing, we should just
  960. // validate that the loaded methods match the original
  961. bool sharedExists = existingShared.MoveTo(0, ot);
  962. if( sharedExists )
  963. {
  964. asCObjectType *dt = ReadObjectType();
  965. if( ot->derivedFrom != dt )
  966. {
  967. asCString str;
  968. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  969. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  970. Error(TXT_INVALID_BYTECODE_d);
  971. }
  972. }
  973. else
  974. {
  975. ot->derivedFrom = ReadObjectType();
  976. if( ot->derivedFrom )
  977. ot->derivedFrom->AddRefInternal();
  978. }
  979. // interfaces[] / interfaceVFTOffsets[]
  980. int size = ReadEncodedUInt();
  981. if( sharedExists )
  982. {
  983. for( int n = 0; n < size; n++ )
  984. {
  985. asCObjectType *intf = ReadObjectType();
  986. ReadEncodedUInt();
  987. if( !ot->Implements(intf) )
  988. {
  989. asCString str;
  990. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  991. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  992. Error(TXT_INVALID_BYTECODE_d);
  993. }
  994. }
  995. }
  996. else
  997. {
  998. ot->interfaces.Allocate(size, false);
  999. ot->interfaceVFTOffsets.Allocate(size, false);
  1000. for( int n = 0; n < size; n++ )
  1001. {
  1002. asCObjectType *intf = ReadObjectType();
  1003. ot->interfaces.PushLast(intf);
  1004. asUINT offset = ReadEncodedUInt();
  1005. ot->interfaceVFTOffsets.PushLast(offset);
  1006. }
  1007. }
  1008. // behaviours
  1009. if( !ot->IsInterface() && ot->flags != asOBJ_TYPEDEF && ot->flags != asOBJ_ENUM )
  1010. {
  1011. bool isNew;
  1012. asCScriptFunction *func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
  1013. if( sharedExists )
  1014. {
  1015. // Find the real function in the object, and update the savedFunctions array
  1016. asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.destruct);
  1017. if( (realFunc == 0 && func == 0) || realFunc->IsSignatureEqual(func) )
  1018. {
  1019. // If the function is not the last, then the substitution has already occurred before
  1020. if( func && savedFunctions[savedFunctions.GetLength()-1] == func )
  1021. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  1022. }
  1023. else
  1024. {
  1025. asCString str;
  1026. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  1027. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1028. Error(TXT_INVALID_BYTECODE_d);
  1029. }
  1030. if( func )
  1031. {
  1032. if( isNew )
  1033. {
  1034. // Destroy the function without releasing any references
  1035. func->id = 0;
  1036. func->scriptData->byteCode.SetLength(0);
  1037. func->ReleaseInternal();
  1038. }
  1039. module->scriptFunctions.PushLast(realFunc);
  1040. realFunc->AddRefInternal();
  1041. dontTranslate.Insert(realFunc, true);
  1042. }
  1043. }
  1044. else
  1045. {
  1046. if( func )
  1047. {
  1048. ot->beh.destruct = func->id;
  1049. func->AddRefInternal();
  1050. }
  1051. else
  1052. ot->beh.destruct = 0;
  1053. }
  1054. size = ReadEncodedUInt();
  1055. for( int n = 0; n < size; n++ )
  1056. {
  1057. bool isNew;
  1058. asCScriptFunction *func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
  1059. if( func )
  1060. {
  1061. if( sharedExists )
  1062. {
  1063. // Find the real function in the object, and update the savedFunctions array
  1064. bool found = false;
  1065. for( asUINT n = 0; n < ot->beh.constructors.GetLength(); n++ )
  1066. {
  1067. asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.constructors[n]);
  1068. if( realFunc->IsSignatureEqual(func) )
  1069. {
  1070. // If the function is not the last, then the substitution has already occurred before
  1071. if( savedFunctions[savedFunctions.GetLength()-1] == func )
  1072. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  1073. found = true;
  1074. module->scriptFunctions.PushLast(realFunc);
  1075. realFunc->AddRefInternal();
  1076. dontTranslate.Insert(realFunc, true);
  1077. break;
  1078. }
  1079. }
  1080. if( !found )
  1081. {
  1082. asCString str;
  1083. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  1084. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1085. Error(TXT_INVALID_BYTECODE_d);
  1086. }
  1087. if( isNew )
  1088. {
  1089. // Destroy the function without releasing any references
  1090. func->id = 0;
  1091. func->scriptData->byteCode.SetLength(0);
  1092. func->ReleaseInternal();
  1093. }
  1094. }
  1095. else
  1096. {
  1097. ot->beh.constructors.PushLast(func->id);
  1098. func->AddRefInternal();
  1099. if( func->parameterTypes.GetLength() == 0 )
  1100. ot->beh.construct = func->id;
  1101. }
  1102. }
  1103. else
  1104. {
  1105. Error(TXT_INVALID_BYTECODE_d);
  1106. }
  1107. func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
  1108. if( func )
  1109. {
  1110. if( sharedExists )
  1111. {
  1112. // Find the real function in the object, and update the savedFunctions array
  1113. bool found = false;
  1114. for( asUINT n = 0; n < ot->beh.factories.GetLength(); n++ )
  1115. {
  1116. asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.factories[n]);
  1117. if( realFunc->IsSignatureEqual(func) )
  1118. {
  1119. // If the function is not the last, then the substitution has already occurred before
  1120. if( savedFunctions[savedFunctions.GetLength()-1] == func )
  1121. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  1122. found = true;
  1123. module->scriptFunctions.PushLast(realFunc);
  1124. realFunc->AddRefInternal();
  1125. dontTranslate.Insert(realFunc, true);
  1126. break;
  1127. }
  1128. }
  1129. if( !found )
  1130. {
  1131. asCString str;
  1132. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  1133. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1134. Error(TXT_INVALID_BYTECODE_d);
  1135. }
  1136. if( isNew )
  1137. {
  1138. // Destroy the function without releasing any references
  1139. func->id = 0;
  1140. func->scriptData->byteCode.SetLength(0);
  1141. func->ReleaseInternal();
  1142. }
  1143. }
  1144. else
  1145. {
  1146. ot->beh.factories.PushLast(func->id);
  1147. func->AddRefInternal();
  1148. if( func->parameterTypes.GetLength() == 0 )
  1149. ot->beh.factory = func->id;
  1150. }
  1151. }
  1152. else
  1153. {
  1154. Error(TXT_INVALID_BYTECODE_d);
  1155. }
  1156. }
  1157. }
  1158. // methods[]
  1159. size = ReadEncodedUInt();
  1160. int n;
  1161. for( n = 0; n < size; n++ )
  1162. {
  1163. bool isNew;
  1164. asCScriptFunction *func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
  1165. if( func )
  1166. {
  1167. if( sharedExists )
  1168. {
  1169. // Find the real function in the object, and update the savedFunctions array
  1170. bool found = false;
  1171. for( asUINT n = 0; n < ot->methods.GetLength(); n++ )
  1172. {
  1173. asCScriptFunction *realFunc = engine->GetScriptFunction(ot->methods[n]);
  1174. if( realFunc->IsSignatureEqual(func) )
  1175. {
  1176. // If the function is not the last, then the substitution has already occurred before
  1177. if( savedFunctions[savedFunctions.GetLength()-1] == func )
  1178. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  1179. found = true;
  1180. module->scriptFunctions.PushLast(realFunc);
  1181. realFunc->AddRefInternal();
  1182. dontTranslate.Insert(realFunc, true);
  1183. break;
  1184. }
  1185. }
  1186. if( !found )
  1187. {
  1188. asCString str;
  1189. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  1190. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1191. Error(TXT_INVALID_BYTECODE_d);
  1192. }
  1193. if( isNew )
  1194. {
  1195. // Destroy the function without releasing any references
  1196. func->id = 0;
  1197. if( func->scriptData )
  1198. func->scriptData->byteCode.SetLength(0);
  1199. func->ReleaseInternal();
  1200. }
  1201. }
  1202. else
  1203. {
  1204. // If the method is the assignment operator we need to replace the default implementation
  1205. if( func->name == "opAssign" && func->parameterTypes.GetLength() == 1 &&
  1206. func->parameterTypes[0].GetObjectType() == func->objectType &&
  1207. (func->inOutFlags[0] & asTM_INREF) )
  1208. {
  1209. engine->scriptFunctions[ot->beh.copy]->ReleaseInternal();
  1210. ot->beh.copy = func->id;
  1211. func->AddRefInternal();
  1212. }
  1213. ot->methods.PushLast(func->id);
  1214. func->AddRefInternal();
  1215. }
  1216. }
  1217. else
  1218. {
  1219. Error(TXT_INVALID_BYTECODE_d);
  1220. }
  1221. }
  1222. // virtualFunctionTable[]
  1223. size = ReadEncodedUInt();
  1224. for( n = 0; n < size; n++ )
  1225. {
  1226. bool isNew;
  1227. asCScriptFunction *func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
  1228. if( func )
  1229. {
  1230. if( sharedExists )
  1231. {
  1232. // Find the real function in the object, and update the savedFunctions array
  1233. bool found = false;
  1234. for( asUINT n = 0; n < ot->virtualFunctionTable.GetLength(); n++ )
  1235. {
  1236. asCScriptFunction *realFunc = ot->virtualFunctionTable[n];
  1237. if( realFunc->IsSignatureEqual(func) )
  1238. {
  1239. // If the function is not the last, then the substitution has already occurred before
  1240. if( savedFunctions[savedFunctions.GetLength()-1] == func )
  1241. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  1242. found = true;
  1243. module->scriptFunctions.PushLast(realFunc);
  1244. realFunc->AddRefInternal();
  1245. dontTranslate.Insert(realFunc, true);
  1246. break;
  1247. }
  1248. }
  1249. if( !found )
  1250. {
  1251. asCString str;
  1252. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  1253. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1254. Error(TXT_INVALID_BYTECODE_d);
  1255. }
  1256. if( isNew )
  1257. {
  1258. // Destroy the function without releasing any references
  1259. func->id = 0;
  1260. if( func->scriptData )
  1261. func->scriptData->byteCode.SetLength(0);
  1262. func->ReleaseInternal();
  1263. }
  1264. }
  1265. else
  1266. {
  1267. ot->virtualFunctionTable.PushLast(func);
  1268. func->AddRefInternal();
  1269. }
  1270. }
  1271. else
  1272. {
  1273. Error(TXT_INVALID_BYTECODE_d);
  1274. }
  1275. }
  1276. }
  1277. }
  1278. else if( phase == 3 )
  1279. {
  1280. // properties[]
  1281. asUINT size = ReadEncodedUInt();
  1282. for( asUINT n = 0; n < size; n++ )
  1283. ReadObjectProperty(ot);
  1284. }
  1285. }
  1286. asWORD asCReader::ReadEncodedUInt16()
  1287. {
  1288. asDWORD dw = ReadEncodedUInt();
  1289. if( (dw>>16) != 0 && (dw>>16) != 0xFFFF )
  1290. {
  1291. Error(TXT_INVALID_BYTECODE_d);
  1292. }
  1293. return asWORD(dw & 0xFFFF);
  1294. }
  1295. asUINT asCReader::ReadEncodedUInt()
  1296. {
  1297. asQWORD qw = ReadEncodedUInt64();
  1298. if( (qw>>32) != 0 && (qw>>32) != 0xFFFFFFFF )
  1299. {
  1300. Error(TXT_INVALID_BYTECODE_d);
  1301. }
  1302. return asUINT(qw & 0xFFFFFFFFu);
  1303. }
  1304. asQWORD asCReader::ReadEncodedUInt64()
  1305. {
  1306. asQWORD i = 0;
  1307. asBYTE b;
  1308. ReadData(&b, 1);
  1309. bool isNegative = ( b & 0x80 ) ? true : false;
  1310. b &= 0x7F;
  1311. if( (b & 0x7F) == 0x7F )
  1312. {
  1313. ReadData(&b, 1); i = asQWORD(b) << 56;
  1314. ReadData(&b, 1); i += asQWORD(b) << 48;
  1315. ReadData(&b, 1); i += asQWORD(b) << 40;
  1316. ReadData(&b, 1); i += asQWORD(b) << 32;
  1317. ReadData(&b, 1); i += asUINT(b) << 24;
  1318. ReadData(&b, 1); i += asUINT(b) << 16;
  1319. ReadData(&b, 1); i += asUINT(b) << 8;
  1320. ReadData(&b, 1); i += b;
  1321. }
  1322. else if( (b & 0x7E) == 0x7E )
  1323. {
  1324. i = asQWORD(b & 0x01) << 48;
  1325. ReadData(&b, 1); i += asQWORD(b) << 40;
  1326. ReadData(&b, 1); i += asQWORD(b) << 32;
  1327. ReadData(&b, 1); i += asUINT(b) << 24;
  1328. ReadData(&b, 1); i += asUINT(b) << 16;
  1329. ReadData(&b, 1); i += asUINT(b) << 8;
  1330. ReadData(&b, 1); i += b;
  1331. }
  1332. else if( (b & 0x7C) == 0x7C )
  1333. {
  1334. i = asQWORD(b & 0x03) << 40;
  1335. ReadData(&b, 1); i += asQWORD(b) << 32;
  1336. ReadData(&b, 1); i += asUINT(b) << 24;
  1337. ReadData(&b, 1); i += asUINT(b) << 16;
  1338. ReadData(&b, 1); i += asUINT(b) << 8;
  1339. ReadData(&b, 1); i += b;
  1340. }
  1341. else if( (b & 0x78) == 0x78 )
  1342. {
  1343. i = asQWORD(b & 0x07) << 32;
  1344. ReadData(&b, 1); i += asUINT(b) << 24;
  1345. ReadData(&b, 1); i += asUINT(b) << 16;
  1346. ReadData(&b, 1); i += asUINT(b) << 8;
  1347. ReadData(&b, 1); i += b;
  1348. }
  1349. else if( (b & 0x70) == 0x70 )
  1350. {
  1351. i = asUINT(b & 0x0F) << 24;
  1352. ReadData(&b, 1); i += asUINT(b) << 16;
  1353. ReadData(&b, 1); i += asUINT(b) << 8;
  1354. ReadData(&b, 1); i += b;
  1355. }
  1356. else if( (b & 0x60) == 0x60 )
  1357. {
  1358. i = asUINT(b & 0x1F) << 16;
  1359. ReadData(&b, 1); i += asUINT(b) << 8;
  1360. ReadData(&b, 1); i += b;
  1361. }
  1362. else if( (b & 0x40) == 0x40 )
  1363. {
  1364. i = asUINT(b & 0x3F) << 8;
  1365. ReadData(&b, 1); i += b;
  1366. }
  1367. else
  1368. {
  1369. i = b;
  1370. }
  1371. if( isNegative )
  1372. i = (asQWORD)(-asINT64(i));
  1373. return i;
  1374. }
  1375. void asCReader::ReadString(asCString* str)
  1376. {
  1377. char b;
  1378. ReadData(&b, 1);
  1379. if( b == '\0' )
  1380. {
  1381. str->SetLength(0);
  1382. }
  1383. else if( b == 'n' )
  1384. {
  1385. asUINT len = ReadEncodedUInt();
  1386. str->SetLength(len);
  1387. stream->Read(str->AddressOf(), len);
  1388. savedStrings.PushLast(*str);
  1389. }
  1390. else
  1391. {
  1392. asUINT n = ReadEncodedUInt();
  1393. if( n < savedStrings.GetLength() )
  1394. *str = savedStrings[n];
  1395. else
  1396. Error(TXT_INVALID_BYTECODE_d);
  1397. }
  1398. }
  1399. void asCReader::ReadGlobalProperty()
  1400. {
  1401. asCString name;
  1402. asCDataType type;
  1403. ReadString(&name);
  1404. asCString ns;
  1405. ReadString(&ns);
  1406. asSNameSpace *nameSpace = engine->AddNameSpace(ns.AddressOf());
  1407. ReadDataType(&type);
  1408. asCGlobalProperty *prop = module->AllocateGlobalProperty(name.AddressOf(), type, nameSpace);
  1409. // Read the initialization function
  1410. bool isNew;
  1411. // Do not add the function to the GC at this time. It will
  1412. // only be added to the GC when the module releases the property
  1413. asCScriptFunction *func = ReadFunction(isNew, false, true, false);
  1414. if( func )
  1415. {
  1416. // Make sure the function knows it is owned by the module
  1417. func->module = module;
  1418. prop->SetInitFunc(func);
  1419. func->ReleaseInternal();
  1420. }
  1421. }
  1422. void asCReader::ReadObjectProperty(asCObjectType *ot)
  1423. {
  1424. asCString name;
  1425. ReadString(&name);
  1426. asCDataType dt;
  1427. ReadDataType(&dt);
  1428. int flags = ReadEncodedUInt();
  1429. bool isPrivate = (flags & 1) ? true : false;
  1430. bool isProtected = (flags & 2) ? true : false;
  1431. bool isInherited = (flags & 4) ? true : false;
  1432. // TODO: shared: If the type is shared and pre-existing, we should just
  1433. // validate that the loaded methods match the original
  1434. if( !existingShared.MoveTo(0, ot) )
  1435. ot->AddPropertyToClass(name, dt, isPrivate, isProtected, isInherited);
  1436. }
  1437. void asCReader::ReadDataType(asCDataType *dt)
  1438. {
  1439. // Check if this is a previously used type
  1440. asUINT n = ReadEncodedUInt();
  1441. if( n != 0 )
  1442. {
  1443. // Get the datatype from the cache
  1444. *dt = savedDataTypes[n-1];
  1445. return;
  1446. }
  1447. // Read the type definition
  1448. eTokenType tokenType = (eTokenType)ReadEncodedUInt();
  1449. // Reserve a spot in the savedDataTypes
  1450. asUINT saveSlot = savedDataTypes.GetLength();
  1451. savedDataTypes.PushLast(asCDataType());
  1452. // Read the datatype for the first time
  1453. asCObjectType *objType = 0;
  1454. if( tokenType == ttIdentifier )
  1455. objType = ReadObjectType();
  1456. struct
  1457. {
  1458. char isObjectHandle :1;
  1459. char isHandleToConst:1;
  1460. char isReference :1;
  1461. char isReadOnly :1;
  1462. } bits = {0};
  1463. asASSERT( sizeof(bits) == 1 );
  1464. ReadData(&bits, 1);
  1465. asCScriptFunction *funcDef = 0;
  1466. if( tokenType == ttIdentifier && objType && objType->name == "_builtin_function_" )
  1467. {
  1468. asCScriptFunction func(engine, module, asFUNC_DUMMY);
  1469. ReadFunctionSignature(&func);
  1470. if( error ) return;
  1471. for( asUINT n = 0; n < engine->registeredFuncDefs.GetLength(); n++ )
  1472. {
  1473. // TODO: access: Only return the definitions that the module has access to
  1474. if( engine->registeredFuncDefs[n]->name == func.name &&
  1475. engine->registeredFuncDefs[n]->nameSpace == func.nameSpace )
  1476. {
  1477. funcDef = engine->registeredFuncDefs[n];
  1478. break;
  1479. }
  1480. }
  1481. if( !funcDef && module )
  1482. {
  1483. for( asUINT n = 0; n < module->funcDefs.GetLength(); n++ )
  1484. {
  1485. if( module->funcDefs[n]->name == func.name &&
  1486. module->funcDefs[n]->nameSpace == func.nameSpace )
  1487. {
  1488. funcDef = module->funcDefs[n];
  1489. break;
  1490. }
  1491. }
  1492. }
  1493. // Set to dummy to avoid unwanted release of resources
  1494. func.funcType = asFUNC_DUMMY;
  1495. }
  1496. if( funcDef )
  1497. *dt = asCDataType::CreateFuncDef(funcDef);
  1498. else if( tokenType == ttIdentifier )
  1499. *dt = asCDataType::CreateObject(objType, false);
  1500. else
  1501. *dt = asCDataType::CreatePrimitive(tokenType, false);
  1502. if( bits.isObjectHandle )
  1503. {
  1504. dt->MakeReadOnly(bits.isHandleToConst ? true : false);
  1505. // Here we must allow a scoped type to be a handle
  1506. // e.g. if the datatype is for a system function
  1507. dt->MakeHandle(true, true);
  1508. }
  1509. dt->MakeReadOnly(bits.isReadOnly ? true : false);
  1510. dt->MakeReference(bits.isReference ? true : false);
  1511. // Update the previously saved slot
  1512. savedDataTypes[saveSlot] = *dt;
  1513. }
  1514. asCObjectType* asCReader::ReadObjectType()
  1515. {
  1516. asCObjectType *ot = 0;
  1517. char ch;
  1518. ReadData(&ch, 1);
  1519. if( ch == 'a' )
  1520. {
  1521. // Read the name of the template type
  1522. asCString typeName, ns;
  1523. ReadString(&typeName);
  1524. ReadString(&ns);
  1525. asSNameSpace *nameSpace = engine->AddNameSpace(ns.AddressOf());
  1526. asCObjectType *tmpl = engine->GetRegisteredObjectType(typeName.AddressOf(), nameSpace);
  1527. if( tmpl == 0 )
  1528. {
  1529. asCString str;
  1530. str.Format(TXT_TEMPLATE_TYPE_s_DOESNT_EXIST, typeName.AddressOf());
  1531. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1532. Error(TXT_INVALID_BYTECODE_d);
  1533. return 0;
  1534. }
  1535. asUINT numSubTypes = ReadEncodedUInt();
  1536. asCArray<asCDataType> subTypes;
  1537. for( asUINT n = 0; n < numSubTypes; n++ )
  1538. {
  1539. ReadData(&ch, 1);
  1540. if( ch == 's' )
  1541. {
  1542. asCDataType dt;
  1543. ReadDataType(&dt);
  1544. subTypes.PushLast(dt);
  1545. }
  1546. else
  1547. {
  1548. eTokenType tokenType = (eTokenType)ReadEncodedUInt();
  1549. asCDataType dt = asCDataType::CreatePrimitive(tokenType, false);
  1550. subTypes.PushLast(dt);
  1551. }
  1552. }
  1553. // Return the actual template if the subtypes are the template's dummy types
  1554. if( tmpl->templateSubTypes == subTypes )
  1555. ot = tmpl;
  1556. else
  1557. {
  1558. // Get the template instance type based on the loaded subtypes
  1559. ot = engine->GetTemplateInstanceType(tmpl, subTypes, module);
  1560. }
  1561. if( ot == 0 )
  1562. {
  1563. // Show all subtypes in error message
  1564. asCString sub = subTypes[0].Format(nameSpace);
  1565. for( asUINT n = 1; n < subTypes.GetLength(); n++ )
  1566. {
  1567. sub += ",";
  1568. sub += subTypes[n].Format(nameSpace);
  1569. }
  1570. asCString str;
  1571. str.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, typeName.AddressOf(), sub.AddressOf());
  1572. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1573. Error(TXT_INVALID_BYTECODE_d);
  1574. return 0;
  1575. }
  1576. }
  1577. else if( ch == 'l' )
  1578. {
  1579. asCObjectType *st = ReadObjectType();
  1580. if( st == 0 || st->beh.listFactory == 0 )
  1581. {
  1582. Error(TXT_INVALID_BYTECODE_d);
  1583. return 0;
  1584. }
  1585. ot = engine->GetListPatternType(st->beh.listFactory);
  1586. }
  1587. else if( ch == 's' )
  1588. {
  1589. // Read the name of the template subtype
  1590. asCString typeName;
  1591. ReadString(&typeName);
  1592. // Find the template subtype
  1593. ot = 0;
  1594. for( asUINT n = 0; n < engine->templateSubTypes.GetLength(); n++ )
  1595. {
  1596. if( engine->templateSubTypes[n] && engine->templateSubTypes[n]->name == typeName )
  1597. {
  1598. ot = engine->templateSubTypes[n];
  1599. break;
  1600. }
  1601. }
  1602. if( ot == 0 )
  1603. {
  1604. asCString str;
  1605. str.Format(TXT_TEMPLATE_SUBTYPE_s_DOESNT_EXIST, typeName.AddressOf());
  1606. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1607. Error(TXT_INVALID_BYTECODE_d);
  1608. return 0;
  1609. }
  1610. }
  1611. else if( ch == 'o' )
  1612. {
  1613. // Read the object type name
  1614. asCString typeName, ns;
  1615. ReadString(&typeName);
  1616. ReadString(&ns);
  1617. asSNameSpace *nameSpace = engine->AddNameSpace(ns.AddressOf());
  1618. if( typeName.GetLength() && typeName != "_builtin_object_" && typeName != "_builtin_function_" )
  1619. {
  1620. // Find the object type
  1621. ot = module->GetObjectType(typeName.AddressOf(), nameSpace);
  1622. if( !ot )
  1623. ot = engine->GetRegisteredObjectType(typeName.AddressOf(), nameSpace);
  1624. if( ot == 0 )
  1625. {
  1626. asCString str;
  1627. str.Format(TXT_OBJECT_TYPE_s_DOESNT_EXIST, typeName.AddressOf());
  1628. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1629. Error(TXT_INVALID_BYTECODE_d);
  1630. return 0;
  1631. }
  1632. }
  1633. else if( typeName == "_builtin_object_" )
  1634. {
  1635. ot = &engine->scriptTypeBehaviours;
  1636. }
  1637. else if( typeName == "_builtin_function_" )
  1638. {
  1639. ot = &engine->functionBehaviours;
  1640. }
  1641. else
  1642. asASSERT( false );
  1643. }
  1644. else
  1645. {
  1646. // No object type
  1647. asASSERT( ch == '\0' || error );
  1648. ot = 0;
  1649. }
  1650. return ot;
  1651. }
  1652. void asCReader::ReadByteCode(asCScriptFunction *func)
  1653. {
  1654. asASSERT( func->scriptData );
  1655. // Read number of instructions
  1656. asUINT total, numInstructions;
  1657. total = numInstructions = ReadEncodedUInt();
  1658. // Reserve some space for the instructions
  1659. func->scriptData->byteCode.AllocateNoConstruct(numInstructions, false);
  1660. asUINT pos = 0;
  1661. while( numInstructions )
  1662. {
  1663. asBYTE b;
  1664. ReadData(&b, 1);
  1665. // Allocate the space for the instruction
  1666. asUINT len = asBCTypeSize[asBCInfo[b].type];
  1667. asUINT newSize = asUINT(func->scriptData->byteCode.GetLength()) + len;
  1668. if( func->scriptData->byteCode.GetCapacity() < newSize )
  1669. {
  1670. // Determine the average size of the loaded instructions and re-estimate the final size
  1671. asUINT size = asUINT(float(newSize) / (total - numInstructions) * total) + 1;
  1672. func->scriptData->byteCode.AllocateNoConstruct(size, true);
  1673. }
  1674. if( !func->scriptData->byteCode.SetLengthNoConstruct(newSize) )
  1675. {
  1676. // Out of memory
  1677. error = true;
  1678. return;
  1679. }
  1680. asDWORD *bc = func->scriptData->byteCode.AddressOf() + pos;
  1681. pos += len;
  1682. switch( asBCInfo[b].type )
  1683. {
  1684. case asBCTYPE_NO_ARG:
  1685. {
  1686. *(asBYTE*)(bc) = b;
  1687. bc++;
  1688. }
  1689. break;
  1690. case asBCTYPE_W_ARG:
  1691. case asBCTYPE_wW_ARG:
  1692. case asBCTYPE_rW_ARG:
  1693. {
  1694. *(asBYTE*)(bc) = b;
  1695. // Read the argument
  1696. asWORD w = ReadEncodedUInt16();
  1697. *(((asWORD*)bc)+1) = w;
  1698. bc++;
  1699. }
  1700. break;
  1701. case asBCTYPE_rW_DW_ARG:
  1702. case asBCTYPE_wW_DW_ARG:
  1703. case asBCTYPE_W_DW_ARG:
  1704. {
  1705. *(asBYTE*)(bc) = b;
  1706. // Read the word argument
  1707. asWORD w = ReadEncodedUInt16();
  1708. *(((asWORD*)bc)+1) = w;
  1709. bc++;
  1710. // Read the dword argument
  1711. *bc++ = ReadEncodedUInt();
  1712. }
  1713. break;
  1714. case asBCTYPE_DW_ARG:
  1715. {
  1716. *(asBYTE*)(bc) = b;
  1717. bc++;
  1718. // Read the argument
  1719. *bc++ = ReadEncodedUInt();
  1720. }
  1721. break;
  1722. case asBCTYPE_DW_DW_ARG:
  1723. {
  1724. *(asBYTE*)(bc) = b;
  1725. bc++;
  1726. // Read the first argument
  1727. *bc++ = ReadEncodedUInt();
  1728. // Read the second argument
  1729. *bc++ = ReadEncodedUInt();
  1730. }
  1731. break;
  1732. case asBCTYPE_wW_rW_rW_ARG:
  1733. {
  1734. *(asBYTE*)(bc) = b;
  1735. // Read the first argument
  1736. asWORD w = ReadEncodedUInt16();
  1737. *(((asWORD*)bc)+1) = w;
  1738. bc++;
  1739. // Read the second argument
  1740. w = ReadEncodedUInt16();
  1741. *(asWORD*)bc = w;
  1742. // Read the third argument
  1743. w = ReadEncodedUInt16();
  1744. *(((asWORD*)bc)+1) = w;
  1745. bc++;
  1746. }
  1747. break;
  1748. case asBCTYPE_wW_rW_ARG:
  1749. case asBCTYPE_rW_rW_ARG:
  1750. case asBCTYPE_wW_W_ARG:
  1751. {
  1752. *(asBYTE*)(bc) = b;
  1753. // Read the first argument
  1754. asWORD w = ReadEncodedUInt16();
  1755. *(((asWORD*)bc)+1) = w;
  1756. bc++;
  1757. // Read the second argument
  1758. w = ReadEncodedUInt16();
  1759. *(asWORD*)bc = w;
  1760. bc++;
  1761. }
  1762. break;
  1763. case asBCTYPE_wW_rW_DW_ARG:
  1764. case asBCTYPE_rW_W_DW_ARG:
  1765. {
  1766. *(asBYTE*)(bc) = b;
  1767. // Read the first argument
  1768. asWORD w = ReadEncodedUInt16();
  1769. *(((asWORD*)bc)+1) = w;
  1770. bc++;
  1771. // Read the second argument
  1772. w = ReadEncodedUInt16();
  1773. *(asWORD*)bc = w;
  1774. bc++;
  1775. // Read the third argument
  1776. asDWORD dw = ReadEncodedUInt();
  1777. *bc++ = dw;
  1778. }
  1779. break;
  1780. case asBCTYPE_QW_ARG:
  1781. {
  1782. *(asBYTE*)(bc) = b;
  1783. bc++;
  1784. // Read the argument
  1785. asQWORD qw = ReadEncodedUInt64();
  1786. *(asQWORD*)bc = qw;
  1787. bc += 2;
  1788. }
  1789. break;
  1790. case asBCTYPE_QW_DW_ARG:
  1791. {
  1792. *(asBYTE*)(bc) = b;
  1793. bc++;
  1794. // Read the first argument
  1795. asQWORD qw = ReadEncodedUInt64();
  1796. *(asQWORD*)bc = qw;
  1797. bc += 2;
  1798. // Read the second argument
  1799. asDWORD dw = ReadEncodedUInt();
  1800. *bc++ = dw;
  1801. }
  1802. break;
  1803. case asBCTYPE_rW_QW_ARG:
  1804. case asBCTYPE_wW_QW_ARG:
  1805. {
  1806. *(asBYTE*)(bc) = b;
  1807. // Read the first argument
  1808. asWORD w = ReadEncodedUInt16();
  1809. *(((asWORD*)bc)+1) = w;
  1810. bc++;
  1811. // Read the argument
  1812. asQWORD qw = ReadEncodedUInt64();
  1813. *(asQWORD*)bc = qw;
  1814. bc += 2;
  1815. }
  1816. break;
  1817. case asBCTYPE_rW_DW_DW_ARG:
  1818. {
  1819. *(asBYTE*)(bc) = b;
  1820. // Read the 1st argument
  1821. asWORD w = ReadEncodedUInt16();
  1822. *(((asWORD*)bc)+1) = w;
  1823. bc++;
  1824. // Read the 2nd argument
  1825. *bc++ = ReadEncodedUInt();
  1826. // Read the 3rd argument
  1827. *bc++ = ReadEncodedUInt();
  1828. }
  1829. break;
  1830. default:
  1831. {
  1832. // This should never happen
  1833. asASSERT(false);
  1834. // Read the next 3 bytes
  1835. asDWORD c; asBYTE t;
  1836. #if defined(AS_BIG_ENDIAN)
  1837. c = b << 24;
  1838. ReadData(&t, 1); c += t << 16;
  1839. ReadData(&t, 1); c += t << 8;
  1840. ReadData(&t, 1); c += t;
  1841. #else
  1842. c = b;
  1843. ReadData(&t, 1); c += t << 8;
  1844. ReadData(&t, 1); c += t << 16;
  1845. ReadData(&t, 1); c += t << 24;
  1846. #endif
  1847. *bc++ = c;
  1848. c = *(asBYTE*)&c;
  1849. // Read the bc as is
  1850. for( int n = 1; n < asBCTypeSize[asBCInfo[c].type]; n++ )
  1851. ReadData(&*bc++, 4);
  1852. }
  1853. }
  1854. numInstructions--;
  1855. }
  1856. // Correct the final size in case we over-estimated it
  1857. func->scriptData->byteCode.SetLengthNoConstruct(pos);
  1858. }
  1859. void asCReader::ReadUsedTypeIds()
  1860. {
  1861. asUINT count = ReadEncodedUInt();
  1862. usedTypeIds.Allocate(count, false);
  1863. for( asUINT n = 0; n < count; n++ )
  1864. {
  1865. asCDataType dt;
  1866. ReadDataType(&dt);
  1867. usedTypeIds.PushLast(engine->GetTypeIdFromDataType(dt));
  1868. }
  1869. }
  1870. void asCReader::ReadUsedGlobalProps()
  1871. {
  1872. int c = ReadEncodedUInt();
  1873. usedGlobalProperties.Allocate(c, false);
  1874. for( int n = 0; n < c; n++ )
  1875. {
  1876. asCString name, ns;
  1877. asCDataType type;
  1878. char moduleProp;
  1879. ReadString(&name);
  1880. ReadString(&ns);
  1881. ReadDataType(&type);
  1882. ReadData(&moduleProp, 1);
  1883. asSNameSpace *nameSpace = engine->AddNameSpace(ns.AddressOf());
  1884. // Find the real property
  1885. asCGlobalProperty *globProp = 0;
  1886. if( moduleProp )
  1887. globProp = module->scriptGlobals.GetFirst(nameSpace, name);
  1888. else
  1889. globProp = engine->registeredGlobalProps.GetFirst(nameSpace, name);
  1890. void *prop = 0;
  1891. if( globProp && globProp->type == type )
  1892. prop = globProp->GetAddressOfValue();
  1893. usedGlobalProperties.PushLast(prop);
  1894. if( prop == 0 )
  1895. {
  1896. Error(TXT_INVALID_BYTECODE_d);
  1897. }
  1898. }
  1899. }
  1900. void asCReader::ReadUsedObjectProps()
  1901. {
  1902. asUINT c = ReadEncodedUInt();
  1903. usedObjectProperties.SetLength(c);
  1904. for( asUINT n = 0; n < c; n++ )
  1905. {
  1906. asCObjectType *objType = ReadObjectType();
  1907. if( objType == 0 )
  1908. {
  1909. Error(TXT_INVALID_BYTECODE_d);
  1910. break;
  1911. }
  1912. asCString name;
  1913. ReadString(&name);
  1914. // Find the property offset
  1915. bool found = false;
  1916. for( asUINT p = 0; p < objType->properties.GetLength(); p++ )
  1917. {
  1918. if( objType->properties[p]->name == name )
  1919. {
  1920. usedObjectProperties[n].objType = objType;
  1921. usedObjectProperties[n].offset = objType->properties[p]->byteOffset;
  1922. found = true;
  1923. break;
  1924. }
  1925. }
  1926. if( !found )
  1927. {
  1928. Error(TXT_INVALID_BYTECODE_d);
  1929. return;
  1930. }
  1931. }
  1932. }
  1933. short asCReader::FindObjectPropOffset(asWORD index)
  1934. {
  1935. if( index >= usedObjectProperties.GetLength() )
  1936. {
  1937. Error(TXT_INVALID_BYTECODE_d);
  1938. return 0;
  1939. }
  1940. return (short)usedObjectProperties[index].offset;
  1941. }
  1942. asCScriptFunction *asCReader::FindFunction(int idx)
  1943. {
  1944. if( idx >= 0 && idx < (int)usedFunctions.GetLength() )
  1945. return usedFunctions[idx];
  1946. else
  1947. {
  1948. Error(TXT_INVALID_BYTECODE_d);
  1949. return 0;
  1950. }
  1951. }
  1952. void asCReader::TranslateFunction(asCScriptFunction *func)
  1953. {
  1954. // Skip this if the function is part of an pre-existing shared object
  1955. if( dontTranslate.MoveTo(0, func) ) return;
  1956. asASSERT( func->scriptData );
  1957. // Pre-compute the size of each instruction in order to translate jump offsets
  1958. asUINT n;
  1959. asDWORD *bc = func->scriptData->byteCode.AddressOf();
  1960. asUINT bcLength = (asUINT)func->scriptData->byteCode.GetLength();
  1961. asCArray<asUINT> bcSizes(bcLength);
  1962. asCArray<asUINT> instructionNbrToPos(bcLength);
  1963. for( n = 0; n < bcLength; )
  1964. {
  1965. int c = *(asBYTE*)&bc[n];
  1966. asUINT size = asBCTypeSize[asBCInfo[c].type];
  1967. if( size == 0 )
  1968. {
  1969. Error(TXT_INVALID_BYTECODE_d);
  1970. return;
  1971. }
  1972. bcSizes.PushLast(size);
  1973. instructionNbrToPos.PushLast(n);
  1974. n += size;
  1975. }
  1976. asUINT bcNum = 0;
  1977. for( n = 0; n < bcLength; bcNum++ )
  1978. {
  1979. int c = *(asBYTE*)&bc[n];
  1980. if( c == asBC_REFCPY ||
  1981. c == asBC_RefCpyV ||
  1982. c == asBC_OBJTYPE )
  1983. {
  1984. // Translate the index to the true object type
  1985. asPWORD *ot = (asPWORD*)&bc[n+1];
  1986. *(asCObjectType**)ot = FindObjectType(*(int*)ot);
  1987. }
  1988. else if( c == asBC_TYPEID ||
  1989. c == asBC_Cast )
  1990. {
  1991. // Translate the index to the type id
  1992. int *tid = (int*)&bc[n+1];
  1993. *tid = FindTypeId(*tid);
  1994. }
  1995. else if( c == asBC_ADDSi ||
  1996. c == asBC_LoadThisR )
  1997. {
  1998. // Translate the index to the type id
  1999. int *tid = (int*)&bc[n+1];
  2000. *tid = FindTypeId(*tid);
  2001. // Translate the prop index into the property offset
  2002. *(((short*)&bc[n])+1) = FindObjectPropOffset(*(((short*)&bc[n])+1));
  2003. }
  2004. else if( c == asBC_LoadRObjR ||
  2005. c == asBC_LoadVObjR )
  2006. {
  2007. // Translate the index to the type id
  2008. int *tid = (int*)&bc[n+2];
  2009. *tid = FindTypeId(*tid);
  2010. asCObjectType *ot = engine->GetObjectTypeFromTypeId(*tid);
  2011. if( ot && (ot->flags & asOBJ_LIST_PATTERN) )
  2012. {
  2013. // List patterns have a different way of adjusting the offsets
  2014. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  2015. *(((short*)&bc[n])+2) = (short)listAdj->AdjustOffset(*(((short*)&bc[n])+2));
  2016. }
  2017. else
  2018. {
  2019. // Translate the prop index into the property offset
  2020. *(((short*)&bc[n])+2) = FindObjectPropOffset(*(((short*)&bc[n])+2));
  2021. }
  2022. }
  2023. else if( c == asBC_COPY )
  2024. {
  2025. // Translate the index to the type id
  2026. int *tid = (int*)&bc[n+1];
  2027. *tid = FindTypeId(*tid);
  2028. // COPY is used to copy POD types that don't have the opAssign method. It is
  2029. // also used to copy references to scoped types during variable initializations.
  2030. // Update the number of dwords to copy as it may be different on the target platform
  2031. if( (*tid) & asTYPEID_OBJHANDLE )
  2032. {
  2033. // It is the actual reference that is being copied, not the object itself
  2034. asBC_SWORDARG0(&bc[n]) = AS_PTR_SIZE;
  2035. }
  2036. else
  2037. {
  2038. asCDataType dt = engine->GetDataTypeFromTypeId(*tid);
  2039. if( !dt.IsValid() )
  2040. {
  2041. Error(TXT_INVALID_BYTECODE_d);
  2042. }
  2043. else
  2044. asBC_SWORDARG0(&bc[n]) = (short)dt.GetSizeInMemoryDWords();
  2045. }
  2046. }
  2047. else if( c == asBC_RET )
  2048. {
  2049. // Determine the correct amount of DWORDs to pop
  2050. asWORD dw = (asWORD)func->GetSpaceNeededForArguments();
  2051. if( func->DoesReturnOnStack() ) dw += AS_PTR_SIZE;
  2052. if( func->objectType ) dw += AS_PTR_SIZE;
  2053. asBC_WORDARG0(&bc[n]) = dw;
  2054. }
  2055. else if( c == asBC_CALL ||
  2056. c == asBC_CALLINTF ||
  2057. c == asBC_CALLSYS ||
  2058. c == asBC_Thiscall1 )
  2059. {
  2060. // Translate the index to the func id
  2061. int *fid = (int*)&bc[n+1];
  2062. asCScriptFunction *f = FindFunction(*fid);
  2063. if( f )
  2064. *fid = f->id;
  2065. else
  2066. {
  2067. Error(TXT_INVALID_BYTECODE_d);
  2068. return;
  2069. }
  2070. }
  2071. else if( c == asBC_FuncPtr )
  2072. {
  2073. // Translate the index to the func pointer
  2074. asPWORD *fid = (asPWORD*)&bc[n+1];
  2075. *fid = (asPWORD)FindFunction((int)*fid);
  2076. }
  2077. else if( c == asBC_ALLOC )
  2078. {
  2079. // Translate the index to the true object type
  2080. asPWORD *arg = (asPWORD*)&bc[n+1];
  2081. *(asCObjectType**)arg = FindObjectType(*(int*)arg);
  2082. // The constructor function id must be translated, unless it is zero
  2083. int *fid = (int*)&bc[n+1+AS_PTR_SIZE];
  2084. if( *fid != 0 )
  2085. {
  2086. // Subtract 1 from the id, as it was incremented during the writing
  2087. asCScriptFunction *f = FindFunction(*fid-1);
  2088. if( f )
  2089. *fid = f->id;
  2090. else
  2091. {
  2092. Error(TXT_INVALID_BYTECODE_d);
  2093. return;
  2094. }
  2095. }
  2096. }
  2097. else if( c == asBC_STR )
  2098. {
  2099. // Translate the index to the true string id
  2100. asWORD *arg = ((asWORD*)&bc[n])+1;
  2101. if( *arg < usedStringConstants.GetLength() )
  2102. *arg = (asWORD)usedStringConstants[*arg];
  2103. else
  2104. {
  2105. Error(TXT_INVALID_BYTECODE_d);
  2106. return;
  2107. }
  2108. }
  2109. else if( c == asBC_CALLBND )
  2110. {
  2111. // Translate the function id
  2112. asUINT *fid = (asUINT*)&bc[n+1];
  2113. if( *fid < module->bindInformations.GetLength() )
  2114. {
  2115. sBindInfo *bi = module->bindInformations[*fid];
  2116. if( bi )
  2117. *fid = bi->importedFunctionSignature->id;
  2118. else
  2119. {
  2120. Error(TXT_INVALID_BYTECODE_d);
  2121. return;
  2122. }
  2123. }
  2124. else
  2125. {
  2126. Error(TXT_INVALID_BYTECODE_d);
  2127. return;
  2128. }
  2129. }
  2130. else if( c == asBC_PGA ||
  2131. c == asBC_PshGPtr ||
  2132. c == asBC_LDG ||
  2133. c == asBC_PshG4 ||
  2134. c == asBC_LdGRdR4 ||
  2135. c == asBC_CpyGtoV4 ||
  2136. c == asBC_CpyVtoG4 ||
  2137. c == asBC_SetG4 )
  2138. {
  2139. // Translate the global var index to pointer
  2140. asPWORD *index = (asPWORD*)&bc[n+1];
  2141. if( *(asUINT*)index < usedGlobalProperties.GetLength() )
  2142. *(void**)index = usedGlobalProperties[*(asUINT*)index];
  2143. else
  2144. {
  2145. Error(TXT_INVALID_BYTECODE_d);
  2146. return;
  2147. }
  2148. }
  2149. else if( c == asBC_JMP ||
  2150. c == asBC_JZ ||
  2151. c == asBC_JNZ ||
  2152. c == asBC_JLowZ ||
  2153. c == asBC_JLowNZ ||
  2154. c == asBC_JS ||
  2155. c == asBC_JNS ||
  2156. c == asBC_JP ||
  2157. c == asBC_JNP ) // The JMPP instruction doesn't need modification
  2158. {
  2159. // Get the offset
  2160. int offset = int(bc[n+1]);
  2161. // Count the instruction sizes to the destination instruction
  2162. int size = 0;
  2163. if( offset >= 0 )
  2164. // If moving ahead, then start from next instruction
  2165. for( asUINT num = bcNum+1; offset-- > 0; num++ )
  2166. size += bcSizes[num];
  2167. else
  2168. // If moving backwards, then start at current instruction
  2169. for( asUINT num = bcNum; offset++ < 0; num-- )
  2170. size -= bcSizes[num];
  2171. // The size is dword offset
  2172. bc[n+1] = size;
  2173. }
  2174. else if( c == asBC_AllocMem )
  2175. {
  2176. // The size of the allocated memory is only known after all the elements has been seen.
  2177. // This helper class will collect this information and adjust the size when the
  2178. // corresponding asBC_FREE is encountered
  2179. // The adjuster also needs to know the list type so it can know the type of the elements
  2180. asCObjectType *ot = func->GetObjectTypeOfLocalVar(asBC_SWORDARG0(&bc[n]));
  2181. listAdjusters.PushLast(asNEW(SListAdjuster)(this, &bc[n], ot));
  2182. }
  2183. else if( c == asBC_FREE )
  2184. {
  2185. // Translate the index to the true object type
  2186. asPWORD *pot = (asPWORD*)&bc[n+1];
  2187. *(asCObjectType**)pot = FindObjectType(*(int*)pot);
  2188. asCObjectType *ot = *(asCObjectType**)pot;
  2189. if( ot && (ot->flags & asOBJ_LIST_PATTERN) )
  2190. {
  2191. if( listAdjusters.GetLength() == 0 )
  2192. {
  2193. Error(TXT_INVALID_BYTECODE_d);
  2194. return;
  2195. }
  2196. // Finalize the adjustment of the list buffer that was initiated with asBC_AllocMem
  2197. SListAdjuster *list = listAdjusters.PopLast();
  2198. list->AdjustAllocMem();
  2199. asDELETE(list, SListAdjuster);
  2200. }
  2201. }
  2202. else if( c == asBC_SetListSize )
  2203. {
  2204. // Adjust the offset in the list where the size is informed
  2205. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  2206. bc[n+1] = listAdj->AdjustOffset(bc[n+1]);
  2207. // Inform the list adjuster how many values will be repeated
  2208. listAdj->SetRepeatCount(bc[n+2]);
  2209. }
  2210. else if( c == asBC_PshListElmnt )
  2211. {
  2212. // Adjust the offset in the list where the size is informed
  2213. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  2214. bc[n+1] = listAdj->AdjustOffset(bc[n+1]);
  2215. }
  2216. else if( c == asBC_SetListType )
  2217. {
  2218. // Adjust the offset in the list where the typeid is informed
  2219. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  2220. bc[n+1] = listAdj->AdjustOffset(bc[n+1]);
  2221. // Translate the type id
  2222. bc[n+2] = FindTypeId(bc[n+2]);
  2223. // Inform the list adjuster the type id of the next element
  2224. listAdj->SetNextType(bc[n+2]);
  2225. }
  2226. n += asBCTypeSize[asBCInfo[c].type];
  2227. }
  2228. // Calculate the stack adjustments
  2229. CalculateAdjustmentByPos(func);
  2230. // Adjust all variable positions in the bytecode
  2231. bc = func->scriptData->byteCode.AddressOf();
  2232. for( n = 0; n < bcLength; )
  2233. {
  2234. int c = *(asBYTE*)&bc[n];
  2235. switch( asBCInfo[c].type )
  2236. {
  2237. case asBCTYPE_wW_ARG:
  2238. case asBCTYPE_rW_DW_ARG:
  2239. case asBCTYPE_wW_QW_ARG:
  2240. case asBCTYPE_rW_ARG:
  2241. case asBCTYPE_wW_DW_ARG:
  2242. case asBCTYPE_wW_W_ARG:
  2243. case asBCTYPE_rW_QW_ARG:
  2244. case asBCTYPE_rW_W_DW_ARG:
  2245. case asBCTYPE_rW_DW_DW_ARG:
  2246. {
  2247. asBC_SWORDARG0(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG0(&bc[n]));
  2248. }
  2249. break;
  2250. case asBCTYPE_wW_rW_ARG:
  2251. case asBCTYPE_wW_rW_DW_ARG:
  2252. case asBCTYPE_rW_rW_ARG:
  2253. {
  2254. asBC_SWORDARG0(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG0(&bc[n]));
  2255. asBC_SWORDARG1(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG1(&bc[n]));
  2256. }
  2257. break;
  2258. case asBCTYPE_wW_rW_rW_ARG:
  2259. {
  2260. asBC_SWORDARG0(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG0(&bc[n]));
  2261. asBC_SWORDARG1(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG1(&bc[n]));
  2262. asBC_SWORDARG2(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG2(&bc[n]));
  2263. }
  2264. break;
  2265. default:
  2266. // The other types don't treat variables so won't be modified
  2267. break;
  2268. }
  2269. n += asBCTypeSize[asBCInfo[c].type];
  2270. }
  2271. // Adjust the space needed for local variables
  2272. func->scriptData->variableSpace = AdjustStackPosition(func->scriptData->variableSpace);
  2273. // Adjust the variable information. This will be used during the adjustment below
  2274. for( n = 0; n < func->scriptData->variables.GetLength(); n++ )
  2275. {
  2276. func->scriptData->variables[n]->declaredAtProgramPos = instructionNbrToPos[func->scriptData->variables[n]->declaredAtProgramPos];
  2277. func->scriptData->variables[n]->stackOffset = AdjustStackPosition(func->scriptData->variables[n]->stackOffset);
  2278. }
  2279. // objVariablePos
  2280. for( n = 0; n < func->scriptData->objVariablePos.GetLength(); n++ )
  2281. {
  2282. func->scriptData->objVariablePos[n] = AdjustStackPosition(func->scriptData->objVariablePos[n]);
  2283. func->scriptData->funcVariableTypes[n] = FindFunction((int)(asPWORD)func->scriptData->funcVariableTypes[n]);
  2284. }
  2285. // Adjust the get offsets. This must be done in the second iteration because
  2286. // it relies on the function ids and variable position already being correct in the
  2287. // bytecodes that come after the GET instructions.
  2288. // TODO: optimize: Instead of doing a full extra loop. We can push the GET instructions
  2289. // on a stack, and then when a call instruction is found update all of them.
  2290. // This will also make the AdjustGetOffset() function quicker as it can
  2291. // receive the called function directly instead of having to search for it.
  2292. bc = func->scriptData->byteCode.AddressOf();
  2293. for( n = 0; n < bcLength; )
  2294. {
  2295. int c = *(asBYTE*)&bc[n];
  2296. if( c == asBC_GETREF ||
  2297. c == asBC_GETOBJ ||
  2298. c == asBC_GETOBJREF )
  2299. {
  2300. asBC_WORDARG0(&bc[n]) = (asWORD)AdjustGetOffset(asBC_WORDARG0(&bc[n]), func, n);
  2301. }
  2302. n += asBCTypeSize[asBCInfo[c].type];
  2303. }
  2304. for( n = 0; n < func->scriptData->objVariableInfo.GetLength(); n++ )
  2305. {
  2306. // The program position must be adjusted as it is stored in number of instructions
  2307. func->scriptData->objVariableInfo[n].programPos = instructionNbrToPos[func->scriptData->objVariableInfo[n].programPos];
  2308. func->scriptData->objVariableInfo[n].variableOffset = AdjustStackPosition(func->scriptData->objVariableInfo[n].variableOffset);
  2309. }
  2310. // The program position (every even number) needs to be adjusted
  2311. // for the line numbers to be in number of dwords instead of number of instructions
  2312. for( n = 0; n < func->scriptData->lineNumbers.GetLength(); n += 2 )
  2313. func->scriptData->lineNumbers[n] = instructionNbrToPos[func->scriptData->lineNumbers[n]];
  2314. for( n = 0; n < func->scriptData->sectionIdxs.GetLength(); n += 2 )
  2315. func->scriptData->sectionIdxs[n] = instructionNbrToPos[func->scriptData->sectionIdxs[n]];
  2316. CalculateStackNeeded(func);
  2317. }
  2318. asCReader::SListAdjuster::SListAdjuster(asCReader *rd, asDWORD *bc, asCObjectType *listType) :
  2319. reader(rd), allocMemBC(bc), maxOffset(0), patternType(listType), repeatCount(0), lastOffset(-1), nextOffset(0), nextTypeId(-1)
  2320. {
  2321. asASSERT( patternType && (patternType->flags & asOBJ_LIST_PATTERN) );
  2322. // Find the first expected value in the list
  2323. asSListPatternNode *node = patternType->engine->scriptFunctions[patternType->templateSubTypes[0].GetBehaviour()->listFactory]->listPattern;
  2324. asASSERT( node && node->type == asLPT_START );
  2325. patternNode = node->next;
  2326. }
  2327. int asCReader::SListAdjuster::AdjustOffset(int offset)
  2328. {
  2329. if( offset < lastOffset )
  2330. {
  2331. reader->Error(TXT_INVALID_BYTECODE_d);
  2332. return 0;
  2333. }
  2334. // If it is the same offset being accessed again, just return the same adjusted value
  2335. if( lastOffset == offset )
  2336. return lastAdjustedOffset;
  2337. lastOffset = offset;
  2338. lastAdjustedOffset = maxOffset;
  2339. // What is being expected at this position?
  2340. if( patternNode->type == asLPT_REPEAT || patternNode->type == asLPT_REPEAT_SAME )
  2341. {
  2342. // Align the offset to 4 bytes boundary
  2343. if( maxOffset & 0x3 )
  2344. {
  2345. maxOffset += 4 - (maxOffset & 0x3);
  2346. lastAdjustedOffset = maxOffset;
  2347. }
  2348. // Don't move the patternNode yet because the caller must make a call to SetRepeatCount too
  2349. maxOffset += 4;
  2350. nextOffset = offset+1;
  2351. return lastAdjustedOffset;
  2352. }
  2353. else if( patternNode->type == asLPT_TYPE )
  2354. {
  2355. const asCDataType &dt = reinterpret_cast<asSListPatternDataTypeNode*>(patternNode)->dataType;
  2356. if( dt.GetTokenType() == ttQuestion )
  2357. {
  2358. if( nextTypeId != -1 )
  2359. {
  2360. if( repeatCount > 0 )
  2361. repeatCount--;
  2362. asCDataType dt = patternType->engine->GetDataTypeFromTypeId(nextTypeId);
  2363. asUINT size;
  2364. if( dt.IsObjectHandle() || (dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_REF)) )
  2365. size = AS_PTR_SIZE*4;
  2366. else
  2367. size = dt.GetSizeInMemoryBytes();
  2368. // Align the offset to 4 bytes boundary
  2369. if( size >= 4 && (maxOffset & 0x3) )
  2370. {
  2371. maxOffset += 4 - (maxOffset & 0x3);
  2372. lastAdjustedOffset = maxOffset;
  2373. }
  2374. // Only move the patternNode if we're not expecting any more repeated entries
  2375. if( repeatCount == 0 )
  2376. patternNode = patternNode->next;
  2377. nextTypeId = -1;
  2378. maxOffset += size;
  2379. nextOffset = offset+1;
  2380. return lastAdjustedOffset;
  2381. }
  2382. else
  2383. {
  2384. // Align the offset to 4 bytes boundary
  2385. if( maxOffset & 0x3 )
  2386. {
  2387. maxOffset += 4 - (maxOffset & 0x3);
  2388. lastAdjustedOffset = maxOffset;
  2389. }
  2390. // The first adjustment is for the typeId
  2391. maxOffset += 4;
  2392. nextOffset = offset+1;
  2393. return lastAdjustedOffset;
  2394. }
  2395. }
  2396. else
  2397. {
  2398. // Determine the size of the element
  2399. asUINT size;
  2400. asCDataType dt = reinterpret_cast<asSListPatternDataTypeNode*>(patternNode)->dataType;
  2401. if( dt.IsObjectHandle() || (dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_REF)) )
  2402. size = AS_PTR_SIZE*4;
  2403. else
  2404. size = dt.GetSizeInMemoryBytes();
  2405. // If values are skipped, the offset needs to be incremented
  2406. while( nextOffset <= offset )
  2407. {
  2408. if( repeatCount > 0 )
  2409. repeatCount--;
  2410. // Align the offset to 4 bytes boundary
  2411. if( size >= 4 && (maxOffset & 0x3) )
  2412. maxOffset += 4 - (maxOffset & 0x3);
  2413. lastAdjustedOffset = maxOffset;
  2414. nextOffset += 1;
  2415. maxOffset += size;
  2416. }
  2417. // Only move the patternNode if we're not expecting any more repeated entries
  2418. if( repeatCount == 0 )
  2419. patternNode = patternNode->next;
  2420. nextOffset = offset+1;
  2421. return lastAdjustedOffset;
  2422. }
  2423. }
  2424. else if( patternNode->type == asLPT_START )
  2425. {
  2426. if( repeatCount > 0 )
  2427. repeatCount--;
  2428. SInfo info = {repeatCount, patternNode};
  2429. stack.PushLast(info);
  2430. repeatCount = 0;
  2431. patternNode = patternNode->next;
  2432. lastOffset--;
  2433. return AdjustOffset(offset);
  2434. }
  2435. else if( patternNode->type == asLPT_END )
  2436. {
  2437. if( stack.GetLength() == 0 )
  2438. {
  2439. reader->Error(TXT_INVALID_BYTECODE_d);
  2440. return 0;
  2441. }
  2442. SInfo info = stack.PopLast();
  2443. repeatCount = info.repeatCount;
  2444. if( repeatCount )
  2445. patternNode = info.startNode;
  2446. else
  2447. patternNode = patternNode->next;
  2448. lastOffset--;
  2449. return AdjustOffset(offset);
  2450. }
  2451. else
  2452. {
  2453. // Something is wrong with the pattern list declaration
  2454. reader->Error(TXT_INVALID_BYTECODE_d);
  2455. return 0;
  2456. }
  2457. UNREACHABLE_RETURN;
  2458. }
  2459. void asCReader::SListAdjuster::SetRepeatCount(asUINT rc)
  2460. {
  2461. // Make sure the list is expecting a repeat at this location
  2462. asASSERT( patternNode->type == asLPT_REPEAT || patternNode->type == asLPT_REPEAT_SAME );
  2463. // Now move to the next patternNode
  2464. patternNode = patternNode->next;
  2465. repeatCount = rc;
  2466. }
  2467. void asCReader::SListAdjuster::AdjustAllocMem()
  2468. {
  2469. allocMemBC[1] = maxOffset;
  2470. }
  2471. void asCReader::SListAdjuster::SetNextType(int typeId)
  2472. {
  2473. asASSERT( nextTypeId == -1 );
  2474. nextTypeId = typeId;
  2475. }
  2476. void asCReader::CalculateStackNeeded(asCScriptFunction *func)
  2477. {
  2478. asASSERT( func->scriptData );
  2479. int largestStackUsed = 0;
  2480. // Clear the known stack size for each bytecode
  2481. asCArray<int> stackSize;
  2482. stackSize.SetLength(func->scriptData->byteCode.GetLength());
  2483. memset(&stackSize[0], -1, stackSize.GetLength()*4);
  2484. // Add the first instruction to the list of unchecked code
  2485. // paths and set the stack size at that instruction to variableSpace
  2486. asCArray<asUINT> paths;
  2487. paths.PushLast(0);
  2488. stackSize[0] = func->scriptData->variableSpace;
  2489. // Go through each of the code paths
  2490. for( asUINT p = 0; p < paths.GetLength(); ++p )
  2491. {
  2492. asUINT pos = paths[p];
  2493. int currStackSize = stackSize[pos];
  2494. asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[pos];
  2495. if( bc == asBC_RET )
  2496. continue;
  2497. // Determine the change in stack size for this instruction
  2498. int stackInc = asBCInfo[bc].stackInc;
  2499. if( stackInc == 0xFFFF )
  2500. {
  2501. // Determine the true delta from the instruction arguments
  2502. if( bc == asBC_CALL ||
  2503. bc == asBC_CALLSYS ||
  2504. bc == asBC_Thiscall1 ||
  2505. bc == asBC_CALLBND ||
  2506. bc == asBC_ALLOC ||
  2507. bc == asBC_CALLINTF ||
  2508. bc == asBC_CallPtr )
  2509. {
  2510. asCScriptFunction *called = GetCalledFunction(func, pos);
  2511. if( called )
  2512. {
  2513. stackInc = -called->GetSpaceNeededForArguments();
  2514. if( called->objectType )
  2515. stackInc -= AS_PTR_SIZE;
  2516. if( called->DoesReturnOnStack() )
  2517. stackInc -= AS_PTR_SIZE;
  2518. }
  2519. else
  2520. {
  2521. // It is an allocation for an object without a constructor
  2522. asASSERT( bc == asBC_ALLOC );
  2523. stackInc = -AS_PTR_SIZE;
  2524. }
  2525. }
  2526. }
  2527. currStackSize += stackInc;
  2528. asASSERT( currStackSize >= 0 );
  2529. if( currStackSize > largestStackUsed )
  2530. largestStackUsed = currStackSize;
  2531. if( bc == asBC_JMP )
  2532. {
  2533. // Find the label that we should jump to
  2534. int offset = asBC_INTARG(&func->scriptData->byteCode[pos]);
  2535. pos += 2 + offset;
  2536. // Add the destination as a new path
  2537. if( stackSize[pos] == -1 )
  2538. {
  2539. stackSize[pos] = currStackSize;
  2540. paths.PushLast(pos);
  2541. }
  2542. else
  2543. asASSERT(stackSize[pos] == currStackSize);
  2544. continue;
  2545. }
  2546. else if( bc == asBC_JZ || bc == asBC_JNZ ||
  2547. bc == asBC_JLowZ || bc == asBC_JLowNZ ||
  2548. bc == asBC_JS || bc == asBC_JNS ||
  2549. bc == asBC_JP || bc == asBC_JNP )
  2550. {
  2551. // Find the label that is being jumped to
  2552. int offset = asBC_INTARG(&func->scriptData->byteCode[pos]);
  2553. // Add both paths to the code paths
  2554. pos += 2;
  2555. if( stackSize[pos] == -1 )
  2556. {
  2557. stackSize[pos] = currStackSize;
  2558. paths.PushLast(pos);
  2559. }
  2560. else
  2561. asASSERT(stackSize[pos] == currStackSize);
  2562. pos += offset;
  2563. if( stackSize[pos] == -1 )
  2564. {
  2565. stackSize[pos] = currStackSize;
  2566. paths.PushLast(pos);
  2567. }
  2568. else
  2569. asASSERT(stackSize[pos] == currStackSize);
  2570. continue;
  2571. }
  2572. else if( bc == asBC_JMPP )
  2573. {
  2574. pos++;
  2575. // Add all subsequent JMP instructions to the path
  2576. while( *(asBYTE*)&func->scriptData->byteCode[pos] == asBC_JMP )
  2577. {
  2578. if( stackSize[pos] == -1 )
  2579. {
  2580. stackSize[pos] = currStackSize;
  2581. paths.PushLast(pos);
  2582. }
  2583. else
  2584. asASSERT(stackSize[pos] == currStackSize);
  2585. pos += 2;
  2586. }
  2587. continue;
  2588. }
  2589. else
  2590. {
  2591. // Add next instruction to the paths
  2592. pos += asBCTypeSize[asBCInfo[bc].type];
  2593. if( stackSize[pos] == -1 )
  2594. {
  2595. stackSize[pos] = currStackSize;
  2596. paths.PushLast(pos);
  2597. }
  2598. else
  2599. asASSERT(stackSize[pos] == currStackSize);
  2600. continue;
  2601. }
  2602. }
  2603. func->scriptData->stackNeeded = largestStackUsed;
  2604. }
  2605. void asCReader::CalculateAdjustmentByPos(asCScriptFunction *func)
  2606. {
  2607. // Adjust the offset of all negative variables (parameters) as
  2608. // all pointers have been stored as having a size of 1 dword
  2609. asUINT n;
  2610. asCArray<int> adjustments;
  2611. asUINT offset = 0;
  2612. if( func->objectType )
  2613. {
  2614. adjustments.PushLast(offset);
  2615. adjustments.PushLast(1-AS_PTR_SIZE);
  2616. offset += 1;
  2617. }
  2618. if( func->DoesReturnOnStack() )
  2619. {
  2620. adjustments.PushLast(offset);
  2621. adjustments.PushLast(1-AS_PTR_SIZE);
  2622. offset += 1;
  2623. }
  2624. for( n = 0; n < func->parameterTypes.GetLength(); n++ )
  2625. {
  2626. if( !func->parameterTypes[n].IsPrimitive() ||
  2627. func->parameterTypes[n].IsReference() )
  2628. {
  2629. adjustments.PushLast(offset);
  2630. adjustments.PushLast(1-AS_PTR_SIZE);
  2631. offset += 1;
  2632. }
  2633. else
  2634. {
  2635. asASSERT( func->parameterTypes[n].IsPrimitive() );
  2636. offset += func->parameterTypes[n].GetSizeOnStackDWords();
  2637. }
  2638. }
  2639. // Build look-up table with the adjustments for each stack position
  2640. adjustNegativeStackByPos.SetLength(offset);
  2641. memset(adjustNegativeStackByPos.AddressOf(), 0, adjustNegativeStackByPos.GetLength()*sizeof(int));
  2642. for( n = 0; n < adjustments.GetLength(); n+=2 )
  2643. {
  2644. int pos = adjustments[n];
  2645. int adjust = adjustments[n+1];
  2646. for( asUINT i = pos+1; i < adjustNegativeStackByPos.GetLength(); i++ )
  2647. adjustNegativeStackByPos[i] += adjust;
  2648. }
  2649. // The bytecode has been stored as if all object variables take up only 1 dword.
  2650. // It is necessary to adjust to the size according to the current platform.
  2651. adjustments.SetLength(0);
  2652. int highestPos = 0;
  2653. for( n = 0; n < func->scriptData->objVariableTypes.GetLength(); n++ )
  2654. {
  2655. if( func->scriptData->objVariableTypes[n] )
  2656. {
  2657. // Determine the size the variable currently occupies on the stack
  2658. int size = AS_PTR_SIZE;
  2659. if( (func->scriptData->objVariableTypes[n]->GetFlags() & asOBJ_VALUE) &&
  2660. n >= func->scriptData->objVariablesOnHeap )
  2661. {
  2662. size = func->scriptData->objVariableTypes[n]->GetSize();
  2663. if( size < 4 )
  2664. size = 1;
  2665. else
  2666. size /= 4;
  2667. }
  2668. // Check if type has a different size than stored
  2669. if( size > 1 )
  2670. {
  2671. if( func->scriptData->objVariablePos[n] > highestPos )
  2672. highestPos = func->scriptData->objVariablePos[n];
  2673. adjustments.PushLast(func->scriptData->objVariablePos[n]);
  2674. adjustments.PushLast(size-1);
  2675. }
  2676. }
  2677. }
  2678. // Count position 0 too
  2679. adjustByPos.SetLength(highestPos+1);
  2680. memset(adjustByPos.AddressOf(), 0, adjustByPos.GetLength()*sizeof(int));
  2681. // Build look-up table with the adjustments for each stack position
  2682. for( n = 0; n < adjustments.GetLength(); n+=2 )
  2683. {
  2684. int pos = adjustments[n];
  2685. int adjust = adjustments[n+1];
  2686. for( asUINT i = pos; i < adjustByPos.GetLength(); i++ )
  2687. adjustByPos[i] += adjust;
  2688. }
  2689. }
  2690. int asCReader::AdjustStackPosition(int pos)
  2691. {
  2692. if( pos >= (int)adjustByPos.GetLength() )
  2693. {
  2694. // It can be higher for primitives allocated on top of highest object variable
  2695. if( adjustByPos.GetLength() )
  2696. pos += (short)adjustByPos[adjustByPos.GetLength()-1];
  2697. }
  2698. else if( pos >= 0 )
  2699. pos += (short)adjustByPos[pos];
  2700. else if( -pos >= (int)adjustNegativeStackByPos.GetLength() )
  2701. Error(TXT_INVALID_BYTECODE_d);
  2702. else
  2703. pos += (short)adjustNegativeStackByPos[-pos];
  2704. return pos;
  2705. }
  2706. asCScriptFunction *asCReader::GetCalledFunction(asCScriptFunction *func, asDWORD programPos)
  2707. {
  2708. asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[programPos];
  2709. if( bc == asBC_CALL ||
  2710. bc == asBC_CALLSYS ||
  2711. bc == asBC_Thiscall1 ||
  2712. bc == asBC_CALLINTF )
  2713. {
  2714. // Find the function from the function id in bytecode
  2715. int funcId = asBC_INTARG(&func->scriptData->byteCode[programPos]);
  2716. return engine->scriptFunctions[funcId];
  2717. }
  2718. else if( bc == asBC_ALLOC )
  2719. {
  2720. // Find the function from the function id in the bytecode
  2721. int funcId = asBC_INTARG(&func->scriptData->byteCode[programPos+AS_PTR_SIZE]);
  2722. return engine->scriptFunctions[funcId];
  2723. }
  2724. else if( bc == asBC_CALLBND )
  2725. {
  2726. // Find the function from the engine's bind array
  2727. int funcId = asBC_INTARG(&func->scriptData->byteCode[programPos]);
  2728. return engine->importedFunctions[funcId & ~FUNC_IMPORTED]->importedFunctionSignature;
  2729. }
  2730. else if( bc == asBC_CallPtr )
  2731. {
  2732. asUINT v;
  2733. int var = asBC_SWORDARG0(&func->scriptData->byteCode[programPos]);
  2734. // Find the funcdef from the local variable
  2735. for( v = 0; v < func->scriptData->objVariablePos.GetLength(); v++ )
  2736. if( func->scriptData->objVariablePos[v] == var )
  2737. return func->scriptData->funcVariableTypes[v];
  2738. // Look in parameters
  2739. int paramPos = 0;
  2740. if( func->objectType )
  2741. paramPos -= AS_PTR_SIZE;
  2742. if( func->DoesReturnOnStack() )
  2743. paramPos -= AS_PTR_SIZE;
  2744. for( v = 0; v < func->parameterTypes.GetLength(); v++ )
  2745. {
  2746. if( var == paramPos )
  2747. return func->parameterTypes[v].GetFuncDef();
  2748. paramPos -= func->parameterTypes[v].GetSizeOnStackDWords();
  2749. }
  2750. }
  2751. return 0;
  2752. }
  2753. int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD programPos)
  2754. {
  2755. // TODO: optimize: multiple instructions for the same function doesn't need to look for the function everytime
  2756. // the function can remember where it found the function and check if the programPos is still valid
  2757. // Get offset 0 doesn't need adjustment
  2758. if( offset == 0 ) return 0;
  2759. // Find out which function that will be called
  2760. asCScriptFunction *calledFunc = 0;
  2761. for( asUINT n = programPos; func->scriptData->byteCode.GetLength(); )
  2762. {
  2763. asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[n];
  2764. if( bc == asBC_CALL ||
  2765. bc == asBC_CALLSYS ||
  2766. bc == asBC_Thiscall1 ||
  2767. bc == asBC_CALLINTF ||
  2768. bc == asBC_ALLOC ||
  2769. bc == asBC_CALLBND ||
  2770. bc == asBC_CallPtr )
  2771. {
  2772. calledFunc = GetCalledFunction(func, n);
  2773. break;
  2774. }
  2775. else if( bc == asBC_REFCPY ||
  2776. bc == asBC_COPY )
  2777. {
  2778. // In this case we know there is only 1 pointer on the stack above
  2779. asASSERT( offset == 1 );
  2780. return offset - (1 - AS_PTR_SIZE);
  2781. }
  2782. n += asBCTypeSize[asBCInfo[bc].type];
  2783. }
  2784. if( calledFunc == 0 )
  2785. {
  2786. Error(TXT_INVALID_BYTECODE_d);
  2787. return offset;
  2788. }
  2789. // Count the number of pointers pushed on the stack above the
  2790. // current offset, and then adjust the offset accordingly
  2791. asUINT numPtrs = 0;
  2792. int currOffset = 0;
  2793. if( offset > currOffset && calledFunc->GetObjectType() )
  2794. {
  2795. numPtrs++;
  2796. currOffset++;
  2797. }
  2798. if( offset > currOffset && calledFunc->DoesReturnOnStack() )
  2799. {
  2800. numPtrs++;
  2801. currOffset++;
  2802. }
  2803. for( asUINT p = 0; p < calledFunc->parameterTypes.GetLength(); p++ )
  2804. {
  2805. if( offset <= currOffset ) break;
  2806. if( !calledFunc->parameterTypes[p].IsPrimitive() ||
  2807. calledFunc->parameterTypes[p].IsReference() )
  2808. {
  2809. numPtrs++;
  2810. currOffset++;
  2811. // The variable arg ? has an additiona 32bit integer with the typeid
  2812. if( calledFunc->parameterTypes[p].IsAnyType() )
  2813. currOffset += 1;
  2814. }
  2815. else
  2816. {
  2817. // Enums or built-in primitives are passed by value
  2818. asASSERT( calledFunc->parameterTypes[p].IsPrimitive() );
  2819. currOffset += calledFunc->parameterTypes[p].GetSizeOnStackDWords();
  2820. }
  2821. }
  2822. return offset - numPtrs * (1 - AS_PTR_SIZE);
  2823. }
  2824. int asCReader::FindTypeId(int idx)
  2825. {
  2826. if( idx >= 0 && idx < (int)usedTypeIds.GetLength() )
  2827. return usedTypeIds[idx];
  2828. else
  2829. {
  2830. Error(TXT_INVALID_BYTECODE_d);
  2831. return 0;
  2832. }
  2833. }
  2834. asCObjectType *asCReader::FindObjectType(int idx)
  2835. {
  2836. if( idx < 0 || idx >= (int)usedTypes.GetLength() )
  2837. {
  2838. Error(TXT_INVALID_BYTECODE_d);
  2839. return 0;
  2840. }
  2841. return usedTypes[idx];
  2842. }
  2843. #ifndef AS_NO_COMPILER
  2844. asCWriter::asCWriter(asCModule* _module, asIBinaryStream* _stream, asCScriptEngine* _engine, bool _stripDebug)
  2845. : module(_module), stream(_stream), engine(_engine), stripDebugInfo(_stripDebug)
  2846. {
  2847. }
  2848. void asCWriter::WriteData(const void *data, asUINT size)
  2849. {
  2850. asASSERT(size == 1 || size == 2 || size == 4 || size == 8);
  2851. #if defined(AS_BIG_ENDIAN)
  2852. for( asUINT n = 0; n < size; n++ )
  2853. stream->Write(((asBYTE*)data)+n, 1);
  2854. #else
  2855. for( int n = size-1; n >= 0; n-- )
  2856. stream->Write(((asBYTE*)data)+n, 1);
  2857. #endif
  2858. }
  2859. int asCWriter::Write()
  2860. {
  2861. unsigned long i, count;
  2862. // Store everything in the same order that the builder parses scripts
  2863. // TODO: Should be possible to skip saving the enum values. They are usually not needed after the script is compiled anyway
  2864. // TODO: Should be possible to skip saving the typedefs. They are usually not needed after the script is compiled anyway
  2865. // TODO: Should be possible to skip saving constants. They are usually not needed after the script is compiled anyway
  2866. WriteData(&stripDebugInfo, sizeof(stripDebugInfo));
  2867. // Store enums
  2868. count = (asUINT)module->enumTypes.GetLength();
  2869. WriteEncodedInt64(count);
  2870. for( i = 0; i < count; i++ )
  2871. {
  2872. WriteObjectTypeDeclaration(module->enumTypes[i], 1);
  2873. WriteObjectTypeDeclaration(module->enumTypes[i], 2);
  2874. }
  2875. // Store type declarations first
  2876. count = (asUINT)module->classTypes.GetLength();
  2877. WriteEncodedInt64(count);
  2878. for( i = 0; i < count; i++ )
  2879. {
  2880. // Store only the name of the class/interface types
  2881. WriteObjectTypeDeclaration(module->classTypes[i], 1);
  2882. }
  2883. // Store func defs
  2884. count = (asUINT)module->funcDefs.GetLength();
  2885. WriteEncodedInt64(count);
  2886. for( i = 0; i < count; i++ )
  2887. WriteFunction(module->funcDefs[i]);
  2888. // Now store all interface methods
  2889. count = (asUINT)module->classTypes.GetLength();
  2890. for( i = 0; i < count; i++ )
  2891. {
  2892. if( module->classTypes[i]->IsInterface() )
  2893. WriteObjectTypeDeclaration(module->classTypes[i], 2);
  2894. }
  2895. // Then store the class methods and behaviours
  2896. for( i = 0; i < count; ++i )
  2897. {
  2898. if( !module->classTypes[i]->IsInterface() )
  2899. WriteObjectTypeDeclaration(module->classTypes[i], 2);
  2900. }
  2901. // Then store the class properties
  2902. for( i = 0; i < count; ++i )
  2903. {
  2904. if( !module->classTypes[i]->IsInterface() )
  2905. WriteObjectTypeDeclaration(module->classTypes[i], 3);
  2906. }
  2907. // Store typedefs
  2908. count = (asUINT)module->typeDefs.GetLength();
  2909. WriteEncodedInt64(count);
  2910. for( i = 0; i < count; i++ )
  2911. {
  2912. WriteObjectTypeDeclaration(module->typeDefs[i], 1);
  2913. WriteObjectTypeDeclaration(module->typeDefs[i], 2);
  2914. }
  2915. // scriptGlobals[]
  2916. count = (asUINT)module->scriptGlobals.GetSize();
  2917. WriteEncodedInt64(count);
  2918. asCSymbolTable<asCGlobalProperty>::iterator it = module->scriptGlobals.List();
  2919. for( ; it; it++ )
  2920. WriteGlobalProperty(*it);
  2921. // scriptFunctions[]
  2922. count = 0;
  2923. for( i = 0; i < module->scriptFunctions.GetLength(); i++ )
  2924. if( module->scriptFunctions[i]->objectType == 0 )
  2925. count++;
  2926. WriteEncodedInt64(count);
  2927. for( i = 0; i < module->scriptFunctions.GetLength(); ++i )
  2928. if( module->scriptFunctions[i]->objectType == 0 )
  2929. WriteFunction(module->scriptFunctions[i]);
  2930. // globalFunctions[]
  2931. count = (int)module->globalFunctions.GetSize();
  2932. asCSymbolTable<asCScriptFunction>::iterator funcIt = module->globalFunctions.List();
  2933. WriteEncodedInt64(count);
  2934. while( funcIt )
  2935. {
  2936. WriteFunction(*funcIt);
  2937. funcIt++;
  2938. }
  2939. // bindInformations[]
  2940. count = (asUINT)module->bindInformations.GetLength();
  2941. WriteEncodedInt64(count);
  2942. for( i = 0; i < count; ++i )
  2943. {
  2944. WriteFunction(module->bindInformations[i]->importedFunctionSignature);
  2945. WriteString(&module->bindInformations[i]->importFromModule);
  2946. }
  2947. // usedTypes[]
  2948. count = (asUINT)usedTypes.GetLength();
  2949. WriteEncodedInt64(count);
  2950. for( i = 0; i < count; ++i )
  2951. WriteObjectType(usedTypes[i]);
  2952. // usedTypeIds[]
  2953. WriteUsedTypeIds();
  2954. // usedFunctions[]
  2955. WriteUsedFunctions();
  2956. // usedGlobalProperties[]
  2957. WriteUsedGlobalProps();
  2958. // usedStringConstants[]
  2959. WriteUsedStringConstants();
  2960. // usedObjectProperties[]
  2961. WriteUsedObjectProps();
  2962. return asSUCCESS;
  2963. }
  2964. int asCWriter::FindStringConstantIndex(int id)
  2965. {
  2966. asSMapNode<int,int> *cursor = 0;
  2967. if (stringIdToIndexMap.MoveTo(&cursor, id))
  2968. return cursor->value;
  2969. usedStringConstants.PushLast(id);
  2970. int index = int(usedStringConstants.GetLength() - 1);
  2971. stringIdToIndexMap.Insert(id, index);
  2972. return index;
  2973. }
  2974. void asCWriter::WriteUsedStringConstants()
  2975. {
  2976. asUINT count = (asUINT)usedStringConstants.GetLength();
  2977. WriteEncodedInt64(count);
  2978. for( asUINT i = 0; i < count; ++i )
  2979. WriteString(engine->stringConstants[usedStringConstants[i]]);
  2980. }
  2981. void asCWriter::WriteUsedFunctions()
  2982. {
  2983. asUINT count = (asUINT)usedFunctions.GetLength();
  2984. WriteEncodedInt64(count);
  2985. for( asUINT n = 0; n < usedFunctions.GetLength(); n++ )
  2986. {
  2987. char c;
  2988. // Write enough data to be able to uniquely identify the function upon load
  2989. if( usedFunctions[n] )
  2990. {
  2991. // Is the function from the module or the application?
  2992. c = usedFunctions[n]->module ? 'm' : 'a';
  2993. WriteData(&c, 1);
  2994. WriteFunctionSignature(usedFunctions[n]);
  2995. }
  2996. else
  2997. {
  2998. // null function pointer
  2999. c = 'n';
  3000. WriteData(&c, 1);
  3001. }
  3002. }
  3003. }
  3004. void asCWriter::WriteFunctionSignature(asCScriptFunction *func)
  3005. {
  3006. asUINT i, count;
  3007. WriteString(&func->name);
  3008. if( func->name == DELEGATE_FACTORY )
  3009. {
  3010. // It's not necessary to write anything else
  3011. return;
  3012. }
  3013. WriteDataType(&func->returnType);
  3014. count = (asUINT)func->parameterTypes.GetLength();
  3015. WriteEncodedInt64(count);
  3016. for( i = 0; i < count; ++i )
  3017. WriteDataType(&func->parameterTypes[i]);
  3018. // Only write the inout flags if any of them are set
  3019. count = 0;
  3020. for( i = asUINT(func->inOutFlags.GetLength()); i > 0; i-- )
  3021. if( func->inOutFlags[i-1] != asTM_NONE )
  3022. {
  3023. count = i;
  3024. break;
  3025. }
  3026. WriteEncodedInt64(count);
  3027. for( i = 0; i < count; ++i )
  3028. WriteEncodedInt64(func->inOutFlags[i]);
  3029. WriteEncodedInt64(func->funcType);
  3030. // Write the default args, from last to first
  3031. count = 0;
  3032. for( i = (asUINT)func->defaultArgs.GetLength(); i-- > 0; )
  3033. if( func->defaultArgs[i] )
  3034. count++;
  3035. WriteEncodedInt64(count);
  3036. for( i = (asUINT)func->defaultArgs.GetLength(); i-- > 0; )
  3037. if( func->defaultArgs[i] )
  3038. WriteString(func->defaultArgs[i]);
  3039. WriteObjectType(func->objectType);
  3040. if( func->objectType )
  3041. {
  3042. asBYTE b = 0;
  3043. b += func->isReadOnly ? 1 : 0;
  3044. b += func->isPrivate ? 2 : 0;
  3045. b += func->isProtected ? 4 : 0;
  3046. WriteData(&b, 1);
  3047. }
  3048. else
  3049. {
  3050. WriteString(&func->nameSpace->name);
  3051. }
  3052. }
  3053. void asCWriter::WriteFunction(asCScriptFunction* func)
  3054. {
  3055. char c;
  3056. // If there is no function, then store a null char
  3057. if( func == 0 )
  3058. {
  3059. c = '\0';
  3060. WriteData(&c, 1);
  3061. return;
  3062. }
  3063. // First check if the function has been saved already
  3064. for( asUINT f = 0; f < savedFunctions.GetLength(); f++ )
  3065. {
  3066. if( savedFunctions[f] == func )
  3067. {
  3068. c = 'r';
  3069. WriteData(&c, 1);
  3070. WriteEncodedInt64(f);
  3071. return;
  3072. }
  3073. }
  3074. // Keep a reference to the function in the list
  3075. savedFunctions.PushLast(func);
  3076. c = 'f';
  3077. WriteData(&c, 1);
  3078. asUINT i, count;
  3079. WriteFunctionSignature(func);
  3080. if( func->funcType == asFUNC_SCRIPT )
  3081. {
  3082. // Calculate the adjustment by position lookup table
  3083. CalculateAdjustmentByPos(func);
  3084. WriteByteCode(func);
  3085. asDWORD varSpace = AdjustStackPosition(func->scriptData->variableSpace);
  3086. WriteEncodedInt64(varSpace);
  3087. count = (asUINT)func->scriptData->objVariablePos.GetLength();
  3088. WriteEncodedInt64(count);
  3089. for( i = 0; i < count; ++i )
  3090. {
  3091. WriteObjectType(func->scriptData->objVariableTypes[i]);
  3092. // TODO: Only write this if the object type is the builtin function type
  3093. WriteEncodedInt64(FindFunctionIndex(func->scriptData->funcVariableTypes[i]));
  3094. WriteEncodedInt64(AdjustStackPosition(func->scriptData->objVariablePos[i]));
  3095. }
  3096. if( count > 0 )
  3097. WriteEncodedInt64(func->scriptData->objVariablesOnHeap);
  3098. WriteEncodedInt64((asUINT)func->scriptData->objVariableInfo.GetLength());
  3099. for( i = 0; i < func->scriptData->objVariableInfo.GetLength(); ++i )
  3100. {
  3101. // The program position must be adjusted to be in number of instructions
  3102. WriteEncodedInt64(bytecodeNbrByPos[func->scriptData->objVariableInfo[i].programPos]);
  3103. WriteEncodedInt64(AdjustStackPosition(func->scriptData->objVariableInfo[i].variableOffset));
  3104. WriteEncodedInt64(func->scriptData->objVariableInfo[i].option);
  3105. }
  3106. // The program position (every even number) needs to be adjusted
  3107. // to be in number of instructions instead of DWORD offset
  3108. if( !stripDebugInfo )
  3109. {
  3110. asUINT length = (asUINT)func->scriptData->lineNumbers.GetLength();
  3111. WriteEncodedInt64(length);
  3112. for( i = 0; i < length; ++i )
  3113. {
  3114. if( (i & 1) == 0 )
  3115. WriteEncodedInt64(bytecodeNbrByPos[func->scriptData->lineNumbers[i]]);
  3116. else
  3117. WriteEncodedInt64(func->scriptData->lineNumbers[i]);
  3118. }
  3119. // Write the array of script sections
  3120. length = (asUINT)func->scriptData->sectionIdxs.GetLength();
  3121. WriteEncodedInt64(length);
  3122. for( i = 0; i < length; ++i )
  3123. {
  3124. if( (i & 1) == 0 )
  3125. WriteEncodedInt64(bytecodeNbrByPos[func->scriptData->sectionIdxs[i]]);
  3126. else
  3127. {
  3128. if( func->scriptData->sectionIdxs[i] >= 0 )
  3129. WriteString(engine->scriptSectionNames[func->scriptData->sectionIdxs[i]]);
  3130. else
  3131. {
  3132. char c = 0;
  3133. WriteData(&c, 1);
  3134. }
  3135. }
  3136. }
  3137. }
  3138. // Write the variable information
  3139. if( !stripDebugInfo )
  3140. {
  3141. WriteEncodedInt64((asUINT)func->scriptData->variables.GetLength());
  3142. for( i = 0; i < func->scriptData->variables.GetLength(); i++ )
  3143. {
  3144. // The program position must be adjusted to be in number of instructions
  3145. WriteEncodedInt64(bytecodeNbrByPos[func->scriptData->variables[i]->declaredAtProgramPos]);
  3146. // The stack position must be adjusted according to the pointer sizes
  3147. WriteEncodedInt64(AdjustStackPosition(func->scriptData->variables[i]->stackOffset));
  3148. WriteString(&func->scriptData->variables[i]->name);
  3149. WriteDataType(&func->scriptData->variables[i]->type);
  3150. }
  3151. }
  3152. char bits = 0;
  3153. bits += func->isShared ? 1 : 0;
  3154. bits += func->dontCleanUpOnException ? 2 : 0;
  3155. WriteData(&bits,1);
  3156. // Store script section name
  3157. if( !stripDebugInfo )
  3158. {
  3159. if( func->scriptData->scriptSectionIdx >= 0 )
  3160. WriteString(engine->scriptSectionNames[func->scriptData->scriptSectionIdx]);
  3161. else
  3162. {
  3163. char c = 0;
  3164. WriteData(&c, 1);
  3165. }
  3166. WriteEncodedInt64(func->scriptData->declaredAt);
  3167. }
  3168. // Store the parameter names
  3169. if( !stripDebugInfo )
  3170. {
  3171. asUINT count = asUINT(func->parameterNames.GetLength());
  3172. WriteEncodedInt64(count);
  3173. for( asUINT n = 0; n < count; n++ )
  3174. WriteString(&func->parameterNames[n]);
  3175. }
  3176. }
  3177. else if( func->funcType == asFUNC_VIRTUAL || func->funcType == asFUNC_INTERFACE )
  3178. {
  3179. // TODO: Do we really need to store this? It can probably be reconstructed by the reader
  3180. WriteEncodedInt64(func->vfTableIdx);
  3181. }
  3182. }
  3183. void asCWriter::WriteObjectTypeDeclaration(asCObjectType *ot, int phase)
  3184. {
  3185. if( phase == 1 )
  3186. {
  3187. // name
  3188. WriteString(&ot->name);
  3189. // flags
  3190. WriteData(&ot->flags, 4);
  3191. // size
  3192. // TODO: Do we really need to store this? The reader should be able to
  3193. // determine the correct size from the object type's flags
  3194. if( (ot->flags & asOBJ_SCRIPT_OBJECT) && ot->size > 0 )
  3195. {
  3196. // The size for script objects may vary from platform to platform so
  3197. // only store 1 to diferentiate from interfaces that have size 0.
  3198. WriteEncodedInt64(1);
  3199. }
  3200. else
  3201. {
  3202. // Enums, typedefs, and interfaces have fixed sizes independently
  3203. // of platform so it is safe to serialize the size directly.
  3204. WriteEncodedInt64(ot->size);
  3205. }
  3206. // namespace
  3207. WriteString(&ot->nameSpace->name);
  3208. }
  3209. else if( phase == 2 )
  3210. {
  3211. if( ot->flags & asOBJ_ENUM )
  3212. {
  3213. // enumValues[]
  3214. int size = (int)ot->enumValues.GetLength();
  3215. WriteEncodedInt64(size);
  3216. for( int n = 0; n < size; n++ )
  3217. {
  3218. WriteString(&ot->enumValues[n]->name);
  3219. WriteData(&ot->enumValues[n]->value, 4);
  3220. }
  3221. }
  3222. else if( ot->flags & asOBJ_TYPEDEF )
  3223. {
  3224. eTokenType t = ot->templateSubTypes[0].GetTokenType();
  3225. WriteEncodedInt64(t);
  3226. }
  3227. else
  3228. {
  3229. WriteObjectType(ot->derivedFrom);
  3230. // interfaces[] / interfaceVFTOffsets[]
  3231. // TOOD: Is it really necessary to store the VFTOffsets? Can't the reader calculate those?
  3232. int size = (asUINT)ot->interfaces.GetLength();
  3233. WriteEncodedInt64(size);
  3234. asUINT n;
  3235. asASSERT( ot->interfaces.GetLength() == ot->interfaceVFTOffsets.GetLength() );
  3236. for( n = 0; n < ot->interfaces.GetLength(); n++ )
  3237. {
  3238. WriteObjectType(ot->interfaces[n]);
  3239. WriteEncodedInt64(ot->interfaceVFTOffsets[n]);
  3240. }
  3241. // behaviours
  3242. // TODO: Default behaviours should just be stored as a indicator
  3243. // to avoid storing the actual function object
  3244. if( !ot->IsInterface() && ot->flags != asOBJ_TYPEDEF && ot->flags != asOBJ_ENUM )
  3245. {
  3246. WriteFunction(engine->scriptFunctions[ot->beh.destruct]);
  3247. size = (int)ot->beh.constructors.GetLength();
  3248. WriteEncodedInt64(size);
  3249. for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
  3250. {
  3251. WriteFunction(engine->scriptFunctions[ot->beh.constructors[n]]);
  3252. WriteFunction(engine->scriptFunctions[ot->beh.factories[n]]);
  3253. }
  3254. }
  3255. // methods[]
  3256. // TODO: Avoid storing inherited methods in interfaces, as the reader
  3257. // can add those directly from the base interface
  3258. size = (int)ot->methods.GetLength();
  3259. WriteEncodedInt64(size);
  3260. for( n = 0; n < ot->methods.GetLength(); n++ )
  3261. {
  3262. WriteFunction(engine->scriptFunctions[ot->methods[n]]);
  3263. }
  3264. // virtualFunctionTable[]
  3265. // TODO: Is it really necessary to store this? Can't it be easily rebuilt by the reader
  3266. size = (int)ot->virtualFunctionTable.GetLength();
  3267. WriteEncodedInt64(size);
  3268. for( n = 0; n < (asUINT)size; n++ )
  3269. {
  3270. WriteFunction(ot->virtualFunctionTable[n]);
  3271. }
  3272. }
  3273. }
  3274. else if( phase == 3 )
  3275. {
  3276. // properties[]
  3277. asUINT size = (asUINT)ot->properties.GetLength();
  3278. WriteEncodedInt64(size);
  3279. for( asUINT n = 0; n < ot->properties.GetLength(); n++ )
  3280. {
  3281. WriteObjectProperty(ot->properties[n]);
  3282. }
  3283. }
  3284. }
  3285. void asCWriter::WriteEncodedInt64(asINT64 i)
  3286. {
  3287. asBYTE signBit = ( i & asINT64(1)<<63 ) ? 0x80 : 0;
  3288. if( signBit ) i = -i;
  3289. asBYTE b;
  3290. if( i < (1<<6) )
  3291. {
  3292. b = (asBYTE)(signBit + i); WriteData(&b, 1);
  3293. }
  3294. else if( i < (1<<13) )
  3295. {
  3296. b = asBYTE(0x40 + signBit + (i >> 8)); WriteData(&b, 1);
  3297. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3298. }
  3299. else if( i < (1<<20) )
  3300. {
  3301. b = asBYTE(0x60 + signBit + (i >> 16)); WriteData(&b, 1);
  3302. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3303. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3304. }
  3305. else if( i < (1<<27) )
  3306. {
  3307. b = asBYTE(0x70 + signBit + (i >> 24)); WriteData(&b, 1);
  3308. b = asBYTE((i >> 16) & 0xFF); WriteData(&b, 1);
  3309. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3310. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3311. }
  3312. else if( i < (asINT64(1)<<34) )
  3313. {
  3314. b = asBYTE(0x78 + signBit + (i >> 32)); WriteData(&b, 1);
  3315. b = asBYTE((i >> 24) & 0xFF); WriteData(&b, 1);
  3316. b = asBYTE((i >> 16) & 0xFF); WriteData(&b, 1);
  3317. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3318. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3319. }
  3320. else if( i < (asINT64(1)<<41) )
  3321. {
  3322. b = asBYTE(0x7C + signBit + (i >> 40)); WriteData(&b, 1);
  3323. b = asBYTE((i >> 32) & 0xFF); WriteData(&b, 1);
  3324. b = asBYTE((i >> 24) & 0xFF); WriteData(&b, 1);
  3325. b = asBYTE((i >> 16) & 0xFF); WriteData(&b, 1);
  3326. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3327. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3328. }
  3329. else if( i < (asINT64(1)<<48) )
  3330. {
  3331. b = asBYTE(0x7E + signBit + (i >> 48)); WriteData(&b, 1);
  3332. b = asBYTE((i >> 40) & 0xFF); WriteData(&b, 1);
  3333. b = asBYTE((i >> 32) & 0xFF); WriteData(&b, 1);
  3334. b = asBYTE((i >> 24) & 0xFF); WriteData(&b, 1);
  3335. b = asBYTE((i >> 16) & 0xFF); WriteData(&b, 1);
  3336. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3337. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3338. }
  3339. else
  3340. {
  3341. b = asBYTE(0x7F + signBit); WriteData(&b, 1);
  3342. b = asBYTE((i >> 56) & 0xFF); WriteData(&b, 1);
  3343. b = asBYTE((i >> 48) & 0xFF); WriteData(&b, 1);
  3344. b = asBYTE((i >> 40) & 0xFF); WriteData(&b, 1);
  3345. b = asBYTE((i >> 32) & 0xFF); WriteData(&b, 1);
  3346. b = asBYTE((i >> 24) & 0xFF); WriteData(&b, 1);
  3347. b = asBYTE((i >> 16) & 0xFF); WriteData(&b, 1);
  3348. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3349. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3350. }
  3351. }
  3352. void asCWriter::WriteString(asCString* str)
  3353. {
  3354. // TODO: All strings should be stored in a separate section, and when
  3355. // they are used an offset into that section should be stored.
  3356. // This will make it unnecessary to store the extra byte to
  3357. // identify new versus old strings.
  3358. if( str->GetLength() == 0 )
  3359. {
  3360. char z = '\0';
  3361. WriteData(&z, 1);
  3362. return;
  3363. }
  3364. // First check if the string hasn't been saved already
  3365. asSMapNode<asCStringPointer, int> *cursor = 0;
  3366. if (stringToIdMap.MoveTo(&cursor, asCStringPointer(str)))
  3367. {
  3368. // Save a reference to the existing string
  3369. char b = 'r';
  3370. WriteData(&b, 1);
  3371. WriteEncodedInt64(cursor->value);
  3372. return;
  3373. }
  3374. // Save a new string
  3375. char b = 'n';
  3376. WriteData(&b, 1);
  3377. asUINT len = (asUINT)str->GetLength();
  3378. WriteEncodedInt64(len);
  3379. stream->Write(str->AddressOf(), (asUINT)len);
  3380. savedStrings.PushLast(*str);
  3381. stringToIdMap.Insert(asCStringPointer(str), int(savedStrings.GetLength()) - 1);
  3382. }
  3383. void asCWriter::WriteGlobalProperty(asCGlobalProperty* prop)
  3384. {
  3385. // TODO: We might be able to avoid storing the name and type of the global
  3386. // properties twice if we merge this with the WriteUsedGlobalProperties.
  3387. WriteString(&prop->name);
  3388. WriteString(&prop->nameSpace->name);
  3389. WriteDataType(&prop->type);
  3390. // Store the initialization function
  3391. WriteFunction(prop->GetInitFunc());
  3392. }
  3393. void asCWriter::WriteObjectProperty(asCObjectProperty* prop)
  3394. {
  3395. WriteString(&prop->name);
  3396. WriteDataType(&prop->type);
  3397. int flags = 0;
  3398. if( prop->isPrivate ) flags |= 1;
  3399. if( prop->isProtected ) flags |= 2;
  3400. if( prop->isInherited ) flags |= 4;
  3401. WriteEncodedInt64(flags);
  3402. }
  3403. void asCWriter::WriteDataType(const asCDataType *dt)
  3404. {
  3405. // First check if the datatype has already been saved
  3406. for( asUINT n = 0; n < savedDataTypes.GetLength(); n++ )
  3407. {
  3408. if( *dt == savedDataTypes[n] )
  3409. {
  3410. WriteEncodedInt64(n+1);
  3411. return;
  3412. }
  3413. }
  3414. // Indicate a new type with a null byte
  3415. asUINT c = 0;
  3416. WriteEncodedInt64(c);
  3417. // Save the new datatype
  3418. savedDataTypes.PushLast(*dt);
  3419. int t = dt->GetTokenType();
  3420. WriteEncodedInt64(t);
  3421. if( t == ttIdentifier )
  3422. WriteObjectType(dt->GetObjectType());
  3423. struct
  3424. {
  3425. char isObjectHandle :1;
  3426. char isHandleToConst:1;
  3427. char isReference :1;
  3428. char isReadOnly :1;
  3429. } bits = {0};
  3430. bits.isObjectHandle = dt->IsObjectHandle();
  3431. bits.isHandleToConst = dt->IsHandleToConst();
  3432. bits.isReference = dt->IsReference();
  3433. bits.isReadOnly = dt->IsReadOnly();
  3434. WriteData(&bits, 1);
  3435. if( t == ttIdentifier && dt->GetObjectType()->name == "_builtin_function_" )
  3436. {
  3437. WriteFunctionSignature(dt->GetFuncDef());
  3438. }
  3439. }
  3440. void asCWriter::WriteObjectType(asCObjectType* ot)
  3441. {
  3442. char ch;
  3443. if( ot )
  3444. {
  3445. // Check for template instances/specializations
  3446. if( ot->templateSubTypes.GetLength() )
  3447. {
  3448. // Check for list pattern type or template type
  3449. if( ot->flags & asOBJ_LIST_PATTERN )
  3450. {
  3451. ch = 'l';
  3452. WriteData(&ch, 1);
  3453. WriteObjectType(ot->templateSubTypes[0].GetObjectType());
  3454. }
  3455. else
  3456. {
  3457. ch = 'a';
  3458. WriteData(&ch, 1);
  3459. WriteString(&ot->name);
  3460. WriteString(&ot->nameSpace->name);
  3461. WriteEncodedInt64(ot->templateSubTypes.GetLength());
  3462. for( asUINT n = 0; n < ot->templateSubTypes.GetLength(); n++ )
  3463. {
  3464. if( ot->templateSubTypes[0].IsObject() || ot->templateSubTypes[0].IsEnumType() )
  3465. {
  3466. ch = 's';
  3467. WriteData(&ch, 1);
  3468. WriteDataType(&ot->templateSubTypes[0]);
  3469. }
  3470. else
  3471. {
  3472. ch = 't';
  3473. WriteData(&ch, 1);
  3474. eTokenType t = ot->templateSubTypes[0].GetTokenType();
  3475. WriteEncodedInt64(t);
  3476. }
  3477. }
  3478. }
  3479. }
  3480. else if( ot->flags & asOBJ_TEMPLATE_SUBTYPE )
  3481. {
  3482. ch = 's';
  3483. WriteData(&ch, 1);
  3484. WriteString(&ot->name);
  3485. }
  3486. else
  3487. {
  3488. ch = 'o';
  3489. WriteData(&ch, 1);
  3490. WriteString(&ot->name);
  3491. WriteString(&ot->nameSpace->name);
  3492. }
  3493. }
  3494. else
  3495. {
  3496. ch = '\0';
  3497. WriteData(&ch, 1);
  3498. }
  3499. }
  3500. void asCWriter::CalculateAdjustmentByPos(asCScriptFunction *func)
  3501. {
  3502. // Adjust the offset of all negative variables (parameters) so all pointers will have a size of 1 dword
  3503. asUINT n;
  3504. asCArray<int> adjustments;
  3505. asUINT offset = 0;
  3506. if( func->objectType )
  3507. {
  3508. adjustments.PushLast(offset);
  3509. adjustments.PushLast(1-AS_PTR_SIZE);
  3510. offset += AS_PTR_SIZE;
  3511. }
  3512. if( func->DoesReturnOnStack() )
  3513. {
  3514. adjustments.PushLast(offset);
  3515. adjustments.PushLast(1-AS_PTR_SIZE);
  3516. offset += AS_PTR_SIZE;
  3517. }
  3518. for( n = 0; n < func->parameterTypes.GetLength(); n++ )
  3519. {
  3520. if( !func->parameterTypes[n].IsPrimitive() ||
  3521. func->parameterTypes[n].IsReference() )
  3522. {
  3523. adjustments.PushLast(offset);
  3524. adjustments.PushLast(1-AS_PTR_SIZE);
  3525. offset += AS_PTR_SIZE;
  3526. }
  3527. else
  3528. {
  3529. asASSERT( func->parameterTypes[n].IsPrimitive() );
  3530. offset += func->parameterTypes[n].GetSizeOnStackDWords();
  3531. }
  3532. }
  3533. // Build look-up table with the adjustments for each stack position
  3534. adjustNegativeStackByPos.SetLength(offset);
  3535. memset(adjustNegativeStackByPos.AddressOf(), 0, adjustNegativeStackByPos.GetLength()*sizeof(int));
  3536. for( n = 0; n < adjustments.GetLength(); n+=2 )
  3537. {
  3538. int pos = adjustments[n];
  3539. int adjust = adjustments[n+1];
  3540. for( asUINT i = pos+1; i < adjustNegativeStackByPos.GetLength(); i++ )
  3541. adjustNegativeStackByPos[i] += adjust;
  3542. }
  3543. // Adjust the offset of all positive variables so that all object types and handles have a size of 1 dword
  3544. // This is similar to how the adjustment is done in the asCReader::TranslateFunction, only the reverse
  3545. adjustments.SetLength(0);
  3546. for( n = 0; n < func->scriptData->objVariableTypes.GetLength(); n++ )
  3547. {
  3548. if( func->scriptData->objVariableTypes[n] )
  3549. {
  3550. // Determine the size the variable currently occupies on the stack
  3551. int size = AS_PTR_SIZE;
  3552. if( (func->scriptData->objVariableTypes[n]->GetFlags() & asOBJ_VALUE) &&
  3553. n >= func->scriptData->objVariablesOnHeap )
  3554. {
  3555. size = func->scriptData->objVariableTypes[n]->GetSize();
  3556. if( size < 4 )
  3557. size = 1;
  3558. else
  3559. size /= 4;
  3560. }
  3561. // If larger than 1 dword, adjust the offsets accordingly
  3562. if( size > 1 )
  3563. {
  3564. // How much needs to be adjusted?
  3565. adjustments.PushLast(func->scriptData->objVariablePos[n]);
  3566. adjustments.PushLast(-(size-1));
  3567. }
  3568. }
  3569. }
  3570. // Build look-up table with the adjustments for each stack position
  3571. adjustStackByPos.SetLength(func->scriptData->stackNeeded);
  3572. memset(adjustStackByPos.AddressOf(), 0, adjustStackByPos.GetLength()*sizeof(int));
  3573. for( n = 0; n < adjustments.GetLength(); n+=2 )
  3574. {
  3575. int pos = adjustments[n];
  3576. int adjust = adjustments[n+1];
  3577. for( asUINT i = pos; i < adjustStackByPos.GetLength(); i++ )
  3578. adjustStackByPos[i] += adjust;
  3579. }
  3580. // Compute the sequence number of each bytecode instruction in order to update the jump offsets
  3581. asUINT length = func->scriptData->byteCode.GetLength();
  3582. asDWORD *bc = func->scriptData->byteCode.AddressOf();
  3583. bytecodeNbrByPos.SetLength(length);
  3584. asUINT num;
  3585. for( offset = 0, num = 0; offset < length; )
  3586. {
  3587. bytecodeNbrByPos[offset] = num;
  3588. offset += asBCTypeSize[asBCInfo[*(asBYTE*)(bc+offset)].type];
  3589. num++;
  3590. }
  3591. // The last instruction is always a BC_RET. This make it possible to query
  3592. // the number of instructions by checking the last entry in bytecodeNbrByPos
  3593. asASSERT(*(asBYTE*)(bc+length-1) == asBC_RET);
  3594. }
  3595. int asCWriter::AdjustStackPosition(int pos)
  3596. {
  3597. if( pos >= (int)adjustStackByPos.GetLength() )
  3598. {
  3599. // This happens for example if the function only have temporary variables
  3600. // The adjustByPos can also be empty if the function doesn't have any variables at all, but receive a handle by parameter
  3601. if( adjustStackByPos.GetLength() > 0 )
  3602. pos += adjustStackByPos[adjustStackByPos.GetLength()-1];
  3603. }
  3604. else if( pos >= 0 )
  3605. pos += adjustStackByPos[pos];
  3606. else
  3607. {
  3608. asASSERT( -pos < (int)adjustNegativeStackByPos.GetLength() );
  3609. pos -= (short)adjustNegativeStackByPos[-pos];
  3610. }
  3611. return pos;
  3612. }
  3613. int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD programPos)
  3614. {
  3615. // TODO: optimize: multiple instructions for the same function doesn't need to look for the function everytime
  3616. // the function can remember where it found the function and check if the programPos is still valid
  3617. // Get offset 0 doesn't need adjustment
  3618. if( offset == 0 ) return 0;
  3619. // Find out which function that will be called
  3620. asCScriptFunction *calledFunc = 0;
  3621. for( asUINT n = programPos; n < func->scriptData->byteCode.GetLength(); )
  3622. {
  3623. asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[n];
  3624. if( bc == asBC_CALL ||
  3625. bc == asBC_CALLSYS ||
  3626. bc == asBC_Thiscall1 ||
  3627. bc == asBC_CALLINTF )
  3628. {
  3629. // Find the function from the function id in bytecode
  3630. int funcId = asBC_INTARG(&func->scriptData->byteCode[n]);
  3631. calledFunc = engine->scriptFunctions[funcId];
  3632. break;
  3633. }
  3634. else if( bc == asBC_ALLOC )
  3635. {
  3636. // Find the function from the function id in the bytecode
  3637. int funcId = asBC_INTARG(&func->scriptData->byteCode[n+AS_PTR_SIZE]);
  3638. calledFunc = engine->scriptFunctions[funcId];
  3639. break;
  3640. }
  3641. else if( bc == asBC_CALLBND )
  3642. {
  3643. // Find the function from the engine's bind array
  3644. int funcId = asBC_INTARG(&func->scriptData->byteCode[n]);
  3645. calledFunc = engine->importedFunctions[funcId & ~FUNC_IMPORTED]->importedFunctionSignature;
  3646. break;
  3647. }
  3648. else if( bc == asBC_CallPtr )
  3649. {
  3650. int var = asBC_SWORDARG0(&func->scriptData->byteCode[n]);
  3651. asUINT v;
  3652. // Find the funcdef from the local variable
  3653. for( v = 0; v < func->scriptData->objVariablePos.GetLength(); v++ )
  3654. {
  3655. if( func->scriptData->objVariablePos[v] == var )
  3656. {
  3657. calledFunc = func->scriptData->funcVariableTypes[v];
  3658. break;
  3659. }
  3660. }
  3661. if( !calledFunc )
  3662. {
  3663. // Look in parameters
  3664. int paramPos = 0;
  3665. if( func->objectType )
  3666. paramPos -= AS_PTR_SIZE;
  3667. if( func->DoesReturnOnStack() )
  3668. paramPos -= AS_PTR_SIZE;
  3669. for( v = 0; v < func->parameterTypes.GetLength(); v++ )
  3670. {
  3671. if( var == paramPos )
  3672. {
  3673. calledFunc = func->parameterTypes[v].GetFuncDef();
  3674. break;
  3675. }
  3676. paramPos -= func->parameterTypes[v].GetSizeOnStackDWords();
  3677. }
  3678. }
  3679. break;
  3680. }
  3681. else if( bc == asBC_REFCPY ||
  3682. bc == asBC_COPY )
  3683. {
  3684. // In this case we know there is only 1 pointer on the stack above
  3685. asASSERT( offset == AS_PTR_SIZE );
  3686. return offset + (1 - AS_PTR_SIZE);
  3687. }
  3688. n += asBCTypeSize[asBCInfo[bc].type];
  3689. }
  3690. asASSERT( calledFunc );
  3691. // Count the number of pointers pushed on the stack above the
  3692. // current offset, and then adjust the offset accordingly
  3693. asUINT numPtrs = 0;
  3694. int currOffset = 0;
  3695. if( offset > currOffset && calledFunc->GetObjectType() )
  3696. {
  3697. numPtrs++;
  3698. currOffset += AS_PTR_SIZE;
  3699. }
  3700. if( offset > currOffset && calledFunc->DoesReturnOnStack() )
  3701. {
  3702. numPtrs++;
  3703. currOffset += AS_PTR_SIZE;
  3704. }
  3705. for( asUINT p = 0; p < calledFunc->parameterTypes.GetLength(); p++ )
  3706. {
  3707. if( offset <= currOffset ) break;
  3708. if( !calledFunc->parameterTypes[p].IsPrimitive() ||
  3709. calledFunc->parameterTypes[p].IsReference() )
  3710. {
  3711. // objects and references are passed by pointer
  3712. numPtrs++;
  3713. currOffset += AS_PTR_SIZE;
  3714. // The variable arg ? has an additional 32bit int with the typeid
  3715. if( calledFunc->parameterTypes[p].IsAnyType() )
  3716. currOffset += 1;
  3717. }
  3718. else
  3719. {
  3720. // built-in primitives or enums are passed by value
  3721. asASSERT( calledFunc->parameterTypes[p].IsPrimitive() );
  3722. currOffset += calledFunc->parameterTypes[p].GetSizeOnStackDWords();
  3723. }
  3724. }
  3725. // The get offset must match one of the parameter offsets
  3726. asASSERT( offset == currOffset );
  3727. return offset + numPtrs * (1 - AS_PTR_SIZE);
  3728. }
  3729. void asCWriter::WriteByteCode(asCScriptFunction *func)
  3730. {
  3731. asDWORD *bc = func->scriptData->byteCode.AddressOf();
  3732. size_t length = func->scriptData->byteCode.GetLength();
  3733. // The length cannot be stored, because it is platform dependent,
  3734. // instead we store the number of instructions
  3735. asUINT count = bytecodeNbrByPos[bytecodeNbrByPos.GetLength()-1] + 1;
  3736. WriteEncodedInt64(count);
  3737. asDWORD *startBC = bc;
  3738. while( length )
  3739. {
  3740. asDWORD tmp[4]; // The biggest instructions take up 4 DWORDs
  3741. asDWORD c = *(asBYTE*)bc;
  3742. // Copy the instruction to a temp buffer so we can work on it before saving
  3743. memcpy(tmp, bc, asBCTypeSize[asBCInfo[c].type]*sizeof(asDWORD));
  3744. if( c == asBC_ALLOC ) // PTR_DW_ARG
  3745. {
  3746. // Translate the object type
  3747. asCObjectType *ot = *(asCObjectType**)(tmp+1);
  3748. *(asPWORD*)(tmp+1) = FindObjectTypeIdx(ot);
  3749. // Translate the constructor func id, unless it is 0
  3750. if( *(int*)&tmp[1+AS_PTR_SIZE] != 0 )
  3751. {
  3752. // Increment 1 to the translated function id, as 0 will be reserved for no function
  3753. *(int*)&tmp[1+AS_PTR_SIZE] = 1+FindFunctionIndex(engine->scriptFunctions[*(int*)&tmp[1+AS_PTR_SIZE]]);
  3754. }
  3755. }
  3756. else if( c == asBC_REFCPY || // PTR_ARG
  3757. c == asBC_RefCpyV || // wW_PTR_ARG
  3758. c == asBC_OBJTYPE ) // PTR_ARG
  3759. {
  3760. // Translate object type pointers into indices
  3761. *(asPWORD*)(tmp+1) = FindObjectTypeIdx(*(asCObjectType**)(tmp+1));
  3762. }
  3763. else if( c == asBC_JitEntry ) // PTR_ARG
  3764. {
  3765. // We don't store the JIT argument
  3766. *(asPWORD*)(tmp+1) = 0;
  3767. }
  3768. else if( c == asBC_TYPEID || // DW_ARG
  3769. c == asBC_Cast ) // DW_ARG
  3770. {
  3771. // Translate type ids into indices
  3772. *(int*)(tmp+1) = FindTypeIdIdx(*(int*)(tmp+1));
  3773. }
  3774. else if( c == asBC_ADDSi || // W_DW_ARG
  3775. c == asBC_LoadThisR ) // W_DW_ARG
  3776. {
  3777. // Translate property offsets into indices
  3778. *(((short*)tmp)+1) = (short)FindObjectPropIndex(*(((short*)tmp)+1), *(int*)(tmp+1));
  3779. // Translate type ids into indices
  3780. *(int*)(tmp+1) = FindTypeIdIdx(*(int*)(tmp+1));
  3781. }
  3782. else if( c == asBC_LoadRObjR || // rW_W_DW_ARG
  3783. c == asBC_LoadVObjR ) // rW_W_DW_ARG
  3784. {
  3785. asCObjectType *ot = engine->GetObjectTypeFromTypeId(*(int*)(tmp+2));
  3786. if( ot->flags & asOBJ_LIST_PATTERN )
  3787. {
  3788. // List patterns have a different way of translating the offsets
  3789. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  3790. *(((short*)tmp)+2) = (short)listAdj->AdjustOffset(*(((short*)tmp)+2), ot);
  3791. }
  3792. else
  3793. {
  3794. // Translate property offsets into indices
  3795. // TODO: optimize: Pass the object type directly to the method instead of the type id
  3796. *(((short*)tmp)+2) = (short)FindObjectPropIndex(*(((short*)tmp)+2), *(int*)(tmp+2));
  3797. }
  3798. // Translate type ids into indices
  3799. *(int*)(tmp+2) = FindTypeIdIdx(*(int*)(tmp+2));
  3800. }
  3801. else if( c == asBC_COPY ) // W_DW_ARG
  3802. {
  3803. // Translate type ids into indices
  3804. *(int*)(tmp+1) = FindTypeIdIdx(*(int*)(tmp+1));
  3805. // Update the WORDARG0 to 0, as this will be recalculated on the target platform
  3806. asBC_WORDARG0(tmp) = 0;
  3807. }
  3808. else if( c == asBC_RET ) // W_ARG
  3809. {
  3810. // Save with arg 0, as this will be recalculated on the target platform
  3811. asBC_WORDARG0(tmp) = 0;
  3812. }
  3813. else if( c == asBC_CALL || // DW_ARG
  3814. c == asBC_CALLINTF || // DW_ARG
  3815. c == asBC_CALLSYS || // DW_ARG
  3816. c == asBC_Thiscall1 ) // DW_ARG
  3817. {
  3818. // Translate the function id
  3819. *(int*)(tmp+1) = FindFunctionIndex(engine->scriptFunctions[*(int*)(tmp+1)]);
  3820. }
  3821. else if( c == asBC_FuncPtr ) // PTR_ARG
  3822. {
  3823. // Translate the function pointer
  3824. *(asPWORD*)(tmp+1) = FindFunctionIndex(*(asCScriptFunction**)(tmp+1));
  3825. }
  3826. else if( c == asBC_STR ) // W_ARG
  3827. {
  3828. // Translate the string constant id
  3829. asWORD *arg = ((asWORD*)tmp)+1;
  3830. *arg = (asWORD)FindStringConstantIndex(*arg);
  3831. }
  3832. else if( c == asBC_CALLBND ) // DW_ARG
  3833. {
  3834. // Translate the function id
  3835. int funcId = tmp[1];
  3836. for( asUINT n = 0; n < module->bindInformations.GetLength(); n++ )
  3837. if( module->bindInformations[n]->importedFunctionSignature->id == funcId )
  3838. {
  3839. funcId = n;
  3840. break;
  3841. }
  3842. tmp[1] = funcId;
  3843. }
  3844. else if( c == asBC_PGA || // PTR_ARG
  3845. c == asBC_PshGPtr || // PTR_ARG
  3846. c == asBC_LDG || // PTR_ARG
  3847. c == asBC_PshG4 || // PTR_ARG
  3848. c == asBC_LdGRdR4 || // wW_PTR_ARG
  3849. c == asBC_CpyGtoV4 || // wW_PTR_ARG
  3850. c == asBC_CpyVtoG4 || // rW_PTR_ARG
  3851. c == asBC_SetG4 ) // PTR_DW_ARG
  3852. {
  3853. // Translate global variable pointers into indices
  3854. *(asPWORD*)(tmp+1) = FindGlobalPropPtrIndex(*(void**)(tmp+1));
  3855. }
  3856. else if( c == asBC_JMP || // DW_ARG
  3857. c == asBC_JZ ||
  3858. c == asBC_JNZ ||
  3859. c == asBC_JLowZ ||
  3860. c == asBC_JLowNZ ||
  3861. c == asBC_JS ||
  3862. c == asBC_JNS ||
  3863. c == asBC_JP ||
  3864. c == asBC_JNP ) // The JMPP instruction doesn't need modification
  3865. {
  3866. // Get the DWORD offset from arg
  3867. int offset = *(int*)(tmp+1);
  3868. // Determine instruction number for next instruction and destination
  3869. int bcSeqNum = bytecodeNbrByPos[asUINT(bc - startBC)] + 1;
  3870. asDWORD *targetBC = bc + 2 + offset;
  3871. int targetBcSeqNum = bytecodeNbrByPos[asUINT(targetBC - startBC)];
  3872. // Set the offset in number of instructions
  3873. *(int*)(tmp+1) = targetBcSeqNum - bcSeqNum;
  3874. }
  3875. else if( c == asBC_GETOBJ || // W_ARG
  3876. c == asBC_GETOBJREF ||
  3877. c == asBC_GETREF )
  3878. {
  3879. // Adjust the offset according to the function call that comes after
  3880. asBC_WORDARG0(tmp) = (asWORD)AdjustGetOffset(asBC_WORDARG0(tmp), func, asDWORD(bc - startBC));
  3881. }
  3882. else if( c == asBC_AllocMem )
  3883. {
  3884. // It's not necessary to store the size of the list buffer, as it will be recalculated in the reader
  3885. asBC_DWORDARG(tmp) = 0;
  3886. // Determine the type of the list pattern from the variable
  3887. short var = asBC_WORDARG0(tmp);
  3888. asCObjectType *ot = func->GetObjectTypeOfLocalVar(var);
  3889. // Create this helper object to adjust the offset of the elements accessed in the buffer
  3890. listAdjusters.PushLast(asNEW(SListAdjuster)(ot));
  3891. }
  3892. else if( c == asBC_FREE ) // wW_PTR_ARG
  3893. {
  3894. // Translate object type pointers into indices
  3895. asCObjectType *ot = *(asCObjectType**)(tmp+1);
  3896. *(asPWORD*)(tmp+1) = FindObjectTypeIdx(ot);
  3897. // Pop and destroy the list adjuster helper that was created with asBC_AllocMem
  3898. if( ot && (ot->flags & asOBJ_LIST_PATTERN) )
  3899. {
  3900. SListAdjuster *list = listAdjusters.PopLast();
  3901. asDELETE(list, SListAdjuster);
  3902. }
  3903. }
  3904. else if( c == asBC_SetListSize )
  3905. {
  3906. // Adjust the offset in the initialization list
  3907. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  3908. tmp[1] = listAdj->AdjustOffset(tmp[1], listAdj->patternType);
  3909. // Tell the adjuster how many repeated values there are
  3910. listAdj->SetRepeatCount(tmp[2]);
  3911. }
  3912. else if( c == asBC_PshListElmnt ) // W_DW_ARG
  3913. {
  3914. // Adjust the offset in the initialization list
  3915. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  3916. tmp[1] = listAdj->AdjustOffset(tmp[1], listAdj->patternType);
  3917. }
  3918. else if( c == asBC_SetListType )
  3919. {
  3920. // Adjust the offset in the initialization list
  3921. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  3922. tmp[1] = listAdj->AdjustOffset(tmp[1], listAdj->patternType);
  3923. // Inform the adjuster of the type id of the next element
  3924. listAdj->SetNextType(tmp[2]);
  3925. // Translate the type id
  3926. tmp[2] = FindTypeIdIdx(tmp[2]);
  3927. }
  3928. // Adjust the variable offsets
  3929. switch( asBCInfo[c].type )
  3930. {
  3931. case asBCTYPE_wW_ARG:
  3932. case asBCTYPE_rW_DW_ARG:
  3933. case asBCTYPE_wW_QW_ARG:
  3934. case asBCTYPE_rW_ARG:
  3935. case asBCTYPE_wW_DW_ARG:
  3936. case asBCTYPE_wW_W_ARG:
  3937. case asBCTYPE_rW_QW_ARG:
  3938. case asBCTYPE_rW_W_DW_ARG:
  3939. case asBCTYPE_rW_DW_DW_ARG:
  3940. {
  3941. asBC_SWORDARG0(tmp) = (short)AdjustStackPosition(asBC_SWORDARG0(tmp));
  3942. }
  3943. break;
  3944. case asBCTYPE_wW_rW_ARG:
  3945. case asBCTYPE_wW_rW_DW_ARG:
  3946. case asBCTYPE_rW_rW_ARG:
  3947. {
  3948. asBC_SWORDARG0(tmp) = (short)AdjustStackPosition(asBC_SWORDARG0(tmp));
  3949. asBC_SWORDARG1(tmp) = (short)AdjustStackPosition(asBC_SWORDARG1(tmp));
  3950. }
  3951. break;
  3952. case asBCTYPE_wW_rW_rW_ARG:
  3953. {
  3954. asBC_SWORDARG0(tmp) = (short)AdjustStackPosition(asBC_SWORDARG0(tmp));
  3955. asBC_SWORDARG1(tmp) = (short)AdjustStackPosition(asBC_SWORDARG1(tmp));
  3956. asBC_SWORDARG2(tmp) = (short)AdjustStackPosition(asBC_SWORDARG2(tmp));
  3957. }
  3958. break;
  3959. default:
  3960. // The other types don't treat variables so won't be modified
  3961. break;
  3962. }
  3963. // TODO: bytecode: Must make sure that floats and doubles are always stored the same way regardless of platform.
  3964. // Some platforms may not use the IEEE 754 standard, in which case it is necessary to encode the values
  3965. // Now store the instruction in the smallest possible way
  3966. switch( asBCInfo[c].type )
  3967. {
  3968. case asBCTYPE_NO_ARG:
  3969. {
  3970. // Just write 1 byte
  3971. asBYTE b = (asBYTE)c;
  3972. WriteData(&b, 1);
  3973. }
  3974. break;
  3975. case asBCTYPE_W_ARG:
  3976. case asBCTYPE_wW_ARG:
  3977. case asBCTYPE_rW_ARG:
  3978. {
  3979. // Write the instruction code
  3980. asBYTE b = (asBYTE)c;
  3981. WriteData(&b, 1);
  3982. // Write the argument
  3983. short w = *(((short*)tmp)+1);
  3984. WriteEncodedInt64(w);
  3985. }
  3986. break;
  3987. case asBCTYPE_rW_DW_ARG:
  3988. case asBCTYPE_wW_DW_ARG:
  3989. case asBCTYPE_W_DW_ARG:
  3990. {
  3991. // Write the instruction code
  3992. asBYTE b = (asBYTE)c;
  3993. WriteData(&b, 1);
  3994. // Write the word argument
  3995. short w = *(((short*)tmp)+1);
  3996. WriteEncodedInt64(w);
  3997. // Write the dword argument
  3998. WriteEncodedInt64((int)tmp[1]);
  3999. }
  4000. break;
  4001. case asBCTYPE_DW_ARG:
  4002. {
  4003. // Write the instruction code
  4004. asBYTE b = (asBYTE)c;
  4005. WriteData(&b, 1);
  4006. // Write the argument
  4007. WriteEncodedInt64((int)tmp[1]);
  4008. }
  4009. break;
  4010. case asBCTYPE_DW_DW_ARG:
  4011. {
  4012. // Write the instruction code
  4013. asBYTE b = (asBYTE)c;
  4014. WriteData(&b, 1);
  4015. // Write the dword argument
  4016. WriteEncodedInt64((int)tmp[1]);
  4017. // Write the dword argument
  4018. WriteEncodedInt64((int)tmp[2]);
  4019. }
  4020. break;
  4021. case asBCTYPE_wW_rW_rW_ARG:
  4022. {
  4023. // Write the instruction code
  4024. asBYTE b = (asBYTE)c;
  4025. WriteData(&b, 1);
  4026. // Write the first argument
  4027. short w = *(((short*)tmp)+1);
  4028. WriteEncodedInt64(w);
  4029. // Write the second argument
  4030. w = *(((short*)tmp)+2);
  4031. WriteEncodedInt64(w);
  4032. // Write the third argument
  4033. w = *(((short*)tmp)+3);
  4034. WriteEncodedInt64(w);
  4035. }
  4036. break;
  4037. case asBCTYPE_wW_rW_ARG:
  4038. case asBCTYPE_rW_rW_ARG:
  4039. case asBCTYPE_wW_W_ARG:
  4040. {
  4041. // Write the instruction code
  4042. asBYTE b = (asBYTE)c;
  4043. WriteData(&b, 1);
  4044. // Write the first argument
  4045. short w = *(((short*)tmp)+1);
  4046. WriteEncodedInt64(w);
  4047. // Write the second argument
  4048. w = *(((short*)tmp)+2);
  4049. WriteEncodedInt64(w);
  4050. }
  4051. break;
  4052. case asBCTYPE_wW_rW_DW_ARG:
  4053. case asBCTYPE_rW_W_DW_ARG:
  4054. {
  4055. // Write the instruction code
  4056. asBYTE b = (asBYTE)c;
  4057. WriteData(&b, 1);
  4058. // Write the first argument
  4059. short w = *(((short*)tmp)+1);
  4060. WriteEncodedInt64(w);
  4061. // Write the second argument
  4062. w = *(((short*)tmp)+2);
  4063. WriteEncodedInt64(w);
  4064. // Write the third argument
  4065. int dw = tmp[2];
  4066. WriteEncodedInt64(dw);
  4067. }
  4068. break;
  4069. case asBCTYPE_QW_ARG:
  4070. {
  4071. // Write the instruction code
  4072. asBYTE b = (asBYTE)c;
  4073. WriteData(&b, 1);
  4074. // Write the argument
  4075. asQWORD qw = *(asQWORD*)&tmp[1];
  4076. WriteEncodedInt64(qw);
  4077. }
  4078. break;
  4079. case asBCTYPE_QW_DW_ARG:
  4080. {
  4081. // Write the instruction code
  4082. asBYTE b = (asBYTE)c;
  4083. WriteData(&b, 1);
  4084. // Write the argument
  4085. asQWORD qw = *(asQWORD*)&tmp[1];
  4086. WriteEncodedInt64(qw);
  4087. // Write the second argument
  4088. int dw = tmp[3];
  4089. WriteEncodedInt64(dw);
  4090. }
  4091. break;
  4092. case asBCTYPE_rW_QW_ARG:
  4093. case asBCTYPE_wW_QW_ARG:
  4094. {
  4095. // Write the instruction code
  4096. asBYTE b = (asBYTE)c;
  4097. WriteData(&b, 1);
  4098. // Write the first argument
  4099. short w = *(((short*)tmp)+1);
  4100. WriteEncodedInt64(w);
  4101. // Write the argument
  4102. asQWORD qw = *(asQWORD*)&tmp[1];
  4103. WriteEncodedInt64(qw);
  4104. }
  4105. break;
  4106. case asBCTYPE_rW_DW_DW_ARG:
  4107. {
  4108. // Write the instruction code
  4109. asBYTE b = (asBYTE)c;
  4110. WriteData(&b, 1);
  4111. // Write the short argument
  4112. short w = *(((short*)tmp)+1);
  4113. WriteEncodedInt64(w);
  4114. // Write the dword argument
  4115. WriteEncodedInt64((int)tmp[1]);
  4116. // Write the dword argument
  4117. WriteEncodedInt64((int)tmp[2]);
  4118. }
  4119. break;
  4120. default:
  4121. {
  4122. // This should never happen
  4123. asASSERT(false);
  4124. // Store the bc as is
  4125. for( int n = 0; n < asBCTypeSize[asBCInfo[c].type]; n++ )
  4126. WriteData(&tmp[n], 4);
  4127. }
  4128. }
  4129. // Move to the next instruction
  4130. bc += asBCTypeSize[asBCInfo[c].type];
  4131. length -= asBCTypeSize[asBCInfo[c].type];
  4132. }
  4133. }
  4134. asCWriter::SListAdjuster::SListAdjuster(asCObjectType *ot) : patternType(ot), repeatCount(0), entries(0), lastOffset(-1), nextOffset(0), nextTypeId(-1)
  4135. {
  4136. asASSERT( ot && (ot->flags & asOBJ_LIST_PATTERN) );
  4137. // Find the first expected value in the list
  4138. asSListPatternNode *node = ot->engine->scriptFunctions[patternType->templateSubTypes[0].GetBehaviour()->listFactory]->listPattern;
  4139. asASSERT( node && node->type == asLPT_START );
  4140. patternNode = node->next;
  4141. }
  4142. int asCWriter::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatternType)
  4143. {
  4144. // TODO: cleanup: The listPatternType parameter is not needed
  4145. asASSERT( patternType == listPatternType );
  4146. UNUSED_VAR(listPatternType);
  4147. asASSERT( offset >= lastOffset );
  4148. // If it is the same offset being accessed again, just return the same adjusted value
  4149. if( offset == lastOffset )
  4150. return entries-1;
  4151. asASSERT( offset >= nextOffset );
  4152. // Update last offset for next call
  4153. lastOffset = offset;
  4154. // What is being expected at this position?
  4155. if( patternNode->type == asLPT_REPEAT || patternNode->type == asLPT_REPEAT_SAME )
  4156. {
  4157. // Don't move the patternNode yet because the caller must make a call to SetRepeatCount too
  4158. nextOffset = offset + 4;
  4159. return entries++;
  4160. }
  4161. else if( patternNode->type == asLPT_TYPE )
  4162. {
  4163. const asCDataType &dt = reinterpret_cast<asSListPatternDataTypeNode*>(patternNode)->dataType;
  4164. if( dt.GetTokenType() == ttQuestion )
  4165. {
  4166. // The bytecode need to inform the type that will
  4167. // come next and then adjust that position too before
  4168. // we can move to the next node
  4169. if( nextTypeId != -1 )
  4170. {
  4171. nextOffset = offset + 4;
  4172. if( repeatCount > 0 )
  4173. repeatCount--;
  4174. // Only move the patternNode if we're not expecting any more repeated entries
  4175. if( repeatCount == 0 )
  4176. patternNode = patternNode->next;
  4177. nextTypeId = -1;
  4178. }
  4179. }
  4180. else
  4181. {
  4182. if( repeatCount > 0 )
  4183. {
  4184. // Was any value skipped?
  4185. asUINT size;
  4186. if( dt.IsObjectHandle() || (dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_REF)) )
  4187. size = AS_PTR_SIZE*4;
  4188. else
  4189. size = dt.GetSizeInMemoryBytes();
  4190. int count = 0;
  4191. while( nextOffset <= offset )
  4192. {
  4193. count++;
  4194. nextOffset += size;
  4195. // Align the offset on 4 byte boundaries
  4196. if( size >= 4 && (nextOffset & 0x3) )
  4197. nextOffset += 4 - (nextOffset & 0x3);
  4198. }
  4199. if( --count > 0 )
  4200. {
  4201. // Skip these values
  4202. repeatCount -= count;
  4203. entries += count;
  4204. }
  4205. nextOffset = offset + size;
  4206. repeatCount--;
  4207. }
  4208. // Only move the patternNode if we're not expecting any more repeated entries
  4209. if( repeatCount == 0 )
  4210. patternNode = patternNode->next;
  4211. }
  4212. return entries++;
  4213. }
  4214. else if( patternNode->type == asLPT_START )
  4215. {
  4216. if( repeatCount > 0 )
  4217. repeatCount--;
  4218. SInfo info = {repeatCount, patternNode};
  4219. stack.PushLast(info);
  4220. repeatCount = 0;
  4221. patternNode = patternNode->next;
  4222. lastOffset--;
  4223. return AdjustOffset(offset, listPatternType);
  4224. }
  4225. else if( patternNode->type == asLPT_END )
  4226. {
  4227. SInfo info = stack.PopLast();
  4228. repeatCount = info.repeatCount;
  4229. if( repeatCount )
  4230. patternNode = info.startNode;
  4231. else
  4232. patternNode = patternNode->next;
  4233. lastOffset--;
  4234. return AdjustOffset(offset, listPatternType);
  4235. }
  4236. else
  4237. {
  4238. // Something is wrong with the pattern list declaration
  4239. asASSERT( false );
  4240. }
  4241. return 0;
  4242. }
  4243. void asCWriter::SListAdjuster::SetRepeatCount(asUINT rc)
  4244. {
  4245. // Make sure the list is expecting a repeat at this location
  4246. asASSERT( patternNode->type == asLPT_REPEAT || patternNode->type == asLPT_REPEAT_SAME );
  4247. // Now move to the next patternNode
  4248. patternNode = patternNode->next;
  4249. repeatCount = rc;
  4250. }
  4251. void asCWriter::SListAdjuster::SetNextType(int typeId)
  4252. {
  4253. // Make sure the list is expecting a type at this location
  4254. asASSERT( patternNode->type == asLPT_TYPE &&
  4255. reinterpret_cast<asSListPatternDataTypeNode*>(patternNode)->dataType.GetTokenType() == ttQuestion );
  4256. // Inform the type id for the next adjustment
  4257. nextTypeId = typeId;
  4258. }
  4259. void asCWriter::WriteUsedTypeIds()
  4260. {
  4261. asUINT count = (asUINT)usedTypeIds.GetLength();
  4262. WriteEncodedInt64(count);
  4263. for( asUINT n = 0; n < count; n++ )
  4264. {
  4265. asCDataType dt = engine->GetDataTypeFromTypeId(usedTypeIds[n]);
  4266. WriteDataType(&dt);
  4267. }
  4268. }
  4269. int asCWriter::FindGlobalPropPtrIndex(void *ptr)
  4270. {
  4271. int i = usedGlobalProperties.IndexOf(ptr);
  4272. if( i >= 0 ) return i;
  4273. usedGlobalProperties.PushLast(ptr);
  4274. return (int)usedGlobalProperties.GetLength()-1;
  4275. }
  4276. void asCWriter::WriteUsedGlobalProps()
  4277. {
  4278. int c = (int)usedGlobalProperties.GetLength();
  4279. WriteEncodedInt64(c);
  4280. for( int n = 0; n < c; n++ )
  4281. {
  4282. asPWORD *p = (asPWORD*)usedGlobalProperties[n];
  4283. // First search for the global in the module
  4284. char moduleProp = 0;
  4285. asCGlobalProperty *prop = 0;
  4286. asCSymbolTable<asCGlobalProperty>::iterator it = module->scriptGlobals.List();
  4287. for( ; it; it++ )
  4288. {
  4289. if( p == (*it)->GetAddressOfValue() )
  4290. {
  4291. prop = (*it);
  4292. moduleProp = 1;
  4293. break;
  4294. }
  4295. }
  4296. // If it is not in the module, it must be an application registered property
  4297. if( !prop )
  4298. {
  4299. asCSymbolTable<asCGlobalProperty>::iterator it = engine->registeredGlobalProps.List();
  4300. for( ; it; it++ )
  4301. {
  4302. if( it->GetAddressOfValue() == p )
  4303. {
  4304. prop = *it;
  4305. break;
  4306. }
  4307. }
  4308. }
  4309. asASSERT(prop);
  4310. // Store the name and type of the property so we can find it again on loading
  4311. WriteString(&prop->name);
  4312. WriteString(&prop->nameSpace->name);
  4313. WriteDataType(&prop->type);
  4314. // Also store whether the property is a module property or a registered property
  4315. WriteData(&moduleProp, 1);
  4316. }
  4317. }
  4318. void asCWriter::WriteUsedObjectProps()
  4319. {
  4320. int c = (int)usedObjectProperties.GetLength();
  4321. WriteEncodedInt64(c);
  4322. for( asUINT n = 0; n < usedObjectProperties.GetLength(); n++ )
  4323. {
  4324. asCObjectType *objType = usedObjectProperties[n].objType;
  4325. WriteObjectType(objType);
  4326. // Find the property name
  4327. for( asUINT p = 0; p < objType->properties.GetLength(); p++ )
  4328. {
  4329. if( objType->properties[p]->byteOffset == usedObjectProperties[n].offset )
  4330. {
  4331. WriteString(&objType->properties[p]->name);
  4332. break;
  4333. }
  4334. }
  4335. }
  4336. }
  4337. int asCWriter::FindObjectPropIndex(short offset, int typeId)
  4338. {
  4339. asCObjectType *objType = engine->GetObjectTypeFromTypeId(typeId);
  4340. for( asUINT n = 0; n < usedObjectProperties.GetLength(); n++ )
  4341. {
  4342. if( usedObjectProperties[n].objType == objType &&
  4343. usedObjectProperties[n].offset == offset )
  4344. return n;
  4345. }
  4346. SObjProp prop = {objType, offset};
  4347. usedObjectProperties.PushLast(prop);
  4348. return (int)usedObjectProperties.GetLength() - 1;
  4349. }
  4350. int asCWriter::FindFunctionIndex(asCScriptFunction *func)
  4351. {
  4352. for( asUINT n = 0; n < usedFunctions.GetLength(); n++ )
  4353. {
  4354. if( usedFunctions[n] == func )
  4355. return n;
  4356. }
  4357. usedFunctions.PushLast(func);
  4358. return (int)usedFunctions.GetLength() - 1;
  4359. }
  4360. int asCWriter::FindTypeIdIdx(int typeId)
  4361. {
  4362. asUINT n;
  4363. for( n = 0; n < usedTypeIds.GetLength(); n++ )
  4364. {
  4365. if( usedTypeIds[n] == typeId )
  4366. return n;
  4367. }
  4368. usedTypeIds.PushLast(typeId);
  4369. return (int)usedTypeIds.GetLength() - 1;
  4370. }
  4371. int asCWriter::FindObjectTypeIdx(asCObjectType *obj)
  4372. {
  4373. asUINT n;
  4374. for( n = 0; n < usedTypes.GetLength(); n++ )
  4375. {
  4376. if( usedTypes[n] == obj )
  4377. return n;
  4378. }
  4379. usedTypes.PushLast(obj);
  4380. return (int)usedTypes.GetLength() - 1;
  4381. }
  4382. #endif // AS_NO_COMPILER
  4383. END_AS_NAMESPACE