as_restore.cpp 125 KB

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