public AILEmitter(ABlock[] Graph, ABlock Root, string SubName) { this.SubName = SubName; Locals = new Dictionary <ARegister, int>(); ILBlocks = new AILBlock[Graph.Length]; AILBlock GetBlock(int Index) { if (Index < 0 || Index >= ILBlocks.Length) { return(null); } if (ILBlocks[Index] == null) { ILBlocks[Index] = new AILBlock(); } return(ILBlocks[Index]); } for (int Index = 0; Index < ILBlocks.Length; Index++) { AILBlock Block = GetBlock(Index); Block.Next = GetBlock(Array.IndexOf(Graph, Graph[Index].Next)); Block.Branch = GetBlock(Array.IndexOf(Graph, Graph[Index].Branch)); } this.Root = ILBlocks[Array.IndexOf(Graph, Root)]; }
public long GetInputs(AILBlock Root) { if (AllInputs.TryGetValue(Root, out long Inputs)) { return(Inputs | (AllOutputs & ~CmnOutputs[Root])); } return(0); }
private long GetInputsImpl(AILBlock Root, IEnumerable <PathIo> Values) { long Inputs = 0; foreach (PathIo Path in Values) { Inputs |= Path.GetInputs(Root); } return(Inputs); }
public ALocalAlloc(AILBlock[] Graph, AILBlock Root) { IntPaths = new Dictionary <AILBlock, PathIo>(); VecPaths = new Dictionary <AILBlock, PathIo>(); if (Graph.Length < MaxOptGraphLength) { InitializeOptimal(Graph, Root); } else { InitializeFast(Graph); } }
public void Set(AILBlock Root, long Inputs, long Outputs) { if (!AllInputs.TryAdd(Root, Inputs)) { AllInputs[Root] |= Inputs; } if (!CmnOutputs.TryAdd(Root, Outputs)) { CmnOutputs[Root] &= Outputs; } AllOutputs |= Outputs; }
public bool AdvanceOpCode() { while (++OpcIndex >= (CurrBlock?.OpCodes.Count ?? 0)) { if (BlkIndex + 1 >= Graph.Length) { return(false); } BlkIndex++; OpcIndex = -1; ILBlock = Emitter.GetILBlock(BlkIndex); } return(true); }
public bool AdvanceOpCode() { if (OpcIndex + 1 == CurrBlock.OpCodes.Count && BlkIndex + 1 == Graph.Length) { return(false); } while (++OpcIndex >= (CurrBlock?.OpCodes.Count ?? 0)) { BlkIndex++; OpcIndex = -1; OptOpLastFlagSet = null; OptOpLastCompare = null; ILBlock = Emitter.GetILBlock(BlkIndex); } return(true); }
public AILEmitterCtx(ATranslator Translator, ABlock[] Graph, ABlock Root) { this.Translator = Translator; this.Graph = Graph; this.Root = Root; string SubName = $"Sub{Root.Position:X16}"; Labels = new Dictionary <long, AILLabel>(); Emitter = new AILEmitter(Graph, Root, SubName); ILBlock = Emitter.GetILBlock(0); OpcIndex = -1; if (!AdvanceOpCode()) { throw new ArgumentException(nameof(Graph)); } }
public AILEmitterCtx( ATranslator Translator, ABlock[] Graph, ABlock Root, string SubName) { if (Translator == null) { throw new ArgumentNullException(nameof(Translator)); } if (Graph == null) { throw new ArgumentNullException(nameof(Graph)); } if (Root == null) { throw new ArgumentNullException(nameof(Root)); } this.Translator = Translator; this.Graph = Graph; this.Root = Root; Callees = new HashSet <long>(); Labels = new Dictionary <long, AILLabel>(); Emitter = new AILEmitter(Graph, Root, SubName); ILBlock = Emitter.GetILBlock(0); OpcIndex = -1; if (Graph.Length == 0 || !AdvanceOpCode()) { throw new ArgumentException(nameof(Graph)); } }
public AILEmitterCtx( ATranslatorCache Cache, ABlock[] Graph, ABlock Root, string SubName) { this.Cache = Cache ?? throw new ArgumentNullException(nameof(Cache)); this.Graph = Graph ?? throw new ArgumentNullException(nameof(Graph)); this.Root = Root ?? throw new ArgumentNullException(nameof(Root)); Labels = new Dictionary <long, AILLabel>(); Emitter = new AILEmitter(Graph, Root, SubName); ILBlock = Emitter.GetILBlock(0); OpcIndex = -1; if (Graph.Length == 0 || !AdvanceOpCode()) { throw new ArgumentException(nameof(Graph)); } }
private void InitializeOptimal(AILBlock[] Graph, AILBlock Root) { //This will go through all possible paths on the graph, //and store all inputs/outputs for each block. A register //that was previously written to already is not considered an input. //When a block can be reached by more than one path, then the //output from all paths needs to be set for this block, and //only outputs present in all of the parent blocks can be considered //when doing input elimination. Each block chain have a root, that's where //the code starts executing. They are present on the subroutine start point, //and on call return points too (address written to X30 by BL). HashSet <BlockIo> Visited = new HashSet <BlockIo>(); Queue <BlockIo> Unvisited = new Queue <BlockIo>(); void Enqueue(BlockIo Block) { if (!Visited.Contains(Block)) { Unvisited.Enqueue(Block); Visited.Add(Block); } } Enqueue(new BlockIo() { Block = Root, Entry = Root }); while (Unvisited.Count > 0) { BlockIo Current = Unvisited.Dequeue(); Current.IntInputs |= Current.Block.IntInputs & ~Current.IntOutputs; Current.VecInputs |= Current.Block.VecInputs & ~Current.VecOutputs; Current.IntOutputs |= Current.Block.IntOutputs; Current.VecOutputs |= Current.Block.VecOutputs; //Check if this is a exit block //(a block that returns or calls another sub). if ((Current.Block.Next == null && Current.Block.Branch == null) || Current.Block.HasStateStore) { if (!IntPaths.TryGetValue(Current.Block, out PathIo IntPath)) { IntPaths.Add(Current.Block, IntPath = new PathIo()); } if (!VecPaths.TryGetValue(Current.Block, out PathIo VecPath)) { VecPaths.Add(Current.Block, VecPath = new PathIo()); } IntPath.Set(Current.Entry, Current.IntInputs, Current.IntOutputs); VecPath.Set(Current.Entry, Current.VecInputs, Current.VecOutputs); } void EnqueueFromCurrent(AILBlock Block, bool RetTarget) { BlockIo BlkIO = new BlockIo() { Block = Block }; if (RetTarget) { BlkIO.Entry = Block; } else { BlkIO.Entry = Current.Entry; BlkIO.IntInputs = Current.IntInputs; BlkIO.VecInputs = Current.VecInputs; BlkIO.IntOutputs = Current.IntOutputs; BlkIO.VecOutputs = Current.VecOutputs; } Enqueue(BlkIO); } if (Current.Block.Next != null) { EnqueueFromCurrent(Current.Block.Next, Current.Block.HasStateStore); } if (Current.Block.Branch != null) { EnqueueFromCurrent(Current.Block.Branch, false); } } }
public long GetVecOutputs(AILBlock Block) => VecPaths[Block].GetOutputs();
public long GetIntOutputs(AILBlock Block) => IntPaths[Block].GetOutputs();
public long GetVecInputs(AILBlock Root) => GetInputsImpl(Root, VecPaths.Values);
public long GetIntInputs(AILBlock Root) => GetInputsImpl(Root, IntPaths.Values);
public PathIo(AILBlock Root, long Inputs, long Outputs) : this() { Set(Root, Inputs, Outputs); }