mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 12:30:32 +00:00
230 lines
No EOL
9 KiB
C#
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();
|
|
}
|
|
}
|
|
} |