OpenSimMirror/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_OPCODE_IL_processor.cs

435 lines
20 KiB
C#

/*
* 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.Region.ScriptEngine.LSOEngine.LSO
{
internal partial class LSO_Parser
{
//internal Stack<Type> ILStack = new Stack<Type>();
//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);
}
}
}