Cosmos/source/Indy.IL2CPU.IL/Op.cs
2008-02-27 18:17:59 +00:00

95 lines
3 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Indy.IL2CPU.Assembler;
using System.Reflection;
namespace Indy.IL2CPU.IL {
public abstract class Op {
private readonly string mCurrentInstructionLabel;
private readonly string mILComment;
private readonly bool mSupportsMetalMode;
public static string GetInstructionLabel(ILReader aReader) {
return GetInstructionLabel(aReader.Position);
}
public static string GetInstructionLabel(long aPosition) {
return ".L" + aPosition.ToString("X8");
}
public delegate void QueueMethodHandler(MethodBase aMethod);
public delegate void QueueStaticFieldHandler(FieldInfo aField);
public void Assemble() {
if (!String.IsNullOrEmpty(mCurrentInstructionLabel)) {
new Label(mCurrentInstructionLabel);
}
if (!String.IsNullOrEmpty(mILComment)) {
new Comment(mILComment);
}
AssembleHeader();
DoAssemble();
}
protected virtual void AssembleHeader() {
}
public abstract void DoAssemble();
public Op(ILReader aReader, MethodInformation aMethodInfo) {
if (aReader != null) {
mCurrentInstructionLabel = GetInstructionLabel(aReader);
// todo: need to add the real operand here?
mILComment = "; IL: " + aReader.OpCode + " " + aReader.Operand;
}
OpCodeAttribute xAttrib = GetType().GetCustomAttributes(typeof(OpCodeAttribute), true).Cast<OpCodeAttribute>().FirstOrDefault();
if (xAttrib != null) {
mSupportsMetalMode = xAttrib.IsMetallic;
}
}
// This is a prop and not a constructor arg for two reasons. Ok, mostly for one
// 1 - Adding a parameterized triggers annoying C# constructor hell, every descendant we'd have to reimplement it
// 2 - This helps to allow changing of assembler while its in use. Currently no idea why we would ever want to do that
// rather than construct a new one though....
// If we end up with more things we need, probably will change to Initialize(x, y), or someone can go thorugh and add
// all the friggin constructors
protected Assembler.Assembler mAssembler;
public Assembler.Assembler Assembler {
get {
return mAssembler;
}
set {
mAssembler = value;
}
}
public bool SupportsMetalMode {
get {
return mSupportsMetalMode;
}
}
protected void DoQueueMethod(MethodBase aMethod) {
if (QueueMethod == null) {
throw new Exception("IL Op wants to queue a method, but no QueueMethod handler suppplied!");
}
QueueMethod(aMethod);
}
protected void DoQueueStaticField(FieldInfo aField) {
if (QueueStaticField == null) {
throw new Exception("IL Op wants to queue a static field, but no QueueStaticField handler supplied!");
}
if (!aField.IsStatic) {
throw new Exception("Cannot add instance fields to the StaticField queue!");
}
QueueStaticField(aField);
}
public static QueueMethodHandler QueueMethod;
public static QueueStaticFieldHandler QueueStaticField;
}
}