LSL_OPCODE_IL_processor.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. /* Original code: Tedd Hansen */
  28. using System;
  29. using System.Reflection;
  30. using System.Reflection.Emit;
  31. using OpenSim.Region.ScriptEngine.Common;
  32. namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO
  33. {
  34. internal partial class LSO_Parser
  35. {
  36. //internal Stack<Type> ILStack = new Stack<Type>();
  37. //LSO_Enums MyLSO_Enums = new LSO_Enums();
  38. internal bool LSL_PROCESS_OPCODE(ILGenerator il)
  39. {
  40. byte bp1;
  41. UInt32 u32p1;
  42. float fp1;
  43. UInt16 opcode = br_read(1)[0];
  44. Common.SendToDebug("OPCODE: " + ((LSO_Enums.Operation_Table) opcode).ToString());
  45. string idesc = ((LSO_Enums.Operation_Table) opcode).ToString();
  46. switch ((LSO_Enums.Operation_Table) opcode)
  47. {
  48. /***************
  49. * IMPLEMENTED *
  50. ***************/
  51. case LSO_Enums.Operation_Table.NOOP:
  52. break;
  53. case LSO_Enums.Operation_Table.PUSHSP:
  54. // Push Stack Top (Memory Address) to stack
  55. Common.SendToDebug("Instruction " + idesc);
  56. Common.SendToDebug("Instruction " + idesc +
  57. ": Description: Pushing Stack Top (Memory Address from header) to stack");
  58. IL_Push(il, (UInt32) myHeader.SP);
  59. break;
  60. // BYTE
  61. case LSO_Enums.Operation_Table.PUSHARGB:
  62. Common.SendToDebug("Param1: " + br_read(1)[0]);
  63. break;
  64. // INTEGER
  65. case LSO_Enums.Operation_Table.PUSHARGI:
  66. u32p1 = BitConverter.ToUInt32(br_read(4), 0);
  67. Common.SendToDebug("Instruction " + idesc + ", Param1: " + u32p1);
  68. IL_Push(il, u32p1);
  69. break;
  70. // FLOAT
  71. case LSO_Enums.Operation_Table.PUSHARGF:
  72. fp1 = BitConverter.ToUInt32(br_read(4), 0);
  73. Common.SendToDebug("Instruction " + idesc + ", Param1: " + fp1);
  74. IL_Push(il, fp1);
  75. break;
  76. // STRING
  77. case LSO_Enums.Operation_Table.PUSHARGS:
  78. string s = Read_String();
  79. Common.SendToDebug("Instruction " + idesc + ", Param1: " + s);
  80. IL_Debug(il, "OPCODE: " + idesc + ":" + s);
  81. IL_Push(il, s);
  82. break;
  83. // VECTOR z,y,x
  84. case LSO_Enums.Operation_Table.PUSHARGV:
  85. LSO_Enums.Vector v = new LSO_Enums.Vector();
  86. v.Z = BitConverter.ToUInt32(br_read(4), 0);
  87. v.Y = BitConverter.ToUInt32(br_read(4), 0);
  88. v.X = BitConverter.ToUInt32(br_read(4), 0);
  89. Common.SendToDebug("Param1 Z: " + v.Z);
  90. Common.SendToDebug("Param1 Y: " + v.Y);
  91. Common.SendToDebug("Param1 X: " + v.X);
  92. IL_Push(il, v);
  93. break;
  94. // ROTATION s,z,y,x
  95. case LSO_Enums.Operation_Table.PUSHARGQ:
  96. LSO_Enums.Rotation r = new LSO_Enums.Rotation();
  97. r.S = BitConverter.ToUInt32(br_read(4), 0);
  98. r.Z = BitConverter.ToUInt32(br_read(4), 0);
  99. r.Y = BitConverter.ToUInt32(br_read(4), 0);
  100. r.X = BitConverter.ToUInt32(br_read(4), 0);
  101. Common.SendToDebug("Param1 S: " + r.S);
  102. Common.SendToDebug("Param1 Z: " + r.Z);
  103. Common.SendToDebug("Param1 Y: " + r.Y);
  104. Common.SendToDebug("Param1 X: " + r.X);
  105. IL_Push(il, r);
  106. break;
  107. case LSO_Enums.Operation_Table.PUSHE:
  108. IL_Push(il, (UInt32) 0);
  109. break;
  110. case LSO_Enums.Operation_Table.PUSHARGE:
  111. u32p1 = BitConverter.ToUInt32(br_read(4), 0);
  112. Common.SendToDebug("Param1: " + u32p1);
  113. //IL_Push(il, new string(" ".ToCharArray()[0], Convert.ToInt32(u32p1)));
  114. IL_Push(il, u32p1);
  115. break;
  116. // BYTE
  117. case LSO_Enums.Operation_Table.ADD:
  118. case LSO_Enums.Operation_Table.SUB:
  119. case LSO_Enums.Operation_Table.MUL:
  120. case LSO_Enums.Operation_Table.DIV:
  121. case LSO_Enums.Operation_Table.EQ:
  122. case LSO_Enums.Operation_Table.NEQ:
  123. case LSO_Enums.Operation_Table.LEQ:
  124. case LSO_Enums.Operation_Table.GEQ:
  125. case LSO_Enums.Operation_Table.LESS:
  126. case LSO_Enums.Operation_Table.GREATER:
  127. case LSO_Enums.Operation_Table.NEG:
  128. case LSO_Enums.Operation_Table.MOD:
  129. bp1 = br_read(1)[0];
  130. Common.SendToDebug("Param1: " + bp1);
  131. IL_CallBaseFunction(il, idesc, (UInt32) bp1);
  132. break;
  133. // NO ARGUMENTS
  134. case LSO_Enums.Operation_Table.BITAND:
  135. case LSO_Enums.Operation_Table.BITOR:
  136. case LSO_Enums.Operation_Table.BITXOR:
  137. case LSO_Enums.Operation_Table.BOOLAND:
  138. case LSO_Enums.Operation_Table.BOOLOR:
  139. case LSO_Enums.Operation_Table.BITNOT:
  140. case LSO_Enums.Operation_Table.BOOLNOT:
  141. IL_CallBaseFunction(il, idesc);
  142. break;
  143. // SHORT
  144. case LSO_Enums.Operation_Table.CALLLIB_TWO_BYTE:
  145. // TODO: What is size of short?
  146. UInt16 U16p1 = BitConverter.ToUInt16(br_read(2), 0);
  147. Common.SendToDebug("Instruction " + idesc + ": Builtin Command: " +
  148. ((LSO_Enums.BuiltIn_Functions) U16p1).ToString());
  149. //Common.SendToDebug("Param1: " + U16p1);
  150. string fname = ((LSO_Enums.BuiltIn_Functions) U16p1).ToString();
  151. bool cmdFound = false;
  152. foreach (MethodInfo mi in typeof (LSL_BuiltIn_Commands_Interface).GetMethods())
  153. {
  154. // Found command
  155. if (mi.Name == fname)
  156. {
  157. il.Emit(OpCodes.Ldarg_0);
  158. il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod("GetLSL_BuiltIn", new Type[] {}));
  159. // Pop required number of items from my stack to .Net stack
  160. IL_PopToStack(il, mi.GetParameters().Length);
  161. il.Emit(OpCodes.Callvirt, mi);
  162. cmdFound = true;
  163. break;
  164. }
  165. }
  166. if (cmdFound == false)
  167. {
  168. Common.SendToDebug("ERROR: UNABLE TO LOCATE OPCODE " + idesc + " IN BASECLASS");
  169. }
  170. break;
  171. // RETURN
  172. case LSO_Enums.Operation_Table.RETURN:
  173. Common.SendToDebug("OPCODE: RETURN");
  174. return true;
  175. case LSO_Enums.Operation_Table.POP:
  176. case LSO_Enums.Operation_Table.POPS:
  177. case LSO_Enums.Operation_Table.POPL:
  178. case LSO_Enums.Operation_Table.POPV:
  179. case LSO_Enums.Operation_Table.POPQ:
  180. // Pops a specific datatype from the stack
  181. // We just ignore the datatype for now
  182. IL_Pop(il);
  183. break;
  184. // LONG
  185. case LSO_Enums.Operation_Table.STORE:
  186. case LSO_Enums.Operation_Table.STORES:
  187. case LSO_Enums.Operation_Table.STOREL:
  188. case LSO_Enums.Operation_Table.STOREV:
  189. case LSO_Enums.Operation_Table.STOREQ:
  190. u32p1 = BitConverter.ToUInt32(br_read(4), 0);
  191. Common.SendToDebug("Param1: " + u32p1.ToString());
  192. IL_CallBaseFunction(il, "StoreToLocal", u32p1);
  193. break;
  194. case LSO_Enums.Operation_Table.STOREG:
  195. case LSO_Enums.Operation_Table.STOREGS:
  196. case LSO_Enums.Operation_Table.STOREGL:
  197. case LSO_Enums.Operation_Table.STOREGV:
  198. case LSO_Enums.Operation_Table.STOREGQ:
  199. u32p1 = BitConverter.ToUInt32(br_read(4), 0);
  200. Common.SendToDebug("Param1: " + u32p1.ToString());
  201. IL_CallBaseFunction(il, "StoreToGlobal", u32p1);
  202. break;
  203. case LSO_Enums.Operation_Table.LOADP:
  204. case LSO_Enums.Operation_Table.LOADSP:
  205. case LSO_Enums.Operation_Table.LOADLP:
  206. case LSO_Enums.Operation_Table.LOADVP:
  207. case LSO_Enums.Operation_Table.LOADQP:
  208. u32p1 = BitConverter.ToUInt32(br_read(4), 0);
  209. Common.SendToDebug("Param1: " + u32p1.ToString());
  210. IL_CallBaseFunction(il, "StoreToLocal", u32p1);
  211. IL_Pop(il);
  212. break;
  213. case LSO_Enums.Operation_Table.LOADGP:
  214. case LSO_Enums.Operation_Table.LOADGSP:
  215. case LSO_Enums.Operation_Table.LOADGLP:
  216. case LSO_Enums.Operation_Table.LOADGVP:
  217. case LSO_Enums.Operation_Table.LOADGQP:
  218. u32p1 = BitConverter.ToUInt32(br_read(4), 0);
  219. Common.SendToDebug("Param1: " + u32p1.ToString());
  220. IL_CallBaseFunction(il, "StoreToStatic", u32p1 - 6 + myHeader.GVR);
  221. IL_Pop(il);
  222. break;
  223. // PUSH FROM LOCAL FRAME
  224. case LSO_Enums.Operation_Table.PUSH:
  225. case LSO_Enums.Operation_Table.PUSHS:
  226. case LSO_Enums.Operation_Table.PUSHL:
  227. case LSO_Enums.Operation_Table.PUSHV:
  228. case LSO_Enums.Operation_Table.PUSHQ:
  229. u32p1 = BitConverter.ToUInt32(br_read(4), 0);
  230. Common.SendToDebug("Param1: " + u32p1.ToString());
  231. IL_CallBaseFunction(il, "GetFromLocal", u32p1);
  232. break;
  233. // PUSH FROM STATIC FRAME
  234. case LSO_Enums.Operation_Table.PUSHG:
  235. case LSO_Enums.Operation_Table.PUSHGS:
  236. case LSO_Enums.Operation_Table.PUSHGL:
  237. case LSO_Enums.Operation_Table.PUSHGV:
  238. case LSO_Enums.Operation_Table.PUSHGQ:
  239. u32p1 = BitConverter.ToUInt32(br_read(4), 0);
  240. Common.SendToDebug("Param1: " + u32p1.ToString());
  241. IL_CallBaseFunction(il, "GetFromStatic", u32p1 - 6 + myHeader.GVR);
  242. break;
  243. /***********************
  244. * NOT IMPLEMENTED YET *
  245. ***********************/
  246. case LSO_Enums.Operation_Table.POPIP:
  247. case LSO_Enums.Operation_Table.POPSP:
  248. case LSO_Enums.Operation_Table.POPSLR:
  249. case LSO_Enums.Operation_Table.POPARG:
  250. case LSO_Enums.Operation_Table.POPBP:
  251. //Common.SendToDebug("Instruction " + idesc + ": Ignored");
  252. Common.SendToDebug("Instruction " + idesc +
  253. ": Description: Drop x bytes from the stack (TODO: Only popping 1)");
  254. //Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0));
  255. IL_Pop(il);
  256. break;
  257. // None
  258. case LSO_Enums.Operation_Table.PUSHIP:
  259. // PUSH INSTRUCTION POINTER
  260. break;
  261. case LSO_Enums.Operation_Table.PUSHBP:
  262. case LSO_Enums.Operation_Table.PUSHEV:
  263. break;
  264. case LSO_Enums.Operation_Table.PUSHEQ:
  265. break;
  266. // LONG
  267. case LSO_Enums.Operation_Table.JUMP:
  268. Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0));
  269. break;
  270. // BYTE, LONG
  271. case LSO_Enums.Operation_Table.JUMPIF:
  272. case LSO_Enums.Operation_Table.JUMPNIF:
  273. Common.SendToDebug("Param1: " + br_read(1)[0]);
  274. Common.SendToDebug("Param2: " + BitConverter.ToUInt32(br_read(4), 0));
  275. break;
  276. // LONG
  277. case LSO_Enums.Operation_Table.STATE:
  278. bp1 = br_read(1)[0];
  279. //il.Emit(OpCodes.Ld); // Load local variable 0 onto stack
  280. //il.Emit(OpCodes.Ldc_I4, 0); // Push index position
  281. //il.Emit(OpCodes.Ldstr, EventList[p1]); // Push value
  282. //il.Emit(OpCodes.Stelem_Ref); // Perform array[index] = value
  283. break;
  284. case LSO_Enums.Operation_Table.CALL:
  285. Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0));
  286. Common.SendToDebug("ERROR: Function CALL not implemented yet.");
  287. break;
  288. // BYTE
  289. case LSO_Enums.Operation_Table.CAST:
  290. bp1 = br_read(1)[0];
  291. Common.SendToDebug("Instruction " + idesc + ": Cast to type: " +
  292. ((LSO_Enums.OpCode_Cast_TypeDefs) bp1));
  293. Common.SendToDebug("Param1: " + bp1);
  294. switch ((LSO_Enums.OpCode_Cast_TypeDefs) bp1)
  295. {
  296. case LSO_Enums.OpCode_Cast_TypeDefs.String:
  297. Common.SendToDebug("Instruction " + idesc + ": il.Emit(OpCodes.Box, ILStack.Pop());");
  298. break;
  299. default:
  300. Common.SendToDebug("Instruction " + idesc + ": Unknown cast type!");
  301. break;
  302. }
  303. break;
  304. // LONG
  305. case LSO_Enums.Operation_Table.STACKTOS:
  306. case LSO_Enums.Operation_Table.STACKTOL:
  307. Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0));
  308. break;
  309. // BYTE
  310. case LSO_Enums.Operation_Table.PRINT:
  311. case LSO_Enums.Operation_Table.CALLLIB:
  312. Common.SendToDebug("Param1: " + br_read(1)[0]);
  313. break;
  314. }
  315. return false;
  316. }
  317. private void IL_PopToStack(ILGenerator il)
  318. {
  319. IL_PopToStack(il, 1);
  320. }
  321. private void IL_PopToStack(ILGenerator il, int count)
  322. {
  323. Common.SendToDebug("IL_PopToStack();");
  324. for (int i = 0; i < count; i++)
  325. {
  326. IL_CallBaseFunction(il, "POPToStack");
  327. //il.Emit(OpCodes.Ldarg_0);
  328. //il.Emit(OpCodes.Call,
  329. // typeof(LSL_BaseClass).GetMethod("POPToStack",
  330. // new Type[] { }));
  331. }
  332. }
  333. private void IL_Pop(ILGenerator il)
  334. {
  335. Common.SendToDebug("IL_Pop();");
  336. IL_CallBaseFunction(il, "POP");
  337. }
  338. private void IL_Debug(ILGenerator il, string text)
  339. {
  340. il.Emit(OpCodes.Ldstr, text);
  341. il.Emit(OpCodes.Call, typeof (Common).GetMethod("SendToDebug",
  342. new Type[] {typeof (string)}
  343. ));
  344. }
  345. private void IL_CallBaseFunction(ILGenerator il, string methodname)
  346. {
  347. il.Emit(OpCodes.Ldarg_0);
  348. il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod(methodname, new Type[] {}));
  349. }
  350. private void IL_CallBaseFunction(ILGenerator il, string methodname, object data)
  351. {
  352. il.Emit(OpCodes.Ldarg_0);
  353. if (data.GetType() == typeof (string))
  354. il.Emit(OpCodes.Ldstr, (string) data);
  355. if (data.GetType() == typeof (UInt32))
  356. il.Emit(OpCodes.Ldc_I4, (UInt32) data);
  357. il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod(methodname, new Type[] {data.GetType()}));
  358. }
  359. private void IL_Push(ILGenerator il, object data)
  360. {
  361. il.Emit(OpCodes.Ldarg_0);
  362. Common.SendToDebug("PUSH datatype: " + data.GetType());
  363. IL_PushDataTypeToILStack(il, data);
  364. il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod("PUSH", new Type[] {data.GetType()}));
  365. }
  366. private void IL_PushDataTypeToILStack(ILGenerator il, object data)
  367. {
  368. if (data.GetType() == typeof (UInt16))
  369. {
  370. il.Emit(OpCodes.Ldc_I4, (UInt16) data);
  371. il.Emit(OpCodes.Box, data.GetType());
  372. }
  373. if (data.GetType() == typeof (UInt32))
  374. {
  375. il.Emit(OpCodes.Ldc_I4, (UInt32) data);
  376. il.Emit(OpCodes.Box, data.GetType());
  377. }
  378. if (data.GetType() == typeof (Int32))
  379. {
  380. il.Emit(OpCodes.Ldc_I4, (Int32) data);
  381. il.Emit(OpCodes.Box, data.GetType());
  382. }
  383. if (data.GetType() == typeof (float))
  384. {
  385. il.Emit(OpCodes.Ldc_I4, (float) data);
  386. il.Emit(OpCodes.Box, data.GetType());
  387. }
  388. if (data.GetType() == typeof (string))
  389. il.Emit(OpCodes.Ldstr, (string) data);
  390. //if (data.GetType() == typeof(LSO_Enums.Rotation))
  391. // il.Emit(OpCodes.Ldobj, (LSO_Enums.Rotation)data);
  392. //if (data.GetType() == typeof(LSO_Enums.Vector))
  393. // il.Emit(OpCodes.Ldobj, (LSO_Enums.Vector)data);
  394. //if (data.GetType() == typeof(LSO_Enums.Key))
  395. // il.Emit(OpCodes.Ldobj, (LSO_Enums.Key)data);
  396. }
  397. }
  398. }