Add offset and index to instructions and operands

This commit is contained in:
Yoshi Askharoun
2025-07-15 21:56:44 -05:00
parent 8b2a88a77c
commit 9495785efb
5 changed files with 61 additions and 73 deletions
+2 -45
View File
@@ -267,51 +267,8 @@ public class Disassembler
// Insert a label to mark the start of the object section.
yield return new SectionDirective("object");
while (reader.CurrentOffset < reader.Size)
{
if (_offsetLabelMap.TryGetValue(reader.CurrentOffset, out var labels))
foreach (var label in labels)
yield return label;
var opCode = (OpCode)reader.ReadByte();
var instSchema = InstructionSet.InstructionSchema[opCode];
Operand[] operands = new Operand[instSchema.Length];
for (int i = 0; i < instSchema.Length; i++)
{
var operandDataType = instSchema[i];
Operand operand;
if (operandDataType == LiteralDataType.ConstantIndex)
{
// Refer to the constant by name rather than index
var constantIndex = reader.ReadUInt16();
// TODO: Only generate name if not using a shared binary table
operand = new OperandReference($"const{constantIndex}");
}
else
{
object literalValue = OperandLiteral.ReduceDataType(operandDataType) switch
{
LiteralDataType.Byte => reader.ReadByte(),
LiteralDataType.UInt16 => reader.ReadUInt16(),
LiteralDataType.UInt32 => reader.ReadUInt32(),
LiteralDataType.Int32 => reader.ReadInt32(),
_ => throw new InvalidOperationException($"Unexpected operand data type '{operandDataType}'")
};
operand = new OperandLiteral(literalValue, operandDataType);
}
operands[i] = operand;
}
yield return new Instruction(opCode, operands);
}
yield break;
foreach (var codeItem in ObjectSection.Decode(reader, _offsetLabelMap))
yield return codeItem;
}
private QualifiedTypeName GetQualifiedName(TypeSchema schema)
+1 -1
View File
@@ -110,7 +110,7 @@ partial class Lexer
}
}
bodyItem = new Instruction(identifier, operands ?? [])
bodyItem = new Instruction(identifier, operands ?? [], 0)
{
Line = line,
Column = column,
+6 -26
View File
@@ -1,5 +1,4 @@
using Microsoft.Iris.Markup;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -7,18 +6,19 @@ using System.Linq;
namespace Microsoft.Iris.Asm.Models;
[DebuggerDisplay("{ToString()} " + DebuggerDisplay)]
public record Instruction(string Mnemonic, IEnumerable<Operand> Operands) : CodeItem
public record Instruction(string Mnemonic, IEnumerable<Operand> Operands, uint Offset) : CodeItem
{
public Instruction(OpCode opCode, OperationType? operationType, IEnumerable<Operand> Operands)
: this(InstructionSet.GetMnemonic(opCode, operationType), Operands)
public Instruction(OpCode opCode, OperationType? operationType, IEnumerable<Operand> operands, uint offset)
: this(InstructionSet.GetMnemonic(opCode, operationType), operands, offset)
{
}
public Instruction(OpCode opCode, IEnumerable<Operand> Operands)
: this(opCode, null, Operands)
public Instruction(OpCode opCode, IEnumerable<Operand> operands, uint offset)
: this(opCode, null, operands, offset)
{
}
public OpCode OpCode => InstructionSet.MnemonicToOpCode(Mnemonic);
public OperationType? OperationType => InstructionSet.TryOperationMnemonicToType(Mnemonic);
public override string ToString() => ToString(true);
@@ -30,24 +30,4 @@ public record Instruction(string Mnemonic, IEnumerable<Operand> Operands) : Code
? $"{mnemonic} {string.Join(", ", Operands)}"
: mnemonic;
}
public static Instruction CreateWithSchema(OpCode opCode, params object[] operands)
{
var schema = InstructionSet.InstructionSchema[opCode];
if (operands.Length != schema.Length)
throw new ArgumentException($"{opCode} requires {schema.Length} operands, got {operands.Length}");
var operandModels = new OperandLiteral[operands.Length];
for (int i = 0; i < schema.Length; i++)
{
var operandValue = operands[i];
// Should we verify types?
operandModels[i] = new(operandValue, schema[i]);
}
var operationType = operands.Length > 0 ? operands[0] as OperationType? : null;
return new Instruction(opCode, operationType, operandModels);
}
}
+4 -1
View File
@@ -49,11 +49,14 @@ public record OperandLiteral : Operand
public record OperandReference : Operand
{
public OperandReference(string constantName) : base(constantName, constantName)
public OperandReference(string constantName, int index = -1) : base(constantName, constantName)
{
Index = index;
}
public string ConstantName => Content;
public int Index { get; }
public override string ToString() => $"@{base.ToString()}";
}
+48
View File
@@ -88,4 +88,52 @@ public class ObjectSection
return writer.CreateReader();
}
public static IEnumerable<ICodeItem> Decode(ByteCodeReader reader, Dictionary<uint, List<Label>> offsetLabelMap = null)
{
while (reader.CurrentOffset < reader.Size)
{
var offset = reader.CurrentOffset;
if (offsetLabelMap?.TryGetValue(offset, out var labels) ?? false)
foreach (var label in labels)
yield return label;
var opCode = (OpCode)reader.ReadByte();
var instSchema = InstructionSet.InstructionSchema[opCode];
Operand[] operands = new Operand[instSchema.Length];
for (int i = 0; i < instSchema.Length; i++)
{
var operandDataType = instSchema[i];
Operand operand;
if (operandDataType == LiteralDataType.ConstantIndex)
{
// Refer to the constant by name rather than index
var constantIndex = reader.ReadUInt16();
// TODO: Only generate name if not using a shared binary table
operand = new OperandReference($"const{constantIndex}", constantIndex);
}
else
{
object literalValue = OperandLiteral.ReduceDataType(operandDataType) switch
{
LiteralDataType.Byte => reader.ReadByte(),
LiteralDataType.UInt16 => reader.ReadUInt16(),
LiteralDataType.UInt32 => reader.ReadUInt32(),
LiteralDataType.Int32 => reader.ReadInt32(),
_ => throw new InvalidOperationException($"Unexpected operand data type '{operandDataType}'")
};
operand = new OperandLiteral(literalValue, operandDataType);
}
operands[i] = operand;
}
yield return new Instruction(opCode, operands, offset);
}
}
}