diff --git a/src/SVM.Assembler.Core/Assembler.cs b/src/SVM.Assembler.Core/Assembler.cs index ca61290..1e1f49c 100644 --- a/src/SVM.Assembler.Core/Assembler.cs +++ b/src/SVM.Assembler.Core/Assembler.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; namespace SVM.Assembler.Core { - public delegate OperationResult AssemblerFunction(ILexer lexer, IntermediateInstruction instruction, LexSegment leadingSegment); + public delegate OperationResult LinkerFunction(LinkingContext context, IntermediateInstruction instruction); public class Assembler { public const string LexDefinition = @@ -55,13 +55,15 @@ LabelData InternalLbl LabelConstant InternalLbl "; LexerDefinition? definition; - public Dictionary assemblerFunctions = new Dictionary(); - public Assembler() + public ISADefinition ISA; + public Assembler(ISADefinition isaDefinition) { if (LexerDefinition.TryParse(LexDefinition, out definition)) { definition.Substitute(); } + + ISA = isaDefinition; } public OperationResult Lex(ILexer lexer) { @@ -113,11 +115,32 @@ LabelConstant InternalLbl { return operationResult; } - if (!assemblerFunctions.TryGetValue(LexDef.LexMatchedItemId, out var assemblerFunction)) + if (!ISA.InstructionDefinitions.TryGetValue(LexDef.LexMatchedItemId, out var instructionDef)) { return operationResult; } - return assemblerFunction(lexer, intermediateInstruction, LexDef); + foreach (var item in instructionDef.ParameterPattern) + { + var next = Lex(lexer); + if (operationResult.CheckAndInheritErrorAndWarnings(next)) + { + return operationResult; + } + if (next.Result is null) + { + return operationResult; + } + if (next.Result.LexSegmentId is null) + { + return operationResult; + } + if (!item.AllowedTokenIds.Contains(next.Result.LexSegmentId)) + { + return operationResult; + } + intermediateInstruction.Parameters.Add(next.Result); + } + return intermediateInstruction; } public OperationResult AssembleIntermediateObject(string input, string ID = "main.asm") { diff --git a/src/SVM.Assembler.Core/ISADefinition.cs b/src/SVM.Assembler.Core/ISADefinition.cs new file mode 100644 index 0000000..0b740df --- /dev/null +++ b/src/SVM.Assembler.Core/ISADefinition.cs @@ -0,0 +1,21 @@ +using SVM.Core; +using System.Collections.Generic; + +namespace SVM.Assembler.Core +{ + public class ISADefinition + { + public Dictionary InstructionDefinitions = new Dictionary(); + public Dictionary LinkerFunctions = new Dictionary(); + public void Init() + { + foreach (var item in InstructionDefinitions) + { + if (!LinkerFunctions.TryAdd(item.Value.PrimaryInstruction, item.Value.linkerFunction)) + { + LinkerFunctions[item.Value.PrimaryInstruction] = item.Value.linkerFunction; + } + } + } + } +} diff --git a/src/SVM.Assembler.Core/InstructionDefinition.cs b/src/SVM.Assembler.Core/InstructionDefinition.cs new file mode 100644 index 0000000..3e5af8f --- /dev/null +++ b/src/SVM.Assembler.Core/InstructionDefinition.cs @@ -0,0 +1,21 @@ +using SVM.Core; +using System; +using System.Collections.Generic; + +namespace SVM.Assembler.Core +{ + [Serializable] + public class InstructionDefinition + { + public string MatchID; + public PrimaryInstruction PrimaryInstruction; + public LinkerFunction linkerFunction; + public InstructionDefinition(string matchID, LinkerFunction assemblerFunction) + { + MatchID = matchID; + this.linkerFunction = assemblerFunction; + } + + public List ParameterPattern = new List(); + } +} diff --git a/src/SVM.Assembler.Core/InstructionParameter.cs b/src/SVM.Assembler.Core/InstructionParameter.cs new file mode 100644 index 0000000..23e6627 --- /dev/null +++ b/src/SVM.Assembler.Core/InstructionParameter.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace SVM.Assembler.Core +{ + public class InstructionParameter + { + public List AllowedTokenIds = new List(); + } +} diff --git a/src/SVM.Assembler.Core/Linker.cs b/src/SVM.Assembler.Core/Linker.cs index 168caf3..8f07b1e 100644 --- a/src/SVM.Assembler.Core/Linker.cs +++ b/src/SVM.Assembler.Core/Linker.cs @@ -1,6 +1,10 @@ using LibCLCC.NET.Operations; using SVM.Core; +using SVM.Core.Utils; +using System; using System.Collections.Generic; +using System.Reflection.Emit; +using System.Text; namespace SVM.Assembler.Core { @@ -33,10 +37,46 @@ namespace SVM.Assembler.Core } return operationResult; } - public static OperationResult Freeze(List objs) + public unsafe static OperationResult Finialize(ISADefinition definition, IntermediateObject Obj) { OperationResult operationResult = new OperationResult(null); - + ManagedSVMProgram program = new ManagedSVMProgram(); + LinkingContext context = new LinkingContext(program, Obj); + List Data = new List(); + uint offset = 0; + foreach (var item in Obj.data) + { + var data = Encoding.UTF8.GetBytes(item.Value); + byte[] data2 = new byte[data.Length + sizeof(int)]; + fixed (byte* ptr = data2) + { + int len = data.Length; + ((IntPtr)ptr).SetData(len); + } + Buffer.BlockCopy(data, 0, data2, sizeof(int), data.Length); + context.DataOffsets.Add(item.Key, offset); + offset += (uint)data2.Length; + Data.Add(data); + } + foreach (var item in Obj.instructions) + { + if (definition.LinkerFunctions.TryGetValue(item.inst, out var func)) + { + var inst = func(context, item); + if (operationResult.CheckAndInheritErrorAndWarnings(inst)) + { + return operationResult; + } + program.instructions.Add(inst.Result); + } + } + program.Datas = new byte[offset]; + int offset2 = 0; + foreach (var item in Data) + { + Buffer.BlockCopy(item, 0, program.Datas, offset2, item.Length); + offset2 += item.Length; + } return operationResult; } } diff --git a/src/SVM.Assembler.Core/LinkingContext.cs b/src/SVM.Assembler.Core/LinkingContext.cs new file mode 100644 index 0000000..52df7cc --- /dev/null +++ b/src/SVM.Assembler.Core/LinkingContext.cs @@ -0,0 +1,38 @@ +using SVM.Core; +using System.Collections.Generic; + +namespace SVM.Assembler.Core +{ + public class LinkingContext + { + public Dictionary DataOffsets = new Dictionary(); + public ManagedSVMProgram Program; + public Dictionary label = new Dictionary(); + public IntermediateObject IntermediateObject; + public LinkingContext(ManagedSVMProgram program, IntermediateObject intermediateObject) + { + Program = program; + IntermediateObject = intermediateObject; + } + public bool TryFindLabel(string label, out int offset) + { + label = label + ":"; + if (this.label.TryGetValue(label, out offset)) + { + return true; + } + for (int i = 0; i < IntermediateObject.instructions.Count; i++) + { + IntermediateInstruction? item = IntermediateObject.instructions[i]; + if (item.Label != null) + if (item.Label.Content == label) + { + this.label.Add(label, i); + offset = i; + return true; + } + } + return false; + } + } +} diff --git a/src/SVM.Assembler.Core/SVM.Assembler.Core.csproj b/src/SVM.Assembler.Core/SVM.Assembler.Core.csproj index 3f0e0c6..a4a3d1f 100644 --- a/src/SVM.Assembler.Core/SVM.Assembler.Core.csproj +++ b/src/SVM.Assembler.Core/SVM.Assembler.Core.csproj @@ -3,6 +3,7 @@ netstandard2.1 enable + true diff --git a/src/SVM.Core/SVMProgram.cs b/src/SVM.Core/SVMProgram.cs index 9fba929..13fe347 100644 --- a/src/SVM.Core/SVMProgram.cs +++ b/src/SVM.Core/SVMProgram.cs @@ -8,7 +8,7 @@ namespace SVM.Core public unsafe class ManagedSVMProgram { public List instructions = new List(); - public List Datas = new List(); + public byte[]? Datas; } public unsafe struct SVMProgram : IDisposable { diff --git a/src/SVM.Core/Utils/PointerUtils.cs b/src/SVM.Core/Utils/PointerUtils.cs index d3881b9..f2ce592 100644 --- a/src/SVM.Core/Utils/PointerUtils.cs +++ b/src/SVM.Core/Utils/PointerUtils.cs @@ -41,5 +41,10 @@ namespace SVM.Core.Utils { GetDataWithOffsetInStructCount(ptr, (IntPtr)dest, offset); } + public static void SetData(this IntPtr ptr, T data) where T : unmanaged + { + var srcPtr = (byte*)&data; + Buffer.MemoryCopy(srcPtr, (byte*)ptr, sizeof(T), sizeof(T)); + } } }