/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the OpenSim Project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Original code: Tedd Hansen */ using System; using System.Reflection; using System.Reflection.Emit; using OpenSim.Region.ScriptEngine.Common; namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO { internal partial class LSO_Parser { //internal Stack ILStack = new Stack(); //LSO_Enums MyLSO_Enums = new LSO_Enums(); internal bool LSL_PROCESS_OPCODE(ILGenerator il) { byte bp1; UInt32 u32p1; float fp1; UInt16 opcode = br_read(1)[0]; Common.SendToDebug("OPCODE: " + ((LSO_Enums.Operation_Table) opcode).ToString()); string idesc = ((LSO_Enums.Operation_Table) opcode).ToString(); switch ((LSO_Enums.Operation_Table) opcode) { /*************** * IMPLEMENTED * ***************/ case LSO_Enums.Operation_Table.NOOP: break; case LSO_Enums.Operation_Table.PUSHSP: // Push Stack Top (Memory Address) to stack Common.SendToDebug("Instruction " + idesc); Common.SendToDebug("Instruction " + idesc + ": Description: Pushing Stack Top (Memory Address from header) to stack"); IL_Push(il, (UInt32) myHeader.SP); break; // BYTE case LSO_Enums.Operation_Table.PUSHARGB: Common.SendToDebug("Param1: " + br_read(1)[0]); break; // INTEGER case LSO_Enums.Operation_Table.PUSHARGI: u32p1 = BitConverter.ToUInt32(br_read(4), 0); Common.SendToDebug("Instruction " + idesc + ", Param1: " + u32p1); IL_Push(il, u32p1); break; // FLOAT case LSO_Enums.Operation_Table.PUSHARGF: fp1 = BitConverter.ToUInt32(br_read(4), 0); Common.SendToDebug("Instruction " + idesc + ", Param1: " + fp1); IL_Push(il, fp1); break; // STRING case LSO_Enums.Operation_Table.PUSHARGS: string s = Read_String(); Common.SendToDebug("Instruction " + idesc + ", Param1: " + s); IL_Debug(il, "OPCODE: " + idesc + ":" + s); IL_Push(il, s); break; // VECTOR z,y,x case LSO_Enums.Operation_Table.PUSHARGV: LSO_Enums.Vector v = new LSO_Enums.Vector(); v.Z = BitConverter.ToUInt32(br_read(4), 0); v.Y = BitConverter.ToUInt32(br_read(4), 0); v.X = BitConverter.ToUInt32(br_read(4), 0); Common.SendToDebug("Param1 Z: " + v.Z); Common.SendToDebug("Param1 Y: " + v.Y); Common.SendToDebug("Param1 X: " + v.X); IL_Push(il, v); break; // ROTATION s,z,y,x case LSO_Enums.Operation_Table.PUSHARGQ: LSO_Enums.Rotation r = new LSO_Enums.Rotation(); r.S = BitConverter.ToUInt32(br_read(4), 0); r.Z = BitConverter.ToUInt32(br_read(4), 0); r.Y = BitConverter.ToUInt32(br_read(4), 0); r.X = BitConverter.ToUInt32(br_read(4), 0); Common.SendToDebug("Param1 S: " + r.S); Common.SendToDebug("Param1 Z: " + r.Z); Common.SendToDebug("Param1 Y: " + r.Y); Common.SendToDebug("Param1 X: " + r.X); IL_Push(il, r); break; case LSO_Enums.Operation_Table.PUSHE: IL_Push(il, (UInt32) 0); break; case LSO_Enums.Operation_Table.PUSHARGE: u32p1 = BitConverter.ToUInt32(br_read(4), 0); Common.SendToDebug("Param1: " + u32p1); //IL_Push(il, new string(" ".ToCharArray()[0], Convert.ToInt32(u32p1))); IL_Push(il, u32p1); break; // BYTE case LSO_Enums.Operation_Table.ADD: case LSO_Enums.Operation_Table.SUB: case LSO_Enums.Operation_Table.MUL: case LSO_Enums.Operation_Table.DIV: case LSO_Enums.Operation_Table.EQ: case LSO_Enums.Operation_Table.NEQ: case LSO_Enums.Operation_Table.LEQ: case LSO_Enums.Operation_Table.GEQ: case LSO_Enums.Operation_Table.LESS: case LSO_Enums.Operation_Table.GREATER: case LSO_Enums.Operation_Table.NEG: case LSO_Enums.Operation_Table.MOD: bp1 = br_read(1)[0]; Common.SendToDebug("Param1: " + bp1); IL_CallBaseFunction(il, idesc, (UInt32) bp1); break; // NO ARGUMENTS case LSO_Enums.Operation_Table.BITAND: case LSO_Enums.Operation_Table.BITOR: case LSO_Enums.Operation_Table.BITXOR: case LSO_Enums.Operation_Table.BOOLAND: case LSO_Enums.Operation_Table.BOOLOR: case LSO_Enums.Operation_Table.BITNOT: case LSO_Enums.Operation_Table.BOOLNOT: IL_CallBaseFunction(il, idesc); break; // SHORT case LSO_Enums.Operation_Table.CALLLIB_TWO_BYTE: // TODO: What is size of short? UInt16 U16p1 = BitConverter.ToUInt16(br_read(2), 0); Common.SendToDebug("Instruction " + idesc + ": Builtin Command: " + ((LSO_Enums.BuiltIn_Functions) U16p1).ToString()); //Common.SendToDebug("Param1: " + U16p1); string fname = ((LSO_Enums.BuiltIn_Functions) U16p1).ToString(); bool cmdFound = false; foreach (MethodInfo mi in typeof (LSL_BuiltIn_Commands_Interface).GetMethods()) { // Found command if (mi.Name == fname) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod("GetLSL_BuiltIn", new Type[] {})); // Pop required number of items from my stack to .Net stack IL_PopToStack(il, mi.GetParameters().Length); il.Emit(OpCodes.Callvirt, mi); cmdFound = true; break; } } if (cmdFound == false) { Common.SendToDebug("ERROR: UNABLE TO LOCATE OPCODE " + idesc + " IN BASECLASS"); } break; // RETURN case LSO_Enums.Operation_Table.RETURN: Common.SendToDebug("OPCODE: RETURN"); return true; case LSO_Enums.Operation_Table.POP: case LSO_Enums.Operation_Table.POPS: case LSO_Enums.Operation_Table.POPL: case LSO_Enums.Operation_Table.POPV: case LSO_Enums.Operation_Table.POPQ: // Pops a specific datatype from the stack // We just ignore the datatype for now IL_Pop(il); break; // LONG case LSO_Enums.Operation_Table.STORE: case LSO_Enums.Operation_Table.STORES: case LSO_Enums.Operation_Table.STOREL: case LSO_Enums.Operation_Table.STOREV: case LSO_Enums.Operation_Table.STOREQ: u32p1 = BitConverter.ToUInt32(br_read(4), 0); Common.SendToDebug("Param1: " + u32p1.ToString()); IL_CallBaseFunction(il, "StoreToLocal", u32p1); break; case LSO_Enums.Operation_Table.STOREG: case LSO_Enums.Operation_Table.STOREGS: case LSO_Enums.Operation_Table.STOREGL: case LSO_Enums.Operation_Table.STOREGV: case LSO_Enums.Operation_Table.STOREGQ: u32p1 = BitConverter.ToUInt32(br_read(4), 0); Common.SendToDebug("Param1: " + u32p1.ToString()); IL_CallBaseFunction(il, "StoreToGlobal", u32p1); break; case LSO_Enums.Operation_Table.LOADP: case LSO_Enums.Operation_Table.LOADSP: case LSO_Enums.Operation_Table.LOADLP: case LSO_Enums.Operation_Table.LOADVP: case LSO_Enums.Operation_Table.LOADQP: u32p1 = BitConverter.ToUInt32(br_read(4), 0); Common.SendToDebug("Param1: " + u32p1.ToString()); IL_CallBaseFunction(il, "StoreToLocal", u32p1); IL_Pop(il); break; case LSO_Enums.Operation_Table.LOADGP: case LSO_Enums.Operation_Table.LOADGSP: case LSO_Enums.Operation_Table.LOADGLP: case LSO_Enums.Operation_Table.LOADGVP: case LSO_Enums.Operation_Table.LOADGQP: u32p1 = BitConverter.ToUInt32(br_read(4), 0); Common.SendToDebug("Param1: " + u32p1.ToString()); IL_CallBaseFunction(il, "StoreToStatic", u32p1 - 6 + myHeader.GVR); IL_Pop(il); break; // PUSH FROM LOCAL FRAME case LSO_Enums.Operation_Table.PUSH: case LSO_Enums.Operation_Table.PUSHS: case LSO_Enums.Operation_Table.PUSHL: case LSO_Enums.Operation_Table.PUSHV: case LSO_Enums.Operation_Table.PUSHQ: u32p1 = BitConverter.ToUInt32(br_read(4), 0); Common.SendToDebug("Param1: " + u32p1.ToString()); IL_CallBaseFunction(il, "GetFromLocal", u32p1); break; // PUSH FROM STATIC FRAME case LSO_Enums.Operation_Table.PUSHG: case LSO_Enums.Operation_Table.PUSHGS: case LSO_Enums.Operation_Table.PUSHGL: case LSO_Enums.Operation_Table.PUSHGV: case LSO_Enums.Operation_Table.PUSHGQ: u32p1 = BitConverter.ToUInt32(br_read(4), 0); Common.SendToDebug("Param1: " + u32p1.ToString()); IL_CallBaseFunction(il, "GetFromStatic", u32p1 - 6 + myHeader.GVR); break; /*********************** * NOT IMPLEMENTED YET * ***********************/ case LSO_Enums.Operation_Table.POPIP: case LSO_Enums.Operation_Table.POPSP: case LSO_Enums.Operation_Table.POPSLR: case LSO_Enums.Operation_Table.POPARG: case LSO_Enums.Operation_Table.POPBP: //Common.SendToDebug("Instruction " + idesc + ": Ignored"); Common.SendToDebug("Instruction " + idesc + ": Description: Drop x bytes from the stack (TODO: Only popping 1)"); //Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); IL_Pop(il); break; // None case LSO_Enums.Operation_Table.PUSHIP: // PUSH INSTRUCTION POINTER break; case LSO_Enums.Operation_Table.PUSHBP: case LSO_Enums.Operation_Table.PUSHEV: break; case LSO_Enums.Operation_Table.PUSHEQ: break; // LONG case LSO_Enums.Operation_Table.JUMP: Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); break; // BYTE, LONG case LSO_Enums.Operation_Table.JUMPIF: case LSO_Enums.Operation_Table.JUMPNIF: Common.SendToDebug("Param1: " + br_read(1)[0]); Common.SendToDebug("Param2: " + BitConverter.ToUInt32(br_read(4), 0)); break; // LONG case LSO_Enums.Operation_Table.STATE: bp1 = br_read(1)[0]; //il.Emit(OpCodes.Ld); // Load local variable 0 onto stack //il.Emit(OpCodes.Ldc_I4, 0); // Push index position //il.Emit(OpCodes.Ldstr, EventList[p1]); // Push value //il.Emit(OpCodes.Stelem_Ref); // Perform array[index] = value break; case LSO_Enums.Operation_Table.CALL: Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); Common.SendToDebug("ERROR: Function CALL not implemented yet."); break; // BYTE case LSO_Enums.Operation_Table.CAST: bp1 = br_read(1)[0]; Common.SendToDebug("Instruction " + idesc + ": Cast to type: " + ((LSO_Enums.OpCode_Cast_TypeDefs) bp1)); Common.SendToDebug("Param1: " + bp1); switch ((LSO_Enums.OpCode_Cast_TypeDefs) bp1) { case LSO_Enums.OpCode_Cast_TypeDefs.String: Common.SendToDebug("Instruction " + idesc + ": il.Emit(OpCodes.Box, ILStack.Pop());"); break; default: Common.SendToDebug("Instruction " + idesc + ": Unknown cast type!"); break; } break; // LONG case LSO_Enums.Operation_Table.STACKTOS: case LSO_Enums.Operation_Table.STACKTOL: Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); break; // BYTE case LSO_Enums.Operation_Table.PRINT: case LSO_Enums.Operation_Table.CALLLIB: Common.SendToDebug("Param1: " + br_read(1)[0]); break; } return false; } private void IL_PopToStack(ILGenerator il) { IL_PopToStack(il, 1); } private void IL_PopToStack(ILGenerator il, int count) { Common.SendToDebug("IL_PopToStack();"); for (int i = 0; i < count; i++) { IL_CallBaseFunction(il, "POPToStack"); //il.Emit(OpCodes.Ldarg_0); //il.Emit(OpCodes.Call, // typeof(LSL_BaseClass).GetMethod("POPToStack", // new Type[] { })); } } private void IL_Pop(ILGenerator il) { Common.SendToDebug("IL_Pop();"); IL_CallBaseFunction(il, "POP"); } private void IL_Debug(ILGenerator il, string text) { il.Emit(OpCodes.Ldstr, text); il.Emit(OpCodes.Call, typeof (Common).GetMethod("SendToDebug", new Type[] {typeof (string)} )); } private void IL_CallBaseFunction(ILGenerator il, string methodname) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod(methodname, new Type[] {})); } private void IL_CallBaseFunction(ILGenerator il, string methodname, object data) { il.Emit(OpCodes.Ldarg_0); if (data.GetType() == typeof (string)) il.Emit(OpCodes.Ldstr, (string) data); if (data.GetType() == typeof (UInt32)) il.Emit(OpCodes.Ldc_I4, (UInt32) data); il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod(methodname, new Type[] {data.GetType()})); } private void IL_Push(ILGenerator il, object data) { il.Emit(OpCodes.Ldarg_0); Common.SendToDebug("PUSH datatype: " + data.GetType()); IL_PushDataTypeToILStack(il, data); il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod("PUSH", new Type[] {data.GetType()})); } private void IL_PushDataTypeToILStack(ILGenerator il, object data) { if (data.GetType() == typeof (UInt16)) { il.Emit(OpCodes.Ldc_I4, (UInt16) data); il.Emit(OpCodes.Box, data.GetType()); } if (data.GetType() == typeof (UInt32)) { il.Emit(OpCodes.Ldc_I4, (UInt32) data); il.Emit(OpCodes.Box, data.GetType()); } if (data.GetType() == typeof (Int32)) { il.Emit(OpCodes.Ldc_I4, (Int32) data); il.Emit(OpCodes.Box, data.GetType()); } if (data.GetType() == typeof (float)) { il.Emit(OpCodes.Ldc_I4, (float) data); il.Emit(OpCodes.Box, data.GetType()); } if (data.GetType() == typeof (string)) il.Emit(OpCodes.Ldstr, (string) data); //if (data.GetType() == typeof(LSO_Enums.Rotation)) // il.Emit(OpCodes.Ldobj, (LSO_Enums.Rotation)data); //if (data.GetType() == typeof(LSO_Enums.Vector)) // il.Emit(OpCodes.Ldobj, (LSO_Enums.Vector)data); //if (data.GetType() == typeof(LSO_Enums.Key)) // il.Emit(OpCodes.Ldobj, (LSO_Enums.Key)data); } } }