2024-02-06 13:15:05 -06:00
|
|
|
using Microsoft.Iris.Asm.Models;
|
|
|
|
|
using Microsoft.Iris.Markup;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
|
|
namespace Microsoft.Iris.Asm;
|
|
|
|
|
|
|
|
|
|
public class ObjectSection
|
|
|
|
|
{
|
2024-02-10 19:19:40 -06:00
|
|
|
readonly IEnumerable<IBodyItem> _body;
|
2024-02-06 13:15:05 -06:00
|
|
|
readonly MarkupLoadResult _loadResult;
|
2024-02-10 19:19:40 -06:00
|
|
|
readonly Dictionary<string, uint> _labelOffsetMap = new();
|
2024-02-06 13:15:05 -06:00
|
|
|
|
|
|
|
|
public ObjectSection(IEnumerable<IBodyItem> body, MarkupLoadResult loadResult)
|
|
|
|
|
{
|
2024-02-10 19:19:40 -06:00
|
|
|
_body = body;
|
|
|
|
|
_loadResult = loadResult;
|
2024-02-06 13:15:05 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ObjectSection(Program program, MarkupLoadResult loadResult)
|
|
|
|
|
: this(program.Body, loadResult)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-10 19:19:40 -06:00
|
|
|
public IReadOnlyDictionary<string, uint> LabelOffsetMap => _labelOffsetMap;
|
|
|
|
|
|
2024-02-06 13:15:05 -06:00
|
|
|
public ByteCodeReader Encode()
|
|
|
|
|
{
|
|
|
|
|
ByteCodeWriter writer = new();
|
|
|
|
|
|
2024-02-10 19:19:40 -06:00
|
|
|
foreach (var bodyItem in _body)
|
2024-02-06 13:15:05 -06:00
|
|
|
{
|
2024-02-10 19:19:40 -06:00
|
|
|
var offset = writer.DataSize;
|
|
|
|
|
|
|
|
|
|
if (bodyItem is Label label)
|
|
|
|
|
{
|
|
|
|
|
_labelOffsetMap[label.Name] = offset;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (bodyItem is not Instruction instruction)
|
|
|
|
|
continue;
|
|
|
|
|
|
2024-02-06 13:21:48 -06:00
|
|
|
// Add entry to line number table
|
2024-02-10 19:19:40 -06:00
|
|
|
_loadResult.LineNumberTable.AddRecord(offset, instruction.Line, instruction.Column);
|
2024-02-06 13:21:48 -06:00
|
|
|
|
2024-02-06 13:15:05 -06:00
|
|
|
var opCode = instruction.OpCode;
|
|
|
|
|
writer.WriteByte(opCode);
|
|
|
|
|
|
|
|
|
|
foreach (var operand in instruction.Operands)
|
|
|
|
|
{
|
|
|
|
|
switch (operand.Value)
|
|
|
|
|
{
|
|
|
|
|
case OperationType opType:
|
|
|
|
|
writer.WriteByte((byte)opType);
|
|
|
|
|
break;
|
|
|
|
|
case byte b:
|
|
|
|
|
writer.WriteByte(b);
|
|
|
|
|
break;
|
|
|
|
|
case ushort uint16:
|
|
|
|
|
writer.WriteUInt16(uint16);
|
|
|
|
|
break;
|
|
|
|
|
case uint uint32:
|
|
|
|
|
writer.WriteUInt32(uint32);
|
|
|
|
|
break;
|
|
|
|
|
case int int32:
|
|
|
|
|
writer.WriteInt32(int32);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if (opCode == OpCode.ConstructFromBinary)
|
|
|
|
|
{
|
|
|
|
|
ushort cbinTypeIndex = (UInt16)instruction.Operands.First().Value;
|
|
|
|
|
TypeSchema cbinTypeSchema = _loadResult.ImportTables.TypeImports[cbinTypeIndex];
|
|
|
|
|
cbinTypeSchema.EncodeBinary(writer, operand.Value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new InvalidOperationException($"Unexpected operand '{operand.Value}' of type '{operand.Value.GetType()}'");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return writer.CreateReader();
|
|
|
|
|
}
|
|
|
|
|
}
|