private Result OnFetchLabel() { var node = _node.As <LabelNode>(); if (node != _functionNode.Exit) { return(Result.Break); } _variableContext.ReturningList.Add(node); return(Result.NextGroup); }
private static void AfterRemoveNode(CodeNode node) { if (!node.Flags.IsSet(CodeNodeFlags.Jmp | CodeNodeFlags.Jcc)) { return; } var jj = new ValueSet <CodeNode, JumpNode>(); var jump = node.As <JumpNode>(); var label = jump.Target; if (label == null) { return; } // Disconnect. jj.Value0 = label; jj.Value1 = label.From; for (; ;) { var current = jj; if (current.Value1 == null) { break; } if (current.Value1 == jump) { jj.Value0 = jump; jj.Value1 = jump.NextJump; break; } jj.Value1 = current.Value1; } if (jj.Value0.Type == CodeNodeType.Label) { jj.Value0.As <LabelNode>().From = jj.Value1; } else { jj.Value0.As <JumpNode>().NextJump = jj.Value1; } label.ReferenceCount--; }
private void OnTarget(CodeNode node, JumpNode from, LivenessTarget ltCur, LivenessTarget ltUnused, BitArray bCur, int bLen, ref int retPtr, bool jumpNext = false) { var label = node.As <LabelNode>(); if (label.ReferenceCount != 0 || jumpNext) { if (!jumpNext) { // Push a new LivenessTarget onto the stack if needed. if (ltCur == null || ltCur.Node != node) { // Allocate a new LivenessTarget object (from pool or zone). var ltTmp = ltUnused; if (ltTmp != null) { ltUnused = ltUnused.Previous; } else { ltTmp = new LivenessTarget(); } // Initialize and make current - ltTmp->from will be set later on. ltTmp.Previous = ltCur; ltTmp.Node = label; ltCur = ltTmp; from = label.From; if (from == null) { throw new ArgumentNullException(); } } else { from = ltCur.From; OnTarget(node, from, ltCur, ltUnused, bCur, bLen, ref retPtr, true); return; // goto _OnJumpNext; } } // Visit/Patch. do { if (!jumpNext) { ltCur.From = from; bCur.CopyBits(node.Liveness, bLen); if (from.Liveness == null) { node = from; OnVisit(node, from, ltCur, ltUnused, bCur, bLen, ref retPtr); } // jumpNext = true; } // Issue #25: Moved '_OnJumpNext' here since it's important to patch // code again if there are more live variables than before. jumpNext = false; if (bCur.DelBits(from.Liveness, bLen)) { node = from; OnPatch(node, from, ltCur, ltUnused, bCur, bLen, ref retPtr); return; } from = from.NextJump; } while (from != null); { // Pop the current LivenessTarget from the stack. var ltTmp = ltCur; ltCur = ltCur.Previous; ltTmp.Previous = ltUnused; ltUnused = ltTmp; } } bCur.CopyBits(node.Liveness, bLen); node = node.Previous; if (node.Flags.IsSet(CodeNodeFlags.Jmp) || !node.IsFetched()) { OnDone(from, ltCur, ltUnused, bCur, bLen, ref retPtr); return; } if (node.Liveness == null) { OnVisit(node, from, ltCur, ltUnused, bCur, bLen, ref retPtr); return; } if (bCur.DelBits(node.Liveness, bLen)) { OnPatch(node, from, ltCur, ltUnused, bCur, bLen, ref retPtr); return; } OnDone(from, ltCur, ltUnused, bCur, bLen, ref retPtr); }
public void Run(CodeNode node) { var map = node.VariableMap; if (map == null) { return; } InitImpl(node, map); UnuseBefore(RegisterClass.Gp); UnuseBefore(RegisterClass.Mm); UnuseBefore(RegisterClass.Xyz); Plan(RegisterClass.Gp); Plan(RegisterClass.Mm); Plan(RegisterClass.Xyz); Spill(RegisterClass.Gp); Spill(RegisterClass.Mm); Spill(RegisterClass.Xyz); Alloc(RegisterClass.Gp); Alloc(RegisterClass.Mm); Alloc(RegisterClass.Xyz); // Translate node operands. if (node.Type == CodeNodeType.Instruction) { var inst = node.As <InstructionNode>(); Translator.TranslateOperands(inst.Operands); } else if (node.Type == CodeNodeType.CallArgument) { var carg = node.As <CallArgumentNode>(); var call = carg.Call; var decl = call.FunctionDeclaration; var argIndex = 0; var argMask = carg.AffectedArguments; var sVd = carg.Source; var cVd = carg.Conv; // Convert first. if (!(sVd.RegisterIndex != RegisterIndex.Invalid)) { throw new ArgumentException(); } if (cVd != null) { if (!(cVd.RegisterIndex != RegisterIndex.Invalid)) { throw new ArgumentException(); } Translator.EmitConvertVarToVar(cVd.Type, cVd.RegisterIndex, sVd.Type, sVd.RegisterIndex); sVd = cVd; } while (argMask != 0) { if (argMask.IsSet(0x1)) { var arg = decl.GetArgument(argIndex); if (!(arg.StackOffset != Constants.InvalidValue)) { throw new ArgumentException(); } var dst = Memory.Ptr(Assembler.Zsp, -Cpu.Info.RegisterSize + arg.StackOffset); Translator.EmitMoveVarOnStack(arg.VariableType, dst, sVd.Type, sVd.RegisterIndex); } argIndex++; argMask >>= 1; } } // Mark variables as modified. Modified(RegisterClass.Gp); Modified(RegisterClass.Mm); Modified(RegisterClass.Xyz); // Cleanup; disconnect Vd->Va. Cleanup(); // Update clobbered mask. VariableContext.ClobberedRegs.Or(_willAlloc); VariableContext.ClobberedRegs.Or(map.ClobberedRegs); // Unuse. UnuseAfter(RegisterClass.Gp); UnuseAfter(RegisterClass.Mm); UnuseAfter(RegisterClass.Xyz); }