private void Return() { var node = Node.As <CallNode>(); var decl = node.FunctionDeclaration; int i; var rets = node.Return; for (i = 0; i < 2; i++) { var ret = decl.GetReturn(i); var op = rets[i]; if (op.IsInvalid() || ret.RegisterIndex == RegisterIndex.Invalid || !op.IsVariable()) { continue; } var vd = Compiler.GetVariableData(op.Id); var vf = vd.Type.GetVariableInfo().ValueFlags; var regIndex = ret.RegisterIndex; switch (vd.Info.RegisterClass) { case RegisterClass.Gp: if (ret.VariableType.GetRegisterClass() != vd.Info.RegisterClass) { throw new ArgumentException(); } Translator.Unuse(vd, RegisterClass.Gp); Translator.Attach(vd, RegisterClass.Gp, regIndex, true); break; case RegisterClass.Mm: if (ret.VariableType.GetRegisterClass() != vd.Info.RegisterClass) { throw new ArgumentException(); } Translator.Unuse(vd, RegisterClass.Mm); Translator.Attach(vd, RegisterClass.Mm, regIndex, true); break; case RegisterClass.Xyz: if (ret.VariableType == VariableType.Fp32 || ret.VariableType == VariableType.Fp64) { var m = new Memory(Translator.GetVarMem(vd), (vf & VariableValueFlags.Sp) != 0 ? 4 : (vf & VariableValueFlags.Dp) != 0 ? 8 : ret.VariableType == VariableType.Fp32 ? 4 : 8); Translator.Unuse(vd, RegisterClass.Xyz, VariableUsage.Mem); CodeContext.Fstp(m); } else { if (ret.VariableType.GetRegisterClass() != vd.Info.RegisterClass) { throw new ArgumentException(); } Translator.Unuse(vd, RegisterClass.Xyz); Translator.Attach(vd, RegisterClass.Xyz, regIndex, true); } break; } } }
private void Alloc(RegisterClass @class) { if (Done.Get(@class) == Count.Get(@class)) { return; } var list = VaList[(int)@class]; var count = Count.Get(@class); var state = VariableContext.State; bool didWork; do { didWork = false; for (var i = 0; i < count; i++) { var aVa = list[i]; var aVd = aVa.VariableData; if ((aVa.Flags & (VariableFlags.RReg | VariableFlags.AllocRDone)) != VariableFlags.RReg) { continue; } var aIndex = aVd.RegisterIndex; var bIndex = aVa.InRegIndex; // Shouldn't be the same. if (!(aIndex != bIndex)) { throw new ArgumentException(); } var bVd = state.GetListByClass(@class)[bIndex]; if (bVd != null) { // Gp registers only - Swap two registers if we can solve two // allocation tasks by a single 'xchg' instruction, swapping // two registers required by the instruction/node or one register // required with another non-required. if (@class != RegisterClass.Gp || aIndex == RegisterIndex.Invalid) { continue; } var bVa = bVd.Attributes; Translator.SwapGp(aVd, bVd); aVa.Flags |= VariableFlags.AllocRDone; Done.Add(@class); // Doublehit, two registers allocated by a single swap. if (bVa != null && bVa.InRegIndex == aIndex) { bVa.Flags |= VariableFlags.AllocRDone; Done.Add(@class); } didWork = true; } else if (aIndex != RegisterIndex.Invalid) { Translator.Move(aVd, @class, bIndex); aVa.Flags |= VariableFlags.AllocRDone; Done.Add(@class); didWork = true; } else { Translator.Alloc(aVd, @class, bIndex); aVa.Flags |= VariableFlags.AllocRDone; Done.Add(@class); didWork = true; } } } while (didWork); // Alloc 'out' regs. for (var i = 0; i < count; i++) { var va = list[i]; var vd = va.VariableData; if ((va.Flags & (VariableFlags.XReg | VariableFlags.AllocWDone)) != VariableFlags.WReg) { continue; } var regIndex = va.OutRegIndex; if (!(regIndex != RegisterIndex.Invalid)) { throw new ArgumentException(); } if (vd.RegisterIndex != regIndex) { if (!(state.GetListByClass(@class)[regIndex] == null)) { throw new ArgumentException(); } Translator.Attach(vd, @class, regIndex, false); } va.Flags |= VariableFlags.AllocWDone; Done.Add(@class); } }