Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        public ILEmitterCtx(
            TranslatorCache cache,
            Block[]         graph,
            Block root,
            string subName)
        {
            _cache = cache ?? throw new ArgumentNullException(nameof(cache));
            _graph = graph ?? throw new ArgumentNullException(nameof(graph));
            _root  = root ?? throw new ArgumentNullException(nameof(root));

            _labels = new Dictionary <long, ILLabel>();

            _emitter = new ILEmitter(graph, root, subName);

            _ilBlock = _emitter.GetIlBlock(0);

            _opcIndex = -1;

            if (graph.Length == 0 || !AdvanceOpCode())
            {
                throw new ArgumentException(nameof(graph));
            }
        }
Exemplo n.º 3
0
 public long GetVecOutputs(ILBlock block) => _vecPaths[block].GetOutputs();
Exemplo n.º 4
0
 public long GetVecNotInputs(ILBlock entry) => GetNotInputsImpl(entry, _vecPaths.Values);
Exemplo n.º 5
0
 public long GetIntOutputs(ILBlock block) => _intPaths[block].GetOutputs();
Exemplo n.º 6
0
        public void BuildUses(ILBlock entry)
        {
            //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 has a entry, 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.Add(block))
                {
                    unvisited.Enqueue(block);
                }
            }

            Enqueue(new BlockIo(entry, entry));

            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(ILBlock block, bool retTarget)
                {
                    BlockIo blockIo;

                    if (retTarget)
                    {
                        blockIo = new BlockIo(block, block);
                    }
                    else
                    {
                        blockIo = new BlockIo(
                            block,
                            current.Entry,
                            current.IntInputs,
                            current.VecInputs,
                            current.IntOutputs,
                            current.VecOutputs);
                    }

                    Enqueue(blockIo);
                }

                if (current.Block.Next != null)
                {
                    EnqueueFromCurrent(current.Block.Next, current.Block.HasStateStore);
                }

                if (current.Block.Branch != null)
                {
                    EnqueueFromCurrent(current.Block.Branch, false);
                }
            }
        }
Exemplo n.º 7
0
 public long GetIntNotInputs(ILBlock entry) => GetNotInputsImpl(entry, _intPaths.Values);
Exemplo n.º 8
0
 public long GetIntInputs(ILBlock root) => GetInputsImpl(root, _intPaths.Values);
Exemplo n.º 9
0
 public long GetVecInputs(ILBlock root) => GetInputsImpl(root, _vecPaths.Values);
Exemplo n.º 10
0
 public PathIo(ILBlock root, long inputs, long outputs) : this()
 {
     Set(root, inputs, outputs);
 }
Exemplo n.º 11
0
 public ILOpCodeStoreState(ILBlock block)
 {
     _block = block;
 }
Exemplo n.º 12
0
 public ILOpCodeStoreState(ILBlock block, TranslatedSub callSub = null)
 {
     _block   = block;
     _callSub = callSub;
 }
Exemplo n.º 13
0
 public ILOpCodeLoadState(ILBlock block)
 {
     _block = block;
 }
Exemplo n.º 14
0
 public ILOpCodeLoadState(ILBlock block, bool isSubEntry = false)
 {
     _block      = block;
     _isSubEntry = isSubEntry;
 }