Add binary encoded constants to lexer and disassembler

This commit is contained in:
Yoshi Askharoun
2024-02-21 09:10:18 -06:00
parent 1125127171
commit 3c95c4e9ce
4 changed files with 107 additions and 13 deletions
+1 -1
View File
@@ -259,7 +259,7 @@ internal class AsmMarkupLoader
object constantValue, persistData = null;
var constantTypeSchema = ResolveTypeFromQualifiedName(constant.TypeName);
if (constant is EncodedConstantDirective encodedConstant)
if (constant is StringEncodedConstantDirective encodedConstant)
{
var parseResult = constantTypeSchema.TypeConverter(encodedConstant.Content, stringTypeSchema, out constantValue);
if (parseResult.Failed)
+17 -5
View File
@@ -4,6 +4,7 @@ using Microsoft.Iris.Markup;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Xml.Linq;
namespace Microsoft.Iris.Asm;
@@ -226,17 +227,28 @@ public class Disassembler
if (constantValue is IStringEncodable encodable)
{
var encodedValue = encodable.EncodeString();
yield return new EncodedConstantDirective(constantName, qualifiedTypeName, encodedValue);
yield return new StringEncodedConstantDirective(constantName, qualifiedTypeName, encodedValue);
}
else if (constantValue is Layout.ILayout constantLayout && Layout.PredefinedLayouts.TryConvertToString(constantLayout, out var constantLayoutString))
{
qualifiedTypeName = GetQualifiedName(UIXTypes.MapIDToType(UIXTypeID.Layout));
yield return new StringEncodedConstantDirective(constantName, qualifiedTypeName, constantLayoutString);
}
else if (typeSchema.SupportsTypeConversion(stringTypeSchema))
{
var encodedValue = constantValue.ToString();
yield return new EncodedConstantDirective(constantName, qualifiedTypeName, encodedValue);
yield return new StringEncodedConstantDirective(constantName, qualifiedTypeName, encodedValue);
}
else if (constantValue is Layout.ILayout constantLayout && Layout.PredefinedLayouts.TryConvertToString(constantLayout, out var constantLayoutString))
else if (typeSchema.SupportsBinaryEncoding)
{
qualifiedTypeName = GetQualifiedName(typeSchema.Base);
yield return new EncodedConstantDirective(constantName, qualifiedTypeName, constantLayoutString);
ByteCodeWriter writer = new();
typeSchema.EncodeBinary(writer, constantValue);
var reader = writer.CreateReader();
byte[] encodedBytes = new byte[reader.Size];
Marshal.Copy(reader.GetAddress(0), encodedBytes, 0, (int)reader.Size);
yield return new BinaryEncodedConstantDirective(constantName, qualifiedTypeName, encodedBytes);
}
else
{
+52 -1
View File
@@ -1,5 +1,7 @@
using Microsoft.Iris.Asm.Models;
using Sprache;
using System;
using System.Globalization;
using System.Linq;
namespace Microsoft.Iris.Asm;
@@ -85,6 +87,10 @@ partial class Lexer
if (!typeNameResult.WasSuccessful)
return Result.Failure<IDirective>(input, "Invalid constant directive", ["Expected qualified name of type to construct"]);
var binaryEncodingMarkerResult = Parse.String(".bin")(input);
input = binaryEncodingMarkerResult.Remainder;
var binaryEncoded = binaryEncodingMarkerResult.WasSuccessful;
var openBracketResult = Parse.Char('(').Token()(input);
input = openBracketResult.Remainder;
if (!openBracketResult.WasSuccessful)
@@ -100,12 +106,57 @@ partial class Lexer
if (!closeBracketResult.WasSuccessful)
return Result.Failure<IDirective>(input, "Invalid constant directive", ["Expected ')'"]);
directive = new EncodedConstantDirective(constNameResult.Value, typeNameResult.Value, contentResult.Value)
var constantName = constNameResult.Value;
var typeName = typeNameResult.Value;
if (!binaryEncoded)
{
directive = new StringEncodedConstantDirective(constantName, typeName, contentResult.Value)
{
Line = line,
Column = column,
};
}
else
{
byte[] constantBytes;
var byteParts = contentResult.Value.Split(',');
if (byteParts.Length == 1)
{
var constantStr = byteParts[0].Trim().TrimStart('0', 'x');
if (constantStr.Length == 2)
{
constantBytes = [byte.Parse(constantStr, NumberStyles.HexNumber)];
}
else if (constantStr.Length == 4)
{
constantBytes = BitConverter.GetBytes(
ushort.Parse(constantStr, NumberStyles.HexNumber));
}
else if (constantStr.Length == 8)
{
constantBytes = BitConverter.GetBytes(
uint.Parse(constantStr, NumberStyles.HexNumber));
}
else
{
return Result.Failure<IDirective>(input, "Invalid constant directive", [$"Expected a 1, 2, or 4 hex number, or a list of bytes."]);
}
}
else
{
constantBytes = byteParts
.Select(s => byte.Parse(s.TrimStart('0', 'x'), NumberStyles.HexNumber))
.ToArray();
}
directive = new BinaryEncodedConstantDirective(constantName, typeName, constantBytes)
{
Line = line,
Column = column,
};
}
}
break;
case "EXPORT":
+34 -3
View File
@@ -1,4 +1,7 @@
namespace Microsoft.Iris.Asm.Models;
using System;
using System.Linq;
namespace Microsoft.Iris.Asm.Models;
public record SectionDirective : Directive
{
@@ -28,9 +31,9 @@ public record ConstantDirective : Directive
public override string ToString() => $"{base.ToString()} {Name} = {Constructor}";
}
public record EncodedConstantDirective : ConstantDirective
public record StringEncodedConstantDirective : ConstantDirective
{
public EncodedConstantDirective(string name, QualifiedTypeName typeName, string content)
public StringEncodedConstantDirective(string name, QualifiedTypeName typeName, string content)
: base(name, typeName, $"{typeName}({content})")
{
Content = content;
@@ -41,6 +44,34 @@ public record EncodedConstantDirective : ConstantDirective
public override string ToString() => base.ToString();
}
public record BinaryEncodedConstantDirective : ConstantDirective
{
public BinaryEncodedConstantDirective(string name, QualifiedTypeName typeName, byte[] content)
: base(name, typeName, GetConstructor(typeName, content))
{
Content = content;
}
public byte[] Content { get; }
public override string ToString() => base.ToString();
private static string GetConstructor(QualifiedTypeName typeName, byte[] content)
{
string contentStr;
if (content.Length == 1)
contentStr = $"0x{content[0]:X2}";
else if (content.Length == 2)
contentStr = $"0x{BitConverter.ToUInt16(content, 0):X4}";
else if (content.Length == 4)
contentStr = $"0x{BitConverter.ToUInt32(content, 0):X8}";
else
contentStr = string.Join(", ", content.Select(b => $"0x{b:X2}"));
return $"{typeName}.bin({contentStr})";
}
}
public record ExportDirective : Directive
{
public ExportDirective(string labelPrefix, uint listenerCount, string baseTypeName) : base("export")