as_restore.cpp 101 KB

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