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); }
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); }
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); }