as_restore.cpp 131 KB

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