as_restore.cpp 99 KB

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