Cosmos/source/Indy.IL2CPU.IL/MethodInformation.cs
2008-05-13 14:27:29 +00:00

230 lines
No EOL
9 KiB
C#

using System;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Reflection;
namespace Indy.IL2CPU.IL {
// TODO: abstract this one out to a X86 specific one
public class MethodInformation {
public struct Variable {
public Variable(int aOffset,
int aSize,
bool aIsReferenceTypeField,
Type aVariableType) {
Offset = aOffset;
Size = aSize;
VirtualAddresses = new string[Size / 4];
for (int i = 0; i < (Size / 4); i++) {
VirtualAddresses[i] = "ebp - 0" + (Offset + ((i + 1) * 4) + 0).ToString("X") + "h";
}
IsReferenceType = aIsReferenceTypeField;
VariableType = aVariableType;
}
public readonly int Offset;
public readonly int Size;
public readonly bool IsReferenceType;
public readonly Type VariableType;
/// <summary>
/// Gives the list of addresses to access this variable. This field contains multiple entries if the <see cref="Size"/> is larger than 4.
/// </summary>
public readonly string[] VirtualAddresses;
}
public struct Argument {
public enum KindEnum {
In,
ByRef,
Out
}
public Argument(int aSize,
int aOffset,
KindEnum aKind,
bool aIsReferenceType,
TypeInformation aTypeInfo,
Type aArgumentType) {
mSize = aSize;
mVirtualAddresses = new string[mSize / 4];
mKind = aKind;
mArgumentType = aArgumentType;
mIsReferenceType = aIsReferenceType;
mOffset = -1;
TypeInfo = aTypeInfo;
Offset = aOffset;
}
private string[] mVirtualAddresses;
public string[] VirtualAddresses {
get {
return mVirtualAddresses;
}
internal set {
mVirtualAddresses = value;
}
}
private int mSize;
public int Size {
get {
return mSize;
}
internal set {
mSize = value;
}
}
private bool mIsReferenceType;
public bool IsReferenceType {
get {
return mIsReferenceType;
}
internal set {
mIsReferenceType = value;
}
}
private int mOffset;
public int Offset {
get {
return mOffset;
}
internal set {
if (mOffset != value) {
mOffset = value;
for (int i = 0; i < (mSize / 4); i++) {
mVirtualAddresses[i] = "ebp + 0" + (mOffset + ((i + 1) * 4) + 4).ToString("X") + "h";
}
}
}
}
private KindEnum mKind;
public KindEnum Kind {
get {
return mKind;
}
internal set {
mKind = value;
}
}
private Type mArgumentType;
public Type ArgumentType {
get {
return mArgumentType;
}
internal set {
mArgumentType = value;
}
}
public readonly TypeInformation TypeInfo;
}
public MethodInformation(string aLabelName,
Variable[] aLocals,
Argument[] aArguments,
int aReturnSize,
bool aIsInstanceMethod,
TypeInformation aTypeInfo,
MethodBase aMethod,
Type aReturnType,
bool debugMode) {
Locals = aLocals;
DebugMode = debugMode;
LabelName = aLabelName;
Arguments = aArguments;
ReturnSize = aReturnSize;
IsInstanceMethod = aIsInstanceMethod;
TypeInfo = aTypeInfo;
Method = aMethod;
ReturnType = aReturnType;
LocalsSize = (from item in aLocals
let xSize = (item.Size % 4 == 0)
? item.Size
: (item.Size + (4 - (item.Size % 4)))
select xSize).Sum();
if (aMethod != null) {
IsNonDebuggable = aMethod.GetCustomAttributes(typeof(DebuggerStepThroughAttribute),
false).Length != 0 || aMethod.DeclaringType.GetCustomAttributes(typeof(DebuggerStepThroughAttribute),
false).Length != 0 || aMethod.DeclaringType.Module.GetCustomAttributes(typeof(DebuggerStepThroughAttribute),
false).Length != 0 || aMethod.DeclaringType.Assembly.GetCustomAttributes(typeof(DebuggerStepThroughAttribute),
false).Length != 0;
}
var xRoundedSize = ReturnSize;
if (xRoundedSize % 4 > 0) {
xRoundedSize += (4 - (ReturnSize % 4));
}
ExtraStackSize = xRoundedSize - (from item in aArguments
select item.Size).Sum();
if (ExtraStackSize > 0) {
for (int i = 0; i < Arguments.Length; i++) {
Arguments[i].Offset += ExtraStackSize;
}
}
}
public readonly int ExtraStackSize;
/// <summary>
/// This variable is only updated when the MethodInformation instance is supplied by the Engine.ProcessAllMethods method
/// </summary>
public ExceptionHandlingClause CurrentHandler;
public readonly MethodBase Method;
public readonly string LabelName;
public readonly Variable[] Locals;
public readonly Argument[] Arguments;
public readonly int ReturnSize;
public readonly Type ReturnType;
public readonly bool IsInstanceMethod;
public readonly TypeInformation TypeInfo;
public readonly int LocalsSize;
public readonly bool DebugMode;
public readonly bool IsNonDebuggable;
public override string ToString() {
var xSB = new StringBuilder();
xSB.AppendLine(String.Format("Method '{0}'\r\n",
Method.GetFullName()));
xSB.AppendLine("Locals:");
if (Locals.Length == 0) {
xSB.AppendLine("\t(none)");
}
var xCurIndex = 0;
foreach (var xVar in Locals) {
xSB.AppendFormat("\t({0}) {1}\t{2}\t{3} (Type = {4})\r\n\r\n",
xCurIndex++,
xVar.Offset,
xVar.Size,
xVar.VirtualAddresses.FirstOrDefault(),
xVar.VariableType.FullName);
}
xSB.AppendLine("Arguments:");
if (Arguments.Length == 0) {
xSB.AppendLine("\t(none)");
}
xCurIndex = 0;
foreach (var xArg in Arguments) {
xSB.AppendLine(String.Format("\t({0}) {1}\t{2}\t{3} (Type = {4})\r\n",
xCurIndex++,
xArg.Offset,
xArg.Size,
xArg.VirtualAddresses.FirstOrDefault(),
xArg.ArgumentType.FullName));
}
xSB.AppendLine("\tReturnSize: " + ReturnSize);
return xSB.ToString();
}
}
}