/*
- Copyright (C) 2008-2011 Jeroen Frijters
+ Copyright (C) 2008-2012 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
using System.Collections.Generic;
using System.Diagnostics.SymbolStore;
using System.Diagnostics;
-using IKVM.Reflection.Metadata;
using IKVM.Reflection.Writer;
namespace IKVM.Reflection.Emit
}
}
- sealed class MarkerType : Type
- {
- public override Type BaseType
- {
- get { throw new InvalidOperationException(); }
- }
-
- public override TypeAttributes Attributes
- {
- get { throw new InvalidOperationException(); }
- }
-
- public override string Name
- {
- get { throw new InvalidOperationException(); }
- }
-
- public override string FullName
- {
- get { throw new InvalidOperationException(); }
- }
-
- public override Module Module
- {
- get { throw new InvalidOperationException(); }
- }
- }
-
public sealed class ILGenerator
{
- private static readonly Type FAULT = new MarkerType();
- private static readonly Type FINALLY = new MarkerType();
- private static readonly Type FILTER = new MarkerType();
private readonly ModuleBuilder moduleBuilder;
private readonly ByteBuffer code;
- private readonly List<LocalBuilder> locals = new List<LocalBuilder>();
- private List<CustomModifiers> localCustomModifiers;
+ private readonly SignatureHelper locals;
+ private int localsCount;
private readonly List<int> tokenFixups = new List<int>();
private readonly List<int> labels = new List<int>();
private readonly List<int> labelStackHeight = new List<int>();
internal int tryLength;
internal int handlerOffset;
internal int handlerLength;
- internal Type exceptionType; // FINALLY = finally block, FILTER = handler with filter, FAULT = fault block
+ internal Type exceptionType; // MarkerType.Finally = finally block, MarkerType.Filter = handler with filter, MarkerType.Fault = fault block
internal int filterOffset;
internal ExceptionBlock(int ordinal)
{
this.code = new ByteBuffer(initialCapacity);
this.moduleBuilder = moduleBuilder;
+ this.locals = SignatureHelper.GetLocalVarSigHelper(moduleBuilder);
if (moduleBuilder.symbolWriter != null)
{
scope = new Scope(null);
}
}
- private bool IsLabelReachable(Label label)
- {
- return labelStackHeight[label.Index] != -1;
- }
-
// non-standard API
public void __DisableExceptionBlockAssistance()
{
UpdateStack(1);
if (exceptionType == null)
{
- if (block.exceptionType != FILTER || block.handlerOffset != 0)
+ if (block.exceptionType != MarkerType.Filter || block.handlerOffset != 0)
{
throw new ArgumentNullException("exceptionType");
}
exceptionStack.Push(block);
}
block.exceptionType = exceptionType;
- if (exceptionType == FILTER)
+ if (exceptionType == MarkerType.Filter)
{
block.filterOffset = code.Position;
}
public void BeginExceptFilterBlock()
{
- BeginCatchBlock(FILTER);
+ BeginCatchBlock(MarkerType.Filter);
}
public void BeginFaultBlock()
{
- BeginFinallyFaultBlock(FAULT);
+ BeginFinallyFaultBlock(MarkerType.Fault);
}
public void BeginFinallyBlock()
{
- BeginFinallyFaultBlock(FINALLY);
+ BeginFinallyFaultBlock(MarkerType.Finally);
}
private void BeginFinallyFaultBlock(Type type)
ExceptionBlock block = exceptionStack.Pop();
if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
{
- if (block.filterOffset != 0 || (block.exceptionType != FINALLY && block.exceptionType != FAULT))
+ if (block.filterOffset != 0 || (block.exceptionType != MarkerType.Finally && block.exceptionType != MarkerType.Fault))
{
Emit(OpCodes.Leave, block.labelEnd);
}
public LocalBuilder DeclareLocal(Type localType, bool pinned)
{
- LocalBuilder local = new LocalBuilder(localType, locals.Count, pinned);
- locals.Add(local);
+ LocalBuilder local = new LocalBuilder(localType, localsCount++, pinned);
+ locals.AddArgument(localType, pinned);
if (scope != null)
{
scope.locals.Add(local);
public LocalBuilder __DeclareLocal(Type localType, bool pinned, CustomModifiers customModifiers)
{
- if (!customModifiers.IsEmpty)
+ LocalBuilder local = new LocalBuilder(localType, localsCount++, pinned);
+ locals.__AddArgument(localType, pinned, customModifiers);
+ if (scope != null)
{
- if (localCustomModifiers == null)
- {
- localCustomModifiers = new List<CustomModifiers>();
- }
- // we lazily fill up the list (to sync with the locals list) and we don't need to
- // make sure that the list has the same length as the locals list, because
- // Signature.WriteLocalVarSig() can tolerate that.
- while (localCustomModifiers.Count < locals.Count)
- {
- localCustomModifiers.Add(new CustomModifiers());
- }
- localCustomModifiers.Add(customModifiers);
+ scope.locals.Add(local);
}
- return DeclareLocal(localType, pinned);
+ return local;
}
public Label DefineLabel()
public void Emit(OpCode opc, string str)
{
Emit(opc);
- code.Write(0x70000000 | moduleBuilder.UserStrings.Add(str));
+ code.Write(moduleBuilder.GetStringConstant(str).Token);
}
public void Emit(OpCode opc, Type type)
{
Emit(opcode);
UpdateStack(opcode, signature.HasThis, signature.ReturnType, signature.ParameterCount);
- code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(signature.GetSignature(moduleBuilder))));
+ code.Write(moduleBuilder.GetSignatureToken(signature).Token);
}
public void EmitCall(OpCode opc, MethodInfo method, Type[] optionalParameterTypes)
{
Emit(opc);
UpdateStack(opc, method.HasThis, method.ReturnType, method.ParameterCount + optionalParameterTypes.Length);
- ByteBuffer sig = new ByteBuffer(16);
- method.MethodSignature.WriteMethodRefSig(moduleBuilder, sig, optionalParameterTypes, customModifiers);
- MemberRefTable.Record record = new MemberRefTable.Record();
- if (method.Module == moduleBuilder)
- {
- record.Class = method.MetadataToken;
- }
- else
- {
- record.Class = moduleBuilder.GetTypeTokenForMemberRef(method.DeclaringType ?? method.Module.GetModuleType());
- }
- record.Name = moduleBuilder.Strings.Add(method.Name);
- record.Signature = moduleBuilder.Blobs.Add(sig);
- code.Write(0x0A000000 | moduleBuilder.MemberRef.FindOrAddRecord(record));
+ code.Write(moduleBuilder.__GetMethodToken(method, optionalParameterTypes, customModifiers).Token);
}
}
public void EmitCalli(OpCode opc, CallingConvention callingConvention, Type returnType, Type[] parameterTypes)
{
- __EmitCalli(opc, moduleBuilder.universe.MakeStandAloneMethodSig(callingConvention, returnType, new CustomModifiers(), parameterTypes, null));
+ SignatureHelper sig = SignatureHelper.GetMethodSigHelper(moduleBuilder, callingConvention, returnType);
+ sig.AddArguments(parameterTypes, null, null);
+ Emit(opc, sig);
}
public void EmitCalli(OpCode opc, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
{
- __EmitCalli(opc, moduleBuilder.universe.MakeStandAloneMethodSig(callingConvention, returnType, new CustomModifiers(), parameterTypes, optionalParameterTypes, null));
+ SignatureHelper sig = SignatureHelper.GetMethodSigHelper(moduleBuilder, callingConvention, returnType);
+ sig.AddArguments(parameterTypes, null, null);
+ sig.AddSentinel();
+ sig.AddArguments(optionalParameterTypes, null, null);
+ Emit(opc, sig);
}
public void __EmitCalli(OpCode opc, __StandAloneMethodSig sig)
int localVarSigTok = 0;
int rva;
- if (locals.Count == 0 && exceptions.Count == 0 && maxStack <= 8 && code.Length < 64 && !fatHeader)
+ if (localsCount == 0 && exceptions.Count == 0 && maxStack <= 8 && code.Length < 64 && !fatHeader)
{
rva = WriteTinyHeaderAndCode(bb);
}
bb.Align(4);
int rva = bb.Position;
- if (locals.Count != 0)
+ if (localsCount != 0)
{
- ByteBuffer localVarSig = new ByteBuffer(locals.Count + 2);
- Signature.WriteLocalVarSig(moduleBuilder, localVarSig, locals, localCustomModifiers);
- localVarSigTok = 0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(localVarSig));
+ localVarSigTok = moduleBuilder.GetSignatureToken(locals).Token;
}
const byte CorILMethod_FatFormat = 0x03;
bb.Write((short)(dataSize >> 8));
foreach (ExceptionBlock block in exceptions)
{
- if (block.exceptionType == FAULT)
+ if (block.exceptionType == MarkerType.Fault)
{
bb.Write((int)COR_ILEXCEPTION_CLAUSE_FAULT);
}
- else if (block.exceptionType == FILTER)
+ else if (block.exceptionType == MarkerType.Filter)
{
bb.Write((int)COR_ILEXCEPTION_CLAUSE_FILTER);
}
- else if (block.exceptionType == FINALLY)
+ else if (block.exceptionType == MarkerType.Finally)
{
bb.Write((int)COR_ILEXCEPTION_CLAUSE_FINALLY);
}
bb.Write(block.tryLength);
bb.Write(block.handlerOffset);
bb.Write(block.handlerLength);
- if (block.exceptionType != FAULT && block.exceptionType != FILTER && block.exceptionType != FINALLY)
+ if (block.exceptionType != MarkerType.Fault && block.exceptionType != MarkerType.Filter && block.exceptionType != MarkerType.Finally)
{
bb.Write(moduleBuilder.GetTypeTokenForMemberRef(block.exceptionType));
}
bb.Write((short)0);
foreach (ExceptionBlock block in exceptions)
{
- if (block.exceptionType == FAULT)
+ if (block.exceptionType == MarkerType.Fault)
{
bb.Write(COR_ILEXCEPTION_CLAUSE_FAULT);
}
- else if (block.exceptionType == FILTER)
+ else if (block.exceptionType == MarkerType.Filter)
{
bb.Write(COR_ILEXCEPTION_CLAUSE_FILTER);
}
- else if (block.exceptionType == FINALLY)
+ else if (block.exceptionType == MarkerType.Finally)
{
bb.Write(COR_ILEXCEPTION_CLAUSE_FINALLY);
}
bb.Write((byte)block.tryLength);
bb.Write((short)block.handlerOffset);
bb.Write((byte)block.handlerLength);
- if (block.exceptionType != FAULT && block.exceptionType != FILTER && block.exceptionType != FINALLY)
+ if (block.exceptionType != MarkerType.Fault && block.exceptionType != MarkerType.Filter && block.exceptionType != MarkerType.Finally)
{
bb.Write(moduleBuilder.GetTypeTokenForMemberRef(block.exceptionType));
}