2609 lines
87 KiB
C#
2609 lines
87 KiB
C#
|
//-----------------------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// ***NOTE*** If this code is changed, make corresponding changes in System.ServiceModel.CodeGenerator also
|
||
|
namespace System.Runtime.Serialization
|
||
|
{
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Diagnostics;
|
||
|
using System.Globalization;
|
||
|
using System.Reflection;
|
||
|
#if !NO_DYNAMIC_CODEGEN
|
||
|
using System.Reflection.Emit;
|
||
|
#endif
|
||
|
using System.Security;
|
||
|
|
||
|
class CodeGenerator
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Static fields are marked SecurityCritical or readonly to prevent"
|
||
|
+ " data from being modified or leaked to other components in appdomain.")]
|
||
|
[SecurityCritical]
|
||
|
static MethodInfo getTypeFromHandle;
|
||
|
static MethodInfo GetTypeFromHandle
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Fetches the critical getTypeFromHandle field.",
|
||
|
Safe = "Get-only properties only needs to be protected for write; initialized in getter if null.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get
|
||
|
{
|
||
|
if (getTypeFromHandle == null)
|
||
|
getTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle");
|
||
|
return getTypeFromHandle;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Fx.Tag.SecurityNote(Critical = "Static fields are marked SecurityCritical or readonly to prevent"
|
||
|
+ " data from being modified or leaked to other components in appdomain.")]
|
||
|
[SecurityCritical]
|
||
|
static MethodInfo stringFormat;
|
||
|
static MethodInfo StringFormat
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Fetches the critical stringFormat field.",
|
||
|
Safe = "Get-only properties only needs to be protected for write; initialized in getter if null.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get
|
||
|
{
|
||
|
if (stringFormat == null)
|
||
|
stringFormat = typeof(string).GetMethod("Format", new Type[] { typeof(string), typeof(object[]) });
|
||
|
return stringFormat;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Fx.Tag.SecurityNote(Critical = "Static fields are marked SecurityCritical or readonly to prevent"
|
||
|
+ " data from being modified or leaked to other components in appdomain.")]
|
||
|
[SecurityCritical]
|
||
|
static MethodInfo stringConcat2;
|
||
|
static MethodInfo StringConcat2
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Fetches the critical stringConcat2 field.",
|
||
|
Safe = "Get-only properties only needs to be protected for write; initialized in getter if null.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get
|
||
|
{
|
||
|
if (stringConcat2 == null)
|
||
|
stringConcat2 = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) });
|
||
|
return stringConcat2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Fx.Tag.SecurityNote(Critical = "Static fields are marked SecurityCritical or readonly to prevent"
|
||
|
+ " data from being modified or leaked to other components in appdomain.")]
|
||
|
[SecurityCritical]
|
||
|
static MethodInfo stringConcat3;
|
||
|
static MethodInfo StringConcat3
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Fetches the critical stringConcat3 field.",
|
||
|
Safe = "Get-only properties only needs to be protected for write; initialized in getter if null.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get
|
||
|
{
|
||
|
if (stringConcat3 == null)
|
||
|
stringConcat3 = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string), typeof(string) });
|
||
|
return stringConcat3;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Fx.Tag.SecurityNote(Critical = "Static fields are marked SecurityCritical or readonly to prevent"
|
||
|
+ " data from being modified or leaked to other components in appdomain.")]
|
||
|
[SecurityCritical]
|
||
|
static MethodInfo objectToString;
|
||
|
static MethodInfo ObjectToString
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Fetches the critical objectToString field.",
|
||
|
Safe = "Get-only properties only needs to be protected for write; initialized in getter if null.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get
|
||
|
{
|
||
|
if (objectToString == null)
|
||
|
objectToString = typeof(object).GetMethod("ToString", new Type[0]);
|
||
|
return objectToString;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Fx.Tag.SecurityNote(Critical = "Static fields are marked SecurityCritical or readonly to prevent"
|
||
|
+ " data from being modified or leaked to other components in appdomain.")]
|
||
|
[SecurityCritical]
|
||
|
static MethodInfo objectEquals;
|
||
|
static MethodInfo ObjectEquals
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Fetches the critical objectEquals field.",
|
||
|
Safe = "Get-only properties only needs to be protected for write; initialized in getter if null.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get
|
||
|
{
|
||
|
if (objectEquals == null)
|
||
|
objectEquals = Globals.TypeOfObject.GetMethod("Equals", BindingFlags.Public | BindingFlags.Static);
|
||
|
return objectEquals;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Fx.Tag.SecurityNote(Critical = "Static fields are marked SecurityCritical or readonly to prevent"
|
||
|
+ " data from being modified or leaked to other components in appdomain.")]
|
||
|
[SecurityCritical]
|
||
|
static MethodInfo arraySetValue;
|
||
|
static MethodInfo ArraySetValue
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Fetches the critical arraySetValue field.",
|
||
|
Safe = "Get-only properties only needs to be protected for write; initialized in getter if null.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get
|
||
|
{
|
||
|
if (arraySetValue == null)
|
||
|
arraySetValue = typeof(Array).GetMethod("SetValue", new Type[] { typeof(object), typeof(int) });
|
||
|
return arraySetValue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Type delegateType;
|
||
|
|
||
|
#if USE_REFEMIT
|
||
|
AssemblyBuilder assemblyBuilder;
|
||
|
ModuleBuilder moduleBuilder;
|
||
|
TypeBuilder typeBuilder;
|
||
|
static int typeCounter;
|
||
|
MethodBuilder methodBuilder;
|
||
|
#else
|
||
|
[Fx.Tag.SecurityNote(Critical = "Static fields are marked SecurityCritical or readonly to prevent"
|
||
|
+ " data from being modified or leaked to other components in appdomain.")]
|
||
|
[SecurityCritical]
|
||
|
static Module serializationModule;
|
||
|
static Module SerializationModule
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Fetches the critical serializationModule field.",
|
||
|
Safe = "Get-only properties only needs to be protected for write; initialized in getter if null.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get
|
||
|
{
|
||
|
if (serializationModule == null)
|
||
|
{
|
||
|
serializationModule = typeof(CodeGenerator).Module; // could to be replaced by different dll that has SkipVerification set to false
|
||
|
}
|
||
|
return serializationModule;
|
||
|
}
|
||
|
}
|
||
|
DynamicMethod dynamicMethod;
|
||
|
#endif
|
||
|
|
||
|
ILGenerator ilGen;
|
||
|
ArrayList argList;
|
||
|
Stack blockStack;
|
||
|
Label methodEndLabel;
|
||
|
|
||
|
LocalBuilder stringFormatArray;
|
||
|
|
||
|
Hashtable localNames;
|
||
|
int lineNo = 1;
|
||
|
enum CodeGenTrace { None, Save, Tron };
|
||
|
CodeGenTrace codeGenTrace;
|
||
|
|
||
|
internal CodeGenerator()
|
||
|
{
|
||
|
SourceSwitch codeGenSwitch = SerializationTrace.CodeGenerationSwitch;
|
||
|
if ((codeGenSwitch.Level & SourceLevels.Verbose) == SourceLevels.Verbose)
|
||
|
codeGenTrace = CodeGenTrace.Tron;
|
||
|
else if ((codeGenSwitch.Level & SourceLevels.Information) == SourceLevels.Information)
|
||
|
codeGenTrace = CodeGenTrace.Save;
|
||
|
else
|
||
|
codeGenTrace = CodeGenTrace.None;
|
||
|
}
|
||
|
|
||
|
#if !USE_REFEMIT
|
||
|
internal void BeginMethod(DynamicMethod dynamicMethod, Type delegateType, string methodName, Type[] argTypes, bool allowPrivateMemberAccess)
|
||
|
{
|
||
|
this.dynamicMethod = dynamicMethod;
|
||
|
this.ilGen = this.dynamicMethod.GetILGenerator();
|
||
|
this.delegateType = delegateType;
|
||
|
|
||
|
InitILGeneration(methodName, argTypes);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
internal void BeginMethod(string methodName, Type delegateType, bool allowPrivateMemberAccess)
|
||
|
{
|
||
|
MethodInfo signature = delegateType.GetMethod("Invoke");
|
||
|
ParameterInfo[] parameters = signature.GetParameters();
|
||
|
Type[] paramTypes = new Type[parameters.Length];
|
||
|
for (int i = 0; i < parameters.Length; i++)
|
||
|
paramTypes[i] = parameters[i].ParameterType;
|
||
|
BeginMethod(signature.ReturnType, methodName, paramTypes, allowPrivateMemberAccess);
|
||
|
this.delegateType = delegateType;
|
||
|
}
|
||
|
|
||
|
void BeginMethod(Type returnType, string methodName, Type[] argTypes, bool allowPrivateMemberAccess)
|
||
|
{
|
||
|
#if USE_REFEMIT
|
||
|
string typeName = "Type" + (typeCounter++);
|
||
|
InitAssemblyBuilder(typeName + "." + methodName);
|
||
|
this.typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public);
|
||
|
this.methodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Public|MethodAttributes.Static, returnType, argTypes);
|
||
|
this.ilGen = this.methodBuilder.GetILGenerator();
|
||
|
#else
|
||
|
this.dynamicMethod = new DynamicMethod(methodName, returnType, argTypes, SerializationModule, allowPrivateMemberAccess);
|
||
|
this.ilGen = this.dynamicMethod.GetILGenerator();
|
||
|
#endif
|
||
|
|
||
|
InitILGeneration(methodName, argTypes);
|
||
|
}
|
||
|
|
||
|
void InitILGeneration(string methodName, Type[] argTypes)
|
||
|
{
|
||
|
this.methodEndLabel = ilGen.DefineLabel();
|
||
|
this.blockStack = new Stack();
|
||
|
this.argList = new ArrayList();
|
||
|
for (int i = 0; i < argTypes.Length; i++)
|
||
|
argList.Add(new ArgBuilder(i, argTypes[i]));
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceLabel("Begin method " + methodName + " {");
|
||
|
}
|
||
|
|
||
|
internal Delegate EndMethod()
|
||
|
{
|
||
|
MarkLabel(methodEndLabel);
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceLabel("} End method");
|
||
|
Ret();
|
||
|
|
||
|
Delegate retVal = null;
|
||
|
#if USE_REFEMIT
|
||
|
Type type = typeBuilder.CreateType();
|
||
|
assemblyBuilder.Save(assemblyBuilder.GetName().Name+".dll");
|
||
|
|
||
|
MethodInfo method = type.GetMethod(methodBuilder.Name);
|
||
|
retVal = Delegate.CreateDelegate(delegateType, method);
|
||
|
methodBuilder = null;
|
||
|
#else
|
||
|
retVal = dynamicMethod.CreateDelegate(delegateType);
|
||
|
dynamicMethod = null;
|
||
|
#endif
|
||
|
delegateType = null;
|
||
|
|
||
|
ilGen = null;
|
||
|
blockStack = null;
|
||
|
argList = null;
|
||
|
return retVal;
|
||
|
}
|
||
|
|
||
|
internal MethodInfo CurrentMethod
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
#if USE_REFEMIT
|
||
|
return methodBuilder;
|
||
|
#else
|
||
|
return dynamicMethod;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal ArgBuilder GetArg(int index)
|
||
|
{
|
||
|
return (ArgBuilder)argList[index];
|
||
|
}
|
||
|
|
||
|
internal Type GetVariableType(object var)
|
||
|
{
|
||
|
if (var is ArgBuilder)
|
||
|
return ((ArgBuilder)var).ArgType;
|
||
|
else if (var is LocalBuilder)
|
||
|
return ((LocalBuilder)var).LocalType;
|
||
|
else
|
||
|
return var.GetType();
|
||
|
}
|
||
|
|
||
|
internal LocalBuilder DeclareLocal(Type type, string name, object initialValue)
|
||
|
{
|
||
|
LocalBuilder local = DeclareLocal(type, name);
|
||
|
Load(initialValue);
|
||
|
Store(local);
|
||
|
return local;
|
||
|
}
|
||
|
|
||
|
internal LocalBuilder DeclareLocal(Type type, string name)
|
||
|
{
|
||
|
return DeclareLocal(type, name, false);
|
||
|
}
|
||
|
|
||
|
internal LocalBuilder DeclareLocal(Type type, string name, bool isPinned)
|
||
|
{
|
||
|
LocalBuilder local = ilGen.DeclareLocal(type, isPinned);
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
{
|
||
|
LocalNames[local] = name;
|
||
|
EmitSourceComment("Declare local '" + name + "' of type " + type);
|
||
|
}
|
||
|
return local;
|
||
|
}
|
||
|
|
||
|
internal void Set(LocalBuilder local, object value)
|
||
|
{
|
||
|
Load(value);
|
||
|
Store(local);
|
||
|
}
|
||
|
|
||
|
internal object For(LocalBuilder local, object start, object end)
|
||
|
{
|
||
|
ForState forState = new ForState(local, DefineLabel(), DefineLabel(), end);
|
||
|
if (forState.Index != null)
|
||
|
{
|
||
|
Load(start);
|
||
|
Stloc(forState.Index);
|
||
|
Br(forState.TestLabel);
|
||
|
}
|
||
|
MarkLabel(forState.BeginLabel);
|
||
|
blockStack.Push(forState);
|
||
|
return forState;
|
||
|
}
|
||
|
|
||
|
internal void EndFor()
|
||
|
{
|
||
|
object stackTop = blockStack.Pop();
|
||
|
ForState forState = stackTop as ForState;
|
||
|
if (forState == null)
|
||
|
ThrowMismatchException(stackTop);
|
||
|
|
||
|
if (forState.Index != null)
|
||
|
{
|
||
|
Ldloc(forState.Index);
|
||
|
Ldc(1);
|
||
|
Add();
|
||
|
Stloc(forState.Index);
|
||
|
MarkLabel(forState.TestLabel);
|
||
|
Ldloc(forState.Index);
|
||
|
Load(forState.End);
|
||
|
if (GetVariableType(forState.End).IsArray)
|
||
|
Ldlen();
|
||
|
Blt(forState.BeginLabel);
|
||
|
}
|
||
|
else
|
||
|
Br(forState.BeginLabel);
|
||
|
if (forState.RequiresEndLabel)
|
||
|
MarkLabel(forState.EndLabel);
|
||
|
}
|
||
|
|
||
|
internal void Break(object forState)
|
||
|
{
|
||
|
InternalBreakFor(forState, OpCodes.Br);
|
||
|
}
|
||
|
|
||
|
internal void IfTrueBreak(object forState)
|
||
|
{
|
||
|
InternalBreakFor(forState, OpCodes.Brtrue);
|
||
|
}
|
||
|
|
||
|
internal void IfFalseBreak(object forState)
|
||
|
{
|
||
|
InternalBreakFor(forState, OpCodes.Brfalse);
|
||
|
}
|
||
|
|
||
|
internal void InternalBreakFor(object userForState, OpCode branchInstruction)
|
||
|
{
|
||
|
foreach (object block in blockStack)
|
||
|
{
|
||
|
ForState forState = block as ForState;
|
||
|
if (forState != null && (object)forState == userForState)
|
||
|
{
|
||
|
if (!forState.RequiresEndLabel)
|
||
|
{
|
||
|
forState.EndLabel = DefineLabel();
|
||
|
forState.RequiresEndLabel = true;
|
||
|
}
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction(branchInstruction + " " + forState.EndLabel.GetHashCode());
|
||
|
ilGen.Emit(branchInstruction, forState.EndLabel);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void ForEach(LocalBuilder local, Type elementType, Type enumeratorType,
|
||
|
LocalBuilder enumerator, MethodInfo getCurrentMethod)
|
||
|
{
|
||
|
ForState forState = new ForState(local, DefineLabel(), DefineLabel(), enumerator);
|
||
|
|
||
|
Br(forState.TestLabel);
|
||
|
MarkLabel(forState.BeginLabel);
|
||
|
|
||
|
Call(enumerator, getCurrentMethod);
|
||
|
|
||
|
ConvertValue(elementType, GetVariableType(local));
|
||
|
Stloc(local);
|
||
|
blockStack.Push(forState);
|
||
|
}
|
||
|
|
||
|
internal void EndForEach(MethodInfo moveNextMethod)
|
||
|
{
|
||
|
object stackTop = blockStack.Pop();
|
||
|
ForState forState = stackTop as ForState;
|
||
|
if (forState == null)
|
||
|
ThrowMismatchException(stackTop);
|
||
|
|
||
|
MarkLabel(forState.TestLabel);
|
||
|
|
||
|
object enumerator = forState.End;
|
||
|
Call(enumerator, moveNextMethod);
|
||
|
|
||
|
|
||
|
Brtrue(forState.BeginLabel);
|
||
|
if (forState.RequiresEndLabel)
|
||
|
MarkLabel(forState.EndLabel);
|
||
|
}
|
||
|
|
||
|
internal void IfNotDefaultValue(object value)
|
||
|
{
|
||
|
Type type = GetVariableType(value);
|
||
|
TypeCode typeCode = Type.GetTypeCode(type);
|
||
|
if ((typeCode == TypeCode.Object && type.IsValueType) ||
|
||
|
typeCode == TypeCode.DateTime || typeCode == TypeCode.Decimal)
|
||
|
{
|
||
|
LoadDefaultValue(type);
|
||
|
ConvertValue(type, Globals.TypeOfObject);
|
||
|
Load(value);
|
||
|
ConvertValue(type, Globals.TypeOfObject);
|
||
|
Call(ObjectEquals);
|
||
|
IfNot();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LoadDefaultValue(type);
|
||
|
Load(value);
|
||
|
If(Cmp.NotEqualTo);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void If()
|
||
|
{
|
||
|
InternalIf(false);
|
||
|
}
|
||
|
|
||
|
internal void IfNot()
|
||
|
{
|
||
|
InternalIf(true);
|
||
|
}
|
||
|
|
||
|
OpCode GetBranchCode(Cmp cmp)
|
||
|
{
|
||
|
switch (cmp)
|
||
|
{
|
||
|
case Cmp.LessThan:
|
||
|
return OpCodes.Bge;
|
||
|
case Cmp.EqualTo:
|
||
|
return OpCodes.Bne_Un;
|
||
|
case Cmp.LessThanOrEqualTo:
|
||
|
return OpCodes.Bgt;
|
||
|
case Cmp.GreaterThan:
|
||
|
return OpCodes.Ble;
|
||
|
case Cmp.NotEqualTo:
|
||
|
return OpCodes.Beq;
|
||
|
default:
|
||
|
Fx.Assert(cmp == Cmp.GreaterThanOrEqualTo, "Unexpected cmp");
|
||
|
return OpCodes.Blt;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Cmp GetCmpInverse(Cmp cmp)
|
||
|
{
|
||
|
switch (cmp)
|
||
|
{
|
||
|
case Cmp.LessThan:
|
||
|
return Cmp.GreaterThanOrEqualTo;
|
||
|
case Cmp.EqualTo:
|
||
|
return Cmp.NotEqualTo;
|
||
|
case Cmp.LessThanOrEqualTo:
|
||
|
return Cmp.GreaterThan;
|
||
|
case Cmp.GreaterThan:
|
||
|
return Cmp.LessThanOrEqualTo;
|
||
|
case Cmp.NotEqualTo:
|
||
|
return Cmp.EqualTo;
|
||
|
default:
|
||
|
Fx.Assert(cmp == Cmp.GreaterThanOrEqualTo, "Unexpected cmp");
|
||
|
return Cmp.LessThan;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void If(Cmp cmpOp)
|
||
|
{
|
||
|
IfState ifState = new IfState();
|
||
|
ifState.EndIf = DefineLabel();
|
||
|
ifState.ElseBegin = DefineLabel();
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Branch if " + GetCmpInverse(cmpOp).ToString() + " to " + ifState.ElseBegin.GetHashCode().ToString(NumberFormatInfo.InvariantInfo));
|
||
|
ilGen.Emit(GetBranchCode(cmpOp), ifState.ElseBegin);
|
||
|
blockStack.Push(ifState);
|
||
|
}
|
||
|
|
||
|
|
||
|
internal void If(object value1, Cmp cmpOp, object value2)
|
||
|
{
|
||
|
Load(value1);
|
||
|
Load(value2);
|
||
|
If(cmpOp);
|
||
|
}
|
||
|
internal void Else()
|
||
|
{
|
||
|
IfState ifState = PopIfState();
|
||
|
Br(ifState.EndIf);
|
||
|
MarkLabel(ifState.ElseBegin);
|
||
|
|
||
|
ifState.ElseBegin = ifState.EndIf;
|
||
|
blockStack.Push(ifState);
|
||
|
}
|
||
|
|
||
|
internal void ElseIf(object value1, Cmp cmpOp, object value2)
|
||
|
{
|
||
|
IfState ifState = (IfState)blockStack.Pop();
|
||
|
Br(ifState.EndIf);
|
||
|
MarkLabel(ifState.ElseBegin);
|
||
|
|
||
|
Load(value1);
|
||
|
Load(value2);
|
||
|
ifState.ElseBegin = DefineLabel();
|
||
|
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Branch if " + GetCmpInverse(cmpOp).ToString() + " to " + ifState.ElseBegin.GetHashCode().ToString(NumberFormatInfo.InvariantInfo));
|
||
|
|
||
|
ilGen.Emit(GetBranchCode(cmpOp), ifState.ElseBegin);
|
||
|
blockStack.Push(ifState);
|
||
|
}
|
||
|
|
||
|
|
||
|
internal void EndIf()
|
||
|
{
|
||
|
IfState ifState = PopIfState();
|
||
|
if (!ifState.ElseBegin.Equals(ifState.EndIf))
|
||
|
MarkLabel(ifState.ElseBegin);
|
||
|
MarkLabel(ifState.EndIf);
|
||
|
}
|
||
|
|
||
|
internal void VerifyParameterCount(MethodInfo methodInfo, int expectedCount)
|
||
|
{
|
||
|
if (methodInfo.GetParameters().Length != expectedCount)
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ParameterCountMismatch, methodInfo.Name, methodInfo.GetParameters().Length, expectedCount)));
|
||
|
}
|
||
|
|
||
|
internal void Call(object thisObj, MethodInfo methodInfo)
|
||
|
{
|
||
|
VerifyParameterCount(methodInfo, 0);
|
||
|
LoadThis(thisObj, methodInfo);
|
||
|
Call(methodInfo);
|
||
|
}
|
||
|
|
||
|
internal void Call(object thisObj, MethodInfo methodInfo, object param1)
|
||
|
{
|
||
|
VerifyParameterCount(methodInfo, 1);
|
||
|
LoadThis(thisObj, methodInfo);
|
||
|
LoadParam(param1, 1, methodInfo);
|
||
|
Call(methodInfo);
|
||
|
}
|
||
|
|
||
|
internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2)
|
||
|
{
|
||
|
VerifyParameterCount(methodInfo, 2);
|
||
|
LoadThis(thisObj, methodInfo);
|
||
|
LoadParam(param1, 1, methodInfo);
|
||
|
LoadParam(param2, 2, methodInfo);
|
||
|
Call(methodInfo);
|
||
|
}
|
||
|
|
||
|
internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3)
|
||
|
{
|
||
|
VerifyParameterCount(methodInfo, 3);
|
||
|
LoadThis(thisObj, methodInfo);
|
||
|
LoadParam(param1, 1, methodInfo);
|
||
|
LoadParam(param2, 2, methodInfo);
|
||
|
LoadParam(param3, 3, methodInfo);
|
||
|
Call(methodInfo);
|
||
|
}
|
||
|
|
||
|
internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4)
|
||
|
{
|
||
|
VerifyParameterCount(methodInfo, 4);
|
||
|
LoadThis(thisObj, methodInfo);
|
||
|
LoadParam(param1, 1, methodInfo);
|
||
|
LoadParam(param2, 2, methodInfo);
|
||
|
LoadParam(param3, 3, methodInfo);
|
||
|
LoadParam(param4, 4, methodInfo);
|
||
|
Call(methodInfo);
|
||
|
}
|
||
|
|
||
|
internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4, object param5)
|
||
|
{
|
||
|
VerifyParameterCount(methodInfo, 5);
|
||
|
LoadThis(thisObj, methodInfo);
|
||
|
LoadParam(param1, 1, methodInfo);
|
||
|
LoadParam(param2, 2, methodInfo);
|
||
|
LoadParam(param3, 3, methodInfo);
|
||
|
LoadParam(param4, 4, methodInfo);
|
||
|
LoadParam(param5, 5, methodInfo);
|
||
|
Call(methodInfo);
|
||
|
}
|
||
|
|
||
|
internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4, object param5, object param6)
|
||
|
{
|
||
|
VerifyParameterCount(methodInfo, 6);
|
||
|
LoadThis(thisObj, methodInfo);
|
||
|
LoadParam(param1, 1, methodInfo);
|
||
|
LoadParam(param2, 2, methodInfo);
|
||
|
LoadParam(param3, 3, methodInfo);
|
||
|
LoadParam(param4, 4, methodInfo);
|
||
|
LoadParam(param5, 5, methodInfo);
|
||
|
LoadParam(param6, 6, methodInfo);
|
||
|
Call(methodInfo);
|
||
|
}
|
||
|
|
||
|
internal void Call(MethodInfo methodInfo)
|
||
|
{
|
||
|
if (methodInfo.IsVirtual && !methodInfo.DeclaringType.IsValueType)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Callvirt " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
|
||
|
ilGen.Emit(OpCodes.Callvirt, methodInfo);
|
||
|
}
|
||
|
else if (methodInfo.IsStatic)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Static Call " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
|
||
|
ilGen.Emit(OpCodes.Call, methodInfo);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Call " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
|
||
|
ilGen.Emit(OpCodes.Call, methodInfo);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Call(ConstructorInfo ctor)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Call " + ctor.ToString() + " on type " + ctor.DeclaringType.ToString());
|
||
|
ilGen.Emit(OpCodes.Call, ctor);
|
||
|
}
|
||
|
|
||
|
internal void New(ConstructorInfo constructorInfo)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Newobj " + constructorInfo.ToString() + " on type " + constructorInfo.DeclaringType.ToString());
|
||
|
ilGen.Emit(OpCodes.Newobj, constructorInfo);
|
||
|
}
|
||
|
|
||
|
internal void New(ConstructorInfo constructorInfo, object param1)
|
||
|
{
|
||
|
LoadParam(param1, 1, constructorInfo);
|
||
|
New(constructorInfo);
|
||
|
}
|
||
|
|
||
|
internal void InitObj(Type valueType)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Initobj " + valueType);
|
||
|
ilGen.Emit(OpCodes.Initobj, valueType);
|
||
|
}
|
||
|
|
||
|
internal void NewArray(Type elementType, object len)
|
||
|
{
|
||
|
Load(len);
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Newarr " + elementType);
|
||
|
ilGen.Emit(OpCodes.Newarr, elementType);
|
||
|
}
|
||
|
|
||
|
internal void IgnoreReturnValue()
|
||
|
{
|
||
|
Pop();
|
||
|
}
|
||
|
|
||
|
internal void LoadArrayElement(object obj, object arrayIndex)
|
||
|
{
|
||
|
Type objType = GetVariableType(obj).GetElementType();
|
||
|
Load(obj);
|
||
|
Load(arrayIndex);
|
||
|
if (IsStruct(objType))
|
||
|
{
|
||
|
Ldelema(objType);
|
||
|
Ldobj(objType);
|
||
|
}
|
||
|
else
|
||
|
Ldelem(objType);
|
||
|
}
|
||
|
|
||
|
internal void StoreArrayElement(object obj, object arrayIndex, object value)
|
||
|
{
|
||
|
Type arrayType = GetVariableType(obj);
|
||
|
if (arrayType == Globals.TypeOfArray)
|
||
|
{
|
||
|
Call(obj, ArraySetValue, value, arrayIndex);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Type objType = arrayType.GetElementType();
|
||
|
Load(obj);
|
||
|
Load(arrayIndex);
|
||
|
if (IsStruct(objType))
|
||
|
Ldelema(objType);
|
||
|
Load(value);
|
||
|
ConvertValue(GetVariableType(value), objType);
|
||
|
if (IsStruct(objType))
|
||
|
Stobj(objType);
|
||
|
else
|
||
|
Stelem(objType);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool IsStruct(Type objType)
|
||
|
{
|
||
|
return objType.IsValueType && !objType.IsPrimitive;
|
||
|
}
|
||
|
|
||
|
internal Type LoadMember(MemberInfo memberInfo)
|
||
|
{
|
||
|
Type memberType = null;
|
||
|
if (memberInfo.MemberType == MemberTypes.Field)
|
||
|
{
|
||
|
FieldInfo fieldInfo = (FieldInfo)memberInfo;
|
||
|
memberType = fieldInfo.FieldType;
|
||
|
if (fieldInfo.IsStatic)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldsfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
|
||
|
ilGen.Emit(OpCodes.Ldsfld, fieldInfo);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
|
||
|
ilGen.Emit(OpCodes.Ldfld, fieldInfo);
|
||
|
}
|
||
|
}
|
||
|
else if (memberInfo.MemberType == MemberTypes.Property)
|
||
|
{
|
||
|
PropertyInfo property = memberInfo as PropertyInfo;
|
||
|
memberType = property.PropertyType;
|
||
|
if (property != null)
|
||
|
{
|
||
|
MethodInfo getMethod = property.GetGetMethod(true);
|
||
|
if (getMethod == null)
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.NoGetMethodForProperty, property.DeclaringType, property)));
|
||
|
Call(getMethod);
|
||
|
}
|
||
|
}
|
||
|
else if (memberInfo.MemberType == MemberTypes.Method)
|
||
|
{
|
||
|
MethodInfo method = (MethodInfo)memberInfo;
|
||
|
memberType = method.ReturnType;
|
||
|
Call(method);
|
||
|
}
|
||
|
else
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.CannotLoadMemberType, memberInfo.MemberType, memberInfo.DeclaringType, memberInfo.Name)));
|
||
|
|
||
|
EmitStackTop(memberType);
|
||
|
return memberType;
|
||
|
}
|
||
|
|
||
|
internal void StoreMember(MemberInfo memberInfo)
|
||
|
{
|
||
|
if (memberInfo.MemberType == MemberTypes.Field)
|
||
|
{
|
||
|
FieldInfo fieldInfo = (FieldInfo)memberInfo;
|
||
|
if (fieldInfo.IsStatic)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Stsfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
|
||
|
ilGen.Emit(OpCodes.Stsfld, fieldInfo);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Stfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
|
||
|
ilGen.Emit(OpCodes.Stfld, fieldInfo);
|
||
|
}
|
||
|
}
|
||
|
else if (memberInfo.MemberType == MemberTypes.Property)
|
||
|
{
|
||
|
PropertyInfo property = memberInfo as PropertyInfo;
|
||
|
if (property != null)
|
||
|
{
|
||
|
MethodInfo setMethod = property.GetSetMethod(true);
|
||
|
if (setMethod == null)
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.NoSetMethodForProperty, property.DeclaringType, property)));
|
||
|
Call(setMethod);
|
||
|
}
|
||
|
}
|
||
|
else if (memberInfo.MemberType == MemberTypes.Method)
|
||
|
Call((MethodInfo)memberInfo);
|
||
|
else
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.CannotLoadMemberType, memberInfo.MemberType)));
|
||
|
}
|
||
|
|
||
|
internal void LoadDefaultValue(Type type)
|
||
|
{
|
||
|
if (type.IsValueType)
|
||
|
{
|
||
|
switch (Type.GetTypeCode(type))
|
||
|
{
|
||
|
case TypeCode.Boolean:
|
||
|
Ldc(false);
|
||
|
break;
|
||
|
case TypeCode.Char:
|
||
|
case TypeCode.SByte:
|
||
|
case TypeCode.Byte:
|
||
|
case TypeCode.Int16:
|
||
|
case TypeCode.UInt16:
|
||
|
case TypeCode.Int32:
|
||
|
case TypeCode.UInt32:
|
||
|
Ldc(0);
|
||
|
break;
|
||
|
case TypeCode.Int64:
|
||
|
case TypeCode.UInt64:
|
||
|
Ldc(0L);
|
||
|
break;
|
||
|
case TypeCode.Single:
|
||
|
Ldc(0.0F);
|
||
|
break;
|
||
|
case TypeCode.Double:
|
||
|
Ldc(0.0);
|
||
|
break;
|
||
|
case TypeCode.Decimal:
|
||
|
case TypeCode.DateTime:
|
||
|
default:
|
||
|
LocalBuilder zero = DeclareLocal(type, "zero");
|
||
|
LoadAddress(zero);
|
||
|
InitObj(type);
|
||
|
Load(zero);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
Load(null);
|
||
|
}
|
||
|
|
||
|
internal void Load(object obj)
|
||
|
{
|
||
|
if (obj == null)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldnull");
|
||
|
ilGen.Emit(OpCodes.Ldnull);
|
||
|
}
|
||
|
else if (obj is ArgBuilder)
|
||
|
Ldarg((ArgBuilder)obj);
|
||
|
else if (obj is LocalBuilder)
|
||
|
Ldloc((LocalBuilder)obj);
|
||
|
else
|
||
|
Ldc(obj);
|
||
|
}
|
||
|
|
||
|
internal void Store(object var)
|
||
|
{
|
||
|
if (var is ArgBuilder)
|
||
|
Starg((ArgBuilder)var);
|
||
|
else if (var is LocalBuilder)
|
||
|
Stloc((LocalBuilder)var);
|
||
|
else
|
||
|
{
|
||
|
Fx.Assert("Data can only be stored into ArgBuilder or LocalBuilder.");
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.CanOnlyStoreIntoArgOrLocGot0, DataContract.GetClrTypeFullName(var.GetType()))));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Dec(object var)
|
||
|
{
|
||
|
Load(var);
|
||
|
Load(1);
|
||
|
Subtract();
|
||
|
Store(var);
|
||
|
}
|
||
|
|
||
|
internal void Inc(object var)
|
||
|
{
|
||
|
Load(var);
|
||
|
Load(1);
|
||
|
Add();
|
||
|
Store(var);
|
||
|
}
|
||
|
|
||
|
internal void LoadAddress(object obj)
|
||
|
{
|
||
|
if (obj is ArgBuilder)
|
||
|
LdargAddress((ArgBuilder)obj);
|
||
|
else if (obj is LocalBuilder)
|
||
|
LdlocAddress((LocalBuilder)obj);
|
||
|
else
|
||
|
Load(obj);
|
||
|
}
|
||
|
|
||
|
|
||
|
internal void ConvertAddress(Type source, Type target)
|
||
|
{
|
||
|
InternalConvert(source, target, true);
|
||
|
}
|
||
|
|
||
|
internal void ConvertValue(Type source, Type target)
|
||
|
{
|
||
|
InternalConvert(source, target, false);
|
||
|
}
|
||
|
|
||
|
|
||
|
internal void Castclass(Type target)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Castclass " + target);
|
||
|
ilGen.Emit(OpCodes.Castclass, target);
|
||
|
}
|
||
|
|
||
|
internal void Box(Type type)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Box " + type);
|
||
|
ilGen.Emit(OpCodes.Box, type);
|
||
|
}
|
||
|
|
||
|
internal void Unbox(Type type)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Unbox " + type);
|
||
|
ilGen.Emit(OpCodes.Unbox, type);
|
||
|
}
|
||
|
|
||
|
OpCode GetLdindOpCode(TypeCode typeCode)
|
||
|
{
|
||
|
switch (typeCode)
|
||
|
{
|
||
|
case TypeCode.Boolean:
|
||
|
return OpCodes.Ldind_I1; // TypeCode.Boolean:
|
||
|
case TypeCode.Char:
|
||
|
return OpCodes.Ldind_I2; // TypeCode.Char:
|
||
|
case TypeCode.SByte:
|
||
|
return OpCodes.Ldind_I1; // TypeCode.SByte:
|
||
|
case TypeCode.Byte:
|
||
|
return OpCodes.Ldind_U1; // TypeCode.Byte:
|
||
|
case TypeCode.Int16:
|
||
|
return OpCodes.Ldind_I2; // TypeCode.Int16:
|
||
|
case TypeCode.UInt16:
|
||
|
return OpCodes.Ldind_U2; // TypeCode.UInt16:
|
||
|
case TypeCode.Int32:
|
||
|
return OpCodes.Ldind_I4; // TypeCode.Int32:
|
||
|
case TypeCode.UInt32:
|
||
|
return OpCodes.Ldind_U4; // TypeCode.UInt32:
|
||
|
case TypeCode.Int64:
|
||
|
return OpCodes.Ldind_I8; // TypeCode.Int64:
|
||
|
case TypeCode.UInt64:
|
||
|
return OpCodes.Ldind_I8; // TypeCode.UInt64:
|
||
|
case TypeCode.Single:
|
||
|
return OpCodes.Ldind_R4; // TypeCode.Single:
|
||
|
case TypeCode.Double:
|
||
|
return OpCodes.Ldind_R8; // TypeCode.Double:
|
||
|
case TypeCode.String:
|
||
|
return OpCodes.Ldind_Ref; // TypeCode.String:
|
||
|
default:
|
||
|
return OpCodes.Nop;
|
||
|
}
|
||
|
//
|
||
|
}
|
||
|
|
||
|
internal void Ldobj(Type type)
|
||
|
{
|
||
|
OpCode opCode = GetLdindOpCode(Type.GetTypeCode(type));
|
||
|
if (!opCode.Equals(OpCodes.Nop))
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction(opCode.ToString());
|
||
|
ilGen.Emit(opCode);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldobj " + type);
|
||
|
ilGen.Emit(OpCodes.Ldobj, type);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Stobj(Type type)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Stobj " + type);
|
||
|
ilGen.Emit(OpCodes.Stobj, type);
|
||
|
}
|
||
|
|
||
|
|
||
|
internal void Ceq()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ceq");
|
||
|
ilGen.Emit(OpCodes.Ceq);
|
||
|
}
|
||
|
|
||
|
internal void Bgt(Label label)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Bgt " + label.GetHashCode());
|
||
|
ilGen.Emit(OpCodes.Bgt, label);
|
||
|
}
|
||
|
|
||
|
internal void Ble(Label label)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ble " + label.GetHashCode());
|
||
|
ilGen.Emit(OpCodes.Ble, label);
|
||
|
}
|
||
|
|
||
|
internal void Throw()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Throw");
|
||
|
ilGen.Emit(OpCodes.Throw);
|
||
|
}
|
||
|
|
||
|
internal void Ldtoken(Type t)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldtoken " + t);
|
||
|
ilGen.Emit(OpCodes.Ldtoken, t);
|
||
|
}
|
||
|
|
||
|
internal void Ldc(object o)
|
||
|
{
|
||
|
Type valueType = o.GetType();
|
||
|
if (o is Type)
|
||
|
{
|
||
|
Ldtoken((Type)o);
|
||
|
Call(GetTypeFromHandle);
|
||
|
}
|
||
|
else if (valueType.IsEnum)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceComment("Ldc " + o.GetType() + "." + o);
|
||
|
Ldc(((IConvertible)o).ToType(Enum.GetUnderlyingType(valueType), null));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
switch (Type.GetTypeCode(valueType))
|
||
|
{
|
||
|
case TypeCode.Boolean:
|
||
|
Ldc((bool)o);
|
||
|
break;
|
||
|
case TypeCode.Char:
|
||
|
Fx.Assert("Char is not a valid schema primitive and should be treated as int in DataContract");
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.CharIsInvalidPrimitive)));
|
||
|
case TypeCode.SByte:
|
||
|
case TypeCode.Byte:
|
||
|
case TypeCode.Int16:
|
||
|
case TypeCode.UInt16:
|
||
|
Ldc(((IConvertible)o).ToInt32(CultureInfo.InvariantCulture));
|
||
|
break;
|
||
|
case TypeCode.Int32:
|
||
|
Ldc((int)o);
|
||
|
break;
|
||
|
case TypeCode.UInt32:
|
||
|
Ldc((int)(uint)o);
|
||
|
break;
|
||
|
case TypeCode.UInt64:
|
||
|
Ldc((long)(ulong)o);
|
||
|
break;
|
||
|
case TypeCode.Int64:
|
||
|
Ldc((long)o);
|
||
|
break;
|
||
|
case TypeCode.Single:
|
||
|
Ldc((float)o);
|
||
|
break;
|
||
|
case TypeCode.Double:
|
||
|
Ldc((double)o);
|
||
|
break;
|
||
|
case TypeCode.String:
|
||
|
Ldstr((string)o);
|
||
|
break;
|
||
|
case TypeCode.Object:
|
||
|
case TypeCode.Decimal:
|
||
|
case TypeCode.DateTime:
|
||
|
case TypeCode.Empty:
|
||
|
case TypeCode.DBNull:
|
||
|
default:
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.UnknownConstantType, DataContract.GetClrTypeFullName(valueType))));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Ldc(bool boolVar)
|
||
|
{
|
||
|
if (boolVar)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldc.i4 1");
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldc.i4 0");
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Ldc(int intVar)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldc.i4 " + intVar);
|
||
|
switch (intVar)
|
||
|
{
|
||
|
case -1:
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_M1);
|
||
|
break;
|
||
|
case 0:
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_0);
|
||
|
break;
|
||
|
case 1:
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_1);
|
||
|
break;
|
||
|
case 2:
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_2);
|
||
|
break;
|
||
|
case 3:
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_3);
|
||
|
break;
|
||
|
case 4:
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_4);
|
||
|
break;
|
||
|
case 5:
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_5);
|
||
|
break;
|
||
|
case 6:
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_6);
|
||
|
break;
|
||
|
case 7:
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_7);
|
||
|
break;
|
||
|
case 8:
|
||
|
ilGen.Emit(OpCodes.Ldc_I4_8);
|
||
|
break;
|
||
|
default:
|
||
|
ilGen.Emit(OpCodes.Ldc_I4, intVar);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Ldc(long l)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldc.i8 " + l);
|
||
|
ilGen.Emit(OpCodes.Ldc_I8, l);
|
||
|
}
|
||
|
|
||
|
internal void Ldc(float f)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldc.r4 " + f);
|
||
|
ilGen.Emit(OpCodes.Ldc_R4, f);
|
||
|
}
|
||
|
|
||
|
internal void Ldc(double d)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldc.r8 " + d);
|
||
|
ilGen.Emit(OpCodes.Ldc_R8, d);
|
||
|
}
|
||
|
|
||
|
internal void Ldstr(string strVar)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldstr " + strVar);
|
||
|
ilGen.Emit(OpCodes.Ldstr, strVar);
|
||
|
}
|
||
|
|
||
|
internal void LdlocAddress(LocalBuilder localBuilder)
|
||
|
{
|
||
|
if (localBuilder.LocalType.IsValueType)
|
||
|
Ldloca(localBuilder);
|
||
|
else
|
||
|
Ldloc(localBuilder);
|
||
|
}
|
||
|
|
||
|
internal void Ldloc(LocalBuilder localBuilder)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldloc " + LocalNames[localBuilder]);
|
||
|
ilGen.Emit(OpCodes.Ldloc, localBuilder);
|
||
|
EmitStackTop(localBuilder.LocalType);
|
||
|
}
|
||
|
|
||
|
internal void Stloc(LocalBuilder local)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Stloc " + LocalNames[local]);
|
||
|
EmitStackTop(local.LocalType);
|
||
|
ilGen.Emit(OpCodes.Stloc, local);
|
||
|
}
|
||
|
|
||
|
internal void Ldloc(int slot)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldloc " + slot);
|
||
|
|
||
|
switch (slot)
|
||
|
{
|
||
|
case 0:
|
||
|
ilGen.Emit(OpCodes.Ldloc_0);
|
||
|
break;
|
||
|
case 1:
|
||
|
ilGen.Emit(OpCodes.Ldloc_1);
|
||
|
break;
|
||
|
case 2:
|
||
|
ilGen.Emit(OpCodes.Ldloc_2);
|
||
|
break;
|
||
|
case 3:
|
||
|
ilGen.Emit(OpCodes.Ldloc_3);
|
||
|
break;
|
||
|
default:
|
||
|
if (slot <= 255)
|
||
|
ilGen.Emit(OpCodes.Ldloc_S, slot);
|
||
|
else
|
||
|
ilGen.Emit(OpCodes.Ldloc, slot);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Stloc(int slot)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Stloc " + slot);
|
||
|
switch (slot)
|
||
|
{
|
||
|
case 0:
|
||
|
ilGen.Emit(OpCodes.Stloc_0);
|
||
|
break;
|
||
|
case 1:
|
||
|
ilGen.Emit(OpCodes.Stloc_1);
|
||
|
break;
|
||
|
case 2:
|
||
|
ilGen.Emit(OpCodes.Stloc_2);
|
||
|
break;
|
||
|
case 3:
|
||
|
ilGen.Emit(OpCodes.Stloc_3);
|
||
|
break;
|
||
|
default:
|
||
|
if (slot <= 255)
|
||
|
ilGen.Emit(OpCodes.Stloc_S, slot);
|
||
|
else
|
||
|
ilGen.Emit(OpCodes.Stloc, slot);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Ldloca(LocalBuilder localBuilder)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldloca " + LocalNames[localBuilder]);
|
||
|
ilGen.Emit(OpCodes.Ldloca, localBuilder);
|
||
|
EmitStackTop(localBuilder.LocalType);
|
||
|
}
|
||
|
|
||
|
internal void Ldloca(int slot)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldloca " + slot);
|
||
|
if (slot <= 255)
|
||
|
ilGen.Emit(OpCodes.Ldloca_S, slot);
|
||
|
else
|
||
|
ilGen.Emit(OpCodes.Ldloca, slot);
|
||
|
}
|
||
|
|
||
|
internal void LdargAddress(ArgBuilder argBuilder)
|
||
|
{
|
||
|
if (argBuilder.ArgType.IsValueType)
|
||
|
Ldarga(argBuilder);
|
||
|
else
|
||
|
Ldarg(argBuilder);
|
||
|
}
|
||
|
|
||
|
internal void Ldarg(ArgBuilder arg)
|
||
|
{
|
||
|
Ldarg(arg.Index);
|
||
|
}
|
||
|
|
||
|
internal void Starg(ArgBuilder arg)
|
||
|
{
|
||
|
Starg(arg.Index);
|
||
|
}
|
||
|
|
||
|
internal void Ldarg(int slot)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldarg " + slot);
|
||
|
switch (slot)
|
||
|
{
|
||
|
case 0:
|
||
|
ilGen.Emit(OpCodes.Ldarg_0);
|
||
|
break;
|
||
|
case 1:
|
||
|
ilGen.Emit(OpCodes.Ldarg_1);
|
||
|
break;
|
||
|
case 2:
|
||
|
ilGen.Emit(OpCodes.Ldarg_2);
|
||
|
break;
|
||
|
case 3:
|
||
|
ilGen.Emit(OpCodes.Ldarg_3);
|
||
|
break;
|
||
|
default:
|
||
|
if (slot <= 255)
|
||
|
ilGen.Emit(OpCodes.Ldarg_S, slot);
|
||
|
else
|
||
|
ilGen.Emit(OpCodes.Ldarg, slot);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Starg(int slot)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Starg " + slot);
|
||
|
if (slot <= 255)
|
||
|
ilGen.Emit(OpCodes.Starg_S, slot);
|
||
|
else
|
||
|
ilGen.Emit(OpCodes.Starg, slot);
|
||
|
}
|
||
|
|
||
|
internal void Ldarga(ArgBuilder argBuilder)
|
||
|
{
|
||
|
Ldarga(argBuilder.Index);
|
||
|
}
|
||
|
|
||
|
internal void Ldarga(int slot)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldarga " + slot);
|
||
|
if (slot <= 255)
|
||
|
ilGen.Emit(OpCodes.Ldarga_S, slot);
|
||
|
else
|
||
|
ilGen.Emit(OpCodes.Ldarga, slot);
|
||
|
}
|
||
|
|
||
|
internal void Ldlen()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldlen");
|
||
|
ilGen.Emit(OpCodes.Ldlen);
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Conv.i4");
|
||
|
ilGen.Emit(OpCodes.Conv_I4);
|
||
|
}
|
||
|
|
||
|
OpCode GetLdelemOpCode(TypeCode typeCode)
|
||
|
{
|
||
|
switch (typeCode)
|
||
|
{
|
||
|
case TypeCode.Object:
|
||
|
case TypeCode.DBNull:
|
||
|
return OpCodes.Ldelem_Ref; // TypeCode.Object:
|
||
|
case TypeCode.Boolean:
|
||
|
return OpCodes.Ldelem_I1; // TypeCode.Boolean:
|
||
|
case TypeCode.Char:
|
||
|
return OpCodes.Ldelem_I2; // TypeCode.Char:
|
||
|
case TypeCode.SByte:
|
||
|
return OpCodes.Ldelem_I1; // TypeCode.SByte:
|
||
|
case TypeCode.Byte:
|
||
|
return OpCodes.Ldelem_U1; // TypeCode.Byte:
|
||
|
case TypeCode.Int16:
|
||
|
return OpCodes.Ldelem_I2; // TypeCode.Int16:
|
||
|
case TypeCode.UInt16:
|
||
|
return OpCodes.Ldelem_U2; // TypeCode.UInt16:
|
||
|
case TypeCode.Int32:
|
||
|
return OpCodes.Ldelem_I4; // TypeCode.Int32:
|
||
|
case TypeCode.UInt32:
|
||
|
return OpCodes.Ldelem_U4; // TypeCode.UInt32:
|
||
|
case TypeCode.Int64:
|
||
|
return OpCodes.Ldelem_I8; // TypeCode.Int64:
|
||
|
case TypeCode.UInt64:
|
||
|
return OpCodes.Ldelem_I8; // TypeCode.UInt64:
|
||
|
case TypeCode.Single:
|
||
|
return OpCodes.Ldelem_R4; // TypeCode.Single:
|
||
|
case TypeCode.Double:
|
||
|
return OpCodes.Ldelem_R8; // TypeCode.Double:
|
||
|
case TypeCode.String:
|
||
|
return OpCodes.Ldelem_Ref; // TypeCode.String:
|
||
|
default:
|
||
|
return OpCodes.Nop;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Ldelem(Type arrayElementType)
|
||
|
{
|
||
|
if (arrayElementType.IsEnum)
|
||
|
{
|
||
|
Ldelem(Enum.GetUnderlyingType(arrayElementType));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
OpCode opCode = GetLdelemOpCode(Type.GetTypeCode(arrayElementType));
|
||
|
if (opCode.Equals(OpCodes.Nop))
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArrayTypeIsNotSupported, DataContract.GetClrTypeFullName(arrayElementType))));
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction(opCode.ToString());
|
||
|
ilGen.Emit(opCode);
|
||
|
EmitStackTop(arrayElementType);
|
||
|
}
|
||
|
}
|
||
|
internal void Ldelema(Type arrayElementType)
|
||
|
{
|
||
|
OpCode opCode = OpCodes.Ldelema;
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction(opCode.ToString());
|
||
|
ilGen.Emit(opCode, arrayElementType);
|
||
|
|
||
|
EmitStackTop(arrayElementType);
|
||
|
}
|
||
|
|
||
|
OpCode GetStelemOpCode(TypeCode typeCode)
|
||
|
{
|
||
|
switch (typeCode)
|
||
|
{
|
||
|
case TypeCode.Object:
|
||
|
case TypeCode.DBNull:
|
||
|
return OpCodes.Stelem_Ref; // TypeCode.Object:
|
||
|
case TypeCode.Boolean:
|
||
|
return OpCodes.Stelem_I1; // TypeCode.Boolean:
|
||
|
case TypeCode.Char:
|
||
|
return OpCodes.Stelem_I2; // TypeCode.Char:
|
||
|
case TypeCode.SByte:
|
||
|
return OpCodes.Stelem_I1; // TypeCode.SByte:
|
||
|
case TypeCode.Byte:
|
||
|
return OpCodes.Stelem_I1; // TypeCode.Byte:
|
||
|
case TypeCode.Int16:
|
||
|
return OpCodes.Stelem_I2; // TypeCode.Int16:
|
||
|
case TypeCode.UInt16:
|
||
|
return OpCodes.Stelem_I2; // TypeCode.UInt16:
|
||
|
case TypeCode.Int32:
|
||
|
return OpCodes.Stelem_I4; // TypeCode.Int32:
|
||
|
case TypeCode.UInt32:
|
||
|
return OpCodes.Stelem_I4; // TypeCode.UInt32:
|
||
|
case TypeCode.Int64:
|
||
|
return OpCodes.Stelem_I8; // TypeCode.Int64:
|
||
|
case TypeCode.UInt64:
|
||
|
return OpCodes.Stelem_I8; // TypeCode.UInt64:
|
||
|
case TypeCode.Single:
|
||
|
return OpCodes.Stelem_R4; // TypeCode.Single:
|
||
|
case TypeCode.Double:
|
||
|
return OpCodes.Stelem_R8; // TypeCode.Double:
|
||
|
case TypeCode.String:
|
||
|
return OpCodes.Stelem_Ref; // TypeCode.String:
|
||
|
default:
|
||
|
return OpCodes.Nop;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Stelem(Type arrayElementType)
|
||
|
{
|
||
|
if (arrayElementType.IsEnum)
|
||
|
Stelem(Enum.GetUnderlyingType(arrayElementType));
|
||
|
else
|
||
|
{
|
||
|
OpCode opCode = GetStelemOpCode(Type.GetTypeCode(arrayElementType));
|
||
|
if (opCode.Equals(OpCodes.Nop))
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArrayTypeIsNotSupported, DataContract.GetClrTypeFullName(arrayElementType))));
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction(opCode.ToString());
|
||
|
EmitStackTop(arrayElementType);
|
||
|
ilGen.Emit(opCode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal Label DefineLabel()
|
||
|
{
|
||
|
return ilGen.DefineLabel();
|
||
|
}
|
||
|
|
||
|
internal void MarkLabel(Label label)
|
||
|
{
|
||
|
ilGen.MarkLabel(label);
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceLabel(label.GetHashCode() + ":");
|
||
|
}
|
||
|
|
||
|
internal void Add()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Add");
|
||
|
ilGen.Emit(OpCodes.Add);
|
||
|
}
|
||
|
|
||
|
internal void Subtract()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Sub");
|
||
|
ilGen.Emit(OpCodes.Sub);
|
||
|
}
|
||
|
|
||
|
internal void And()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("And");
|
||
|
ilGen.Emit(OpCodes.And);
|
||
|
}
|
||
|
internal void Or()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Or");
|
||
|
ilGen.Emit(OpCodes.Or);
|
||
|
}
|
||
|
|
||
|
internal void Not()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Not");
|
||
|
ilGen.Emit(OpCodes.Not);
|
||
|
}
|
||
|
|
||
|
internal void Ret()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ret");
|
||
|
ilGen.Emit(OpCodes.Ret);
|
||
|
}
|
||
|
|
||
|
internal void Br(Label label)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Br " + label.GetHashCode());
|
||
|
ilGen.Emit(OpCodes.Br, label);
|
||
|
}
|
||
|
|
||
|
internal void Blt(Label label)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Blt " + label.GetHashCode());
|
||
|
ilGen.Emit(OpCodes.Blt, label);
|
||
|
}
|
||
|
|
||
|
internal void Brfalse(Label label)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Brfalse " + label.GetHashCode());
|
||
|
ilGen.Emit(OpCodes.Brfalse, label);
|
||
|
}
|
||
|
|
||
|
internal void Brtrue(Label label)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Brtrue " + label.GetHashCode());
|
||
|
ilGen.Emit(OpCodes.Brtrue, label);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
internal void Pop()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Pop");
|
||
|
ilGen.Emit(OpCodes.Pop);
|
||
|
}
|
||
|
|
||
|
internal void Dup()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Dup");
|
||
|
ilGen.Emit(OpCodes.Dup);
|
||
|
}
|
||
|
|
||
|
void LoadThis(object thisObj, MethodInfo methodInfo)
|
||
|
{
|
||
|
if (thisObj != null && !methodInfo.IsStatic)
|
||
|
{
|
||
|
LoadAddress(thisObj);
|
||
|
ConvertAddress(GetVariableType(thisObj), methodInfo.DeclaringType);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void LoadParam(object arg, int oneBasedArgIndex, MethodBase methodInfo)
|
||
|
{
|
||
|
Load(arg);
|
||
|
if (arg != null)
|
||
|
ConvertValue(GetVariableType(arg), methodInfo.GetParameters()[oneBasedArgIndex - 1].ParameterType);
|
||
|
}
|
||
|
|
||
|
void InternalIf(bool negate)
|
||
|
{
|
||
|
IfState ifState = new IfState();
|
||
|
ifState.EndIf = DefineLabel();
|
||
|
ifState.ElseBegin = DefineLabel();
|
||
|
if (negate)
|
||
|
Brtrue(ifState.ElseBegin);
|
||
|
else
|
||
|
Brfalse(ifState.ElseBegin);
|
||
|
blockStack.Push(ifState);
|
||
|
}
|
||
|
|
||
|
OpCode GetConvOpCode(TypeCode typeCode)
|
||
|
{
|
||
|
switch (typeCode)
|
||
|
{
|
||
|
case TypeCode.Boolean:
|
||
|
return OpCodes.Conv_I1; // TypeCode.Boolean:
|
||
|
case TypeCode.Char:
|
||
|
return OpCodes.Conv_I2; // TypeCode.Char:
|
||
|
case TypeCode.SByte:
|
||
|
return OpCodes.Conv_I1; // TypeCode.SByte:
|
||
|
case TypeCode.Byte:
|
||
|
return OpCodes.Conv_U1; // TypeCode.Byte:
|
||
|
case TypeCode.Int16:
|
||
|
return OpCodes.Conv_I2; // TypeCode.Int16:
|
||
|
case TypeCode.UInt16:
|
||
|
return OpCodes.Conv_U2; // TypeCode.UInt16:
|
||
|
case TypeCode.Int32:
|
||
|
return OpCodes.Conv_I4; // TypeCode.Int32:
|
||
|
case TypeCode.UInt32:
|
||
|
return OpCodes.Conv_U4; // TypeCode.UInt32:
|
||
|
case TypeCode.Int64:
|
||
|
return OpCodes.Conv_I8; // TypeCode.Int64:
|
||
|
case TypeCode.UInt64:
|
||
|
return OpCodes.Conv_I8; // TypeCode.UInt64:
|
||
|
case TypeCode.Single:
|
||
|
return OpCodes.Conv_R4; // TypeCode.Single:
|
||
|
case TypeCode.Double:
|
||
|
return OpCodes.Conv_R8; // TypeCode.Double:
|
||
|
default:
|
||
|
return OpCodes.Nop;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void InternalConvert(Type source, Type target, bool isAddress)
|
||
|
{
|
||
|
if (target == source)
|
||
|
return;
|
||
|
if (target.IsValueType)
|
||
|
{
|
||
|
if (source.IsValueType)
|
||
|
{
|
||
|
OpCode opCode = GetConvOpCode(Type.GetTypeCode(target));
|
||
|
if (opCode.Equals(OpCodes.Nop))
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.NoConversionPossibleTo, DataContract.GetClrTypeFullName(target))));
|
||
|
else
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction(opCode.ToString());
|
||
|
ilGen.Emit(opCode);
|
||
|
}
|
||
|
}
|
||
|
else if (source.IsAssignableFrom(target))
|
||
|
{
|
||
|
Unbox(target);
|
||
|
if (!isAddress)
|
||
|
Ldobj(target);
|
||
|
}
|
||
|
else
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.IsNotAssignableFrom, DataContract.GetClrTypeFullName(target), DataContract.GetClrTypeFullName(source))));
|
||
|
}
|
||
|
else if (target.IsAssignableFrom(source))
|
||
|
{
|
||
|
if (source.IsValueType)
|
||
|
{
|
||
|
if (isAddress)
|
||
|
Ldobj(source);
|
||
|
Box(source);
|
||
|
}
|
||
|
}
|
||
|
else if (source.IsAssignableFrom(target))
|
||
|
{
|
||
|
//assert(source.IsValueType == false);
|
||
|
Castclass(target);
|
||
|
}
|
||
|
else if (target.IsInterface || source.IsInterface)
|
||
|
{
|
||
|
Castclass(target);
|
||
|
}
|
||
|
else
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.IsNotAssignableFrom, DataContract.GetClrTypeFullName(target), DataContract.GetClrTypeFullName(source))));
|
||
|
}
|
||
|
|
||
|
IfState PopIfState()
|
||
|
{
|
||
|
object stackTop = blockStack.Pop();
|
||
|
IfState ifState = stackTop as IfState;
|
||
|
if (ifState == null)
|
||
|
ThrowMismatchException(stackTop);
|
||
|
return ifState;
|
||
|
}
|
||
|
|
||
|
#if USE_REFEMIT
|
||
|
void InitAssemblyBuilder(string methodName)
|
||
|
{
|
||
|
AssemblyName name = new AssemblyName();
|
||
|
name.Name = "Microsoft.GeneratedCode."+methodName;
|
||
|
assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
|
||
|
moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name, name.Name + ".dll", false);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void ThrowMismatchException(object expected)
|
||
|
{
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ExpectingEnd, expected.ToString())));
|
||
|
}
|
||
|
|
||
|
Hashtable LocalNames
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (localNames == null)
|
||
|
localNames = new Hashtable();
|
||
|
return localNames;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void EmitSourceInstruction(string line)
|
||
|
{
|
||
|
EmitSourceLine(" " + line);
|
||
|
}
|
||
|
|
||
|
internal void EmitSourceLabel(string line)
|
||
|
{
|
||
|
EmitSourceLine(line);
|
||
|
}
|
||
|
|
||
|
internal void EmitSourceComment(string comment)
|
||
|
{
|
||
|
EmitSourceInstruction("// " + comment);
|
||
|
}
|
||
|
|
||
|
internal void EmitSourceLine(string line)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
SerializationTrace.WriteInstruction(lineNo++, line);
|
||
|
if (ilGen != null && codeGenTrace == CodeGenTrace.Tron)
|
||
|
{
|
||
|
ilGen.Emit(OpCodes.Ldstr, string.Format(CultureInfo.InvariantCulture, "{0:00000}: {1}", lineNo - 1, line));
|
||
|
ilGen.Emit(OpCodes.Call, XmlFormatGeneratorStatics.TraceInstructionMethod);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void EmitStackTop(Type stackTopType)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.Tron)
|
||
|
return;
|
||
|
codeGenTrace = CodeGenTrace.None;
|
||
|
Dup();
|
||
|
ToDebuggableString(stackTopType);
|
||
|
LocalBuilder topValue = DeclareLocal(Globals.TypeOfString, "topValue");
|
||
|
Store(topValue);
|
||
|
Load("//value = ");
|
||
|
Load(topValue);
|
||
|
Concat2();
|
||
|
Call(XmlFormatGeneratorStatics.TraceInstructionMethod);
|
||
|
codeGenTrace = CodeGenTrace.Tron;
|
||
|
}
|
||
|
|
||
|
internal void ToString(Type type)
|
||
|
{
|
||
|
if (type != Globals.TypeOfString)
|
||
|
{
|
||
|
if (type.IsValueType)
|
||
|
{
|
||
|
Box(type);
|
||
|
}
|
||
|
Call(ObjectToString);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void ToDebuggableString(Type type)
|
||
|
{
|
||
|
if (type.IsValueType)
|
||
|
{
|
||
|
Box(type);
|
||
|
Call(ObjectToString);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Dup();
|
||
|
Load(null);
|
||
|
If(Cmp.EqualTo);
|
||
|
Pop();
|
||
|
Load("<null>");
|
||
|
Else();
|
||
|
if (type.IsArray)
|
||
|
{
|
||
|
LocalBuilder arrayVar = DeclareLocal(type, "arrayVar");
|
||
|
Store(arrayVar);
|
||
|
Load("{ ");
|
||
|
LocalBuilder arrayValueString = DeclareLocal(typeof(string), "arrayValueString");
|
||
|
Store(arrayValueString);
|
||
|
LocalBuilder i = DeclareLocal(typeof(int), "i");
|
||
|
For(i, 0, arrayVar);
|
||
|
Load(arrayValueString);
|
||
|
LoadArrayElement(arrayVar, i);
|
||
|
ToDebuggableString(arrayVar.LocalType.GetElementType());
|
||
|
Load(", ");
|
||
|
Concat3();
|
||
|
Store(arrayValueString);
|
||
|
EndFor();
|
||
|
Load(arrayValueString);
|
||
|
Load("}");
|
||
|
Concat2();
|
||
|
}
|
||
|
else
|
||
|
Call(ObjectToString);
|
||
|
EndIf();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Concat2()
|
||
|
{
|
||
|
Call(StringConcat2);
|
||
|
}
|
||
|
|
||
|
internal void Concat3()
|
||
|
{
|
||
|
Call(StringConcat3);
|
||
|
}
|
||
|
|
||
|
internal Label[] Switch(int labelCount)
|
||
|
{
|
||
|
SwitchState switchState = new SwitchState(DefineLabel(), DefineLabel());
|
||
|
Label[] caseLabels = new Label[labelCount];
|
||
|
for (int i = 0; i < caseLabels.Length; i++)
|
||
|
caseLabels[i] = DefineLabel();
|
||
|
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
{
|
||
|
EmitSourceInstruction("switch (");
|
||
|
foreach (Label l in caseLabels)
|
||
|
EmitSourceInstruction(" " + l.GetHashCode());
|
||
|
EmitSourceInstruction(") {");
|
||
|
}
|
||
|
ilGen.Emit(OpCodes.Switch, caseLabels);
|
||
|
Br(switchState.DefaultLabel);
|
||
|
blockStack.Push(switchState);
|
||
|
return caseLabels;
|
||
|
}
|
||
|
internal void Case(Label caseLabel1, string caseLabelName)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("case " + caseLabelName + "{");
|
||
|
MarkLabel(caseLabel1);
|
||
|
}
|
||
|
|
||
|
internal void EndCase()
|
||
|
{
|
||
|
object stackTop = blockStack.Peek();
|
||
|
SwitchState switchState = stackTop as SwitchState;
|
||
|
if (switchState == null)
|
||
|
ThrowMismatchException(stackTop);
|
||
|
Br(switchState.EndOfSwitchLabel);
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("} //end case ");
|
||
|
}
|
||
|
|
||
|
internal void DefaultCase()
|
||
|
{
|
||
|
object stackTop = blockStack.Peek();
|
||
|
SwitchState switchState = stackTop as SwitchState;
|
||
|
if (switchState == null)
|
||
|
ThrowMismatchException(stackTop);
|
||
|
MarkLabel(switchState.DefaultLabel);
|
||
|
switchState.DefaultDefined = true;
|
||
|
}
|
||
|
|
||
|
internal void EndSwitch()
|
||
|
{
|
||
|
object stackTop = blockStack.Pop();
|
||
|
SwitchState switchState = stackTop as SwitchState;
|
||
|
if (switchState == null)
|
||
|
ThrowMismatchException(stackTop);
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("} //end switch");
|
||
|
if (!switchState.DefaultDefined)
|
||
|
MarkLabel(switchState.DefaultLabel);
|
||
|
MarkLabel(switchState.EndOfSwitchLabel);
|
||
|
}
|
||
|
|
||
|
internal void CallStringFormat(string msg, params object[] values)
|
||
|
{
|
||
|
NewArray(typeof(object), values.Length);
|
||
|
if (stringFormatArray == null)
|
||
|
stringFormatArray = DeclareLocal(typeof(object[]), "stringFormatArray");
|
||
|
Stloc(stringFormatArray);
|
||
|
for (int i = 0; i < values.Length; i++)
|
||
|
StoreArrayElement(stringFormatArray, i, values[i]);
|
||
|
|
||
|
Load(msg);
|
||
|
Load(stringFormatArray);
|
||
|
Call(StringFormat);
|
||
|
}
|
||
|
|
||
|
static MethodInfo stringLength = typeof(string).GetProperty("Length").GetGetMethod();
|
||
|
internal void ElseIfIsEmptyString(LocalBuilder strLocal)
|
||
|
{
|
||
|
IfState ifState = (IfState)blockStack.Pop();
|
||
|
Br(ifState.EndIf);
|
||
|
MarkLabel(ifState.ElseBegin);
|
||
|
|
||
|
Load(strLocal);
|
||
|
Call(stringLength);
|
||
|
Load(0);
|
||
|
ifState.ElseBegin = DefineLabel();
|
||
|
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Branch if " + GetCmpInverse(Cmp.EqualTo).ToString() + " to " + ifState.ElseBegin.GetHashCode().ToString(NumberFormatInfo.InvariantInfo));
|
||
|
|
||
|
ilGen.Emit(GetBranchCode(Cmp.EqualTo), ifState.ElseBegin);
|
||
|
blockStack.Push(ifState);
|
||
|
}
|
||
|
|
||
|
internal void IfNotIsEmptyString(LocalBuilder strLocal)
|
||
|
{
|
||
|
Load(strLocal);
|
||
|
Call(stringLength);
|
||
|
Load(0);
|
||
|
If(Cmp.NotEqualTo);
|
||
|
}
|
||
|
|
||
|
internal void BeginWhileCondition()
|
||
|
{
|
||
|
Label startWhile = DefineLabel();
|
||
|
MarkLabel(startWhile);
|
||
|
blockStack.Push(startWhile);
|
||
|
}
|
||
|
|
||
|
internal void BeginWhileBody(Cmp cmpOp)
|
||
|
{
|
||
|
Label startWhile = (Label)blockStack.Pop();
|
||
|
If(cmpOp);
|
||
|
blockStack.Push(startWhile);
|
||
|
}
|
||
|
|
||
|
internal void EndWhile()
|
||
|
{
|
||
|
Label startWhile = (Label)blockStack.Pop();
|
||
|
Br(startWhile);
|
||
|
EndIf();
|
||
|
}
|
||
|
|
||
|
#if NotUsed
|
||
|
static MethodInfo stringCompare = typeof(string).GetMethod("Compare", new Type[] { typeof(string), typeof(string) });
|
||
|
internal void ElseIfString(object s1, Cmp cmpOp, object s2)
|
||
|
{
|
||
|
IfState ifState = (IfState)blockStack.Pop();
|
||
|
Br(ifState.EndIf);
|
||
|
MarkLabel(ifState.ElseBegin);
|
||
|
|
||
|
Load(s1);
|
||
|
Load(s2);
|
||
|
Call(stringCompare);
|
||
|
Load(0);
|
||
|
ifState.ElseBegin = DefineLabel();
|
||
|
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Branch if " + GetCmpInverse(cmpOp).ToString() + " to " + ifState.ElseBegin.GetHashCode().ToString(NumberFormatInfo.InvariantInfo));
|
||
|
|
||
|
ilGen.Emit(GetBranchCode(cmpOp), ifState.ElseBegin);
|
||
|
blockStack.Push(ifState);
|
||
|
}
|
||
|
|
||
|
internal void IfString(object s1, Cmp cmpOp, object s2)
|
||
|
{
|
||
|
Load(s1);
|
||
|
Load(s2);
|
||
|
Call(stringCompare);
|
||
|
Load(0);
|
||
|
If(cmpOp);
|
||
|
}
|
||
|
|
||
|
static MethodInfo stringEquals = typeof(string).GetMethod("Equals", new Type[]{ typeof(string), typeof(string)});
|
||
|
static ConstructorInfo permissionSetCtor = typeof(PermissionSet).GetConstructor(new Type[]{ typeof(PermissionState)});
|
||
|
static MethodInfo permissionSetDemand = typeof(PermissionSet).GetMethod("Demand", new Type[0]);
|
||
|
|
||
|
internal void AndIf(Cmp cmpOp)
|
||
|
{
|
||
|
IfState ifState = (IfState) blockStack.Peek();
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Branch if " + CmpInverse[(int) cmpOp].ToString() + " to " + ifState.ElseBegin.GetHashCode().ToString());
|
||
|
ilGen.Emit(BranchCode[(int)cmpOp], ifState.ElseBegin);
|
||
|
}
|
||
|
|
||
|
internal void AndIf()
|
||
|
{
|
||
|
IfState ifState = (IfState) blockStack.Peek();
|
||
|
Brfalse(ifState.ElseBegin);
|
||
|
}
|
||
|
internal void ElseIf(object boolVal)
|
||
|
{
|
||
|
InternalElseIf(boolVal, false);
|
||
|
}
|
||
|
void InternalElseIf(object boolVal, bool negate)
|
||
|
{
|
||
|
IfState ifState = (IfState)blockStack.Pop();
|
||
|
Br(ifState.EndIf);
|
||
|
MarkLabel(ifState.ElseBegin);
|
||
|
|
||
|
Load(boolVal);
|
||
|
ifState.ElseBegin = DefineLabel();
|
||
|
if (negate)
|
||
|
Brtrue(ifState.ElseBegin);
|
||
|
else
|
||
|
Brfalse(ifState.ElseBegin);
|
||
|
blockStack.Push(ifState);
|
||
|
}
|
||
|
|
||
|
internal void While(object value1, Cmp cmpOp, object value2)
|
||
|
{
|
||
|
IfState ifState = new IfState();
|
||
|
ifState.EndIf = DefineLabel();
|
||
|
ifState.ElseBegin = DefineLabel();
|
||
|
ilGen.MarkLabel(ifState.ElseBegin);
|
||
|
Load(value1);
|
||
|
Load(value2);
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Branch if " + CmpInverse[(int) cmpOp].ToString() + " to " + ifState.ElseBegin.GetHashCode().ToString());
|
||
|
ilGen.Emit(BranchCode[(int)cmpOp], ifState.EndIf);
|
||
|
blockStack.Push(ifState);
|
||
|
}
|
||
|
|
||
|
internal void EndWhile()
|
||
|
{
|
||
|
IfState ifState = PopIfState();
|
||
|
Br(ifState.ElseBegin);
|
||
|
MarkLabel(ifState.EndIf);
|
||
|
}
|
||
|
|
||
|
internal void ElseIfNot(object boolVal)
|
||
|
{
|
||
|
InternalElseIf(boolVal, true);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
internal void Ldc(long l)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldc.i8 " + l);
|
||
|
ilGen.Emit(OpCodes.Ldc_I8, l);
|
||
|
}
|
||
|
|
||
|
internal void Ldc(float f)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldc.r4 " + f);
|
||
|
ilGen.Emit(OpCodes.Ldc_R4, f);
|
||
|
}
|
||
|
|
||
|
internal void Ldc(double d)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Ldc.r8 " + d);
|
||
|
ilGen.Emit(OpCodes.Ldc_R8, d);
|
||
|
}
|
||
|
|
||
|
internal void IsInst(Type type)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("IsInst " + DataContract.GetClrTypeFullName(type));
|
||
|
ilGen.Emit(OpCodes.Isinst, type);
|
||
|
}
|
||
|
|
||
|
internal void Clt()
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Clt");
|
||
|
ilGen.Emit(OpCodes.Clt);
|
||
|
}
|
||
|
|
||
|
internal void StringEquals()
|
||
|
{
|
||
|
Call(stringEquals);
|
||
|
}
|
||
|
|
||
|
internal void StringEquals(object s1, object s2)
|
||
|
{
|
||
|
Load(s1);
|
||
|
ConvertValue(GetVariableType(s1), typeof(string));
|
||
|
Load(s2);
|
||
|
ConvertValue(GetVariableType(s2), typeof(string));
|
||
|
StringEquals();
|
||
|
}
|
||
|
|
||
|
internal void Bge(Label label)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Bge " + label.GetHashCode());
|
||
|
ilGen.Emit(OpCodes.Bge, label);
|
||
|
}
|
||
|
|
||
|
internal void Beq(Label label)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Beq " + label.GetHashCode());
|
||
|
ilGen.Emit(OpCodes.Beq, label);
|
||
|
}
|
||
|
|
||
|
internal void Bne(Label label)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Bne " + label.GetHashCode());
|
||
|
ilGen.Emit(OpCodes.Bne_Un, label);
|
||
|
}
|
||
|
internal void ResizeArray(object arrayVar, object sizeVar)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceComment("ResizeArray() {");
|
||
|
|
||
|
Label doResize = DefineLabel();
|
||
|
Load(arrayVar);
|
||
|
Load(null);
|
||
|
Beq(doResize);
|
||
|
Ldlen(arrayVar);
|
||
|
Load(sizeVar);
|
||
|
If(Cmp.NotEqualTo);
|
||
|
MarkLabel(doResize);
|
||
|
Type arrayType = GetVariableType(arrayVar);
|
||
|
Type elementType = arrayType.GetElementType();
|
||
|
LocalBuilder tempArray = DeclareLocal(arrayType, "tempArray");
|
||
|
NewArray(elementType, sizeVar);
|
||
|
Store(tempArray);
|
||
|
CopyArray(arrayVar, tempArray, sizeVar);
|
||
|
Load(tempArray);
|
||
|
Store(arrayVar);
|
||
|
EndIf();
|
||
|
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceComment("} // ResizeArray");
|
||
|
}
|
||
|
|
||
|
LocalBuilder resizeLen, resizeCounter;
|
||
|
internal void EnsureArrayCapacity(object arrayVar, object lastElementVar)
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceComment("EnsureArrayCapacity() {");
|
||
|
|
||
|
Type arrayType = GetVariableType(arrayVar);
|
||
|
Type elementType = arrayType.GetElementType();
|
||
|
If(arrayVar, Cmp.EqualTo, null);
|
||
|
NewArray(elementType, 4);
|
||
|
Store(arrayVar);
|
||
|
Else();
|
||
|
Load(lastElementVar);
|
||
|
Ldlen(arrayVar);
|
||
|
If(Cmp.GreaterThanOrEqualTo);
|
||
|
LocalBuilder tempArray = DeclareLocal(arrayType, "tempArray");
|
||
|
if (resizeLen == null)
|
||
|
resizeLen = DeclareLocal(typeof(int), "resizeLen");
|
||
|
Load(lastElementVar);
|
||
|
Load(2);
|
||
|
Mul();
|
||
|
Store(resizeLen);
|
||
|
NewArray(elementType, resizeLen);
|
||
|
Store(tempArray);
|
||
|
CopyArray(arrayVar, tempArray, arrayVar);
|
||
|
Load(tempArray);
|
||
|
Store(arrayVar);
|
||
|
EndIf();
|
||
|
EndIf();
|
||
|
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceComment("} // EnsureArrayCapacity");
|
||
|
}
|
||
|
|
||
|
internal void CopyArray(object sourceArray, object destArray, object length)
|
||
|
{
|
||
|
If(sourceArray, Cmp.NotEqualTo, null);
|
||
|
if (resizeCounter == null)
|
||
|
resizeCounter = DeclareLocal(typeof(int), "resizeCounter");
|
||
|
For(resizeCounter, 0, length);
|
||
|
Load(destArray);
|
||
|
Load(resizeCounter);
|
||
|
LoadArrayElement(sourceArray, resizeCounter);
|
||
|
Stelem(GetVariableType(destArray).GetElementType());
|
||
|
EndFor();
|
||
|
EndIf();
|
||
|
}
|
||
|
internal void GotoMethodEnd()
|
||
|
{
|
||
|
Br(this.methodEndLabel);
|
||
|
}
|
||
|
|
||
|
internal void AndWhile(Cmp cmpOp)
|
||
|
{
|
||
|
object startWhile = blockStack.Pop();
|
||
|
AndIf(cmpOp);
|
||
|
blockStack.Push(startWhile);
|
||
|
}
|
||
|
|
||
|
internal void BeginWhileBody(Cmp cmpOp)
|
||
|
{
|
||
|
Label startWhile = (Label) blockStack.Pop();
|
||
|
If(cmpOp);
|
||
|
blockStack.Push(startWhile);
|
||
|
}
|
||
|
|
||
|
internal void Cne()
|
||
|
{
|
||
|
Ceq();
|
||
|
Load(0);
|
||
|
Ceq();
|
||
|
}
|
||
|
|
||
|
internal void New(ConstructorInfo constructorInfo, object param1, object param2)
|
||
|
{
|
||
|
LoadParam(param1, 1, constructorInfo);
|
||
|
LoadParam(param2, 2, constructorInfo);
|
||
|
New(constructorInfo);
|
||
|
}
|
||
|
|
||
|
//This code is not tested
|
||
|
internal void Stind(Type type)
|
||
|
{
|
||
|
OpCode opCode = StindOpCodes[(int) Type.GetTypeCode(type)];
|
||
|
if (!opCode.Equals(OpCodes.Nop))
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction(opCode.ToString());
|
||
|
ilGen.Emit(opCode);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceInstruction("Stobj " + type);
|
||
|
ilGen.Emit(OpCodes.Stobj, type);
|
||
|
}
|
||
|
}
|
||
|
//This code is not tested
|
||
|
internal void StoreOutParam(ArgBuilder arg, object value)
|
||
|
{
|
||
|
Type destType = arg.ArgType;
|
||
|
if (!destType.IsByRef)
|
||
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.OutParametersMustBeByRefTypeReceived, DataContract.GetClrTypeFullName(destType))));
|
||
|
destType = destType.GetElementType();
|
||
|
|
||
|
Type sourceType;
|
||
|
if (value is ArgBuilder)
|
||
|
sourceType = ((ArgBuilder) value).ArgType;
|
||
|
else if (value is LocalBuilder)
|
||
|
sourceType = ((LocalBuilder) value).LocalType;
|
||
|
else if (value != null)
|
||
|
sourceType = value.GetType();
|
||
|
else
|
||
|
sourceType = null;
|
||
|
|
||
|
Load(arg);
|
||
|
Load(value);
|
||
|
if (sourceType != null)
|
||
|
ConvertAddress(sourceType, destType);
|
||
|
Stind(destType);
|
||
|
}
|
||
|
void CheckSecurity(FieldInfo field)
|
||
|
{
|
||
|
if (fullTrustDemanded)
|
||
|
return;
|
||
|
if (IsProtectedWithSecurity(field))
|
||
|
DemandFullTrust();
|
||
|
}
|
||
|
|
||
|
void CheckSecurity(MethodBase method)
|
||
|
{
|
||
|
if (fullTrustDemanded)
|
||
|
return;
|
||
|
if (IsProtectedWithSecurity(method))
|
||
|
DemandFullTrust();
|
||
|
}
|
||
|
|
||
|
void CheckSecurity(Type type)
|
||
|
{
|
||
|
if (fullTrustDemanded)
|
||
|
return;
|
||
|
if (IsProtectedWithSecurity(type))
|
||
|
DemandFullTrust();
|
||
|
}
|
||
|
|
||
|
void CheckSecurity(Assembly assembly)
|
||
|
{
|
||
|
if (fullTrustDemanded)
|
||
|
return;
|
||
|
if (IsProtectedWithSecurity(assembly))
|
||
|
DemandFullTrust();
|
||
|
}
|
||
|
|
||
|
static bool IsProtectedWithSecurity(FieldInfo field)
|
||
|
{
|
||
|
return IsProtectedWithSecurity(field.DeclaringType);
|
||
|
}
|
||
|
|
||
|
static bool IsProtectedWithSecurity(Type type)
|
||
|
{
|
||
|
return IsProtectedWithSecurity(type.Assembly) || (type.Attributes & TypeAttributes.HasSecurity) != 0;
|
||
|
}
|
||
|
|
||
|
static bool IsProtectedWithSecurity(Assembly assembly)
|
||
|
{
|
||
|
object[] attrs = assembly.GetCustomAttributes(typeof(AllowPartiallyTrustedCallersAttribute), true);
|
||
|
bool hasAptca = attrs != null && attrs.Length > 0;
|
||
|
return !hasAptca;
|
||
|
}
|
||
|
|
||
|
void DemandFullTrust()
|
||
|
{
|
||
|
fullTrustDemanded = true;
|
||
|
/*
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceComment("DemandFullTrust() {");
|
||
|
|
||
|
Ldc(PermissionState.Unrestricted);
|
||
|
New(permissionSetCtor);
|
||
|
Call(permissionSetDemand);
|
||
|
|
||
|
if (codeGenTrace != CodeGenTrace.None)
|
||
|
EmitSourceComment("}");
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
static bool IsProtectedWithSecurity(MethodBase method)
|
||
|
{
|
||
|
return false;
|
||
|
//return (method.Attributes & MethodAttributes.HasSecurity) != 0;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
internal class ArgBuilder
|
||
|
{
|
||
|
internal int Index;
|
||
|
internal Type ArgType;
|
||
|
internal ArgBuilder(int index, Type argType)
|
||
|
{
|
||
|
this.Index = index;
|
||
|
this.ArgType = argType;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class ForState
|
||
|
{
|
||
|
LocalBuilder indexVar;
|
||
|
Label beginLabel;
|
||
|
Label testLabel;
|
||
|
Label endLabel;
|
||
|
bool requiresEndLabel;
|
||
|
object end;
|
||
|
|
||
|
internal ForState(LocalBuilder indexVar, Label beginLabel, Label testLabel, object end)
|
||
|
{
|
||
|
this.indexVar = indexVar;
|
||
|
this.beginLabel = beginLabel;
|
||
|
this.testLabel = testLabel;
|
||
|
this.end = end;
|
||
|
}
|
||
|
|
||
|
internal LocalBuilder Index
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return indexVar;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal Label BeginLabel
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return beginLabel;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal Label TestLabel
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return testLabel;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal Label EndLabel
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return endLabel;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
endLabel = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool RequiresEndLabel
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return requiresEndLabel;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
requiresEndLabel = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal object End
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return end;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal enum Cmp
|
||
|
{
|
||
|
LessThan,
|
||
|
EqualTo,
|
||
|
LessThanOrEqualTo,
|
||
|
GreaterThan,
|
||
|
NotEqualTo,
|
||
|
GreaterThanOrEqualTo
|
||
|
}
|
||
|
|
||
|
internal class IfState
|
||
|
{
|
||
|
Label elseBegin;
|
||
|
Label endIf;
|
||
|
|
||
|
internal Label EndIf
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.endIf;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
this.endIf = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal Label ElseBegin
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.elseBegin;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
this.elseBegin = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
#if NotUsed
|
||
|
internal class BitFlagsGenerator
|
||
|
{
|
||
|
LocalBuilder[] locals;
|
||
|
CodeGenerator ilg;
|
||
|
int bitCount;
|
||
|
internal BitFlagsGenerator(int bitCount, CodeGenerator ilg, string localName)
|
||
|
{
|
||
|
this.ilg = ilg;
|
||
|
this.bitCount = bitCount;
|
||
|
int localCount = (bitCount+7)/8;
|
||
|
locals = new LocalBuilder[localCount];
|
||
|
for (int i=0;i<locals.Length;i++)
|
||
|
locals[i] = ilg.DeclareLocal(Globals.TypeOfByte, localName+i, (byte)0);
|
||
|
}
|
||
|
internal void Store(int bitIndex, bool value)
|
||
|
{
|
||
|
LocalBuilder local = locals[GetByteIndex(bitIndex)];
|
||
|
byte bitValue = GetBitValue(bitIndex);
|
||
|
if (value)
|
||
|
{
|
||
|
ilg.Load(local);
|
||
|
ilg.Load(bitValue);
|
||
|
ilg.Or();
|
||
|
ilg.Stloc(local);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ilg.Load(local);
|
||
|
ilg.Load(bitValue);
|
||
|
ilg.Not();
|
||
|
ilg.And();
|
||
|
ilg.Stloc(local);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Load(int bitIndex)
|
||
|
{
|
||
|
LocalBuilder local = locals[GetByteIndex(bitIndex)];
|
||
|
byte bitValue = GetBitValue(bitIndex);
|
||
|
ilg.Load(local);
|
||
|
ilg.Load(bitValue);
|
||
|
ilg.And();
|
||
|
ilg.Load(bitValue);
|
||
|
ilg.Ceq();
|
||
|
}
|
||
|
|
||
|
internal void LoadArray()
|
||
|
{
|
||
|
LocalBuilder localArray = ilg.DeclareLocal(Globals.TypeOfByteArray, "localArray");
|
||
|
ilg.NewArray(Globals.TypeOfByte, locals.Length);
|
||
|
ilg.Store(localArray);
|
||
|
for (int i=0;i<locals.Length;i++)
|
||
|
ilg.StoreArrayElement(localArray, i, locals[i]);
|
||
|
ilg.Load(localArray);
|
||
|
}
|
||
|
|
||
|
internal int GetLocalCount()
|
||
|
{
|
||
|
return locals.Length;
|
||
|
}
|
||
|
|
||
|
internal int GetBitCount()
|
||
|
{
|
||
|
return bitCount;
|
||
|
}
|
||
|
|
||
|
internal LocalBuilder GetLocal(int i)
|
||
|
{
|
||
|
return locals[i];
|
||
|
}
|
||
|
|
||
|
internal static bool IsBitSet(byte[] bytes, int bitIndex)
|
||
|
{
|
||
|
int byteIndex = GetByteIndex(bitIndex);
|
||
|
byte bitValue = GetBitValue(bitIndex);
|
||
|
return (bytes[byteIndex] & bitValue) == bitValue;
|
||
|
}
|
||
|
|
||
|
internal static void SetBit(byte[] bytes, int bitIndex)
|
||
|
{
|
||
|
int byteIndex = GetByteIndex(bitIndex);
|
||
|
byte bitValue = GetBitValue(bitIndex);
|
||
|
bytes[byteIndex] |= bitValue;
|
||
|
}
|
||
|
|
||
|
static int GetByteIndex(int bitIndex)
|
||
|
{
|
||
|
return bitIndex >> 3;
|
||
|
}
|
||
|
|
||
|
static byte GetBitValue(int bitIndex)
|
||
|
{
|
||
|
return (byte)(1 << (bitIndex & 7));
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
internal class SwitchState
|
||
|
{
|
||
|
Label defaultLabel;
|
||
|
Label endOfSwitchLabel;
|
||
|
bool defaultDefined;
|
||
|
internal SwitchState(Label defaultLabel, Label endOfSwitchLabel)
|
||
|
{
|
||
|
this.defaultLabel = defaultLabel;
|
||
|
this.endOfSwitchLabel = endOfSwitchLabel;
|
||
|
this.defaultDefined = false;
|
||
|
}
|
||
|
internal Label DefaultLabel
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return defaultLabel;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal Label EndOfSwitchLabel
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return endOfSwitchLabel;
|
||
|
}
|
||
|
}
|
||
|
internal bool DefaultDefined
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return defaultDefined;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
defaultDefined = value;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|