2003-05-30 16:08:59 +04:00
|
|
|
/*
|
2009-04-06 14:10:17 +04:00
|
|
|
Copyright (C) 2002, 2004, 2005, 2006, 2008, 2009 Jeroen Frijters
|
2003-05-30 16:08:59 +04:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
|
|
|
|
Jeroen Frijters
|
|
|
|
jeroen@frijters.net
|
|
|
|
|
|
|
|
*/
|
|
|
|
using System;
|
2008-08-15 16:01:06 +04:00
|
|
|
using System.Collections.Generic;
|
2010-01-28 12:18:33 +03:00
|
|
|
#if STATIC_COMPILER
|
2010-01-25 10:52:27 +03:00
|
|
|
using IKVM.Reflection;
|
2008-11-14 11:42:07 +03:00
|
|
|
using IKVM.Reflection.Emit;
|
2010-01-25 10:52:27 +03:00
|
|
|
using Type = IKVM.Reflection.Type;
|
2008-11-14 11:42:07 +03:00
|
|
|
#else
|
2010-01-25 10:52:27 +03:00
|
|
|
using System.Reflection;
|
2003-05-30 16:08:59 +04:00
|
|
|
using System.Reflection.Emit;
|
2008-11-14 11:42:07 +03:00
|
|
|
#endif
|
2004-10-19 17:43:55 +04:00
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
using System.Diagnostics.SymbolStore;
|
2009-02-27 09:17:06 +03:00
|
|
|
using System.Diagnostics;
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
namespace IKVM.Internal
|
2004-10-19 17:43:55 +04:00
|
|
|
{
|
2008-06-03 16:10:07 +04:00
|
|
|
class CodeEmitterLabel
|
2005-12-29 18:48:32 +03:00
|
|
|
{
|
|
|
|
private Label label;
|
|
|
|
private int offset = -1;
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal CodeEmitterLabel(Label label)
|
2005-12-29 18:48:32 +03:00
|
|
|
{
|
|
|
|
this.label = label;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal Label Label
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return label;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int Offset
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
offset = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-31 09:02:34 +04:00
|
|
|
sealed class CodeEmitter
|
2005-06-01 13:49:30 +04:00
|
|
|
{
|
2009-10-14 18:58:41 +04:00
|
|
|
private static readonly MethodInfo objectToString = Types.Object.GetMethod("ToString", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
|
2009-08-31 09:02:34 +04:00
|
|
|
private static readonly MethodInfo verboseCastFailure = JVM.SafeGetEnvironmentVariable("IKVM_VERBOSE_CAST") == null ? null : ByteCodeHelperMethods.VerboseCastFailure;
|
2008-02-15 18:32:51 +03:00
|
|
|
private ILGenerator ilgen_real;
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
private int offset;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-08-15 16:01:06 +04:00
|
|
|
private Stack<bool> exceptionStack = new Stack<bool>();
|
2005-06-01 13:49:30 +04:00
|
|
|
private bool inFinally;
|
2006-05-04 12:09:56 +04:00
|
|
|
#if STATIC_COMPILER
|
2005-06-19 14:44:53 +04:00
|
|
|
private IKVM.Attributes.LineNumberTableAttribute.LineNumberWriter linenums;
|
2006-05-04 12:09:56 +04:00
|
|
|
#endif // STATIC_COMPILER
|
2009-02-27 09:17:06 +03:00
|
|
|
private Expr[] stackArray = new Expr[8];
|
|
|
|
private int topOfStack;
|
2008-06-03 16:10:07 +04:00
|
|
|
private CodeEmitterLabel lazyBranch;
|
2008-02-15 18:32:51 +03:00
|
|
|
private LocalBuilder[] tempLocals = new LocalBuilder[32];
|
2004-11-04 15:50:28 +03:00
|
|
|
#if LABELCHECK
|
2009-04-06 14:14:47 +04:00
|
|
|
private Dictionary<CodeEmitterLabel, System.Diagnostics.StackFrame> labels = new Dictionary<CodeEmitterLabel, System.Diagnostics.StackFrame>();
|
2004-11-04 15:50:28 +03:00
|
|
|
#endif
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal static CodeEmitter Create(MethodBuilder mb)
|
2005-06-01 13:49:30 +04:00
|
|
|
{
|
2008-06-03 16:10:07 +04:00
|
|
|
return new CodeEmitter(mb.GetILGenerator());
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal static CodeEmitter Create(ConstructorBuilder cb)
|
|
|
|
{
|
|
|
|
return new CodeEmitter(cb.GetILGenerator());
|
|
|
|
}
|
|
|
|
|
2008-08-12 18:57:04 +04:00
|
|
|
#if !STATIC_COMPILER
|
2008-06-03 16:10:07 +04:00
|
|
|
internal static CodeEmitter Create(DynamicMethod dm)
|
|
|
|
{
|
|
|
|
return new CodeEmitter(dm.GetILGenerator());
|
|
|
|
}
|
2008-08-12 18:57:04 +04:00
|
|
|
#endif
|
2008-06-03 16:10:07 +04:00
|
|
|
|
|
|
|
private CodeEmitter(ILGenerator ilgen)
|
2005-06-01 13:49:30 +04:00
|
|
|
{
|
2010-01-28 12:18:33 +03:00
|
|
|
#if STATIC_COMPILER
|
2009-08-14 17:36:53 +04:00
|
|
|
ilgen.__CleverExceptionBlockAssistance();
|
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
this.ilgen_real = ilgen;
|
|
|
|
}
|
|
|
|
|
2009-02-27 09:17:06 +03:00
|
|
|
private void PushStack(Expr expr)
|
|
|
|
{
|
|
|
|
Debug.Assert(expr != null);
|
|
|
|
if (topOfStack == stackArray.Length)
|
|
|
|
{
|
|
|
|
Array.Resize(ref stackArray, stackArray.Length * 2);
|
|
|
|
}
|
|
|
|
stackArray[topOfStack++] = expr;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void PushStackMayBeNull(Expr expr)
|
|
|
|
{
|
|
|
|
if (expr != null)
|
|
|
|
{
|
|
|
|
PushStack(expr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private Expr PopStack()
|
|
|
|
{
|
|
|
|
if (topOfStack == 0)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return stackArray[--topOfStack];
|
|
|
|
}
|
|
|
|
|
|
|
|
private Expr PeekStack()
|
|
|
|
{
|
|
|
|
if (topOfStack == 0)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return stackArray[topOfStack - 1];
|
|
|
|
}
|
|
|
|
|
2008-02-15 18:32:51 +03:00
|
|
|
internal LocalBuilder UnsafeAllocTempLocal(Type type)
|
|
|
|
{
|
|
|
|
int free = -1;
|
|
|
|
for (int i = 0; i < tempLocals.Length; i++)
|
|
|
|
{
|
|
|
|
LocalBuilder lb = tempLocals[i];
|
|
|
|
if (lb == null)
|
|
|
|
{
|
|
|
|
if (free == -1)
|
|
|
|
{
|
|
|
|
free = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (lb.LocalType == type)
|
|
|
|
{
|
|
|
|
return lb;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LocalBuilder lb1 = DeclareLocal(type);
|
|
|
|
if (free != -1)
|
|
|
|
{
|
|
|
|
tempLocals[free] = lb1;
|
|
|
|
}
|
|
|
|
return lb1;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal LocalBuilder AllocTempLocal(Type type)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < tempLocals.Length; i++)
|
|
|
|
{
|
|
|
|
LocalBuilder lb = tempLocals[i];
|
|
|
|
if (lb != null && lb.LocalType == type)
|
|
|
|
{
|
|
|
|
tempLocals[i] = null;
|
|
|
|
return lb;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return DeclareLocal(type);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void ReleaseTempLocal(LocalBuilder lb)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < tempLocals.Length; i++)
|
|
|
|
{
|
|
|
|
if (tempLocals[i] == null)
|
|
|
|
{
|
|
|
|
tempLocals[i] = lb;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2007-06-12 13:47:40 +04:00
|
|
|
internal bool IsStackEmpty
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
return topOfStack == 0;
|
2007-06-12 13:47:40 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal int GetILOffset()
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if STATIC_COMPILER
|
2009-11-06 08:13:37 +03:00
|
|
|
return ilgen_real.ILOffset;
|
2009-08-13 11:16:19 +04:00
|
|
|
#else
|
2005-06-01 13:49:30 +04:00
|
|
|
return offset;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void BeginCatchBlock(Type exceptionType)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += 5;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.BeginCatchBlock(exceptionType);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal Label BeginExceptionBlock()
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2005-06-01 13:49:30 +04:00
|
|
|
exceptionStack.Push(inFinally);
|
|
|
|
inFinally = false;
|
2008-02-15 18:32:51 +03:00
|
|
|
return ilgen_real.BeginExceptionBlock();
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void BeginFaultBlock()
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2005-07-20 11:26:10 +04:00
|
|
|
inFinally = true;
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += 5;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.BeginFaultBlock();
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void BeginFinallyBlock()
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2005-06-01 13:49:30 +04:00
|
|
|
inFinally = true;
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += 5;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.BeginFinallyBlock();
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void BeginScope()
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.BeginScope();
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal LocalBuilder DeclareLocal(Type localType)
|
|
|
|
{
|
2008-08-13 17:05:43 +04:00
|
|
|
return ilgen_real.DeclareLocal(localType);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal CodeEmitterLabel DefineLabel()
|
2005-06-01 13:49:30 +04:00
|
|
|
{
|
2009-04-06 14:14:47 +04:00
|
|
|
CodeEmitterLabel label = new CodeEmitterLabel(ilgen_real.DefineLabel());
|
2004-11-04 15:50:28 +03:00
|
|
|
#if LABELCHECK
|
2005-12-19 18:12:49 +03:00
|
|
|
labels.Add(label, new System.Diagnostics.StackFrame(1, true));
|
2004-11-04 15:50:28 +03:00
|
|
|
#endif
|
2009-04-06 14:14:47 +04:00
|
|
|
return label;
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, byte arg)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 1;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, arg);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, ConstructorInfo con)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 4;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, con);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, double arg)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 8;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, arg);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, FieldInfo field)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 4;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, field);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, short arg)
|
2004-10-19 17:43:55 +04:00
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 2;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, arg);
|
2004-10-19 17:43:55 +04:00
|
|
|
}
|
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, int arg)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 4;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, arg);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, long arg)
|
2004-10-19 17:43:55 +04:00
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 8;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, arg);
|
2004-10-19 17:43:55 +04:00
|
|
|
}
|
2005-06-01 13:49:30 +04:00
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal void Emit(OpCode opcode, CodeEmitterLabel label)
|
2004-10-19 17:43:55 +04:00
|
|
|
{
|
2009-08-13 11:16:19 +04:00
|
|
|
int currOffset = GetILOffset();
|
2006-01-02 13:59:51 +03:00
|
|
|
if(label.Offset == -1)
|
|
|
|
{
|
|
|
|
if(opcode.Value == OpCodes.Br.Value)
|
|
|
|
{
|
|
|
|
lazyBranch = label;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2009-08-13 11:16:19 +04:00
|
|
|
else if(currOffset - label.Offset < 126)
|
2005-12-29 18:48:32 +03:00
|
|
|
{
|
|
|
|
if(opcode.Value == OpCodes.Brtrue.Value)
|
|
|
|
{
|
|
|
|
opcode = OpCodes.Brtrue_S;
|
|
|
|
}
|
|
|
|
else if(opcode.Value == OpCodes.Brfalse.Value)
|
|
|
|
{
|
|
|
|
opcode = OpCodes.Brfalse_S;
|
|
|
|
}
|
|
|
|
else if(opcode.Value == OpCodes.Br.Value)
|
|
|
|
{
|
|
|
|
opcode = OpCodes.Br_S;
|
|
|
|
}
|
|
|
|
else if(opcode.Value == OpCodes.Beq.Value)
|
|
|
|
{
|
|
|
|
opcode = OpCodes.Beq_S;
|
|
|
|
}
|
|
|
|
else if(opcode.Value == OpCodes.Bne_Un.Value)
|
|
|
|
{
|
|
|
|
opcode = OpCodes.Bne_Un_S;
|
|
|
|
}
|
|
|
|
else if(opcode.Value == OpCodes.Ble.Value)
|
|
|
|
{
|
|
|
|
opcode = OpCodes.Ble_S;
|
|
|
|
}
|
|
|
|
else if(opcode.Value == OpCodes.Blt.Value)
|
|
|
|
{
|
|
|
|
opcode = OpCodes.Blt_S;
|
|
|
|
}
|
|
|
|
else if(opcode.Value == OpCodes.Bge.Value)
|
|
|
|
{
|
|
|
|
opcode = OpCodes.Bge_S;
|
|
|
|
}
|
|
|
|
else if(opcode.Value == OpCodes.Bgt.Value)
|
|
|
|
{
|
|
|
|
opcode = OpCodes.Bgt_S;
|
|
|
|
}
|
|
|
|
}
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
switch(opcode.OperandType)
|
|
|
|
{
|
|
|
|
case OperandType.InlineBrTarget:
|
2009-08-13 11:16:19 +04:00
|
|
|
offset += opcode.Size + 4;
|
2005-06-01 13:49:30 +04:00
|
|
|
break;
|
|
|
|
case OperandType.ShortInlineBrTarget:
|
2009-08-13 11:16:19 +04:00
|
|
|
offset += opcode.Size + 1;
|
2005-06-01 13:49:30 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new NotImplementedException();
|
|
|
|
}
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
|
|
|
ilgen_real.Emit(opcode, label.Label);
|
2004-10-19 17:43:55 +04:00
|
|
|
}
|
2005-06-01 13:49:30 +04:00
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal void Emit(OpCode opcode, CodeEmitterLabel[] labels)
|
2004-10-19 17:43:55 +04:00
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += 5 + labels.Length * 4;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2005-12-29 18:48:32 +03:00
|
|
|
Label[] real = new Label[labels.Length];
|
|
|
|
for(int i = 0; i < labels.Length; i++)
|
|
|
|
{
|
|
|
|
real[i] = labels[i].Label;
|
|
|
|
}
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, real);
|
2004-10-19 17:43:55 +04:00
|
|
|
}
|
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, LocalBuilder local)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2008-08-13 17:05:43 +04:00
|
|
|
int index = local.LocalIndex;
|
2005-06-01 13:49:30 +04:00
|
|
|
if(index < 4 && opcode.Value != OpCodes.Ldloca.Value && opcode.Value != OpCodes.Ldloca_S.Value)
|
|
|
|
{
|
|
|
|
offset += 1;
|
|
|
|
}
|
|
|
|
else if(index < 256)
|
|
|
|
{
|
|
|
|
offset += 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
offset += 4;
|
|
|
|
}
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
|
|
|
ilgen_real.Emit(opcode, local);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, MethodInfo meth)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 4;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, meth);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, sbyte arg)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 1;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, arg);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, float arg)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 4;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, arg);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, string arg)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 4;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, arg);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void Emit(OpCode opcode, Type cls)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += opcode.Size + 4;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(opcode, cls);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type returnType, Type[] parameterTypes)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += 5;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.EmitCalli(opcode, unmanagedCallConv, returnType, parameterTypes);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void EmitWriteLine(string value)
|
2004-10-19 17:43:55 +04:00
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += 10;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.EmitWriteLine(value);
|
2004-10-19 17:43:55 +04:00
|
|
|
}
|
2005-06-01 13:49:30 +04:00
|
|
|
|
2009-08-14 17:36:53 +04:00
|
|
|
internal void EndExceptionBlockNoFallThrough()
|
|
|
|
{
|
|
|
|
EndExceptionBlock();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2009-08-14 17:36:53 +04:00
|
|
|
// HACK to keep the verifier happy we need this bogus jump
|
|
|
|
// (because of the bogus Leave that Ref.Emit ends the try block with)
|
|
|
|
Emit(OpCodes.Br_S, (sbyte)-2);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void EndExceptionBlock()
|
2004-10-19 17:43:55 +04:00
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
if(inFinally)
|
|
|
|
{
|
|
|
|
offset += 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
offset += 5;
|
|
|
|
}
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-08-15 16:01:06 +04:00
|
|
|
inFinally = exceptionStack.Pop();
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.EndExceptionBlock();
|
2004-10-19 17:43:55 +04:00
|
|
|
}
|
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void EndScope()
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.EndScope();
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal void MarkLabel(CodeEmitterLabel loc)
|
2005-06-01 13:49:30 +04:00
|
|
|
{
|
2006-01-02 13:59:51 +03:00
|
|
|
if(lazyBranch == loc)
|
|
|
|
{
|
|
|
|
lazyBranch = null;
|
|
|
|
}
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2004-11-04 15:50:28 +03:00
|
|
|
#if LABELCHECK
|
2009-04-06 14:14:47 +04:00
|
|
|
labels.Remove(loc);
|
2004-11-04 15:50:28 +03:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.MarkLabel(loc.Label);
|
2009-08-13 11:16:19 +04:00
|
|
|
loc.Offset = GetILOffset();
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void MarkSequencePoint(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.MarkSequencePoint(document, startLine, startColumn, endLine, endColumn);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void ThrowException(Type excType)
|
|
|
|
{
|
2005-12-19 18:12:49 +03:00
|
|
|
LazyGen();
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
offset += 6;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.ThrowException(excType);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
|
2006-05-04 12:09:56 +04:00
|
|
|
#if STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void SetLineNumber(ushort line)
|
2004-10-19 17:43:55 +04:00
|
|
|
{
|
2005-06-01 13:49:30 +04:00
|
|
|
if(linenums == null)
|
|
|
|
{
|
2005-06-19 14:44:53 +04:00
|
|
|
linenums = new IKVM.Attributes.LineNumberTableAttribute.LineNumberWriter(32);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2009-08-13 11:16:19 +04:00
|
|
|
linenums.AddMapping(GetILOffset(), line);
|
2004-10-19 17:43:55 +04:00
|
|
|
}
|
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal void EmitLineNumberTable(MethodBase mb)
|
2004-10-19 17:43:55 +04:00
|
|
|
{
|
2006-08-29 10:28:34 +04:00
|
|
|
if(linenums != null)
|
2005-06-01 13:49:30 +04:00
|
|
|
{
|
2005-08-22 16:42:02 +04:00
|
|
|
AttributeHelper.SetLineNumberTable(mb, linenums);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
}
|
2006-05-04 12:09:56 +04:00
|
|
|
#endif // STATIC_COMPILER
|
2004-11-04 15:50:28 +03:00
|
|
|
|
2009-08-31 09:02:34 +04:00
|
|
|
internal void EmitThrow(string dottedClassName)
|
|
|
|
{
|
|
|
|
TypeWrapper exception = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(dottedClassName);
|
|
|
|
MethodWrapper mw = exception.GetMethodWrapper("<init>", "()V", false);
|
|
|
|
mw.Link();
|
|
|
|
mw.EmitNewobj(this);
|
|
|
|
Emit(OpCodes.Throw);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void EmitThrow(string dottedClassName, string message)
|
|
|
|
{
|
|
|
|
TypeWrapper exception = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(dottedClassName);
|
|
|
|
Emit(OpCodes.Ldstr, message);
|
|
|
|
MethodWrapper mw = exception.GetMethodWrapper("<init>", "(Ljava.lang.String;)V", false);
|
|
|
|
mw.Link();
|
|
|
|
mw.EmitNewobj(this);
|
|
|
|
Emit(OpCodes.Throw);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void EmitNullCheck()
|
|
|
|
{
|
|
|
|
// I think this is the most efficient way to generate a NullReferenceException if the reference is null
|
|
|
|
Emit(OpCodes.Ldvirtftn, objectToString);
|
|
|
|
Emit(OpCodes.Pop);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void EmitCastclass(Type type)
|
|
|
|
{
|
|
|
|
if (verboseCastFailure != null)
|
|
|
|
{
|
2009-10-14 18:58:41 +04:00
|
|
|
LocalBuilder lb = DeclareLocal(Types.Object);
|
2009-08-31 09:02:34 +04:00
|
|
|
Emit(OpCodes.Stloc, lb);
|
|
|
|
Emit(OpCodes.Ldloc, lb);
|
|
|
|
Emit(OpCodes.Isinst, type);
|
|
|
|
Emit(OpCodes.Dup);
|
|
|
|
CodeEmitterLabel ok = DefineLabel();
|
|
|
|
Emit(OpCodes.Brtrue_S, ok);
|
|
|
|
Emit(OpCodes.Ldloc, lb);
|
|
|
|
Emit(OpCodes.Brfalse_S, ok); // handle null
|
|
|
|
Emit(OpCodes.Ldtoken, type);
|
|
|
|
Emit(OpCodes.Ldloc, lb);
|
|
|
|
Emit(OpCodes.Call, verboseCastFailure);
|
|
|
|
MarkLabel(ok);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Emit(OpCodes.Castclass, type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is basically the same as Castclass, except that it
|
|
|
|
// throws an IncompatibleClassChangeError on failure.
|
|
|
|
internal void EmitAssertType(Type type)
|
|
|
|
{
|
2009-10-14 18:58:41 +04:00
|
|
|
LocalBuilder lb = DeclareLocal(Types.Object);
|
2009-08-31 09:02:34 +04:00
|
|
|
Emit(OpCodes.Stloc, lb);
|
|
|
|
Emit(OpCodes.Ldloc, lb);
|
|
|
|
Emit(OpCodes.Isinst, type);
|
|
|
|
Emit(OpCodes.Dup);
|
|
|
|
CodeEmitterLabel ok = DefineLabel();
|
|
|
|
Emit(OpCodes.Brtrue_S, ok);
|
|
|
|
Emit(OpCodes.Ldloc, lb);
|
|
|
|
Emit(OpCodes.Brfalse_S, ok); // handle null
|
|
|
|
EmitThrow("java.lang.IncompatibleClassChangeError");
|
|
|
|
MarkLabel(ok);
|
|
|
|
}
|
|
|
|
|
2009-02-27 09:17:06 +03:00
|
|
|
internal void LazyEmitPop()
|
|
|
|
{
|
|
|
|
Expr exp = PeekStack();
|
2009-03-02 07:52:05 +03:00
|
|
|
if (exp == null || exp.HasSideEffect || exp.IsIncomplete)
|
2009-02-27 09:17:06 +03:00
|
|
|
{
|
|
|
|
Emit(OpCodes.Pop);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PopStack();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-02 09:31:55 +03:00
|
|
|
internal void LazyEmitLoadClass(TypeWrapper type)
|
2009-02-27 09:17:06 +03:00
|
|
|
{
|
|
|
|
PushStack(new ClassLiteralExpr(type));
|
|
|
|
}
|
|
|
|
|
2005-12-19 18:12:49 +03:00
|
|
|
internal void LazyEmitBox(Type type)
|
2005-06-01 13:49:30 +04:00
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new BoxExpr(PopStack(), type));
|
2005-12-19 18:12:49 +03:00
|
|
|
}
|
|
|
|
|
2006-11-27 10:39:30 +03:00
|
|
|
internal void LazyEmitUnbox(Type type)
|
2005-12-20 15:44:29 +03:00
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
BoxExpr box = PeekStack() as BoxExpr;
|
2006-11-27 10:39:30 +03:00
|
|
|
if(box != null)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PopStack();
|
|
|
|
PushStack(new BoxUnboxExpr(box.Expr, type));
|
2006-11-27 10:39:30 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new UnboxExpr(PopStack(), type));
|
2006-11-27 10:39:30 +03:00
|
|
|
}
|
2005-12-20 15:44:29 +03:00
|
|
|
}
|
|
|
|
|
2006-11-27 10:39:30 +03:00
|
|
|
internal void LazyEmitLdobj(Type type)
|
2005-12-20 15:44:29 +03:00
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
BoxUnboxExpr boxunbox = PeekStack() as BoxUnboxExpr;
|
2006-11-27 10:39:30 +03:00
|
|
|
if(boxunbox != null)
|
2005-12-20 15:44:29 +03:00
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PopStack();
|
2006-11-27 10:39:30 +03:00
|
|
|
// box/unbox+ldobj annihilate each other
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStackMayBeNull(boxunbox.Expr);
|
2005-12-20 15:44:29 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new LdobjExpr(PopStack(), type));
|
2005-12-20 15:44:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-19 18:12:49 +03:00
|
|
|
internal void LazyEmitUnboxSpecial(Type type)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
BoxExpr box = PeekStack() as BoxExpr;
|
2006-11-27 10:39:30 +03:00
|
|
|
if(box != null)
|
2005-12-19 18:12:49 +03:00
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PopStack();
|
2005-12-19 18:12:49 +03:00
|
|
|
// the unbox and lazy box cancel each other out
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStackMayBeNull(box.Expr);
|
2005-12-19 18:12:49 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// NOTE if the reference is null, we treat it as a default instance of the value type.
|
|
|
|
Emit(OpCodes.Dup);
|
2008-06-03 16:10:07 +04:00
|
|
|
CodeEmitterLabel label1 = DefineLabel();
|
2005-12-19 18:12:49 +03:00
|
|
|
Emit(OpCodes.Brtrue_S, label1);
|
|
|
|
Emit(OpCodes.Pop);
|
|
|
|
Emit(OpCodes.Ldloc, DeclareLocal(type));
|
2008-06-03 16:10:07 +04:00
|
|
|
CodeEmitterLabel label2 = DefineLabel();
|
2005-12-19 18:12:49 +03:00
|
|
|
Emit(OpCodes.Br_S, label2);
|
|
|
|
MarkLabel(label1);
|
|
|
|
Emit(OpCodes.Unbox, type);
|
|
|
|
Emit(OpCodes.Ldobj, type);
|
|
|
|
MarkLabel(label2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-27 09:17:06 +03:00
|
|
|
internal void LazyEmitLdnull()
|
|
|
|
{
|
|
|
|
PushStack(new NullExpr());
|
|
|
|
}
|
|
|
|
|
2006-11-27 10:39:30 +03:00
|
|
|
internal void LazyEmitLdc_I4(int i)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new ConstIntExpr(i));
|
2006-11-27 10:39:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmitLdc_I8(long l)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new ConstLongExpr(l));
|
2006-11-27 10:39:30 +03:00
|
|
|
}
|
|
|
|
|
2007-06-12 13:47:40 +04:00
|
|
|
internal void LazyEmitLdstr(string str)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new ConstStringExpr(str));
|
2007-06-12 13:47:40 +04:00
|
|
|
}
|
|
|
|
|
2006-11-27 10:39:30 +03:00
|
|
|
internal void LazyEmit_idiv()
|
|
|
|
{
|
|
|
|
// we need to special case dividing by -1, because the CLR div instruction
|
|
|
|
// throws an OverflowException when dividing Int32.MinValue by -1, and
|
|
|
|
// Java just silently overflows
|
2009-02-27 09:17:06 +03:00
|
|
|
ConstIntExpr v = PeekStack() as ConstIntExpr;
|
2006-11-27 10:39:30 +03:00
|
|
|
if(v != null)
|
|
|
|
{
|
|
|
|
if(v.i == -1)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PopStack();
|
2006-11-27 10:39:30 +03:00
|
|
|
Emit(OpCodes.Neg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Emit(OpCodes.Div);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Emit(OpCodes.Dup);
|
|
|
|
Emit(OpCodes.Ldc_I4_M1);
|
2008-06-03 16:10:07 +04:00
|
|
|
CodeEmitterLabel label = DefineLabel();
|
2006-11-27 10:39:30 +03:00
|
|
|
Emit(OpCodes.Bne_Un_S, label);
|
|
|
|
Emit(OpCodes.Pop);
|
|
|
|
Emit(OpCodes.Neg);
|
2008-06-03 16:10:07 +04:00
|
|
|
CodeEmitterLabel label2 = DefineLabel();
|
2006-11-27 10:39:30 +03:00
|
|
|
Emit(OpCodes.Br_S, label2);
|
|
|
|
MarkLabel(label);
|
|
|
|
Emit(OpCodes.Div);
|
|
|
|
MarkLabel(label2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmit_ldiv()
|
|
|
|
{
|
|
|
|
// we need to special case dividing by -1, because the CLR div instruction
|
|
|
|
// throws an OverflowException when dividing Int32.MinValue by -1, and
|
|
|
|
// Java just silently overflows
|
2009-02-27 09:17:06 +03:00
|
|
|
ConstLongExpr v = PeekStack() as ConstLongExpr;
|
2006-11-27 10:39:30 +03:00
|
|
|
if(v != null)
|
|
|
|
{
|
|
|
|
if(v.l == -1)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PopStack();
|
2006-11-27 10:39:30 +03:00
|
|
|
Emit(OpCodes.Neg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Emit(OpCodes.Div);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Emit(OpCodes.Dup);
|
|
|
|
Emit(OpCodes.Ldc_I4_M1);
|
|
|
|
Emit(OpCodes.Conv_I8);
|
2008-06-03 16:10:07 +04:00
|
|
|
CodeEmitterLabel label = DefineLabel();
|
2006-11-27 10:39:30 +03:00
|
|
|
Emit(OpCodes.Bne_Un_S, label);
|
|
|
|
Emit(OpCodes.Pop);
|
|
|
|
Emit(OpCodes.Neg);
|
2008-06-03 16:10:07 +04:00
|
|
|
CodeEmitterLabel label2 = DefineLabel();
|
2006-11-27 10:39:30 +03:00
|
|
|
Emit(OpCodes.Br_S, label2);
|
|
|
|
MarkLabel(label);
|
|
|
|
Emit(OpCodes.Div);
|
|
|
|
MarkLabel(label2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmit_instanceof(Type type)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new InstanceOfExpr(type));
|
2006-11-27 10:39:30 +03:00
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal void LazyEmit_ifeq(CodeEmitterLabel label)
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
|
|
|
LazyEmit_if_ne_eq(label, false);
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal void LazyEmit_ifne(CodeEmitterLabel label)
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
|
|
|
LazyEmit_if_ne_eq(label, true);
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
private void LazyEmit_if_ne_eq(CodeEmitterLabel label, bool brtrue)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
InstanceOfExpr instanceof = PeekStack() as InstanceOfExpr;
|
2008-02-15 18:32:51 +03:00
|
|
|
if (instanceof != null)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PopStack();
|
2006-11-27 10:39:30 +03:00
|
|
|
Emit(OpCodes.Isinst, instanceof.Type);
|
|
|
|
}
|
2008-02-15 18:32:51 +03:00
|
|
|
else
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
CmpExpr cmp = PeekStack() as CmpExpr;
|
2008-02-15 18:32:51 +03:00
|
|
|
if (cmp != null)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PopStack();
|
2008-02-15 18:32:51 +03:00
|
|
|
Emit(brtrue ? OpCodes.Bne_Un : OpCodes.Beq, label);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Emit(brtrue ? OpCodes.Brtrue : OpCodes.Brfalse, label);
|
2006-11-27 10:39:30 +03:00
|
|
|
}
|
|
|
|
|
2008-02-15 18:32:51 +03:00
|
|
|
internal enum Comparison
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
2008-02-15 18:32:51 +03:00
|
|
|
LessOrEqual,
|
|
|
|
LessThan,
|
|
|
|
GreaterOrEqual,
|
|
|
|
GreaterThan
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
private void EmitBcc(Comparison comp, CodeEmitterLabel label)
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
|
|
|
switch (comp)
|
|
|
|
{
|
|
|
|
case Comparison.LessOrEqual:
|
|
|
|
Emit(OpCodes.Ble, label);
|
|
|
|
break;
|
|
|
|
case Comparison.LessThan:
|
|
|
|
Emit(OpCodes.Blt, label);
|
|
|
|
break;
|
|
|
|
case Comparison.GreaterOrEqual:
|
|
|
|
Emit(OpCodes.Bge, label);
|
|
|
|
break;
|
|
|
|
case Comparison.GreaterThan:
|
|
|
|
Emit(OpCodes.Bgt, label);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal void LazyEmit_if_le_lt_ge_gt(Comparison comp, CodeEmitterLabel label)
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
CmpExpr cmp = PeekStack() as CmpExpr;
|
2008-02-15 18:32:51 +03:00
|
|
|
if (cmp != null)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PopStack();
|
2008-02-15 18:32:51 +03:00
|
|
|
cmp.EmitBcc(this, comp, label);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Emit(OpCodes.Ldc_I4_0);
|
|
|
|
EmitBcc(comp, label);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmit_lcmp()
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new LCmpExpr());
|
2008-02-15 18:32:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmit_fcmpl()
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new FCmplExpr());
|
2008-02-15 18:32:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmit_fcmpg()
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new FCmpgExpr());
|
2008-02-15 18:32:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmit_dcmpl()
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new DCmplExpr());
|
2008-02-15 18:32:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmit_dcmpg()
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PushStack(new DCmpgExpr());
|
2008-02-15 18:32:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmitAnd_I4(int v2)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
ConstIntExpr v1 = PeekStack() as ConstIntExpr;
|
2008-02-15 18:32:51 +03:00
|
|
|
if (v1 != null)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PopStack();
|
2008-02-15 18:32:51 +03:00
|
|
|
LazyEmitLdc_I4(v1.i & v2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LazyEmitLdc_I4(v2);
|
|
|
|
Emit(OpCodes.And);
|
2006-11-27 10:39:30 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
internal void LazyEmit_baload()
|
|
|
|
{
|
|
|
|
PushStack(new ByteArrayLoadExpr());
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool Match<T1, T2>(out T1 t1, out T2 t2)
|
|
|
|
where T1 : Expr
|
|
|
|
where T2 : Expr
|
|
|
|
{
|
|
|
|
if (topOfStack < 2)
|
|
|
|
{
|
|
|
|
t1 = null;
|
|
|
|
t2 = null;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
t1 = stackArray[topOfStack - 1] as T1;
|
|
|
|
t2 = stackArray[topOfStack - 2] as T2;
|
|
|
|
return t1 != null && t2 != null;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmit_iand()
|
|
|
|
{
|
|
|
|
ConstIntExpr v1;
|
|
|
|
ByteArrayLoadExpr v2;
|
|
|
|
if (Match(out v1, out v2) && v1.i == 0xFF)
|
|
|
|
{
|
|
|
|
PopStack();
|
|
|
|
PopStack();
|
|
|
|
Emit(OpCodes.Ldelem_U1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Emit(OpCodes.And);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmit_land()
|
|
|
|
{
|
|
|
|
ConstLongExpr v1;
|
|
|
|
ConvertLong v2;
|
|
|
|
if (Match(out v1, out v2) && v1.l == 0xFF && v2.Expr is ByteArrayLoadExpr)
|
|
|
|
{
|
|
|
|
PopStack();
|
|
|
|
PopStack();
|
|
|
|
Emit(OpCodes.Ldelem_U1);
|
|
|
|
Emit(OpCodes.Conv_I8);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Emit(OpCodes.And);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void LazyEmit_i2l()
|
|
|
|
{
|
|
|
|
PushStack(new ConvertLong(PopStack()));
|
|
|
|
}
|
|
|
|
|
2007-06-12 13:47:40 +04:00
|
|
|
internal string PopLazyLdstr()
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
ConstStringExpr str = PeekStack() as ConstStringExpr;
|
2007-06-12 13:47:40 +04:00
|
|
|
if(str != null)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
PopStack();
|
2007-06-12 13:47:40 +04:00
|
|
|
return str.str;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2009-03-02 09:31:55 +03:00
|
|
|
internal TypeWrapper PeekLazyClassLiteral()
|
|
|
|
{
|
|
|
|
ClassLiteralExpr lit = PeekStack() as ClassLiteralExpr;
|
|
|
|
if (lit != null)
|
|
|
|
{
|
|
|
|
return lit.Type;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2005-12-19 18:12:49 +03:00
|
|
|
private void LazyGen()
|
2004-11-04 15:50:28 +03:00
|
|
|
{
|
2006-01-02 13:59:51 +03:00
|
|
|
if(lazyBranch != null)
|
|
|
|
{
|
2010-01-28 12:18:33 +03:00
|
|
|
#if !STATIC_COMPILER
|
2006-01-02 13:59:51 +03:00
|
|
|
offset += OpCodes.Br.Size + 4;
|
2009-08-13 11:16:19 +04:00
|
|
|
#endif
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen_real.Emit(OpCodes.Br, lazyBranch.Label);
|
2006-01-02 13:59:51 +03:00
|
|
|
lazyBranch = null;
|
|
|
|
}
|
2009-02-27 09:17:06 +03:00
|
|
|
int len = topOfStack;
|
|
|
|
topOfStack = 0;
|
|
|
|
for(int i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
stackArray[i].Emit(this);
|
|
|
|
}
|
2004-11-04 15:50:28 +03:00
|
|
|
}
|
2005-12-19 18:12:49 +03:00
|
|
|
|
2009-04-06 14:10:17 +04:00
|
|
|
internal void CheckLabels()
|
2005-12-19 18:12:49 +03:00
|
|
|
{
|
|
|
|
#if LABELCHECK
|
|
|
|
foreach(System.Diagnostics.StackFrame frame in labels.Values)
|
|
|
|
{
|
|
|
|
string name = frame.GetFileName() + ":" + frame.GetFileLineNumber();
|
|
|
|
IKVM.Internal.JVM.CriticalFailure("Label failure: " + name, null);
|
|
|
|
}
|
2004-11-04 15:50:28 +03:00
|
|
|
#endif
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2006-11-27 10:39:30 +03:00
|
|
|
|
|
|
|
abstract class Expr
|
|
|
|
{
|
2009-07-14 11:25:46 +04:00
|
|
|
internal virtual bool HasSideEffect { get { return false; } }
|
2006-11-27 10:39:30 +03:00
|
|
|
|
2009-03-02 07:52:05 +03:00
|
|
|
internal virtual bool IsIncomplete { get { return false; } }
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal abstract void Emit(CodeEmitter ilgen);
|
2006-11-27 10:39:30 +03:00
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
abstract class UnaryExpr : Expr
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
internal readonly Expr Expr;
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
protected UnaryExpr(Expr expr)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
this.Expr = expr;
|
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
internal sealed override bool IsIncomplete
|
2009-03-02 07:52:05 +03:00
|
|
|
{
|
|
|
|
get { return Expr == null; }
|
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
internal override bool HasSideEffect
|
|
|
|
{
|
|
|
|
get { return Expr != null && Expr.HasSideEffect; }
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
if (Expr != null)
|
|
|
|
{
|
|
|
|
Expr.Emit(ilgen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
abstract class ExprWithExprAndType : UnaryExpr
|
|
|
|
{
|
|
|
|
internal readonly Type Type;
|
|
|
|
|
|
|
|
protected ExprWithExprAndType(Expr expr, Type type)
|
|
|
|
: base(expr)
|
|
|
|
{
|
|
|
|
this.Type = type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class BoxExpr : ExprWithExprAndType
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
internal BoxExpr(Expr expr, Type type)
|
|
|
|
: base(expr, type)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
base.Emit(ilgen);
|
|
|
|
ilgen.Emit(OpCodes.Box, Type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
sealed class UnboxExpr : ExprWithExprAndType
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
internal UnboxExpr(Expr expr, Type type)
|
|
|
|
: base(expr, type)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
base.Emit(ilgen);
|
|
|
|
ilgen.Emit(OpCodes.Unbox, Type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
sealed class BoxUnboxExpr : ExprWithExprAndType
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
internal BoxUnboxExpr(Expr expr, Type type)
|
|
|
|
: base(expr, type)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
base.Emit(ilgen);
|
|
|
|
// unbox leaves a pointer to the value of the stack (instead of the value)
|
|
|
|
// so we have to copy the value into a local variable and load the address
|
|
|
|
// of the local onto the stack
|
|
|
|
LocalBuilder local = ilgen.DeclareLocal(Type);
|
|
|
|
ilgen.Emit(OpCodes.Stloc, local);
|
|
|
|
ilgen.Emit(OpCodes.Ldloca, local);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
sealed class LdobjExpr : ExprWithExprAndType
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
internal LdobjExpr(Expr expr, Type type)
|
|
|
|
: base(expr, type)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
base.Emit(ilgen);
|
|
|
|
ilgen.Emit(OpCodes.Ldobj, Type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
sealed class NullExpr : Expr
|
2009-02-27 09:17:06 +03:00
|
|
|
{
|
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
|
|
|
{
|
|
|
|
ilgen.Emit(OpCodes.Ldnull);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
sealed class ConstIntExpr : Expr
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
internal readonly int i;
|
|
|
|
|
|
|
|
internal ConstIntExpr(int i)
|
|
|
|
{
|
|
|
|
this.i = i;
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
switch(i)
|
|
|
|
{
|
|
|
|
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:
|
|
|
|
if(i >= -128 && i <= 127)
|
|
|
|
{
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_S, (sbyte)i);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-15 18:32:51 +03:00
|
|
|
sealed class ConstLongExpr : Expr
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
internal readonly long l;
|
|
|
|
|
|
|
|
internal ConstLongExpr(long l)
|
|
|
|
{
|
|
|
|
this.l = l;
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
2008-02-15 18:32:51 +03:00
|
|
|
switch (l)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
case -1:
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_M1);
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_0);
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_1);
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_2);
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_3);
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_4);
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_5);
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_6);
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_7);
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_8);
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
break;
|
|
|
|
default:
|
2008-02-15 18:32:51 +03:00
|
|
|
if (l >= -2147483648L && l <= 4294967295L)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
2008-02-15 18:32:51 +03:00
|
|
|
if (l >= -128 && l <= 127)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4_S, (sbyte)l);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I4, (int)l);
|
|
|
|
}
|
2008-02-15 18:32:51 +03:00
|
|
|
if (l < 0)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ilgen.Emit(OpCodes.Conv_U8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ilgen.Emit(OpCodes.Ldc_I8, l);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-15 18:32:51 +03:00
|
|
|
sealed class ConstStringExpr : Expr
|
2007-06-12 13:47:40 +04:00
|
|
|
{
|
|
|
|
internal readonly string str;
|
|
|
|
|
|
|
|
internal ConstStringExpr(string str)
|
|
|
|
{
|
|
|
|
this.str = str;
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
2007-06-12 13:47:40 +04:00
|
|
|
{
|
|
|
|
ilgen.Emit(OpCodes.Ldstr, str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-15 18:32:51 +03:00
|
|
|
sealed class InstanceOfExpr : Expr
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
internal readonly Type Type;
|
|
|
|
|
2006-11-27 10:39:30 +03:00
|
|
|
internal InstanceOfExpr(Type type)
|
|
|
|
{
|
2009-02-27 09:17:06 +03:00
|
|
|
this.Type = type;
|
2006-11-27 10:39:30 +03:00
|
|
|
}
|
|
|
|
|
2009-03-02 07:52:05 +03:00
|
|
|
internal override bool IsIncomplete
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
2006-11-27 10:39:30 +03:00
|
|
|
{
|
|
|
|
ilgen.Emit(OpCodes.Isinst, this.Type);
|
|
|
|
ilgen.Emit(OpCodes.Ldnull);
|
|
|
|
ilgen.Emit(OpCodes.Cgt_Un);
|
|
|
|
}
|
|
|
|
}
|
2008-02-15 18:32:51 +03:00
|
|
|
|
|
|
|
abstract class CmpExpr : Expr
|
|
|
|
{
|
|
|
|
internal CmpExpr()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-03-02 07:52:05 +03:00
|
|
|
internal override bool IsIncomplete
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal abstract void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label);
|
2008-02-15 18:32:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
sealed class LCmpExpr : CmpExpr
|
|
|
|
{
|
|
|
|
internal LCmpExpr()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal sealed override void Emit(CodeEmitter ilgen)
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
2009-10-14 18:58:41 +04:00
|
|
|
LocalBuilder value1 = ilgen.AllocTempLocal(Types.Int64);
|
|
|
|
LocalBuilder value2 = ilgen.AllocTempLocal(Types.Int64);
|
2008-02-15 18:32:51 +03:00
|
|
|
ilgen.Emit(OpCodes.Stloc, value2);
|
|
|
|
ilgen.Emit(OpCodes.Stloc, value1);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value1);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value2);
|
|
|
|
ilgen.Emit(OpCodes.Cgt);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value1);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value2);
|
|
|
|
ilgen.Emit(OpCodes.Clt);
|
|
|
|
ilgen.Emit(OpCodes.Sub);
|
|
|
|
ilgen.ReleaseTempLocal(value2);
|
|
|
|
ilgen.ReleaseTempLocal(value1);
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal sealed override void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label)
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
|
|
|
ilgen.EmitBcc(comp, label);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class FCmplExpr : CmpExpr
|
|
|
|
{
|
|
|
|
protected virtual Type FloatOrDouble()
|
|
|
|
{
|
2009-10-14 18:58:41 +04:00
|
|
|
return Types.Single;
|
2008-02-15 18:32:51 +03:00
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal sealed override void Emit(CodeEmitter ilgen)
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
|
|
|
LocalBuilder value1 = ilgen.AllocTempLocal(FloatOrDouble());
|
|
|
|
LocalBuilder value2 = ilgen.AllocTempLocal(FloatOrDouble());
|
|
|
|
ilgen.Emit(OpCodes.Stloc, value2);
|
|
|
|
ilgen.Emit(OpCodes.Stloc, value1);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value1);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value2);
|
|
|
|
ilgen.Emit(OpCodes.Cgt);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value1);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value2);
|
|
|
|
ilgen.Emit(OpCodes.Clt_Un);
|
|
|
|
ilgen.Emit(OpCodes.Sub);
|
|
|
|
ilgen.ReleaseTempLocal(value1);
|
|
|
|
ilgen.ReleaseTempLocal(value2);
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal sealed override void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label)
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
|
|
|
switch (comp)
|
|
|
|
{
|
|
|
|
case Comparison.LessOrEqual:
|
|
|
|
ilgen.Emit(OpCodes.Ble_Un, label);
|
|
|
|
break;
|
|
|
|
case Comparison.LessThan:
|
|
|
|
ilgen.Emit(OpCodes.Blt_Un, label);
|
|
|
|
break;
|
|
|
|
case Comparison.GreaterOrEqual:
|
|
|
|
ilgen.Emit(OpCodes.Bge, label);
|
|
|
|
break;
|
|
|
|
case Comparison.GreaterThan:
|
|
|
|
ilgen.Emit(OpCodes.Bgt, label);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class FCmpgExpr : CmpExpr
|
|
|
|
{
|
|
|
|
protected virtual Type FloatOrDouble()
|
|
|
|
{
|
2009-10-14 18:58:41 +04:00
|
|
|
return Types.Single;
|
2008-02-15 18:32:51 +03:00
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal sealed override void Emit(CodeEmitter ilgen)
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
|
|
|
LocalBuilder value1 = ilgen.AllocTempLocal(FloatOrDouble());
|
|
|
|
LocalBuilder value2 = ilgen.AllocTempLocal(FloatOrDouble());
|
|
|
|
ilgen.Emit(OpCodes.Stloc, value2);
|
|
|
|
ilgen.Emit(OpCodes.Stloc, value1);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value1);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value2);
|
|
|
|
ilgen.Emit(OpCodes.Cgt_Un);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value1);
|
|
|
|
ilgen.Emit(OpCodes.Ldloc, value2);
|
|
|
|
ilgen.Emit(OpCodes.Clt);
|
|
|
|
ilgen.Emit(OpCodes.Sub);
|
|
|
|
ilgen.ReleaseTempLocal(value1);
|
|
|
|
ilgen.ReleaseTempLocal(value2);
|
|
|
|
}
|
|
|
|
|
2008-06-03 16:10:07 +04:00
|
|
|
internal sealed override void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label)
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
|
|
|
switch (comp)
|
|
|
|
{
|
|
|
|
case Comparison.LessOrEqual:
|
|
|
|
ilgen.Emit(OpCodes.Ble, label);
|
|
|
|
break;
|
|
|
|
case Comparison.LessThan:
|
|
|
|
ilgen.Emit(OpCodes.Blt, label);
|
|
|
|
break;
|
|
|
|
case Comparison.GreaterOrEqual:
|
|
|
|
ilgen.Emit(OpCodes.Bge_Un, label);
|
|
|
|
break;
|
|
|
|
case Comparison.GreaterThan:
|
|
|
|
ilgen.Emit(OpCodes.Bgt_Un, label);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
sealed class DCmplExpr : FCmplExpr
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
|
|
|
protected override Type FloatOrDouble()
|
|
|
|
{
|
2009-10-14 18:58:41 +04:00
|
|
|
return Types.Double;
|
2008-02-15 18:32:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
sealed class DCmpgExpr : FCmpgExpr
|
2008-02-15 18:32:51 +03:00
|
|
|
{
|
|
|
|
protected override Type FloatOrDouble()
|
|
|
|
{
|
2009-10-14 18:58:41 +04:00
|
|
|
return Types.Double;
|
2008-02-15 18:32:51 +03:00
|
|
|
}
|
|
|
|
}
|
2009-02-27 09:17:06 +03:00
|
|
|
|
2009-07-14 11:25:46 +04:00
|
|
|
sealed class ClassLiteralExpr : Expr
|
2009-02-27 09:17:06 +03:00
|
|
|
{
|
2009-03-02 09:31:55 +03:00
|
|
|
internal readonly TypeWrapper Type;
|
2009-02-27 09:17:06 +03:00
|
|
|
|
2009-03-02 09:31:55 +03:00
|
|
|
internal ClassLiteralExpr(TypeWrapper type)
|
2009-02-27 09:17:06 +03:00
|
|
|
{
|
2009-03-02 09:31:55 +03:00
|
|
|
this.Type = type;
|
2009-02-27 09:17:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
|
|
|
{
|
2009-07-13 12:34:37 +04:00
|
|
|
Type.EmitClassLiteral(ilgen);
|
2009-02-27 09:17:06 +03:00
|
|
|
}
|
|
|
|
}
|
2009-07-14 11:25:46 +04:00
|
|
|
|
|
|
|
sealed class ByteArrayLoadExpr : Expr
|
|
|
|
{
|
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
|
|
|
{
|
|
|
|
ilgen.Emit(OpCodes.Ldelem_I1);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override bool HasSideEffect
|
|
|
|
{
|
|
|
|
get { return true; }
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override bool IsIncomplete
|
|
|
|
{
|
|
|
|
get { return true; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class ConvertLong : UnaryExpr
|
|
|
|
{
|
|
|
|
internal ConvertLong(Expr expr)
|
|
|
|
: base(expr)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Emit(CodeEmitter ilgen)
|
|
|
|
{
|
|
|
|
base.Emit(ilgen);
|
|
|
|
ilgen.Emit(OpCodes.Conv_I8);
|
|
|
|
}
|
|
|
|
}
|
2004-11-04 15:50:28 +03:00
|
|
|
}
|
2003-05-30 16:08:59 +04:00
|
|
|
}
|