Пример #1
0
        private Result OnFetchReturn()
        {
            var retn = _node.As <ReturnNode>();

            _variableContext.ReturningList.Add(retn);

            if (_functionDeclaration.ReturnCount != 0)
            {
                var ret      = _functionDeclaration.GetReturn(0);
                var retClass = ret.VariableType.GetRegisterClass();

                _variableContext.Begin();

                for (var i = 0; i < 2; i++)
                {
                    var op = retn.Operands[i];
                    if (!op.IsVariable())
                    {
                        continue;
                    }
                    var vd = _compiler.GetVariableData(op.Id);

                    var va = _variableContext.Merge(vd, 0, 0);

                    if (retClass == vd.Info.RegisterClass)
                    {
                        // TODO: [COMPILER] Fix HLRet fetch.
                        va.Flags |= VariableFlags.RReg;
                        va.InRegs = i == 0 ? Utils.Mask(RegisterIndex.Ax) : Utils.Mask(RegisterIndex.Dx);
                        _variableContext.InRegs.Or(retClass, va.InRegs);
                    }
                    else if (retClass == RegisterClass.Fp)
                    {
                        var fldFlag = ret.VariableType == VariableType.Fp32 ? VariableFlags.X86Fld4 : VariableFlags.X86Fld8;
                        va.Flags |= VariableFlags.RMem | fldFlag;
                    }
                    else
                    {
                        // TODO: Fix possible other return type conversions.
                    }
                }
                _variableContext.End(_node);
            }
            if (_next.IsFetched())
            {
                return(Result.Break);
            }
            _unreachableList.Add(_next);
            return(Result.NextGroup);
        }
Пример #2
0
 private Result GoTo(bool @do)
 {
     if (!@do || _node.IsFetched())
     {
         if (_jLinkIndex == -1)
         {
             _jLinkIndex = 0;
         }
         else
         {
             _jLinkIndex++;
         }
         if (_jLinkIndex >= _variableContext.JccList.Count)
         {
             _node = null;
             return(Result.Done);
         }
         _node = GetOppositeJccFlow(_variableContext.JccList[_jLinkIndex].As <JumpNode>());
     }
     return(Result.Break);
 }
Пример #3
0
        internal VariableContext Run()
        {
            var flowId = 0;

            _next = null;
            _node = _functionNode;

            var result = Result.Do;

            do
            {
                if (result == Result.Done)
                {
                    break;
                }

                if (GoTo(@do: result != Result.NextGroup) == Result.Done)
                {
                    break;
                }

                flowId++;

                _next        = _node.Next;
                _node.FlowId = flowId;

                switch (_node.Type)
                {
                case CodeNodeType.None:
                case CodeNodeType.Data:
                case CodeNodeType.Alignment:
                case CodeNodeType.Comment:
                case CodeNodeType.CallArgument:
                    break;

                case CodeNodeType.Label:
                    result = OnFetchLabel();
                    break;

                case CodeNodeType.Sentinel:
                    result = OnFetchSentinel();
                    break;

                case CodeNodeType.Instruction:
                    result = OnFetchInstruction();
                    break;

                case CodeNodeType.Hint:
                    result = OnFetchHint();
                    break;

                case CodeNodeType.Function:
                    result = OnFetchFunction();
                    break;

                case CodeNodeType.Return:
                    result = OnFetchReturn();
                    break;

                case CodeNodeType.Call:
                    result = OnFetchCall();
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
                if (result == Result.Do || result == Result.NextGroup || result == Result.Done)
                {
                    continue;
                }
                _node = _next;
            } while (_node != _stopNode);
            // Mark exit label and end node as fetched, otherwise they can be removed by
            // `removeUnreachableCode()`, which would lead to crash in some later step.
            _node = _functionNode.End;
            if (_node.IsFetched())
            {
                RemoveUnreachableCode();

                return(_variableContext);
            }
            _functionNode.Exit.FlowId = ++flowId;
            _node.FlowId = ++flowId;

            RemoveUnreachableCode();

            return(_variableContext);
        }