as_restore.cpp 109 KB

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