Fix export tables and remove static Load method

This commit is contained in:
Yoshi Askharoun
2024-02-10 21:38:18 -06:00
parent 93fa998caa
commit 97001fbd29
4 changed files with 69 additions and 55 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ internal class AsmMarkupLoadResult : MarkupLoadResult
_resource = resource; _resource = resource;
if (uri != resource.Uri) if (uri != resource.Uri)
_uriUnderlying = resource.Uri; _uriUnderlying = resource.Uri;
_loader = AsmMarkupLoader.Load(this, resource); _loader = new AsmMarkupLoader(this, resource);
} }
public AsmMarkupLoadResult(string uri) public AsmMarkupLoadResult(string uri)
+63 -53
View File
@@ -13,7 +13,6 @@ namespace Microsoft.Iris.Asm;
internal class AsmMarkupLoader internal class AsmMarkupLoader
{ {
private string _asmSource; private string _asmSource;
private Program _program;
private LoadPass _currentValidationPass; private LoadPass _currentValidationPass;
private readonly AsmMarkupLoadResult _loadResult; private readonly AsmMarkupLoadResult _loadResult;
private bool _usingSharedBinaryDataTable; private bool _usingSharedBinaryDataTable;
@@ -23,18 +22,9 @@ internal class AsmMarkupLoader
private readonly Dictionary<string, LoadResult> _importedNamespaces = new(); private readonly Dictionary<string, LoadResult> _importedNamespaces = new();
private readonly HashSet<string> _referencedNamespaces = new(); private readonly HashSet<string> _referencedNamespaces = new();
protected AsmMarkupLoader(AsmMarkupLoadResult loadResult) internal unsafe AsmMarkupLoader(AsmMarkupLoadResult loadResult, Resource resource)
{ {
_loadResult = loadResult; _loadResult = loadResult;
_objectSection = new(_program, _loadResult);
}
public bool HasErrors { get; protected set; }
internal static unsafe AsmMarkupLoader Load(AsmMarkupLoadResult loadResult, Resource resource)
{
AsmMarkupLoader owner = new(loadResult);
if (resource.Status != ResourceStatus.Available) if (resource.Status != ResourceStatus.Available)
throw new InvalidOperationException("Resource must be available for reading"); throw new InvalidOperationException("Resource must be available for reading");
@@ -44,18 +34,19 @@ internal class AsmMarkupLoader
int sourceStartOffset = 0; int sourceStartOffset = 0;
if (resource.Length >= 4 && *data == 0xEF && *(data + 1) == 0xBB && *(data + 2) == 0xBF) if (resource.Length >= 4 && *data == 0xEF && *(data + 1) == 0xBB && *(data + 2) == 0xBF)
sourceStartOffset = 3; sourceStartOffset = 3;
_asmSource = Encoding.UTF8.GetString(data + sourceStartOffset, (int)(resource.Length - sourceStartOffset));
owner._asmSource = Encoding.UTF8.GetString(data + sourceStartOffset, (int)(resource.Length - sourceStartOffset)); var parseResult = Lexer.Program.TryParse(_asmSource);
var parseResult = Lexer.Program.TryParse(owner._asmSource);
if (parseResult.WasSuccessful) if (parseResult.WasSuccessful)
owner._program = parseResult.Value; Program = parseResult.Value;
else else
owner.MarkHasErrors(); MarkHasErrors();
return owner;
} }
public bool HasErrors { get; protected set; }
private Program Program { get; set; }
public LoadResult FindDependency(string prefix) public LoadResult FindDependency(string prefix)
{ {
if (prefix == null) if (prefix == null)
@@ -110,10 +101,15 @@ internal class AsmMarkupLoader
var parseResult = Lexer.Program.TryParse(_asmSource); var parseResult = Lexer.Program.TryParse(_asmSource);
if (parseResult.WasSuccessful) if (parseResult.WasSuccessful)
_program = parseResult.Value; {
Program = parseResult.Value;
_objectSection = new(Program, _loadResult);
}
else else
{
foreach (var errors in parseResult.Expectations) foreach (var errors in parseResult.Expectations)
ReportError(errors, -1, -1); ReportError(errors, -1, -1);
}
if (_loadResult.BinaryDataTable != null) if (_loadResult.BinaryDataTable != null)
{ {
@@ -125,7 +121,7 @@ internal class AsmMarkupLoader
_importTables = new SourceMarkupImportTables(); _importTables = new SourceMarkupImportTables();
} }
foreach (var nsImport in _program.Directives.OfType<NamespaceImport>()) foreach (var nsImport in Program.Directives.OfType<NamespaceImport>())
{ {
LoadResult loadResult; LoadResult loadResult;
if (nsImport.Uri == "Me") if (nsImport.Uri == "Me")
@@ -158,7 +154,7 @@ internal class AsmMarkupLoader
} }
} }
if (_program != null && currentPass != LoadPass.Done) if (Program != null && currentPass != LoadPass.Done)
{ {
//foreach (ValidateClass validateClass in _program.ClassList) //foreach (ValidateClass validateClass in _program.ClassList)
// validateClass.Validate(_currentValidationPass); // validateClass.Validate(_currentValidationPass);
@@ -171,7 +167,7 @@ internal class AsmMarkupLoader
if (_currentValidationPass == LoadPass.Full) if (_currentValidationPass == LoadPass.Full)
{ {
foreach (var nsImport in _program.Directives.OfType<NamespaceImport>()) foreach (var nsImport in Program.Directives.OfType<NamespaceImport>())
{ {
if (!_referencedNamespaces.Contains(nsImport.Name)) if (!_referencedNamespaces.Contains(nsImport.Name))
ErrorManager.ReportWarning(nsImport.Line, nsImport.Column, $"Unreferenced namespace '{nsImport.Name}'"); ErrorManager.ReportWarning(nsImport.Line, nsImport.Column, $"Unreferenced namespace '{nsImport.Name}'");
@@ -186,7 +182,7 @@ internal class AsmMarkupLoader
} }
else if (_currentValidationPass == LoadPass.PopulatePublicModel) else if (_currentValidationPass == LoadPass.PopulatePublicModel)
{ {
if (_program == null) if (Program == null)
return; return;
//foreach (ValidateClass validateClass in _parseResult.ClassList) //foreach (ValidateClass validateClass in _parseResult.ClassList)
@@ -216,7 +212,10 @@ internal class AsmMarkupLoader
ByteCodeReader reader = null; ByteCodeReader reader = null;
if (!HasErrors) if (!HasErrors)
{
reader = _objectSection.Encode(); reader = _objectSection.Encode();
UpdateExportOffsets();
}
if (!_usingSharedBinaryDataTable) if (!_usingSharedBinaryDataTable)
{ {
@@ -232,7 +231,7 @@ internal class AsmMarkupLoader
_loadResult.SetDependenciesTable(PrepareDependenciesTable()); _loadResult.SetDependenciesTable(PrepareDependenciesTable());
if (!MarkupSystem.TrackAdditionalMetadata) if (!MarkupSystem.TrackAdditionalMetadata)
_program = null; Program = null;
//foreach (DisposableObject validateObject in _validateObjects) //foreach (DisposableObject validateObject in _validateObjects)
// validateObject.Dispose(this); // validateObject.Dispose(this);
@@ -241,7 +240,7 @@ internal class AsmMarkupLoader
private TypeSchema[] PrepareExportTable() private TypeSchema[] PrepareExportTable()
{ {
var exportDirectives = _program.Directives.OfType<ExportDirective>().ToArray(); var exportDirectives = Program.Directives.OfType<ExportDirective>().ToArray();
var exports = new TypeSchema[exportDirectives.Length]; var exports = new TypeSchema[exportDirectives.Length];
for (int i = 0; i < exportDirectives.Length; i++) for (int i = 0; i < exportDirectives.Length; i++)
@@ -251,41 +250,17 @@ internal class AsmMarkupLoader
var markupType = (MarkupType)Enum.Parse(typeof(MarkupType), exportDirective.BaseTypeName); var markupType = (MarkupType)Enum.Parse(typeof(MarkupType), exportDirective.BaseTypeName);
var exportedTypeSchema = MarkupTypeSchema.Build(markupType, _loadResult, exportDirective.LabelPrefix); var exportedTypeSchema = MarkupTypeSchema.Build(markupType, _loadResult, exportDirective.LabelPrefix);
// Set all offsets
var propOffset = _objectSection.LabelOffsetMap[exportDirective.InitializePropertiesLabel];
exportedTypeSchema.SetInitializePropertiesOffset(propOffset);
var contOffset = _objectSection.LabelOffsetMap[exportDirective.InitializeContentLabel];
exportedTypeSchema.SetInitializeContentOffset(contOffset);
var loclOffset = _objectSection.LabelOffsetMap[exportDirective.InitializeLocalsInputLabel];
exportedTypeSchema.SetInitializeLocalsInputOffset(loclOffset);
var evaliOffsets = _objectSection.LabelOffsetMap
.Where(kvp => kvp.Key.StartsWith(exportDirective.InitialEvaluateOffsetsLabelPrefix))
.Select(kvp => kvp.Value)
.ToArray();
exportedTypeSchema.SetInitialEvaluateOffsets(evaliOffsets);
var evalfOffsets = _objectSection.LabelOffsetMap
.Where(kvp => kvp.Key.StartsWith(exportDirective.FinalEvaluateOffsetsLabelPrefix))
.Select(kvp => kvp.Value)
.ToArray();
exportedTypeSchema.SetFinalEvaluateOffsets(evalfOffsets);
var rfshOffsets = _objectSection.LabelOffsetMap
.Where(kvp => kvp.Key.StartsWith(exportDirective.RefreshGroupOffsetsLabelPrefix))
.Select(kvp => kvp.Value)
.ToArray();
exportedTypeSchema.SetRefreshListenerGroupOffsets(rfshOffsets);
exportedTypeSchema.SetListenerCount(exportDirective.ListenerCount); exportedTypeSchema.SetListenerCount(exportDirective.ListenerCount);
// The offsets aren't known until the object section has been encoded,
// so we have to defer setting them until the Full load pass.
exports[i] = exportedTypeSchema; exports[i] = exportedTypeSchema;
} }
return exports; return exports;
} }
private LoadResult[] PrepareDependenciesTable() private LoadResult[] PrepareDependenciesTable()
{ {
// TODO // TODO
@@ -298,6 +273,41 @@ internal class AsmMarkupLoader
return []; return [];
} }
private void UpdateExportOffsets()
{
var exportDirectives = Program.Directives.OfType<ExportDirective>().ToArray();
uint[] GetOffsets(string prefix) => _objectSection.LabelOffsetMap
.Where(kvp => kvp.Key.StartsWith(prefix))
.Select(kvp => kvp.Value)
.ToArray();
for (int i = 0; i < _loadResult.ExportTable.Length; i++)
{
var exportedTypeSchema = (MarkupTypeSchema)_loadResult.ExportTable[i];
var exportDirective = exportDirectives[i];
// Set all offsets
if (_objectSection.LabelOffsetMap.TryGetValue(exportDirective.InitializePropertiesLabel, out var propOffset))
exportedTypeSchema.SetInitializePropertiesOffset(propOffset);
if (_objectSection.LabelOffsetMap.TryGetValue(exportDirective.InitializeContentLabel, out var contOffset))
exportedTypeSchema.SetInitializeContentOffset(contOffset);
if (_objectSection.LabelOffsetMap.TryGetValue(exportDirective.InitializeLocalsInputLabel, out var loclOffset))
exportedTypeSchema.SetInitializeLocalsInputOffset(loclOffset);
var evaliOffsets = GetOffsets(exportDirective.InitialEvaluateOffsetsLabelPrefix);
exportedTypeSchema.SetInitialEvaluateOffsets(evaliOffsets);
var evalfOffsets = GetOffsets(exportDirective.FinalEvaluateOffsetsLabelPrefix);
exportedTypeSchema.SetFinalEvaluateOffsets(evalfOffsets);
var rfshOffsets = GetOffsets(exportDirective.FinalEvaluateOffsetsLabelPrefix);
exportedTypeSchema.SetRefreshListenerGroupOffsets(rfshOffsets);
}
}
public void ReportError(string error, int line, int column) public void ReportError(string error, int line, int column)
{ {
MarkHasErrors(); MarkHasErrors();
+3
View File
@@ -38,12 +38,15 @@ public class Disassembler
yield return new ExportDirective(labelPrefix, markupTypeSchema.ListenerCount, baseName); yield return new ExportDirective(labelPrefix, markupTypeSchema.ListenerCount, baseName);
var propOffset = markupTypeSchema.InitializePropertiesOffset; var propOffset = markupTypeSchema.InitializePropertiesOffset;
if (propOffset != uint.MaxValue)
InsertLabel(propOffset, ExportDirective.GetInitializePropertiesLabel(labelPrefix)); InsertLabel(propOffset, ExportDirective.GetInitializePropertiesLabel(labelPrefix));
var loclOffset = markupTypeSchema.InitializeLocalsInputOffset; var loclOffset = markupTypeSchema.InitializeLocalsInputOffset;
if (loclOffset != uint.MaxValue)
InsertLabel(loclOffset, ExportDirective.GetInitializeLocalsInputLabel(labelPrefix)); InsertLabel(loclOffset, ExportDirective.GetInitializeLocalsInputLabel(labelPrefix));
var contOffset = markupTypeSchema.InitializeContentOffset; var contOffset = markupTypeSchema.InitializeContentOffset;
if (contOffset != uint.MaxValue)
InsertLabel(contOffset, ExportDirective.GetInitializeContentLabel(labelPrefix)); InsertLabel(contOffset, ExportDirective.GetInitializeContentLabel(labelPrefix));
if (markupTypeSchema.InitialEvaluateOffsets != null) if (markupTypeSchema.InitialEvaluateOffsets != null)
+2 -1
View File
@@ -10,7 +10,7 @@ public class ObjectSection
{ {
readonly IEnumerable<IBodyItem> _body; readonly IEnumerable<IBodyItem> _body;
readonly MarkupLoadResult _loadResult; readonly MarkupLoadResult _loadResult;
readonly Dictionary<string, uint> _labelOffsetMap = new(); Dictionary<string, uint> _labelOffsetMap;
public ObjectSection(IEnumerable<IBodyItem> body, MarkupLoadResult loadResult) public ObjectSection(IEnumerable<IBodyItem> body, MarkupLoadResult loadResult)
{ {
@@ -28,6 +28,7 @@ public class ObjectSection
public ByteCodeReader Encode() public ByteCodeReader Encode()
{ {
ByteCodeWriter writer = new(); ByteCodeWriter writer = new();
_labelOffsetMap = new();
foreach (var bodyItem in _body) foreach (var bodyItem in _body)
{ {