as_bytecode.cpp 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2011 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_bytecode.cpp
  25. //
  26. // A class for constructing the final byte code
  27. //
  28. #include <stdio.h> // fopen(), fprintf(), fclose()
  29. #include "as_config.h"
  30. #include "as_bytecode.h"
  31. #include "as_debug.h" // mkdir()
  32. #include "as_array.h"
  33. #include "as_string.h"
  34. #include "as_scriptengine.h"
  35. BEGIN_AS_NAMESPACE
  36. asCByteCode::asCByteCode(asCScriptEngine *engine)
  37. {
  38. first = 0;
  39. last = 0;
  40. largestStackUsed = -1;
  41. this->engine = engine;
  42. }
  43. asCByteCode::~asCByteCode()
  44. {
  45. ClearAll();
  46. }
  47. void asCByteCode::Finalize()
  48. {
  49. // verify the bytecode
  50. PostProcess();
  51. // Optimize the code (optionally)
  52. if( engine->ep.optimizeByteCode )
  53. Optimize();
  54. // Resolve jumps
  55. ResolveJumpAddresses();
  56. // Build line numbers buffer
  57. ExtractLineNumbers();
  58. }
  59. void asCByteCode::ClearAll()
  60. {
  61. cByteInstruction *del = first;
  62. while( del )
  63. {
  64. first = del->next;
  65. engine->memoryMgr.FreeByteInstruction(del);
  66. del = first;
  67. }
  68. first = 0;
  69. last = 0;
  70. lineNumbers.SetLength(0);
  71. largestStackUsed = -1;
  72. temporaryVariables.SetLength(0);
  73. }
  74. void asCByteCode::InsertIfNotExists(asCArray<int> &vars, int var)
  75. {
  76. if( !vars.Exists(var) )
  77. vars.PushLast(var);
  78. }
  79. void asCByteCode::GetVarsUsed(asCArray<int> &vars)
  80. {
  81. cByteInstruction *curr = first;
  82. while( curr )
  83. {
  84. if( asBCInfo[curr->op].type == asBCTYPE_wW_rW_rW_ARG )
  85. {
  86. InsertIfNotExists(vars, curr->wArg[0]);
  87. InsertIfNotExists(vars, curr->wArg[1]);
  88. InsertIfNotExists(vars, curr->wArg[2]);
  89. }
  90. else if( asBCInfo[curr->op].type == asBCTYPE_rW_ARG ||
  91. asBCInfo[curr->op].type == asBCTYPE_wW_ARG ||
  92. asBCInfo[curr->op].type == asBCTYPE_wW_W_ARG ||
  93. asBCInfo[curr->op].type == asBCTYPE_rW_DW_ARG ||
  94. asBCInfo[curr->op].type == asBCTYPE_wW_DW_ARG ||
  95. asBCInfo[curr->op].type == asBCTYPE_wW_QW_ARG ||
  96. asBCInfo[curr->op].type == asBCTYPE_rW_W_DW_ARG )
  97. {
  98. InsertIfNotExists(vars, curr->wArg[0]);
  99. }
  100. else if( asBCInfo[curr->op].type == asBCTYPE_wW_rW_ARG ||
  101. asBCInfo[curr->op].type == asBCTYPE_rW_rW_ARG ||
  102. asBCInfo[curr->op].type == asBCTYPE_wW_rW_DW_ARG )
  103. {
  104. InsertIfNotExists(vars, curr->wArg[0]);
  105. InsertIfNotExists(vars, curr->wArg[1]);
  106. }
  107. else if( curr->op == asBC_LoadThisR )
  108. {
  109. InsertIfNotExists(vars, 0);
  110. }
  111. curr = curr->next;
  112. }
  113. }
  114. bool asCByteCode::IsVarUsed(int offset)
  115. {
  116. cByteInstruction *curr = first;
  117. while( curr )
  118. {
  119. // Verify all ops that use variables
  120. if( asBCInfo[curr->op].type == asBCTYPE_wW_rW_rW_ARG )
  121. {
  122. if( curr->wArg[0] == offset || curr->wArg[1] == offset || curr->wArg[2] == offset )
  123. return true;
  124. }
  125. else if( asBCInfo[curr->op].type == asBCTYPE_rW_ARG ||
  126. asBCInfo[curr->op].type == asBCTYPE_wW_ARG ||
  127. asBCInfo[curr->op].type == asBCTYPE_wW_W_ARG ||
  128. asBCInfo[curr->op].type == asBCTYPE_rW_DW_ARG ||
  129. asBCInfo[curr->op].type == asBCTYPE_wW_DW_ARG ||
  130. asBCInfo[curr->op].type == asBCTYPE_wW_QW_ARG ||
  131. asBCInfo[curr->op].type == asBCTYPE_rW_W_DW_ARG )
  132. {
  133. if( curr->wArg[0] == offset )
  134. return true;
  135. }
  136. else if( asBCInfo[curr->op].type == asBCTYPE_wW_rW_ARG ||
  137. asBCInfo[curr->op].type == asBCTYPE_rW_rW_ARG ||
  138. asBCInfo[curr->op].type == asBCTYPE_wW_rW_DW_ARG )
  139. {
  140. if( curr->wArg[0] == offset || curr->wArg[1] == offset )
  141. return true;
  142. }
  143. else if( curr->op == asBC_LoadThisR )
  144. {
  145. if( offset == 0 )
  146. return true;
  147. }
  148. curr = curr->next;
  149. }
  150. return false;
  151. }
  152. void asCByteCode::ExchangeVar(int oldOffset, int newOffset)
  153. {
  154. asASSERT(oldOffset != 0);
  155. cByteInstruction *curr = first;
  156. while( curr )
  157. {
  158. // Verify all ops that use variables
  159. if( asBCInfo[curr->op].type == asBCTYPE_wW_rW_rW_ARG )
  160. {
  161. if( curr->wArg[0] == oldOffset )
  162. curr->wArg[0] = (short)newOffset;
  163. if( curr->wArg[1] == oldOffset )
  164. curr->wArg[1] = (short)newOffset;
  165. if( curr->wArg[2] == oldOffset )
  166. curr->wArg[2] = (short)newOffset;
  167. }
  168. else if( asBCInfo[curr->op].type == asBCTYPE_rW_ARG ||
  169. asBCInfo[curr->op].type == asBCTYPE_wW_ARG ||
  170. asBCInfo[curr->op].type == asBCTYPE_wW_W_ARG ||
  171. asBCInfo[curr->op].type == asBCTYPE_rW_DW_ARG ||
  172. asBCInfo[curr->op].type == asBCTYPE_wW_DW_ARG ||
  173. asBCInfo[curr->op].type == asBCTYPE_wW_QW_ARG )
  174. {
  175. if( curr->wArg[0] == oldOffset )
  176. curr->wArg[0] = (short)newOffset;
  177. }
  178. else if( asBCInfo[curr->op].type == asBCTYPE_wW_rW_ARG ||
  179. asBCInfo[curr->op].type == asBCTYPE_rW_rW_ARG )
  180. {
  181. if( curr->wArg[0] == oldOffset )
  182. curr->wArg[0] = (short)newOffset;
  183. if( curr->wArg[1] == oldOffset )
  184. curr->wArg[1] = (short)newOffset;
  185. }
  186. curr = curr->next;
  187. }
  188. }
  189. void asCByteCode::AddPath(asCArray<cByteInstruction *> &paths, cByteInstruction *instr, int stackSize)
  190. {
  191. if( instr->marked )
  192. {
  193. // Verify the size of the stack
  194. asASSERT(instr->stackSize == stackSize);
  195. }
  196. else
  197. {
  198. // Add the destination to the code paths
  199. instr->marked = true;
  200. instr->stackSize = stackSize;
  201. paths.PushLast(instr);
  202. }
  203. }
  204. bool asCByteCode::IsCombination(cByteInstruction *curr, asEBCInstr bc1, asEBCInstr bc2)
  205. {
  206. if( curr->op == bc1 && curr->next && curr->next->op == bc2 )
  207. return true;
  208. return false;
  209. }
  210. bool asCByteCode::IsCombination(cByteInstruction *curr, asEBCInstr bc1, asEBCInstr bc2, asEBCInstr bc3)
  211. {
  212. if( curr->op == bc1 &&
  213. curr->next && curr->next->op == bc2 &&
  214. curr->next->next && curr->next->next->op == bc3 )
  215. return true;
  216. return false;
  217. }
  218. cByteInstruction *asCByteCode::ChangeFirstDeleteNext(cByteInstruction *curr, asEBCInstr bc)
  219. {
  220. curr->op = bc;
  221. if( curr->next ) DeleteInstruction(curr->next);
  222. // Continue optimization with the instruction before the altered one
  223. if( curr->prev )
  224. return curr->prev;
  225. else
  226. return curr;
  227. }
  228. cByteInstruction *asCByteCode::DeleteFirstChangeNext(cByteInstruction *curr, asEBCInstr bc)
  229. {
  230. asASSERT( curr->next );
  231. cByteInstruction *instr = curr->next;
  232. instr->op = bc;
  233. DeleteInstruction(curr);
  234. // Continue optimization with the instruction before the altered one
  235. if( instr->prev )
  236. return instr->prev;
  237. else
  238. return instr;
  239. }
  240. void asCByteCode::InsertBefore(cByteInstruction *before, cByteInstruction *instr)
  241. {
  242. asASSERT(instr->next == 0);
  243. asASSERT(instr->prev == 0);
  244. if( before->prev ) before->prev->next = instr;
  245. instr->prev = before->prev;
  246. before->prev = instr;
  247. instr->next = before;
  248. if( first == before ) first = instr;
  249. }
  250. void asCByteCode::RemoveInstruction(cByteInstruction *instr)
  251. {
  252. if( instr == first ) first = first->next;
  253. if( instr == last ) last = last->prev;
  254. if( instr->prev ) instr->prev->next = instr->next;
  255. if( instr->next ) instr->next->prev = instr->prev;
  256. instr->next = 0;
  257. instr->prev = 0;
  258. }
  259. bool asCByteCode::CanBeSwapped(cByteInstruction *curr)
  260. {
  261. if( !curr || !curr->next || !curr->next->next ) return false;
  262. if( curr->next->next->op != asBC_SWAP4 ) return false;
  263. cByteInstruction *next = curr->next;
  264. if( curr->op != asBC_PshC4 &&
  265. curr->op != asBC_PshV4 &&
  266. curr->op != asBC_PSF )
  267. return false;
  268. if( next->op != asBC_PshC4 &&
  269. next->op != asBC_PshV4 &&
  270. next->op != asBC_PSF )
  271. return false;
  272. return true;
  273. }
  274. cByteInstruction *asCByteCode::GoBack(cByteInstruction *curr)
  275. {
  276. // Go back 2 instructions
  277. if( !curr ) return 0;
  278. if( curr->prev ) curr = curr->prev;
  279. if( curr->prev ) curr = curr->prev;
  280. return curr;
  281. }
  282. bool asCByteCode::PostponeInitOfTemp(cByteInstruction *curr, cByteInstruction **next)
  283. {
  284. if( curr->op != asBC_SetV4 || !IsTemporary(curr->wArg[0]) ) return false;
  285. // Move the initialization to just before it's use.
  286. // Don't move it beyond any labels or jumps.
  287. cByteInstruction *use = curr->next;
  288. while( use )
  289. {
  290. if( IsTempVarReadByInstr(use, curr->wArg[0]) )
  291. break;
  292. if( IsTempVarOverwrittenByInstr(use, curr->wArg[0]) )
  293. return false;
  294. if( IsInstrJmpOrLabel(use) )
  295. return false;
  296. use = use->next;
  297. }
  298. if( use && use->prev != curr )
  299. {
  300. *next = curr->next;
  301. // Move the instruction
  302. RemoveInstruction(curr);
  303. InsertBefore(use, curr);
  304. // Try a RemoveUnusedValue to see if it can be combined with the other
  305. cByteInstruction *temp;
  306. if( RemoveUnusedValue(curr, &temp) )
  307. {
  308. *next = GoBack(*next);
  309. return true;
  310. }
  311. // Return the instructions to its original position as it wasn't useful
  312. RemoveInstruction(curr);
  313. InsertBefore(*next, curr);
  314. }
  315. return false;
  316. }
  317. bool asCByteCode::RemoveUnusedValue(cByteInstruction *curr, cByteInstruction **next)
  318. {
  319. // TODO: optimize: Should work for 64bit types as well
  320. // The value isn't used for anything
  321. if( (asBCInfo[curr->op].type == asBCTYPE_wW_rW_rW_ARG ||
  322. asBCInfo[curr->op].type == asBCTYPE_wW_rW_ARG ||
  323. asBCInfo[curr->op].type == asBCTYPE_wW_rW_DW_ARG ||
  324. asBCInfo[curr->op].type == asBCTYPE_wW_ARG ||
  325. asBCInfo[curr->op].type == asBCTYPE_wW_DW_ARG ||
  326. asBCInfo[curr->op].type == asBCTYPE_wW_QW_ARG) &&
  327. IsTemporary(curr->wArg[0]) &&
  328. !IsTempVarRead(curr, curr->wArg[0]) &&
  329. curr->op != asBC_FREE ) // Can't remove the FREE instruction
  330. {
  331. if( curr->op == asBC_LdGRdR4 && IsTempRegUsed(curr) )
  332. {
  333. curr->op = asBC_LDG;
  334. *next = GoBack(curr);
  335. return true;
  336. }
  337. *next = GoBack(DeleteInstruction(curr));
  338. return true;
  339. }
  340. // TODO: optimize: There should be one for doubles as well
  341. // The value is immediately used and then never again
  342. if( curr->op == asBC_SetV4 &&
  343. curr->next &&
  344. (curr->next->op == asBC_CMPi ||
  345. curr->next->op == asBC_CMPf ||
  346. curr->next->op == asBC_CMPu) &&
  347. curr->wArg[0] == curr->next->wArg[1] &&
  348. (IsTemporary(curr->wArg[0]) && // The variable is temporary and never used again
  349. !IsTempVarRead(curr->next, curr->wArg[0])) )
  350. {
  351. if( curr->next->op == asBC_CMPi ) curr->next->op = asBC_CMPIi;
  352. else if( curr->next->op == asBC_CMPf ) curr->next->op = asBC_CMPIf;
  353. else if( curr->next->op == asBC_CMPu ) curr->next->op = asBC_CMPIu;
  354. curr->next->size = asBCTypeSize[asBCInfo[asBC_CMPIi].type];
  355. curr->next->arg = curr->arg;
  356. *next = GoBack(DeleteInstruction(curr));
  357. return true;
  358. }
  359. // The value is immediately used and then never again
  360. if( curr->op == asBC_SetV4 &&
  361. curr->next &&
  362. (curr->next->op == asBC_ADDi ||
  363. curr->next->op == asBC_SUBi ||
  364. curr->next->op == asBC_MULi ||
  365. curr->next->op == asBC_ADDf ||
  366. curr->next->op == asBC_SUBf ||
  367. curr->next->op == asBC_MULf) &&
  368. curr->wArg[0] == curr->next->wArg[2] &&
  369. (curr->next->wArg[0] == curr->wArg[0] || // The variable is overwritten
  370. (IsTemporary(curr->wArg[0]) && // The variable is temporary and never used again
  371. !IsTempVarRead(curr->next, curr->wArg[0]))) )
  372. {
  373. if( curr->next->op == asBC_ADDi ) curr->next->op = asBC_ADDIi;
  374. else if( curr->next->op == asBC_SUBi ) curr->next->op = asBC_SUBIi;
  375. else if( curr->next->op == asBC_MULi ) curr->next->op = asBC_MULIi;
  376. else if( curr->next->op == asBC_ADDf ) curr->next->op = asBC_ADDIf;
  377. else if( curr->next->op == asBC_SUBf ) curr->next->op = asBC_SUBIf;
  378. else if( curr->next->op == asBC_MULf ) curr->next->op = asBC_MULIf;
  379. curr->next->size = asBCTypeSize[asBCInfo[asBC_ADDIi].type];
  380. curr->next->arg = curr->arg;
  381. *next = GoBack(DeleteInstruction(curr));
  382. return true;
  383. }
  384. if( curr->op == asBC_SetV4 &&
  385. curr->next &&
  386. (curr->next->op == asBC_ADDi ||
  387. curr->next->op == asBC_MULi ||
  388. curr->next->op == asBC_ADDf ||
  389. curr->next->op == asBC_MULf) &&
  390. curr->wArg[0] == curr->next->wArg[1] &&
  391. (curr->next->wArg[0] == curr->wArg[0] || // The variable is overwritten
  392. (IsTemporary(curr->wArg[0]) && // The variable is temporary and never used again
  393. !IsTempVarRead(curr->next, curr->wArg[0]))) )
  394. {
  395. if( curr->next->op == asBC_ADDi ) curr->next->op = asBC_ADDIi;
  396. else if( curr->next->op == asBC_MULi ) curr->next->op = asBC_MULIi;
  397. else if( curr->next->op == asBC_ADDf ) curr->next->op = asBC_ADDIf;
  398. else if( curr->next->op == asBC_MULf ) curr->next->op = asBC_MULIf;
  399. curr->next->size = asBCTypeSize[asBCInfo[asBC_ADDIi].type];
  400. curr->next->arg = curr->arg;
  401. // The order of the operands are changed
  402. curr->next->wArg[1] = curr->next->wArg[2];
  403. *next = GoBack(DeleteInstruction(curr));
  404. return true;
  405. }
  406. // The values is immediately moved to another variable and then not used again
  407. if( (asBCInfo[curr->op].type == asBCTYPE_wW_rW_rW_ARG ||
  408. asBCInfo[curr->op].type == asBCTYPE_wW_rW_DW_ARG) &&
  409. curr->next && curr->next->op == asBC_CpyVtoV4 &&
  410. curr->wArg[0] == curr->next->wArg[1] &&
  411. IsTemporary(curr->wArg[0]) &&
  412. !IsTempVarRead(curr->next, curr->wArg[0]) )
  413. {
  414. curr->wArg[0] = curr->next->wArg[0];
  415. DeleteInstruction(curr->next);
  416. *next = GoBack(curr);
  417. return true;
  418. }
  419. // The constant value is immediately moved to another variable and then not used again
  420. if( curr->op == asBC_SetV4 && curr->next && curr->next->op == asBC_CpyVtoV4 &&
  421. curr->wArg[0] == curr->next->wArg[1] &&
  422. IsTemporary(curr->wArg[0]) &&
  423. !IsTempVarRead(curr->next, curr->wArg[0]) )
  424. {
  425. curr->wArg[0] = curr->next->wArg[0];
  426. DeleteInstruction(curr->next);
  427. *next = GoBack(curr);
  428. return true;
  429. }
  430. // The register is copied to a temp variable and then back to the register again without being used afterwards
  431. if( curr->op == asBC_CpyRtoV4 && curr->next && curr->next->op == asBC_CpyVtoR4 &&
  432. curr->wArg[0] == curr->next->wArg[0] &&
  433. IsTemporary(curr->wArg[0]) &&
  434. !IsTempVarRead(curr->next, curr->wArg[0]) )
  435. {
  436. // Delete both instructions
  437. DeleteInstruction(curr->next);
  438. *next = GoBack(DeleteInstruction(curr));
  439. return true;
  440. }
  441. // The global value is copied to a temp and then immediately pushed on the stack
  442. if( curr->op == asBC_CpyGtoV4 && curr->next && curr->next->op == asBC_PshV4 &&
  443. curr->wArg[0] == curr->next->wArg[0] &&
  444. IsTemporary(curr->wArg[0]) &&
  445. !IsTempVarRead(curr->next, curr->wArg[0]) )
  446. {
  447. curr->op = asBC_PshG4;
  448. curr->size = asBCTypeSize[asBCInfo[asBC_PshG4].type];
  449. curr->stackInc = asBCInfo[asBC_PshG4].stackInc;
  450. DeleteInstruction(curr->next);
  451. *next = GoBack(curr);
  452. return true;
  453. }
  454. // The constant is copied to a temp and then immediately pushed on the stack
  455. if( curr->op == asBC_SetV4 && curr->next && curr->next->op == asBC_PshV4 &&
  456. curr->wArg[0] == curr->next->wArg[0] &&
  457. IsTemporary(curr->wArg[0]) &&
  458. !IsTempVarRead(curr->next, curr->wArg[0]) )
  459. {
  460. curr->op = asBC_PshC4;
  461. curr->stackInc = asBCInfo[asBC_PshC4].stackInc;
  462. DeleteInstruction(curr->next);
  463. *next = GoBack(curr);
  464. return true;
  465. }
  466. if( curr->op == asBC_SetV8 && curr->next && curr->next->op == asBC_PshV8 &&
  467. curr->wArg[0] == curr->next->wArg[0] &&
  468. IsTemporary(curr->wArg[0]) &&
  469. !IsTempVarRead(curr->next, curr->wArg[0]) )
  470. {
  471. curr->op = asBC_PshC8;
  472. curr->stackInc = asBCInfo[asBC_PshC8].stackInc;
  473. DeleteInstruction(curr->next);
  474. *next = GoBack(curr);
  475. return true;
  476. }
  477. // The constant is copied to a global variable and then never used again
  478. if( curr->op == asBC_SetV4 && curr->next && curr->next->op == asBC_CpyVtoG4 &&
  479. curr->wArg[0] == curr->next->wArg[0] &&
  480. IsTemporary(curr->wArg[0]) &&
  481. !IsTempVarRead(curr->next, curr->wArg[0]) )
  482. {
  483. curr->op = asBC_SetG4;
  484. curr->size = asBCTypeSize[asBCInfo[asBC_SetG4].type];
  485. *(((asDWORD*)&curr->arg)+AS_PTR_SIZE) = *ARG_DW(curr->arg);
  486. *ARG_PTR(curr->arg) = *ARG_PTR(curr->next->arg);
  487. DeleteInstruction(curr->next);
  488. *next = GoBack(curr);
  489. return true;
  490. }
  491. return false;
  492. }
  493. bool asCByteCode::IsTemporary(short offset)
  494. {
  495. for( asUINT n = 0; n < temporaryVariables.GetLength(); n++ )
  496. if( temporaryVariables[n] == offset )
  497. return true;
  498. return false;
  499. }
  500. int asCByteCode::Optimize()
  501. {
  502. // TODO: optimize: The optimizer should be able to inline function calls.
  503. // If the called function has only a few instructions, the function call should be inlined.
  504. // This is especially useful with the factory stubs used for template types and script classes.
  505. // TODO: optimize: Need a bytecode BC_AddRef so that BC_CALLSYS doesn't have to be used for this trivial call
  506. // TODO: optimize: A bytecode BC_RefCpyV that copies a handle from a local variable to another local variable
  507. // can easily substitute the frequently appearing pattern BC_PshV4, BC_PSF, BC_REFCPY, BC_POP
  508. // TODO: optimize: Script class methods are currently implemented to increase the ref count of the object upon
  509. // entry, and then release it upon exit. When the method isn't doing anything at all, this is
  510. // not necessary, as the function could simply do a RET immediately. This optimization is only
  511. // possible if the code has been built without the line cues, as if the SUSPEND is within the
  512. // function, then we can't do this optimization. Of course, this optimization may not be all
  513. // that useful, since in a real world app, it is probably not very common that empty class
  514. // methods are called.
  515. cByteInstruction *instr = first;
  516. while( instr )
  517. {
  518. cByteInstruction *curr = instr;
  519. instr = instr->next;
  520. // Remove or combine instructions
  521. if( RemoveUnusedValue(curr, &instr) ) continue;
  522. // Postpone initializations so that they may be combined in the second pass
  523. if( PostponeInitOfTemp(curr, &instr) ) continue;
  524. // XXX x, YYY y, SWAP4 -> YYY y, XXX x
  525. if( CanBeSwapped(curr) )
  526. {
  527. // Delete SWAP4
  528. DeleteInstruction(instr->next);
  529. // Swap instructions
  530. RemoveInstruction(instr);
  531. InsertBefore(curr, instr);
  532. instr = GoBack(instr);
  533. }
  534. // SWAP4, OP -> OP
  535. else if( IsCombination(curr, asBC_SWAP4, asBC_ADDi) ||
  536. IsCombination(curr, asBC_SWAP4, asBC_MULi) ||
  537. IsCombination(curr, asBC_SWAP4, asBC_ADDf) ||
  538. IsCombination(curr, asBC_SWAP4, asBC_MULf) )
  539. instr = GoBack(DeleteInstruction(curr));
  540. // T??, ClrHi -> T??
  541. else if( IsCombination(curr, asBC_TZ, asBC_ClrHi) ||
  542. IsCombination(curr, asBC_TNZ, asBC_ClrHi) ||
  543. IsCombination(curr, asBC_TS, asBC_ClrHi) ||
  544. IsCombination(curr, asBC_TNS, asBC_ClrHi) ||
  545. IsCombination(curr, asBC_TP, asBC_ClrHi) ||
  546. IsCombination(curr, asBC_TNP, asBC_ClrHi) )
  547. {
  548. // Remove the ClrHi instruction, since the test instructions always clear the top bytes anyway
  549. DeleteInstruction(instr);
  550. instr = GoBack(curr);
  551. }
  552. // PshV4 0, ADDSi, PopRPtr -> LoadThisR
  553. // PshV8 0, ADDSi, PopRPtr -> LoadThisR
  554. else if( (IsCombination(curr, asBC_PshV4, asBC_ADDSi) ||
  555. IsCombination(curr, asBC_PshV8, asBC_ADDSi)) &&
  556. IsCombination(instr, asBC_ADDSi, asBC_PopRPtr) &&
  557. curr->wArg[0] == 0 )
  558. {
  559. DeleteInstruction(curr);
  560. instr = GoBack(ChangeFirstDeleteNext(instr, asBC_LoadThisR));
  561. }
  562. // PshV4 x, ADDSi, PopRPtr -> LoadRObjR
  563. // PshV8 x, ADDSi, PopRPtr -> LoadRObjR
  564. else if( (IsCombination(curr, asBC_PshV4, asBC_ADDSi) ||
  565. IsCombination(curr, asBC_PshV8, asBC_ADDSi)) &&
  566. IsCombination(instr, asBC_ADDSi, asBC_PopRPtr) &&
  567. curr->wArg[0] != 0 )
  568. {
  569. curr->op = asBC_LoadRObjR;
  570. curr->size = asBCTypeSize[asBCInfo[asBC_LoadRObjR].type];
  571. curr->stackInc = asBCInfo[asBC_LoadRObjR].stackInc;
  572. curr->wArg[1] = instr->wArg[0];
  573. *(asDWORD*)&curr->arg = *(asDWORD*)&instr->arg;
  574. DeleteInstruction(instr->next);
  575. DeleteInstruction(instr);
  576. instr = GoBack(curr);
  577. }
  578. // PSF x, ADDSi, PopRPtr -> LoadVObjR
  579. else if( IsCombination(curr, asBC_PSF, asBC_ADDSi) &&
  580. IsCombination(instr, asBC_ADDSi, asBC_PopRPtr) )
  581. {
  582. curr->op = asBC_LoadVObjR;
  583. curr->size = asBCTypeSize[asBCInfo[asBC_LoadVObjR].type];
  584. curr->stackInc = asBCInfo[asBC_LoadVObjR].stackInc;
  585. curr->wArg[1] = instr->wArg[0];
  586. *(asDWORD*)&curr->arg = *(asDWORD*)&instr->arg;
  587. DeleteInstruction(instr->next);
  588. DeleteInstruction(instr);
  589. instr = GoBack(curr);
  590. }
  591. // PSF x, RDS4 -> PshV4 x
  592. else if( IsCombination(curr, asBC_PSF, asBC_RDS4) )
  593. instr = GoBack(ChangeFirstDeleteNext(curr, asBC_PshV4));
  594. // PSF x, RDS8 -> PshV8 x
  595. else if( IsCombination(curr, asBC_PSF, asBC_RDS8) )
  596. instr = GoBack(ChangeFirstDeleteNext(curr, asBC_PshV8));
  597. // RDS4, POP x -> POP x
  598. else if( IsCombination(curr, asBC_RDS4, asBC_POP) && instr->wArg[0] >= 1 )
  599. {
  600. DeleteInstruction(curr);
  601. // Transform the pop to remove the address instead of the 4 byte word
  602. instr->wArg[0] -= 1-AS_PTR_SIZE;
  603. instr = GoBack(instr);
  604. }
  605. // RDS8, POP 2 -> POP x-1
  606. else if( IsCombination(curr, asBC_RDS8, asBC_POP) && instr->wArg[0] >= 2 )
  607. {
  608. DeleteInstruction(curr);
  609. // Transform the pop to remove the address instead of the 8 byte word
  610. instr->wArg[0] -= 2-AS_PTR_SIZE;
  611. instr = GoBack(instr);
  612. }
  613. // LDG x, WRTV4 y -> CpyVtoG4 y, x
  614. else if( IsCombination(curr, asBC_LDG, asBC_WRTV4) && !IsTempRegUsed(instr) )
  615. {
  616. curr->op = asBC_CpyVtoG4;
  617. curr->size = asBCTypeSize[asBCInfo[asBC_CpyVtoG4].type];
  618. curr->wArg[0] = instr->wArg[0];
  619. DeleteInstruction(instr);
  620. instr = GoBack(curr);
  621. }
  622. // LDG x, RDR4 y -> CpyGtoV4 y, x
  623. else if( IsCombination(curr, asBC_LDG, asBC_RDR4) )
  624. {
  625. if( !IsTempRegUsed(instr) )
  626. curr->op = asBC_CpyGtoV4;
  627. else
  628. curr->op = asBC_LdGRdR4;
  629. curr->size = asBCTypeSize[asBCInfo[asBC_CpyGtoV4].type];
  630. curr->wArg[0] = instr->wArg[0];
  631. DeleteInstruction(instr);
  632. instr = GoBack(curr);
  633. }
  634. // LDV x, INCi -> IncVi x
  635. else if( IsCombination(curr, asBC_LDV, asBC_INCi) && !IsTempRegUsed(instr) )
  636. {
  637. curr->op = asBC_IncVi;
  638. DeleteInstruction(instr);
  639. instr = GoBack(curr);
  640. }
  641. // LDV x, DECi -> DecVi x
  642. else if( IsCombination(curr, asBC_LDV, asBC_DECi) && !IsTempRegUsed(instr) )
  643. {
  644. curr->op = asBC_DecVi;
  645. DeleteInstruction(instr);
  646. instr = GoBack(curr);
  647. }
  648. // POP a, RET b -> RET b
  649. else if( IsCombination(curr, asBC_POP, asBC_RET) )
  650. {
  651. // We don't combine the POP+RET because RET first restores
  652. // the previous stack pointer and then pops the arguments
  653. // Delete POP
  654. instr = GoBack(DeleteInstruction(curr));
  655. }
  656. // Delete JitEntry if the JIT instructions are not supposed to be included
  657. else if( curr->op == asBC_JitEntry && !engine->ep.includeJitInstructions )
  658. {
  659. instr = GoBack(DeleteInstruction(curr));
  660. }
  661. // SUSPEND, JitEntry, SUSPEND -> SUSPEND
  662. // LINE, JitEntry, LINE -> LINE
  663. else if( (IsCombination(curr, asBC_SUSPEND, asBC_JitEntry) && IsCombination(instr, asBC_JitEntry, asBC_SUSPEND)) ||
  664. (IsCombination(curr, asBC_LINE, asBC_JitEntry) && IsCombination(instr, asBC_JitEntry, asBC_LINE)) )
  665. {
  666. // Delete the two first instructions
  667. DeleteInstruction(instr);
  668. instr = GoBack(DeleteInstruction(curr));
  669. }
  670. // SUSPEND, SUSPEND -> SUSPEND
  671. // LINE, LINE -> LINE
  672. else if( IsCombination(curr, asBC_SUSPEND, asBC_SUSPEND) ||
  673. IsCombination(curr, asBC_LINE, asBC_LINE) )
  674. {
  675. // Delete the first instruction
  676. instr = GoBack(DeleteInstruction(curr));
  677. }
  678. // SUSPEND, Block, SUSPEND -> Block, SUSPEND
  679. else if( (IsCombination(curr, asBC_SUSPEND, asBC_Block) && IsCombination(instr, asBC_Block, asBC_SUSPEND)) ||
  680. (IsCombination(curr, asBC_LINE, asBC_Block) && IsCombination(instr, asBC_Block, asBC_LINE)) )
  681. {
  682. // Delete the first instruction
  683. instr = GoBack(DeleteInstruction(curr));
  684. }
  685. // PUSH a, PUSH b -> PUSH a+b
  686. else if( IsCombination(curr, asBC_PUSH, asBC_PUSH) )
  687. {
  688. // Combine the two PUSH
  689. instr->wArg[0] = curr->wArg[0] + instr->wArg[0];
  690. // Delete current
  691. DeleteInstruction(curr);
  692. // Continue with the instruction before the one removed
  693. instr = GoBack(instr);
  694. }
  695. // PshC4 a, GETREF 0 -> PSF a
  696. else if( IsCombination(curr, asBC_PshC4, asBC_GETREF) && instr->wArg[0] == 0 )
  697. {
  698. // Convert PshC4 a, to PSF a
  699. curr->wArg[0] = (short)*ARG_DW(curr->arg);
  700. curr->size = asBCTypeSize[asBCInfo[asBC_PSF].type];
  701. curr->op = asBC_PSF;
  702. DeleteInstruction(instr);
  703. instr = GoBack(curr);
  704. }
  705. // PGA, CHKREF -> PGA
  706. // PSF, CHKREF -> PSF
  707. else if( IsCombination(curr, asBC_PGA, asBC_CHKREF) ||
  708. IsCombination(curr, asBC_PSF, asBC_CHKREF) )
  709. {
  710. // Delete CHKREF since PGA and PSF always pushes a valid address on the stack
  711. DeleteInstruction(instr);
  712. instr = GoBack(curr);
  713. }
  714. // PGA, ChkRefS, CHKREF -> PGA, ChkRefS
  715. else if( IsCombination(curr, asBC_PGA, asBC_ChkRefS) &&
  716. IsCombination(instr, asBC_ChkRefS, asBC_CHKREF) )
  717. {
  718. // Delete CHKREF since PGA always pushes a valid address on the stack
  719. DeleteInstruction(instr->next);
  720. instr = GoBack(curr);
  721. }
  722. // PSF, FREE -> FREE, PSF
  723. else if( IsCombination(curr, asBC_PSF, asBC_FREE) )
  724. {
  725. // This pattern usually happens when a function returns an object, or handle
  726. // and then releases a temporary variable, possibly used in one of the arguments.
  727. // By swapping the order of these instructions, the code can be further optimized
  728. // to combine the PSF with the following instructions
  729. RemoveInstruction(instr);
  730. InsertBefore(curr, instr);
  731. instr = GoBack(instr);
  732. }
  733. // PshV4 y, POP x -> POP x-1
  734. // PshC4 y, POP x -> POP x-1
  735. else if( (IsCombination(curr, asBC_PshV4, asBC_POP) ||
  736. IsCombination(curr, asBC_PshC4, asBC_POP)) && instr->wArg[0] >= 1 )
  737. {
  738. DeleteInstruction(curr);
  739. instr->wArg[0]--;
  740. instr = GoBack(instr);
  741. }
  742. // PshRPtr, POP x -> POP x - 1
  743. else if( (IsCombination(curr, asBC_PshRPtr, asBC_POP) ||
  744. IsCombination(curr, asBC_PSF , asBC_POP) ||
  745. IsCombination(curr, asBC_VAR , asBC_POP))
  746. && instr->wArg[0] >= AS_PTR_SIZE )
  747. {
  748. DeleteInstruction(curr);
  749. instr->wArg[0] -= AS_PTR_SIZE;
  750. instr = GoBack(instr);
  751. }
  752. // PshV8 y, POP x -> POP x-2
  753. // PshC8 y, POP x -> POP x-2
  754. else if( (IsCombination(curr, asBC_PshV8, asBC_POP) ||
  755. IsCombination(curr, asBC_PshC8, asBC_POP)) && instr->wArg[0] >= 2 )
  756. {
  757. DeleteInstruction(curr);
  758. instr->wArg[0] -= 2;
  759. instr = GoBack(instr);
  760. }
  761. // POP 0 -> remove
  762. // PUSH 0 -> remove
  763. else if( (curr->op == asBC_POP || curr->op == asBC_PUSH ) && curr->wArg[0] == 0 )
  764. instr = GoBack(DeleteInstruction(curr));
  765. // Begin PATTERN
  766. // T**; J** +x -> J** +x
  767. else if( IsCombination(curr, asBC_TZ , asBC_JZ ) ||
  768. IsCombination(curr, asBC_TNZ, asBC_JNZ) )
  769. instr = GoBack(DeleteFirstChangeNext(curr, asBC_JNZ));
  770. else if( IsCombination(curr, asBC_TNZ, asBC_JZ ) ||
  771. IsCombination(curr, asBC_TZ , asBC_JNZ) )
  772. instr = GoBack(DeleteFirstChangeNext(curr, asBC_JZ));
  773. else if( IsCombination(curr, asBC_TS , asBC_JZ ) ||
  774. IsCombination(curr, asBC_TNS, asBC_JNZ) )
  775. instr = GoBack(DeleteFirstChangeNext(curr, asBC_JNS));
  776. else if( IsCombination(curr, asBC_TNS, asBC_JZ ) ||
  777. IsCombination(curr, asBC_TS , asBC_JNZ) )
  778. instr = GoBack(DeleteFirstChangeNext(curr, asBC_JS));
  779. else if( IsCombination(curr, asBC_TP , asBC_JZ ) ||
  780. IsCombination(curr, asBC_TNP, asBC_JNZ) )
  781. instr = GoBack(DeleteFirstChangeNext(curr, asBC_JNP));
  782. else if( IsCombination(curr, asBC_TNP, asBC_JZ ) ||
  783. IsCombination(curr, asBC_TP , asBC_JNZ) )
  784. instr = GoBack(DeleteFirstChangeNext(curr, asBC_JP));
  785. // End PATTERN
  786. // JMP +0 -> remove
  787. else if( IsCombination(curr, asBC_JMP, asBC_LABEL) && *(int*)&curr->arg == instr->wArg[0] )
  788. instr = GoBack(DeleteInstruction(curr));
  789. // PSF, ChkRefS, RDS4 -> PshV4, CHKREF
  790. else if( IsCombination(curr, asBC_PSF, asBC_ChkRefS) &&
  791. IsCombination(instr, asBC_ChkRefS, asBC_RDS4) )
  792. {
  793. asASSERT( AS_PTR_SIZE == 1 );
  794. curr->op = asBC_PshV4;
  795. instr->op = asBC_CHKREF;
  796. DeleteInstruction(instr->next);
  797. instr = GoBack(curr);
  798. }
  799. // PSF, ChkRefS, RDS8 -> PshV8, CHKREF
  800. else if( IsCombination(curr, asBC_PSF, asBC_ChkRefS) &&
  801. IsCombination(instr, asBC_ChkRefS, asBC_RDS8) )
  802. {
  803. asASSERT( AS_PTR_SIZE == 2 );
  804. curr->op = asBC_PshV8;
  805. instr->op = asBC_CHKREF;
  806. DeleteInstruction(instr->next);
  807. instr = GoBack(curr);
  808. }
  809. // PSF, ChkRefS, POP -> ChkNullV
  810. else if( (IsCombination(curr, asBC_PSF, asBC_ChkRefS) &&
  811. IsCombination(instr, asBC_ChkRefS, asBC_POP) &&
  812. instr->next->wArg[0] >= AS_PTR_SIZE) )
  813. {
  814. curr->op = asBC_ChkNullV;
  815. curr->stackInc = 0;
  816. // Decrease the number of DWORDs popped
  817. instr->next->wArg[0] -= AS_PTR_SIZE;
  818. // Delete the ChkRefS instruction
  819. DeleteInstruction(instr);
  820. instr = GoBack(curr);
  821. }
  822. // PshV4, CHKREF, POP -> ChkNullV
  823. else if( (IsCombination(curr, asBC_PshV4, asBC_CHKREF) &&
  824. IsCombination(instr, asBC_CHKREF, asBC_POP) &&
  825. instr->next->wArg[0] >= 1) )
  826. {
  827. asASSERT( AS_PTR_SIZE == 1 );
  828. curr->op = asBC_ChkNullV;
  829. curr->stackInc = 0;
  830. DeleteInstruction(instr->next);
  831. DeleteInstruction(instr);
  832. instr = GoBack(curr);
  833. }
  834. // PshV8, CHKREF, POP -> ChkNullV
  835. else if( (IsCombination(curr, asBC_PshV8, asBC_CHKREF) &&
  836. IsCombination(instr, asBC_CHKREF, asBC_POP) &&
  837. instr->next->wArg[0] >= 2) )
  838. {
  839. asASSERT( AS_PTR_SIZE == 2 );
  840. curr->op = asBC_ChkNullV;
  841. curr->stackInc = 0;
  842. DeleteInstruction(instr->next);
  843. DeleteInstruction(instr);
  844. instr = GoBack(curr);
  845. }
  846. }
  847. return 0;
  848. }
  849. bool asCByteCode::IsTempVarReadByInstr(cByteInstruction *curr, int offset)
  850. {
  851. // Which instructions read from variables?
  852. if( asBCInfo[curr->op].type == asBCTYPE_wW_rW_rW_ARG &&
  853. (curr->wArg[1] == offset || curr->wArg[2] == offset) )
  854. return true;
  855. else if( (asBCInfo[curr->op].type == asBCTYPE_rW_ARG ||
  856. asBCInfo[curr->op].type == asBCTYPE_rW_DW_ARG ||
  857. asBCInfo[curr->op].type == asBCTYPE_rW_QW_ARG ||
  858. asBCInfo[curr->op].type == asBCTYPE_rW_W_DW_ARG ||
  859. curr->op == asBC_FREE) && // FREE both read and write to the variable
  860. curr->wArg[0] == offset )
  861. return true;
  862. else if( (asBCInfo[curr->op].type == asBCTYPE_wW_rW_ARG ||
  863. asBCInfo[curr->op].type == asBCTYPE_wW_rW_DW_ARG) &&
  864. curr->wArg[1] == offset )
  865. return true;
  866. else if( asBCInfo[curr->op].type == asBCTYPE_rW_rW_ARG &&
  867. ((signed)curr->wArg[0] == offset || (signed)curr->wArg[1] == offset) )
  868. return true;
  869. else if( curr->op == asBC_LoadThisR && offset == 0 )
  870. return true;
  871. return false;
  872. }
  873. bool asCByteCode::IsInstrJmpOrLabel(cByteInstruction *curr)
  874. {
  875. if( curr->op == asBC_JS ||
  876. curr->op == asBC_JNS ||
  877. curr->op == asBC_JP ||
  878. curr->op == asBC_JNP ||
  879. curr->op == asBC_JMPP ||
  880. curr->op == asBC_JMP ||
  881. curr->op == asBC_JZ ||
  882. curr->op == asBC_JNZ ||
  883. curr->op == asBC_LABEL )
  884. return true;
  885. return false;
  886. }
  887. bool asCByteCode::IsTempVarOverwrittenByInstr(cByteInstruction *curr, int offset)
  888. {
  889. // Which instructions overwrite the variable or discard it?
  890. if( curr->op == asBC_RET ||
  891. curr->op == asBC_SUSPEND )
  892. return true;
  893. else if( (asBCInfo[curr->op].type == asBCTYPE_wW_rW_rW_ARG ||
  894. asBCInfo[curr->op].type == asBCTYPE_wW_rW_ARG ||
  895. asBCInfo[curr->op].type == asBCTYPE_wW_rW_DW_ARG ||
  896. asBCInfo[curr->op].type == asBCTYPE_wW_ARG ||
  897. asBCInfo[curr->op].type == asBCTYPE_wW_W_ARG ||
  898. asBCInfo[curr->op].type == asBCTYPE_wW_DW_ARG ||
  899. asBCInfo[curr->op].type == asBCTYPE_wW_QW_ARG) &&
  900. curr->wArg[0] == offset )
  901. return true;
  902. return false;
  903. }
  904. bool asCByteCode::IsTempVarRead(cByteInstruction *curr, int offset)
  905. {
  906. asCArray<cByteInstruction *> openPaths;
  907. asCArray<cByteInstruction *> closedPaths;
  908. // We're not interested in the first instruction, since it is the one that sets the variable
  909. openPaths.PushLast(curr->next);
  910. while( openPaths.GetLength() )
  911. {
  912. curr = openPaths.PopLast();
  913. // Add the instruction to the closed paths so that we don't verify it again
  914. closedPaths.PushLast(curr);
  915. while( curr )
  916. {
  917. if( IsTempVarReadByInstr(curr, offset) ) return true;
  918. if( IsTempVarOverwrittenByInstr(curr, offset) ) break;
  919. // In case of jumps, we must follow the each of the paths
  920. if( curr->op == asBC_JMP )
  921. {
  922. int label = *((int*)ARG_DW(curr->arg));
  923. int r = FindLabel(label, curr, &curr, 0); asASSERT( r == 0 ); UNUSED_VAR(r);
  924. if( !closedPaths.Exists(curr) &&
  925. !openPaths.Exists(curr) )
  926. openPaths.PushLast(curr);
  927. break;
  928. }
  929. else if( curr->op == asBC_JZ || curr->op == asBC_JNZ ||
  930. curr->op == asBC_JS || curr->op == asBC_JNS ||
  931. curr->op == asBC_JP || curr->op == asBC_JNP )
  932. {
  933. cByteInstruction *dest = 0;
  934. int label = *((int*)ARG_DW(curr->arg));
  935. int r = FindLabel(label, curr, &dest, 0); asASSERT( r == 0 ); UNUSED_VAR(r);
  936. if( !closedPaths.Exists(dest) &&
  937. !openPaths.Exists(dest) )
  938. openPaths.PushLast(dest);
  939. }
  940. else if( curr->op == asBC_JMPP )
  941. {
  942. // A JMPP instruction is always followed by a series of JMP instructions
  943. // that give the real destination (like a look-up table). We need add all
  944. // of these as open paths.
  945. curr = curr->next;
  946. while( curr->op == asBC_JMP )
  947. {
  948. cByteInstruction *dest = 0;
  949. int label = *((int*)ARG_DW(curr->arg));
  950. int r = FindLabel(label, curr, &dest, 0); asASSERT( r == 0 ); UNUSED_VAR(r);
  951. if( !closedPaths.Exists(dest) &&
  952. !openPaths.Exists(dest) )
  953. openPaths.PushLast(dest);
  954. curr = curr->next;
  955. }
  956. // We should now be on a label which is the destination of the
  957. // first JMP in the sequence and is already added in the open paths
  958. asASSERT(curr->op == asBC_LABEL);
  959. break;
  960. }
  961. curr = curr->next;
  962. }
  963. }
  964. return false;
  965. }
  966. bool asCByteCode::IsTempRegUsed(cByteInstruction *curr)
  967. {
  968. // We're not interested in the first instruction, since it is the one that sets the register
  969. while( curr->next )
  970. {
  971. curr = curr->next;
  972. // Which instructions read from the register?
  973. if( curr->op == asBC_INCi ||
  974. curr->op == asBC_INCi16 ||
  975. curr->op == asBC_INCi8 ||
  976. curr->op == asBC_INCf ||
  977. curr->op == asBC_INCd ||
  978. curr->op == asBC_DECi ||
  979. curr->op == asBC_DECi16 ||
  980. curr->op == asBC_DECi8 ||
  981. curr->op == asBC_DECf ||
  982. curr->op == asBC_DECd ||
  983. curr->op == asBC_WRTV1 ||
  984. curr->op == asBC_WRTV2 ||
  985. curr->op == asBC_WRTV4 ||
  986. curr->op == asBC_WRTV8 ||
  987. curr->op == asBC_RDR1 ||
  988. curr->op == asBC_RDR2 ||
  989. curr->op == asBC_RDR4 ||
  990. curr->op == asBC_RDR8 ||
  991. curr->op == asBC_PshRPtr ||
  992. curr->op == asBC_CpyRtoV4 ||
  993. curr->op == asBC_CpyRtoV8 ||
  994. curr->op == asBC_TZ ||
  995. curr->op == asBC_TNZ ||
  996. curr->op == asBC_TS ||
  997. curr->op == asBC_TNS ||
  998. curr->op == asBC_TP ||
  999. curr->op == asBC_TNP ||
  1000. curr->op == asBC_JZ ||
  1001. curr->op == asBC_JNZ ||
  1002. curr->op == asBC_JS ||
  1003. curr->op == asBC_JNS ||
  1004. curr->op == asBC_JP ||
  1005. curr->op == asBC_JNP )
  1006. return true;
  1007. // Which instructions overwrite the register or discard the value?
  1008. if( curr->op == asBC_CALL ||
  1009. curr->op == asBC_PopRPtr ||
  1010. curr->op == asBC_CALLSYS ||
  1011. curr->op == asBC_CALLBND ||
  1012. curr->op == asBC_SUSPEND ||
  1013. curr->op == asBC_ALLOC ||
  1014. curr->op == asBC_CpyVtoR4 ||
  1015. curr->op == asBC_LdGRdR4 ||
  1016. curr->op == asBC_LDG ||
  1017. curr->op == asBC_LDV ||
  1018. curr->op == asBC_TZ ||
  1019. curr->op == asBC_TNZ ||
  1020. curr->op == asBC_TS ||
  1021. curr->op == asBC_TNS ||
  1022. curr->op == asBC_TP ||
  1023. curr->op == asBC_TNP ||
  1024. curr->op == asBC_JS ||
  1025. curr->op == asBC_JNS ||
  1026. curr->op == asBC_JP ||
  1027. curr->op == asBC_JNP ||
  1028. curr->op == asBC_JMPP ||
  1029. curr->op == asBC_JMP ||
  1030. curr->op == asBC_JZ ||
  1031. curr->op == asBC_JNZ ||
  1032. curr->op == asBC_CMPi ||
  1033. curr->op == asBC_CMPu ||
  1034. curr->op == asBC_CMPf ||
  1035. curr->op == asBC_CMPd ||
  1036. curr->op == asBC_CMPIi ||
  1037. curr->op == asBC_CMPIu ||
  1038. curr->op == asBC_CMPIf ||
  1039. curr->op == asBC_LABEL ||
  1040. curr->op == asBC_LoadThisR ||
  1041. curr->op == asBC_LoadRObjR ||
  1042. curr->op == asBC_LoadVObjR )
  1043. return false;
  1044. }
  1045. return false;
  1046. }
  1047. bool asCByteCode::IsSimpleExpression()
  1048. {
  1049. // A simple expression is one that cannot be suspended at any time, i.e.
  1050. // it doesn't have any calls to other routines, and doesn't have any suspend instructions
  1051. cByteInstruction *instr = first;
  1052. while( instr )
  1053. {
  1054. if( instr->op == asBC_ALLOC ||
  1055. instr->op == asBC_CALL ||
  1056. instr->op == asBC_CALLSYS ||
  1057. instr->op == asBC_SUSPEND ||
  1058. instr->op == asBC_LINE ||
  1059. instr->op == asBC_FREE ||
  1060. instr->op == asBC_CallPtr ||
  1061. instr->op == asBC_CALLINTF ||
  1062. instr->op == asBC_CALLBND )
  1063. return false;
  1064. instr = instr->next;
  1065. }
  1066. return true;
  1067. }
  1068. void asCByteCode::ExtractLineNumbers()
  1069. {
  1070. int lastLinePos = -1;
  1071. int pos = 0;
  1072. cByteInstruction *instr = first;
  1073. while( instr )
  1074. {
  1075. cByteInstruction *curr = instr;
  1076. instr = instr->next;
  1077. if( curr->op == asBC_LINE )
  1078. {
  1079. if( lastLinePos == pos )
  1080. {
  1081. lineNumbers.PopLast();
  1082. lineNumbers.PopLast();
  1083. }
  1084. lastLinePos = pos;
  1085. lineNumbers.PushLast(pos);
  1086. lineNumbers.PushLast(*(int*)ARG_DW(curr->arg));
  1087. if( !engine->ep.buildWithoutLineCues )
  1088. {
  1089. // Transform BC_LINE into BC_SUSPEND
  1090. curr->op = asBC_SUSPEND;
  1091. curr->size = asBCTypeSize[asBCInfo[asBC_SUSPEND].type];
  1092. pos += curr->size;
  1093. }
  1094. else
  1095. {
  1096. // Delete the instruction
  1097. DeleteInstruction(curr);
  1098. }
  1099. }
  1100. else
  1101. pos += curr->size;
  1102. }
  1103. }
  1104. void asCByteCode::ExtractObjectVariableInfo(asCScriptFunction *outFunc)
  1105. {
  1106. int pos = 0;
  1107. cByteInstruction *instr = first;
  1108. while( instr )
  1109. {
  1110. if( instr->op == asBC_Block )
  1111. {
  1112. asSObjectVariableInfo info;
  1113. info.programPos = pos;
  1114. info.variableOffset = 0;
  1115. info.option = instr->wArg[0] ? asBLOCK_BEGIN : asBLOCK_END;
  1116. outFunc->objVariableInfo.PushLast(info);
  1117. }
  1118. else if( instr->op == asBC_ObjInfo )
  1119. {
  1120. asSObjectVariableInfo info;
  1121. info.programPos = pos;
  1122. info.variableOffset = (short)instr->wArg[0];
  1123. info.option = *(int*)ARG_DW(instr->arg);
  1124. outFunc->objVariableInfo.PushLast(info);
  1125. }
  1126. else if( instr->op == asBC_VarDecl )
  1127. {
  1128. outFunc->variables[instr->wArg[0]]->declaredAtProgramPos = pos;
  1129. }
  1130. else
  1131. pos += instr->size;
  1132. instr = instr->next;
  1133. }
  1134. }
  1135. int asCByteCode::GetSize()
  1136. {
  1137. int size = 0;
  1138. cByteInstruction *instr = first;
  1139. while( instr )
  1140. {
  1141. size += instr->GetSize();
  1142. instr = instr->next;
  1143. }
  1144. return size;
  1145. }
  1146. void asCByteCode::AddCode(asCByteCode *bc)
  1147. {
  1148. if( bc->first )
  1149. {
  1150. if( first == 0 )
  1151. {
  1152. first = bc->first;
  1153. last = bc->last;
  1154. bc->first = 0;
  1155. bc->last = 0;
  1156. }
  1157. else
  1158. {
  1159. last->next = bc->first;
  1160. bc->first->prev = last;
  1161. last = bc->last;
  1162. bc->first = 0;
  1163. bc->last = 0;
  1164. }
  1165. }
  1166. }
  1167. int asCByteCode::AddInstruction()
  1168. {
  1169. cByteInstruction *instr = new(engine->memoryMgr.AllocByteInstruction()) cByteInstruction();
  1170. if( first == 0 )
  1171. {
  1172. first = last = instr;
  1173. }
  1174. else
  1175. {
  1176. last->AddAfter(instr);
  1177. last = instr;
  1178. }
  1179. return 0;
  1180. }
  1181. int asCByteCode::AddInstructionFirst()
  1182. {
  1183. cByteInstruction *instr = new(engine->memoryMgr.AllocByteInstruction()) cByteInstruction();
  1184. if( first == 0 )
  1185. {
  1186. first = last = instr;
  1187. }
  1188. else
  1189. {
  1190. first->AddBefore(instr);
  1191. first = instr;
  1192. }
  1193. return 0;
  1194. }
  1195. void asCByteCode::Call(asEBCInstr instr, int funcID, int pop)
  1196. {
  1197. if( AddInstruction() < 0 )
  1198. return;
  1199. asASSERT(asBCInfo[instr].type == asBCTYPE_DW_ARG);
  1200. last->op = instr;
  1201. last->size = asBCTypeSize[asBCInfo[instr].type];
  1202. last->stackInc = -pop; // BC_CALL and BC_CALLBND doesn't pop the argument but when the callee returns the arguments are already popped
  1203. *((int*)ARG_DW(last->arg)) = funcID;
  1204. // Add a JitEntry instruction after function calls so that JIT's can resume execution
  1205. InstrPTR(asBC_JitEntry, 0);
  1206. }
  1207. void asCByteCode::CallPtr(asEBCInstr instr, int funcPtrVar, int pop)
  1208. {
  1209. if( AddInstruction() < 0 )
  1210. return;
  1211. asASSERT(asBCInfo[instr].type == asBCTYPE_rW_ARG);
  1212. last->op = instr;
  1213. last->size = asBCTypeSize[asBCInfo[instr].type];
  1214. last->stackInc = -pop;
  1215. last->wArg[0] = (short)funcPtrVar;
  1216. // Add a JitEntry instruction after function calls so that JIT's can resume execution
  1217. InstrPTR(asBC_JitEntry, 0);
  1218. }
  1219. void asCByteCode::Alloc(asEBCInstr instr, void *objID, int funcID, int pop)
  1220. {
  1221. if( AddInstruction() < 0 )
  1222. return;
  1223. last->op = instr;
  1224. last->size = asBCTypeSize[asBCInfo[instr].type];
  1225. last->stackInc = -pop; // BC_ALLOC
  1226. asASSERT(asBCInfo[instr].type == asBCTYPE_PTR_DW_ARG);
  1227. *ARG_PTR(last->arg) = (asPTRWORD)(size_t)objID;
  1228. *((int*)(ARG_DW(last->arg)+AS_PTR_SIZE)) = funcID;
  1229. // Add a JitEntry instruction after function calls so that JIT's can resume execution
  1230. InstrPTR(asBC_JitEntry, 0);
  1231. }
  1232. void asCByteCode::Ret(int pop)
  1233. {
  1234. if( AddInstruction() < 0 )
  1235. return;
  1236. asASSERT(asBCInfo[asBC_RET].type == asBCTYPE_W_ARG);
  1237. last->op = asBC_RET;
  1238. last->size = asBCTypeSize[asBCInfo[asBC_RET].type];
  1239. last->stackInc = 0; // The instruction pops the argument, but it doesn't affect current function
  1240. last->wArg[0] = (short)pop;
  1241. }
  1242. void asCByteCode::JmpP(int var, asDWORD max)
  1243. {
  1244. if( AddInstruction() < 0 )
  1245. return;
  1246. asASSERT(asBCInfo[asBC_JMPP].type == asBCTYPE_rW_ARG);
  1247. last->op = asBC_JMPP;
  1248. last->size = asBCTypeSize[asBCInfo[asBC_JMPP].type];
  1249. last->stackInc = asBCInfo[asBC_JMPP].stackInc;
  1250. last->wArg[0] = (short)var;
  1251. // Store the largest jump that is made for PostProcess()
  1252. *ARG_DW(last->arg) = max;
  1253. }
  1254. void asCByteCode::Label(short label)
  1255. {
  1256. if( AddInstruction() < 0 )
  1257. return;
  1258. last->op = asBC_LABEL;
  1259. last->size = 0;
  1260. last->stackInc = 0;
  1261. last->wArg[0] = label;
  1262. }
  1263. void asCByteCode::Line(int line, int column)
  1264. {
  1265. if( AddInstruction() < 0 )
  1266. return;
  1267. last->op = asBC_LINE;
  1268. // If the build is without line cues these instructions will be removed
  1269. // otherwise they will be transformed into SUSPEND instructions.
  1270. if( engine->ep.buildWithoutLineCues )
  1271. last->size = 0;
  1272. else
  1273. last->size = asBCTypeSize[asBCInfo[asBC_SUSPEND].type];
  1274. last->stackInc = 0;
  1275. *((int*)ARG_DW(last->arg)) = (line & 0xFFFFF)|((column & 0xFFF)<<20);
  1276. // Add a JitEntry after the line instruction to allow the JIT function to resume after a suspend
  1277. InstrPTR(asBC_JitEntry, 0);
  1278. }
  1279. void asCByteCode::ObjInfo(int offset, int info)
  1280. {
  1281. if( AddInstruction() < 0 )
  1282. return;
  1283. // Add the special instruction that will be used to tell the exception
  1284. // handler when an object is initialized and deinitialized.
  1285. last->op = asBC_ObjInfo;
  1286. last->size = 0;
  1287. last->stackInc = 0;
  1288. last->wArg[0] = (short)offset;
  1289. *((int*)ARG_DW(last->arg)) = info;
  1290. }
  1291. void asCByteCode::Block(bool start)
  1292. {
  1293. if( AddInstruction() < 0 )
  1294. return;
  1295. last->op = asBC_Block;
  1296. last->size = 0;
  1297. last->stackInc = 0;
  1298. last->wArg[0] = start ? 1 : 0;
  1299. }
  1300. void asCByteCode::VarDecl(int varDeclIdx)
  1301. {
  1302. if( AddInstruction() < 0 )
  1303. return;
  1304. last->op = asBC_VarDecl;
  1305. last->size = 0;
  1306. last->stackInc = 0;
  1307. last->wArg[0] = (asWORD)varDeclIdx;
  1308. }
  1309. int asCByteCode::FindLabel(int label, cByteInstruction *from, cByteInstruction **dest, int *positionDelta)
  1310. {
  1311. // Search forward
  1312. int labelPos = -from->GetSize();
  1313. cByteInstruction *labelInstr = from;
  1314. while( labelInstr )
  1315. {
  1316. labelPos += labelInstr->GetSize();
  1317. labelInstr = labelInstr->next;
  1318. if( labelInstr && labelInstr->op == asBC_LABEL )
  1319. {
  1320. if( labelInstr->wArg[0] == label )
  1321. break;
  1322. }
  1323. }
  1324. if( labelInstr == 0 )
  1325. {
  1326. // Search backwards
  1327. labelPos = -from->GetSize();
  1328. labelInstr = from;
  1329. while( labelInstr )
  1330. {
  1331. labelInstr = labelInstr->prev;
  1332. if( labelInstr )
  1333. {
  1334. labelPos -= labelInstr->GetSize();
  1335. if( labelInstr->op == asBC_LABEL )
  1336. {
  1337. if( labelInstr->wArg[0] == label )
  1338. break;
  1339. }
  1340. }
  1341. }
  1342. }
  1343. if( labelInstr != 0 )
  1344. {
  1345. if( dest ) *dest = labelInstr;
  1346. if( positionDelta ) *positionDelta = labelPos;
  1347. return 0;
  1348. }
  1349. return -1;
  1350. }
  1351. int asCByteCode::ResolveJumpAddresses()
  1352. {
  1353. int pos = 0;
  1354. cByteInstruction *instr = first;
  1355. while( instr )
  1356. {
  1357. // The program pointer is updated as the instruction is read
  1358. pos += instr->GetSize();
  1359. if( instr->op == asBC_JMP ||
  1360. instr->op == asBC_JZ || instr->op == asBC_JNZ ||
  1361. instr->op == asBC_JS || instr->op == asBC_JNS ||
  1362. instr->op == asBC_JP || instr->op == asBC_JNP )
  1363. {
  1364. int label = *((int*) ARG_DW(instr->arg));
  1365. int labelPosOffset;
  1366. int r = FindLabel(label, instr, 0, &labelPosOffset);
  1367. if( r == 0 )
  1368. *((int*) ARG_DW(instr->arg)) = labelPosOffset;
  1369. else
  1370. return -1;
  1371. }
  1372. instr = instr->next;
  1373. }
  1374. return 0;
  1375. }
  1376. cByteInstruction *asCByteCode::DeleteInstruction(cByteInstruction *instr)
  1377. {
  1378. if( instr == 0 ) return 0;
  1379. cByteInstruction *ret = instr->prev ? instr->prev : instr->next;
  1380. RemoveInstruction(instr);
  1381. engine->memoryMgr.FreeByteInstruction(instr);
  1382. return ret;
  1383. }
  1384. void asCByteCode::Output(asDWORD *array)
  1385. {
  1386. // TODO: Receive a script function pointer
  1387. asDWORD *ap = array;
  1388. cByteInstruction *instr = first;
  1389. while( instr )
  1390. {
  1391. if( instr->GetSize() > 0 )
  1392. {
  1393. *(asBYTE*)ap = asBYTE(instr->op);
  1394. *(((asBYTE*)ap)+1) = 0; // Second byte is always zero
  1395. switch( asBCInfo[instr->op].type )
  1396. {
  1397. case asBCTYPE_NO_ARG:
  1398. *(((asWORD*)ap)+1) = 0; // Clear upper bytes
  1399. break;
  1400. case asBCTYPE_wW_rW_rW_ARG:
  1401. *(((asWORD*)ap)+1) = instr->wArg[0];
  1402. *(((asWORD*)ap)+2) = instr->wArg[1];
  1403. *(((asWORD*)ap)+3) = instr->wArg[2];
  1404. break;
  1405. case asBCTYPE_wW_DW_ARG:
  1406. case asBCTYPE_rW_DW_ARG:
  1407. case asBCTYPE_W_DW_ARG:
  1408. *(((asWORD*)ap)+1) = instr->wArg[0];
  1409. *(ap+1) = *(asDWORD*)&instr->arg;
  1410. break;
  1411. case asBCTYPE_wW_rW_DW_ARG:
  1412. case asBCTYPE_rW_W_DW_ARG:
  1413. *(((asWORD*)ap)+1) = instr->wArg[0];
  1414. *(((asWORD*)ap)+2) = instr->wArg[1];
  1415. *(ap+2) = *(asDWORD*)&instr->arg;
  1416. break;
  1417. case asBCTYPE_wW_QW_ARG:
  1418. case asBCTYPE_rW_QW_ARG:
  1419. *(((asWORD*)ap)+1) = instr->wArg[0];
  1420. *(asQWORD*)(ap+1) = asQWORD(instr->arg);
  1421. break;
  1422. case asBCTYPE_W_ARG:
  1423. case asBCTYPE_rW_ARG:
  1424. case asBCTYPE_wW_ARG:
  1425. *(((asWORD*)ap)+1) = instr->wArg[0];
  1426. break;
  1427. case asBCTYPE_wW_rW_ARG:
  1428. case asBCTYPE_rW_rW_ARG:
  1429. case asBCTYPE_wW_W_ARG:
  1430. *(((asWORD *)ap)+1) = instr->wArg[0];
  1431. *(((asWORD *)ap)+2) = instr->wArg[1];
  1432. break;
  1433. case asBCTYPE_QW_DW_ARG:
  1434. case asBCTYPE_DW_DW_ARG:
  1435. case asBCTYPE_QW_ARG:
  1436. case asBCTYPE_DW_ARG:
  1437. *(((asWORD*)ap)+1) = 0; // Clear upper bytes
  1438. memcpy(ap+1, &instr->arg, instr->GetSize()*4-4);
  1439. break;
  1440. default:
  1441. // How did we get here?
  1442. asASSERT(false);
  1443. break;
  1444. }
  1445. }
  1446. ap += instr->GetSize();
  1447. instr = instr->next;
  1448. }
  1449. }
  1450. void asCByteCode::PostProcess()
  1451. {
  1452. if( first == 0 ) return;
  1453. // This function will do the following
  1454. // - Verify if there is any code that never gets executed and remove it
  1455. // - Calculate the stack size at the position of each byte code
  1456. // - Calculate the largest stack needed
  1457. largestStackUsed = 0;
  1458. cByteInstruction *instr = first;
  1459. while( instr )
  1460. {
  1461. instr->marked = false;
  1462. instr->stackSize = -1;
  1463. instr = instr->next;
  1464. }
  1465. // Add the first instruction to the list of unchecked code paths
  1466. asCArray<cByteInstruction *> paths;
  1467. AddPath(paths, first, 0);
  1468. // Go through each of the code paths
  1469. for( asUINT p = 0; p < paths.GetLength(); ++p )
  1470. {
  1471. instr = paths[p];
  1472. int stackSize = instr->stackSize;
  1473. while( instr )
  1474. {
  1475. instr->marked = true;
  1476. instr->stackSize = stackSize;
  1477. stackSize += instr->stackInc;
  1478. if( stackSize > largestStackUsed )
  1479. largestStackUsed = stackSize;
  1480. if( instr->op == asBC_JMP )
  1481. {
  1482. // Find the label that we should jump to
  1483. int label = *((int*) ARG_DW(instr->arg));
  1484. cByteInstruction *dest = 0;
  1485. int r = FindLabel(label, instr, &dest, 0); asASSERT( r == 0 ); UNUSED_VAR(r);
  1486. AddPath(paths, dest, stackSize);
  1487. break;
  1488. }
  1489. else if( instr->op == asBC_JZ || instr->op == asBC_JNZ ||
  1490. instr->op == asBC_JS || instr->op == asBC_JNS ||
  1491. instr->op == asBC_JP || instr->op == asBC_JNP )
  1492. {
  1493. // Find the label that is being jumped to
  1494. int label = *((int*) ARG_DW(instr->arg));
  1495. cByteInstruction *dest = 0;
  1496. int r = FindLabel(label, instr, &dest, 0); asASSERT( r == 0 ); UNUSED_VAR(r);
  1497. AddPath(paths, dest, stackSize);
  1498. // Add both paths to the code paths
  1499. AddPath(paths, instr->next, stackSize);
  1500. break;
  1501. }
  1502. else if( instr->op == asBC_JMPP )
  1503. {
  1504. // I need to know the largest value possible
  1505. asDWORD max = *ARG_DW(instr->arg);
  1506. // Add all destinations to the code paths
  1507. cByteInstruction *dest = instr->next;
  1508. for( asDWORD n = 0; n <= max && dest != 0; ++n )
  1509. {
  1510. AddPath(paths, dest, stackSize);
  1511. dest = dest->next;
  1512. }
  1513. break;
  1514. }
  1515. else
  1516. {
  1517. instr = instr->next;
  1518. if( instr == 0 || instr->marked )
  1519. break;
  1520. }
  1521. }
  1522. }
  1523. // Are there any instructions that didn't get visited?
  1524. instr = first;
  1525. while( instr )
  1526. {
  1527. if( instr->marked == false )
  1528. {
  1529. // TODO: Give warning of unvisited code
  1530. // Remove it
  1531. cByteInstruction *curr = instr;
  1532. instr = instr->next;
  1533. DeleteInstruction(curr);
  1534. }
  1535. else
  1536. instr = instr->next;
  1537. }
  1538. }
  1539. #ifdef AS_DEBUG
  1540. void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScriptFunction *func)
  1541. {
  1542. _mkdir("AS_DEBUG");
  1543. asCString str = "AS_DEBUG/";
  1544. str += name;
  1545. #if _MSC_VER >= 1500
  1546. FILE *file;
  1547. fopen_s(&file, str.AddressOf(), "w");
  1548. #else
  1549. FILE *file = fopen(str.AddressOf(), "w");
  1550. #endif
  1551. #ifdef AS_XENON // XBox 360
  1552. // When running in DVD Emu, no write is allowed
  1553. if( file == 0 )
  1554. return;
  1555. #endif
  1556. asUINT n;
  1557. fprintf(file, "%s\n\n", func->GetDeclaration());
  1558. fprintf(file, "Temps: ");
  1559. for( n = 0; n < temporaryVariables.GetLength(); n++ )
  1560. {
  1561. fprintf(file, "%d", temporaryVariables[n]);
  1562. if( n < temporaryVariables.GetLength()-1 )
  1563. fprintf(file, ", ");
  1564. }
  1565. fprintf(file, "\n\n");
  1566. fprintf(file, "Variables: \n");
  1567. for( n = 0; n < func->variables.GetLength(); n++ )
  1568. {
  1569. fprintf(file, " %.3d: %s %s\n", func->variables[n]->stackOffset, func->variables[n]->type.Format().AddressOf(), func->variables[n]->name.AddressOf());
  1570. }
  1571. asUINT offset = 0;
  1572. if( func->objectType )
  1573. {
  1574. fprintf(file, " %.3d: %s this\n", 0, func->objectType->name.AddressOf());
  1575. offset -= AS_PTR_SIZE;
  1576. }
  1577. for( n = 0; n < func->parameterTypes.GetLength(); n++ )
  1578. {
  1579. bool found = false;
  1580. for( asUINT v = 0; v < func->variables.GetLength(); v++ )
  1581. {
  1582. if( func->variables[v]->stackOffset == (int)offset )
  1583. {
  1584. found = true;
  1585. break;
  1586. }
  1587. }
  1588. if( !found )
  1589. fprintf(file, " %.3d: %s {noname param}\n", offset, func->parameterTypes[n].Format().AddressOf());
  1590. offset -= func->parameterTypes[n].GetSizeOnStackDWords();
  1591. }
  1592. for( n = 0; n < func->objVariablePos.GetLength(); n++ )
  1593. {
  1594. bool found = false;
  1595. for( asUINT v = 0; v < func->variables.GetLength(); v++ )
  1596. {
  1597. if( func->variables[v]->stackOffset == func->objVariablePos[n] )
  1598. {
  1599. found = true;
  1600. break;
  1601. }
  1602. }
  1603. if( !found )
  1604. fprintf(file, " %.3d: %s {noname}\n", func->objVariablePos[n], func->objVariableTypes[n]->name.AddressOf());
  1605. }
  1606. fprintf(file, "\n\n");
  1607. int pos = 0;
  1608. asUINT lineIndex = 0;
  1609. cByteInstruction *instr = first;
  1610. while( instr )
  1611. {
  1612. if( lineIndex < lineNumbers.GetLength() && lineNumbers[lineIndex] == pos )
  1613. {
  1614. asDWORD line = lineNumbers[lineIndex+1];
  1615. fprintf(file, "- %d,%d -\n", (int)(line&0xFFFFF), (int)(line>>20));
  1616. lineIndex += 2;
  1617. }
  1618. fprintf(file, "%5d ", pos);
  1619. pos += instr->GetSize();
  1620. fprintf(file, "%3d %c ", instr->stackSize, instr->marked ? '*' : ' ');
  1621. switch( asBCInfo[instr->op].type )
  1622. {
  1623. case asBCTYPE_W_ARG:
  1624. if( instr->op == asBC_STR )
  1625. {
  1626. int id = instr->wArg[0];
  1627. const asCString &str = engine->GetConstantString(id);
  1628. fprintf(file, " %-8s %d (l:%ld s:\"%.10s\")\n", asBCInfo[instr->op].name, instr->wArg[0], (long int)str.GetLength(), str.AddressOf());
  1629. }
  1630. else
  1631. fprintf(file, " %-8s %d\n", asBCInfo[instr->op].name, instr->wArg[0]);
  1632. break;
  1633. case asBCTYPE_wW_ARG:
  1634. case asBCTYPE_rW_ARG:
  1635. fprintf(file, " %-8s v%d\n", asBCInfo[instr->op].name, instr->wArg[0]);
  1636. break;
  1637. case asBCTYPE_wW_rW_ARG:
  1638. case asBCTYPE_rW_rW_ARG:
  1639. fprintf(file, " %-8s v%d, v%d\n", asBCInfo[instr->op].name, instr->wArg[0], instr->wArg[1]);
  1640. break;
  1641. case asBCTYPE_wW_W_ARG:
  1642. fprintf(file, " %-8s v%d, %d\n", asBCInfo[instr->op].name, instr->wArg[0], instr->wArg[1]);
  1643. break;
  1644. case asBCTYPE_wW_rW_DW_ARG:
  1645. case asBCTYPE_rW_W_DW_ARG:
  1646. switch( instr->op )
  1647. {
  1648. case asBC_ADDIf:
  1649. case asBC_SUBIf:
  1650. case asBC_MULIf:
  1651. fprintf(file, " %-8s v%d, v%d, %f\n", asBCInfo[instr->op].name, instr->wArg[0], instr->wArg[1], *((float*) ARG_DW(instr->arg)));
  1652. break;
  1653. default:
  1654. fprintf(file, " %-8s v%d, v%d, %d\n", asBCInfo[instr->op].name, instr->wArg[0], instr->wArg[1], *((int*) ARG_DW(instr->arg)));
  1655. break;
  1656. }
  1657. break;
  1658. case asBCTYPE_DW_ARG:
  1659. switch( instr->op )
  1660. {
  1661. case asBC_OBJTYPE:
  1662. fprintf(file, " %-8s 0x%x\n", asBCInfo[instr->op].name, (asUINT)*ARG_DW(instr->arg));
  1663. break;
  1664. case asBC_PshC4:
  1665. case asBC_Cast:
  1666. fprintf(file, " %-8s 0x%x (i:%d, f:%g)\n", asBCInfo[instr->op].name, (asUINT)*ARG_DW(instr->arg), *((int*) ARG_DW(instr->arg)), *((float*) ARG_DW(instr->arg)));
  1667. break;
  1668. case asBC_TYPEID:
  1669. fprintf(file, " %-8s 0x%x '%s'\n", asBCInfo[instr->op].name, (asUINT)*ARG_DW(instr->arg), engine->GetTypeDeclaration((int)*ARG_DW(instr->arg)));
  1670. break;
  1671. case asBC_CALL:
  1672. case asBC_CALLSYS:
  1673. case asBC_CALLBND:
  1674. case asBC_CALLINTF:
  1675. {
  1676. int funcID = *(int*)ARG_DW(instr->arg);
  1677. asCString decl = engine->GetFunctionDeclaration(funcID);
  1678. fprintf(file, " %-8s %d (%s)\n", asBCInfo[instr->op].name, *((int*) ARG_DW(instr->arg)), decl.AddressOf());
  1679. }
  1680. break;
  1681. case asBC_REFCPY:
  1682. fprintf(file, " %-8s 0x%x\n", asBCInfo[instr->op].name, *((int*) ARG_DW(instr->arg)));
  1683. break;
  1684. case asBC_JMP:
  1685. case asBC_JZ:
  1686. case asBC_JS:
  1687. case asBC_JP:
  1688. case asBC_JNZ:
  1689. case asBC_JNS:
  1690. case asBC_JNP:
  1691. fprintf(file, " %-8s %+d (d:%d)\n", asBCInfo[instr->op].name, *((int*) ARG_DW(instr->arg)), pos+*((int*) ARG_DW(instr->arg)));
  1692. break;
  1693. default:
  1694. fprintf(file, " %-8s %d\n", asBCInfo[instr->op].name, *((int*) ARG_DW(instr->arg)));
  1695. break;
  1696. }
  1697. break;
  1698. case asBCTYPE_QW_ARG:
  1699. #ifdef __GNUC__
  1700. #ifdef _LP64
  1701. fprintf(file, " %-8s 0x%lx (i:%ld, f:%g)\n", asBCInfo[instr->op].name, *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
  1702. #else
  1703. fprintf(file, " %-8s 0x%llx (i:%lld, f:%g)\n", asBCInfo[instr->op].name, *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
  1704. #endif
  1705. #else
  1706. fprintf(file, " %-8s 0x%I64x (i:%I64d, f:%g)\n", asBCInfo[instr->op].name, *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
  1707. #endif
  1708. break;
  1709. case asBCTYPE_wW_QW_ARG:
  1710. case asBCTYPE_rW_QW_ARG:
  1711. #ifdef __GNUC__
  1712. #ifdef _LP64
  1713. fprintf(file, " %-8s v%d, 0x%lx (i:%ld, f:%g)\n", asBCInfo[instr->op].name, instr->wArg[0], *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
  1714. #else
  1715. fprintf(file, " %-8s v%d, 0x%llx (i:%lld, f:%g)\n", asBCInfo[instr->op].name, instr->wArg[0], *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
  1716. #endif
  1717. #else
  1718. fprintf(file, " %-8s v%d, 0x%I64x (i:%I64d, f:%g)\n", asBCInfo[instr->op].name, instr->wArg[0], *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
  1719. #endif
  1720. break;
  1721. case asBCTYPE_DW_DW_ARG:
  1722. if( instr->op == asBC_ALLOC )
  1723. {
  1724. asCObjectType *ot = *(asCObjectType**)ARG_DW(instr->arg);
  1725. fprintf(file, " %-8s 0x%x, %d (type:%s)\n", asBCInfo[instr->op].name, *(int*)ARG_DW(instr->arg), *(int*)(ARG_DW(instr->arg)+1), ot->GetName());
  1726. }
  1727. else
  1728. fprintf(file, " %-8s %u, %d\n", asBCInfo[instr->op].name, *(int*)ARG_DW(instr->arg), *(int*)(ARG_DW(instr->arg)+1));
  1729. break;
  1730. case asBCTYPE_QW_DW_ARG:
  1731. if( instr->op == asBC_ALLOC )
  1732. {
  1733. asCObjectType *ot = *(asCObjectType**)ARG_QW(instr->arg);
  1734. #ifdef __GNUC__
  1735. #ifdef AS_64BIT_PTR
  1736. fprintf(file, " %-8s 0x%lx, %d (type:%s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName());
  1737. #else
  1738. fprintf(file, " %-8s 0x%llx, %d (type:%s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName());
  1739. #endif
  1740. #else
  1741. fprintf(file, " %-8s 0x%I64x, %d (type:%s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName());
  1742. #endif
  1743. }
  1744. else
  1745. #ifdef __GNUC__
  1746. #ifdef AS_64BIT_PTR
  1747. fprintf(file, " %-8s %lu, %d\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2));
  1748. #else
  1749. fprintf(file, " %-8s %llu, %d\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2));
  1750. #endif
  1751. #else
  1752. fprintf(file, " %-8s %I64u, %d\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2));
  1753. #endif
  1754. break;
  1755. case asBCTYPE_INFO:
  1756. if( instr->op == asBC_LABEL )
  1757. fprintf(file, "%d:\n", instr->wArg[0]);
  1758. else if( instr->op == asBC_LINE )
  1759. fprintf(file, " %s\n", asBCInfo[instr->op].name);
  1760. else if( instr->op == asBC_Block )
  1761. fprintf(file, "%c\n", instr->wArg[0] ? '{' : '}');
  1762. break;
  1763. case asBCTYPE_rW_DW_ARG:
  1764. case asBCTYPE_wW_DW_ARG:
  1765. case asBCTYPE_W_DW_ARG:
  1766. if( instr->op == asBC_SetV1 )
  1767. fprintf(file, " %-8s v%d, 0x%x\n", asBCInfo[instr->op].name, instr->wArg[0], *(asBYTE*)ARG_DW(instr->arg));
  1768. else if( instr->op == asBC_SetV2 )
  1769. fprintf(file, " %-8s v%d, 0x%x\n", asBCInfo[instr->op].name, instr->wArg[0], *(asWORD*)ARG_DW(instr->arg));
  1770. else if( instr->op == asBC_SetV4 )
  1771. fprintf(file, " %-8s v%d, 0x%x (i:%d, f:%g)\n", asBCInfo[instr->op].name, instr->wArg[0], (asUINT)*ARG_DW(instr->arg), *((int*) ARG_DW(instr->arg)), *((float*) ARG_DW(instr->arg)));
  1772. else if( instr->op == asBC_CMPIf )
  1773. fprintf(file, " %-8s v%d, %f\n", asBCInfo[instr->op].name, instr->wArg[0], *(float*)ARG_DW(instr->arg));
  1774. else
  1775. fprintf(file, " %-8s v%d, %d\n", asBCInfo[instr->op].name, instr->wArg[0], (asUINT)*ARG_DW(instr->arg));
  1776. break;
  1777. case asBCTYPE_wW_rW_rW_ARG:
  1778. fprintf(file, " %-8s v%d, v%d, v%d\n", asBCInfo[instr->op].name, instr->wArg[0], instr->wArg[1], instr->wArg[2]);
  1779. break;
  1780. case asBCTYPE_NO_ARG:
  1781. fprintf(file, " %s\n", asBCInfo[instr->op].name);
  1782. break;
  1783. default:
  1784. asASSERT(false);
  1785. }
  1786. instr = instr->next;
  1787. }
  1788. fclose(file);
  1789. }
  1790. #endif
  1791. //=============================================================================
  1792. // Decrease stack with "numDwords"
  1793. int asCByteCode::Pop(int numDwords)
  1794. {
  1795. asASSERT(asBCInfo[asBC_POP].type == asBCTYPE_W_ARG);
  1796. if( AddInstruction() < 0 )
  1797. return 0;
  1798. last->op = asBC_POP;
  1799. last->wArg[0] = (short)numDwords;
  1800. last->size = asBCTypeSize[asBCInfo[asBC_POP].type];
  1801. last->stackInc = -numDwords;
  1802. return last->stackInc;
  1803. }
  1804. // Increase stack with "numDwords"
  1805. int asCByteCode::Push(int numDwords)
  1806. {
  1807. asASSERT(asBCInfo[asBC_PUSH].type == asBCTYPE_W_ARG);
  1808. if( AddInstruction() < 0 )
  1809. return 0;
  1810. last->op = asBC_PUSH;
  1811. last->wArg[0] = (short)numDwords;
  1812. last->size = asBCTypeSize[asBCInfo[asBC_PUSH].type];
  1813. last->stackInc = numDwords;
  1814. return last->stackInc;
  1815. }
  1816. int asCByteCode::InsertFirstInstrDWORD(asEBCInstr bc, asDWORD param)
  1817. {
  1818. asASSERT(asBCInfo[bc].type == asBCTYPE_DW_ARG);
  1819. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  1820. if( AddInstructionFirst() < 0 )
  1821. return 0;
  1822. first->op = bc;
  1823. *ARG_DW(first->arg) = param;
  1824. first->size = asBCTypeSize[asBCInfo[bc].type];
  1825. first->stackInc = asBCInfo[bc].stackInc;
  1826. return first->stackInc;
  1827. }
  1828. int asCByteCode::InsertFirstInstrQWORD(asEBCInstr bc, asQWORD param)
  1829. {
  1830. asASSERT(asBCInfo[bc].type == asBCTYPE_QW_ARG);
  1831. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  1832. if( AddInstructionFirst() < 0 )
  1833. return 0;
  1834. first->op = bc;
  1835. *ARG_QW(first->arg) = param;
  1836. first->size = asBCTypeSize[asBCInfo[bc].type];
  1837. first->stackInc = asBCInfo[bc].stackInc;
  1838. return first->stackInc;
  1839. }
  1840. int asCByteCode::Instr(asEBCInstr bc)
  1841. {
  1842. asASSERT(asBCInfo[bc].type == asBCTYPE_NO_ARG);
  1843. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  1844. if( AddInstruction() < 0 )
  1845. return 0;
  1846. last->op = bc;
  1847. last->size = asBCTypeSize[asBCInfo[bc].type];
  1848. last->stackInc = asBCInfo[bc].stackInc;
  1849. return last->stackInc;
  1850. }
  1851. int asCByteCode::InstrW_W_W(asEBCInstr bc, int a, int b, int c)
  1852. {
  1853. asASSERT(asBCInfo[bc].type == asBCTYPE_wW_rW_rW_ARG);
  1854. asASSERT(asBCInfo[bc].stackInc == 0);
  1855. if( AddInstruction() < 0 )
  1856. return 0;
  1857. last->op = bc;
  1858. last->wArg[0] = (short)a;
  1859. last->wArg[1] = (short)b;
  1860. last->wArg[2] = (short)c;
  1861. last->size = asBCTypeSize[asBCInfo[bc].type];
  1862. last->stackInc = asBCInfo[bc].stackInc;
  1863. return last->stackInc;
  1864. }
  1865. int asCByteCode::InstrW_W(asEBCInstr bc, int a, int b)
  1866. {
  1867. asASSERT(asBCInfo[bc].type == asBCTYPE_wW_rW_ARG ||
  1868. asBCInfo[bc].type == asBCTYPE_rW_rW_ARG);
  1869. asASSERT(asBCInfo[bc].stackInc == 0);
  1870. if( AddInstruction() < 0 )
  1871. return 0;
  1872. last->op = bc;
  1873. last->wArg[0] = (short)a;
  1874. last->wArg[1] = (short)b;
  1875. last->size = asBCTypeSize[asBCInfo[bc].type];
  1876. last->stackInc = asBCInfo[bc].stackInc;
  1877. return last->stackInc;
  1878. }
  1879. int asCByteCode::InstrW_PTR(asEBCInstr bc, short a, void *param)
  1880. {
  1881. asASSERT(asBCInfo[bc].type == asBCTYPE_wW_PTR_ARG);
  1882. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  1883. if( AddInstruction() < 0 )
  1884. return 0;
  1885. last->op = bc;
  1886. last->wArg[0] = a;
  1887. *ARG_PTR(last->arg) = (asPTRWORD)(size_t)param;
  1888. last->size = asBCTypeSize[asBCInfo[bc].type];
  1889. last->stackInc = asBCInfo[bc].stackInc;
  1890. return last->stackInc;
  1891. }
  1892. int asCByteCode::InstrW_DW(asEBCInstr bc, asWORD a, asDWORD b)
  1893. {
  1894. asASSERT(asBCInfo[bc].type == asBCTYPE_wW_DW_ARG ||
  1895. asBCInfo[bc].type == asBCTYPE_rW_DW_ARG ||
  1896. asBCInfo[bc].type == asBCTYPE_W_DW_ARG);
  1897. asASSERT(asBCInfo[bc].stackInc == 0);
  1898. if( AddInstruction() < 0 )
  1899. return 0;
  1900. last->op = bc;
  1901. last->wArg[0] = a;
  1902. *((int*) ARG_DW(last->arg)) = b;
  1903. last->size = asBCTypeSize[asBCInfo[bc].type];
  1904. last->stackInc = asBCInfo[bc].stackInc;
  1905. return last->stackInc;
  1906. }
  1907. int asCByteCode::InstrSHORT_B(asEBCInstr bc, short a, asBYTE b)
  1908. {
  1909. asASSERT(asBCInfo[bc].type == asBCTYPE_wW_DW_ARG ||
  1910. asBCInfo[bc].type == asBCTYPE_rW_DW_ARG ||
  1911. asBCInfo[bc].type == asBCTYPE_W_DW_ARG);
  1912. asASSERT(asBCInfo[bc].stackInc == 0);
  1913. if( AddInstruction() < 0 )
  1914. return 0;
  1915. last->op = bc;
  1916. last->wArg[0] = a;
  1917. // We'll have to be careful to store the byte correctly, independent of endianess.
  1918. // Some optimizing compilers may change the order of operations, so we make sure
  1919. // the value is not overwritten even if that happens.
  1920. asBYTE *argPtr = (asBYTE*)ARG_DW(last->arg);
  1921. argPtr[0] = b; // The value is always stored in the lower byte
  1922. argPtr[1] = 0; // and clear the rest of the DWORD
  1923. argPtr[2] = 0;
  1924. argPtr[3] = 0;
  1925. last->size = asBCTypeSize[asBCInfo[bc].type];
  1926. last->stackInc = asBCInfo[bc].stackInc;
  1927. return last->stackInc;
  1928. }
  1929. int asCByteCode::InstrSHORT_W(asEBCInstr bc, short a, asWORD b)
  1930. {
  1931. asASSERT(asBCInfo[bc].type == asBCTYPE_wW_DW_ARG ||
  1932. asBCInfo[bc].type == asBCTYPE_rW_DW_ARG ||
  1933. asBCInfo[bc].type == asBCTYPE_W_DW_ARG);
  1934. asASSERT(asBCInfo[bc].stackInc == 0);
  1935. if( AddInstruction() < 0 )
  1936. return 0;
  1937. last->op = bc;
  1938. last->wArg[0] = a;
  1939. // We'll have to be careful to store the word correctly, independent of endianess.
  1940. // Some optimizing compilers may change the order of operations, so we make sure
  1941. // the value is not overwritten even if that happens.
  1942. asWORD *argPtr = (asWORD*)ARG_DW(last->arg);
  1943. argPtr[0] = b; // The value is always stored in the lower word
  1944. argPtr[1] = 0; // and clear the rest of the DWORD
  1945. last->size = asBCTypeSize[asBCInfo[bc].type];
  1946. last->stackInc = asBCInfo[bc].stackInc;
  1947. return last->stackInc;
  1948. }
  1949. int asCByteCode::InstrSHORT_DW(asEBCInstr bc, short a, asDWORD b)
  1950. {
  1951. asASSERT(asBCInfo[bc].type == asBCTYPE_wW_DW_ARG ||
  1952. asBCInfo[bc].type == asBCTYPE_rW_DW_ARG ||
  1953. asBCInfo[bc].type == asBCTYPE_W_DW_ARG);
  1954. if( AddInstruction() < 0 )
  1955. return 0;
  1956. last->op = bc;
  1957. last->wArg[0] = a;
  1958. *((int*) ARG_DW(last->arg)) = b;
  1959. last->size = asBCTypeSize[asBCInfo[bc].type];
  1960. last->stackInc = asBCInfo[bc].stackInc;
  1961. return last->stackInc;
  1962. }
  1963. int asCByteCode::InstrW_QW(asEBCInstr bc, asWORD a, asQWORD b)
  1964. {
  1965. asASSERT(asBCInfo[bc].type == asBCTYPE_wW_QW_ARG);
  1966. asASSERT(asBCInfo[bc].stackInc == 0);
  1967. if( AddInstruction() < 0 )
  1968. return 0;
  1969. last->op = bc;
  1970. last->wArg[0] = a;
  1971. *ARG_QW(last->arg) = b;
  1972. last->size = asBCTypeSize[asBCInfo[bc].type];
  1973. last->stackInc = asBCInfo[bc].stackInc;
  1974. return last->stackInc;
  1975. }
  1976. int asCByteCode::InstrSHORT_QW(asEBCInstr bc, short a, asQWORD b)
  1977. {
  1978. asASSERT(asBCInfo[bc].type == asBCTYPE_wW_QW_ARG);
  1979. asASSERT(asBCInfo[bc].stackInc == 0);
  1980. if( AddInstruction() < 0 )
  1981. return 0;
  1982. last->op = bc;
  1983. last->wArg[0] = a;
  1984. *ARG_QW(last->arg) = b;
  1985. last->size = asBCTypeSize[asBCInfo[bc].type];
  1986. last->stackInc = asBCInfo[bc].stackInc;
  1987. return last->stackInc;
  1988. }
  1989. int asCByteCode::InstrW_FLOAT(asEBCInstr bc, asWORD a, float b)
  1990. {
  1991. asASSERT(asBCInfo[bc].type == asBCTYPE_wW_DW_ARG);
  1992. asASSERT(asBCInfo[bc].stackInc == 0);
  1993. if( AddInstruction() < 0 )
  1994. return 0;
  1995. last->op = bc;
  1996. last->wArg[0] = a;
  1997. *((float*) ARG_DW(last->arg)) = b;
  1998. last->size = asBCTypeSize[asBCInfo[bc].type];
  1999. last->stackInc = asBCInfo[bc].stackInc;
  2000. return last->stackInc;
  2001. }
  2002. int asCByteCode::InstrSHORT(asEBCInstr bc, short param)
  2003. {
  2004. asASSERT(asBCInfo[bc].type == asBCTYPE_rW_ARG ||
  2005. asBCInfo[bc].type == asBCTYPE_wW_ARG ||
  2006. asBCInfo[bc].type == asBCTYPE_W_ARG);
  2007. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  2008. if( AddInstruction() < 0 )
  2009. return 0;
  2010. last->op = bc;
  2011. last->wArg[0] = param;
  2012. last->size = asBCTypeSize[asBCInfo[bc].type];
  2013. last->stackInc = asBCInfo[bc].stackInc;
  2014. return last->stackInc;
  2015. }
  2016. int asCByteCode::InstrINT(asEBCInstr bc, int param)
  2017. {
  2018. asASSERT(asBCInfo[bc].type == asBCTYPE_DW_ARG);
  2019. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  2020. if( AddInstruction() < 0 )
  2021. return 0;
  2022. last->op = bc;
  2023. *((int*) ARG_DW(last->arg)) = param;
  2024. last->size = asBCTypeSize[asBCInfo[bc].type];
  2025. last->stackInc = asBCInfo[bc].stackInc;
  2026. return last->stackInc;
  2027. }
  2028. int asCByteCode::InstrDWORD(asEBCInstr bc, asDWORD param)
  2029. {
  2030. asASSERT(asBCInfo[bc].type == asBCTYPE_DW_ARG);
  2031. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  2032. if( AddInstruction() < 0 )
  2033. return 0;
  2034. last->op = bc;
  2035. *ARG_DW(last->arg) = param;
  2036. last->size = asBCTypeSize[asBCInfo[bc].type];
  2037. last->stackInc = asBCInfo[bc].stackInc;
  2038. return last->stackInc;
  2039. }
  2040. int asCByteCode::InstrPTR(asEBCInstr bc, void *param)
  2041. {
  2042. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  2043. if( AddInstruction() < 0 )
  2044. return 0;
  2045. last->op = bc;
  2046. asASSERT(asBCInfo[bc].type == asBCTYPE_PTR_ARG);
  2047. *ARG_PTR(last->arg) = (asPTRWORD)(size_t)param;
  2048. last->size = asBCTypeSize[asBCInfo[bc].type];
  2049. last->stackInc = asBCInfo[bc].stackInc;
  2050. return last->stackInc;
  2051. }
  2052. int asCByteCode::InstrQWORD(asEBCInstr bc, asQWORD param)
  2053. {
  2054. asASSERT(asBCInfo[bc].type == asBCTYPE_QW_ARG);
  2055. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  2056. if( AddInstruction() < 0 )
  2057. return 0;
  2058. last->op = bc;
  2059. *ARG_QW(last->arg) = param;
  2060. last->size = asBCTypeSize[asBCInfo[bc].type];
  2061. last->stackInc = asBCInfo[bc].stackInc;
  2062. return last->stackInc;
  2063. }
  2064. int asCByteCode::InstrWORD(asEBCInstr bc, asWORD param)
  2065. {
  2066. asASSERT(asBCInfo[bc].type == asBCTYPE_W_ARG ||
  2067. asBCInfo[bc].type == asBCTYPE_rW_ARG ||
  2068. asBCInfo[bc].type == asBCTYPE_wW_ARG);
  2069. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  2070. if( AddInstruction() < 0 )
  2071. return 0;
  2072. last->op = bc;
  2073. last->wArg[0] = param;
  2074. last->size = asBCTypeSize[asBCInfo[bc].type];
  2075. last->stackInc = asBCInfo[bc].stackInc;
  2076. return last->stackInc;
  2077. }
  2078. int asCByteCode::InstrFLOAT(asEBCInstr bc, float param)
  2079. {
  2080. asASSERT(asBCInfo[bc].type == asBCTYPE_DW_ARG);
  2081. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  2082. if( AddInstruction() < 0 )
  2083. return 0;
  2084. last->op = bc;
  2085. *((float*) ARG_DW(last->arg)) = param;
  2086. last->size = asBCTypeSize[asBCInfo[bc].type];
  2087. last->stackInc = asBCInfo[bc].stackInc;
  2088. return last->stackInc;
  2089. }
  2090. int asCByteCode::InstrDOUBLE(asEBCInstr bc, double param)
  2091. {
  2092. asASSERT(asBCInfo[bc].type == asBCTYPE_QW_ARG);
  2093. asASSERT(asBCInfo[bc].stackInc != 0xFFFF);
  2094. if( AddInstruction() < 0 )
  2095. return 0;
  2096. last->op = bc;
  2097. *((double*) ARG_QW(last->arg)) = param;
  2098. last->size = asBCTypeSize[asBCInfo[bc].type];
  2099. last->stackInc = asBCInfo[bc].stackInc;
  2100. return last->stackInc;
  2101. }
  2102. int asCByteCode::GetLastInstr()
  2103. {
  2104. if( last == 0 ) return -1;
  2105. return last->op;
  2106. }
  2107. int asCByteCode::RemoveLastInstr()
  2108. {
  2109. if( last == 0 ) return -1;
  2110. if( first == last )
  2111. {
  2112. engine->memoryMgr.FreeByteInstruction(last);
  2113. first = 0;
  2114. last = 0;
  2115. }
  2116. else
  2117. {
  2118. cByteInstruction *bc = last;
  2119. last = bc->prev;
  2120. bc->Remove();
  2121. engine->memoryMgr.FreeByteInstruction(bc);
  2122. }
  2123. return 0;
  2124. }
  2125. asDWORD asCByteCode::GetLastInstrValueDW()
  2126. {
  2127. if( last == 0 ) return 0;
  2128. return *ARG_DW(last->arg);
  2129. }
  2130. void asCByteCode::DefineTemporaryVariable(int varOffset)
  2131. {
  2132. temporaryVariables.PushLast(varOffset);
  2133. }
  2134. //===================================================================
  2135. cByteInstruction::cByteInstruction()
  2136. {
  2137. next = 0;
  2138. prev = 0;
  2139. op = asBC_LABEL;
  2140. arg = 0;
  2141. wArg[0] = 0;
  2142. wArg[1] = 0;
  2143. wArg[2] = 0;
  2144. size = 0;
  2145. stackInc = 0;
  2146. marked = false;
  2147. stackSize = 0;
  2148. }
  2149. void cByteInstruction::AddAfter(cByteInstruction *nextCode)
  2150. {
  2151. if( next )
  2152. next->prev = nextCode;
  2153. nextCode->next = next;
  2154. nextCode->prev = this;
  2155. next = nextCode;
  2156. }
  2157. void cByteInstruction::AddBefore(cByteInstruction *prevCode)
  2158. {
  2159. if( prev )
  2160. prev->next = prevCode;
  2161. prevCode->prev = prev;
  2162. prevCode->next = this;
  2163. prev = prevCode;
  2164. }
  2165. int cByteInstruction::GetSize()
  2166. {
  2167. return size;
  2168. }
  2169. int cByteInstruction::GetStackIncrease()
  2170. {
  2171. return stackInc;
  2172. }
  2173. void cByteInstruction::Remove()
  2174. {
  2175. if( prev ) prev->next = next;
  2176. if( next ) next->prev = prev;
  2177. prev = 0;
  2178. next = 0;
  2179. }
  2180. END_AS_NAMESPACE