зеркало из https://github.com/mono/ikvm-fork.git
Added new .NET 4.5 methods ConstructorBuilder.SetMethodBody() and MethodBuilder.SetMethodBody(). Note that the implementation is currently completely untested.
This commit is contained in:
Родитель
62d4e09303
Коммит
6e68dacc83
|
@ -22,6 +22,7 @@
|
|||
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IKVM.Reflection.Emit
|
||||
{
|
||||
|
@ -122,6 +123,11 @@ namespace IKVM.Reflection.Emit
|
|||
set { methodBuilder.InitLocals = value; }
|
||||
}
|
||||
|
||||
public void SetMethodBody(byte[] il, int maxStack, byte[] localSignature, IEnumerable<ExceptionHandler> exceptionHandlers, IEnumerable<int> tokenFixups)
|
||||
{
|
||||
methodBuilder.SetMethodBody(il, maxStack, localSignature, exceptionHandlers, tokenFixups);
|
||||
}
|
||||
|
||||
internal override MethodInfo GetMethodInfo()
|
||||
{
|
||||
return methodBuilder;
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Copyright (C) 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
|
||||
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;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IKVM.Reflection.Emit
|
||||
{
|
||||
public struct ExceptionHandler : IEquatable<ExceptionHandler>
|
||||
{
|
||||
private readonly int tryOffset;
|
||||
private readonly int tryLength;
|
||||
private readonly int filterOffset;
|
||||
private readonly int handlerOffset;
|
||||
private readonly int handlerLength;
|
||||
private readonly ExceptionHandlingClauseOptions kind;
|
||||
private readonly int exceptionTypeToken;
|
||||
|
||||
public ExceptionHandler(int tryOffset, int tryLength, int filterOffset, int handlerOffset, int handlerLength, ExceptionHandlingClauseOptions kind, int exceptionTypeToken)
|
||||
{
|
||||
if (tryOffset < 0 || tryLength < 0 || filterOffset < 0 || handlerOffset < 0 || handlerLength < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
this.tryOffset = tryOffset;
|
||||
this.tryLength = tryLength;
|
||||
this.filterOffset = filterOffset;
|
||||
this.handlerOffset = handlerOffset;
|
||||
this.handlerLength = handlerLength;
|
||||
this.kind = kind;
|
||||
this.exceptionTypeToken = exceptionTypeToken;
|
||||
}
|
||||
|
||||
public int TryOffset
|
||||
{
|
||||
get { return tryOffset; }
|
||||
}
|
||||
|
||||
public int TryLength
|
||||
{
|
||||
get { return tryLength; }
|
||||
}
|
||||
|
||||
public int FilterOffset
|
||||
{
|
||||
get { return filterOffset; }
|
||||
}
|
||||
|
||||
public int HandlerOffset
|
||||
{
|
||||
get { return handlerOffset; }
|
||||
}
|
||||
|
||||
public int HandlerLength
|
||||
{
|
||||
get { return handlerLength; }
|
||||
}
|
||||
|
||||
public ExceptionHandlingClauseOptions Kind
|
||||
{
|
||||
get { return kind; }
|
||||
}
|
||||
|
||||
public int ExceptionTypeToken
|
||||
{
|
||||
get { return exceptionTypeToken; }
|
||||
}
|
||||
|
||||
public bool Equals(ExceptionHandler other)
|
||||
{
|
||||
return tryOffset == other.tryOffset
|
||||
&& tryLength == other.tryLength
|
||||
&& filterOffset == other.filterOffset
|
||||
&& handlerOffset == other.handlerOffset
|
||||
&& handlerLength == other.handlerLength
|
||||
&& kind == other.kind
|
||||
&& exceptionTypeToken == other.exceptionTypeToken;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
ExceptionHandler? other = obj as ExceptionHandler?;
|
||||
return other != null && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return tryOffset ^ tryLength * 33 ^ filterOffset * 333 ^ handlerOffset * 3333 ^ handlerLength * 33333;
|
||||
}
|
||||
|
||||
public static bool operator ==(ExceptionHandler left, ExceptionHandler right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
public static bool operator !=(ExceptionHandler left, ExceptionHandler right)
|
||||
{
|
||||
return !left.Equals(right);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -622,6 +622,114 @@ namespace IKVM.Reflection.Emit
|
|||
this.ModuleBuilder.AddUnmanagedExport(name, ordinal, this, new RelativeVirtualAddress(0xFFFFFFFF));
|
||||
}
|
||||
|
||||
public void SetMethodBody(byte[] il, int maxStack, byte[] localSignature, IEnumerable<ExceptionHandler> exceptionHandlers, IEnumerable<int> tokenFixups)
|
||||
{
|
||||
// TODO this should be refactored to share code with ILGenerator
|
||||
// TODO for now we always write a fat header
|
||||
ByteBuffer bb = this.ModuleBuilder.methodBodies;
|
||||
// fat headers require 4-byte alignment
|
||||
bb.Align(4);
|
||||
rva = bb.Position;
|
||||
|
||||
const byte CorILMethod_FatFormat = 0x03;
|
||||
const byte CorILMethod_MoreSects = 0x08;
|
||||
const byte CorILMethod_InitLocals = 0x10;
|
||||
|
||||
short flagsAndSize = (short)(CorILMethod_FatFormat | (3 << 12));
|
||||
if (initLocals)
|
||||
{
|
||||
flagsAndSize |= CorILMethod_InitLocals;
|
||||
}
|
||||
|
||||
List<ExceptionHandler> exceptions = new List<ExceptionHandler>(exceptionHandlers ?? Empty<ExceptionHandler>.Array);
|
||||
if (exceptions.Count > 0)
|
||||
{
|
||||
flagsAndSize |= CorILMethod_MoreSects;
|
||||
}
|
||||
|
||||
bb.Write(flagsAndSize);
|
||||
bb.Write(maxStack);
|
||||
bb.Write(il.Length);
|
||||
bb.Write(localSignature == null ? 0 : this.ModuleBuilder.GetSignatureToken(localSignature, localSignature.Length).Token);
|
||||
|
||||
int codeOffset = bb.Position;
|
||||
foreach (int fixup in tokenFixups)
|
||||
{
|
||||
this.ModuleBuilder.tokenFixupOffsets.Add(fixup + codeOffset);
|
||||
}
|
||||
bb.Write(il);
|
||||
|
||||
if (exceptions.Count > 0)
|
||||
{
|
||||
bb.Align(4);
|
||||
|
||||
bool fat = false;
|
||||
if (exceptions.Count * 12 + 4 > 255)
|
||||
{
|
||||
fat = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (ExceptionHandler block in exceptions)
|
||||
{
|
||||
if (block.TryOffset > 65535 || block.TryLength > 255 || block.HandlerOffset > 65535 || block.HandlerLength > 255)
|
||||
{
|
||||
fat = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const byte CorILMethod_Sect_EHTable = 0x1;
|
||||
const byte CorILMethod_Sect_FatFormat = 0x40;
|
||||
|
||||
if (fat)
|
||||
{
|
||||
bb.Write((byte)(CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat));
|
||||
int dataSize = exceptions.Count * 24 + 4;
|
||||
bb.Write((byte)dataSize);
|
||||
bb.Write((short)(dataSize >> 8));
|
||||
foreach (ExceptionHandler block in exceptions)
|
||||
{
|
||||
bb.Write((int)block.Kind);
|
||||
bb.Write(block.TryOffset);
|
||||
bb.Write(block.TryLength);
|
||||
bb.Write(block.HandlerOffset);
|
||||
bb.Write(block.HandlerLength);
|
||||
if (block.Kind == ExceptionHandlingClauseOptions.Filter)
|
||||
{
|
||||
bb.Write(block.FilterOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
bb.Write(block.ExceptionTypeToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bb.Write(CorILMethod_Sect_EHTable);
|
||||
bb.Write((byte)(exceptions.Count * 12 + 4));
|
||||
bb.Write((short)0);
|
||||
foreach (ExceptionHandler block in exceptions)
|
||||
{
|
||||
bb.Write((short)block.Kind);
|
||||
bb.Write((short)block.TryOffset);
|
||||
bb.Write((byte)block.TryLength);
|
||||
bb.Write((short)block.HandlerOffset);
|
||||
bb.Write((byte)block.HandlerLength);
|
||||
if (block.Kind == ExceptionHandlingClauseOptions.Filter)
|
||||
{
|
||||
bb.Write(block.FilterOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
bb.Write(block.ExceptionTypeToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void Bake()
|
||||
{
|
||||
this.nameIndex = this.ModuleBuilder.Strings.Add(name);
|
||||
|
|
Загрузка…
Ссылка в новой задаче