/// <summary> /// Make a function signature based on the procedure flow <paramref name="flow"/>. /// </summary> /// <returns>A valid function signature.</returns> public FunctionType MakeSignature(SsaState ssa, IStorageBinder frame, ProcedureFlow flow) { if (ssa.Procedure.Name == "fn0800_C779") { ssa.ToString(); //$DEBUG } var allLiveOut = flow.BitsLiveOut; var sb = new SignatureBuilder(frame, platform.Architecture); var implicitRegs = platform.CreateImplicitArgumentRegisters(); var liveOutFlagGroups = flow.grfLiveOut.Select(de => platform.Architecture.GetFlagGroup(de.Key, de.Value) !); AddModifiedFlags(frame, liveOutFlagGroups, sb); var mayUseSeqs = flow.BitsUsed.Keys.OfType <SequenceStorage>().ToHashSet(); var seqRegs = mayUseSeqs.SelectMany(s => s.Elements).Distinct().ToHashSet(); //$BUG: should be sorted by ABI register order. foreach (var seq in mayUseSeqs.OrderBy(r => r.Name)) { sb.AddSequenceArgument(seq); } var mayUseRegs = flow.BitsUsed .Select(de => (Key: de.Key as RegisterStorage, de.Value)) .Where(b => { return(b.Key is RegisterStorage reg && !implicitRegs.Contains(reg)); }) .Select(MakeRegisterParameter) .ToDictionary(de => de.Item1, de => de.Item2); //$BUG: should be sorted by ABI register order. Need a new method // IPlatform.CreateAbiRegisterCollator(). foreach (var reg in mayUseRegs.OrderBy(r => r.Key.Number)) { if (!IsSubRegisterOfRegisters(reg.Key, mayUseRegs) && !seqRegs.Contains(reg.Key)) { sb.AddRegisterArgument(reg.Key); } } foreach (var id in GetSortedStackArguments((Frame)frame, flow.BitsUsed)) { sb.AddInParam(id.Item2); } foreach (var oFpu in flow.BitsUsed .Where(f => f.Key is FpuStackStorage) .OrderBy(r => ((FpuStackStorage)r.Key).FpuStackOffset)) { var fpu = (FpuStackStorage)oFpu.Key; var id = frame.EnsureFpuStackVariable(fpu.FpuStackOffset, fpu.DataType); sb.AddFpuStackArgument(fpu.FpuStackOffset, id); } var liveOut = allLiveOut .Select(de => (Key: de.Key as RegisterStorage, de.Value)) .Where(de => { return(de.Key != null && !implicitRegs.Contains(de.Key)); }) .Select(MakeRegisterParameter) .ToDictionary(de => de.Item1, de => de.Item2); // Sort the names in a stable way to avoid regression tests failing. foreach (var r in liveOut.OrderBy(r => r.Key.Number).ThenBy(r => r.Key.BitAddress)) { if (!IsSubRegisterOfRegisters(r.Key, liveOut)) { var regOut = sb.AddOutParam(frame.EnsureRegister(r.Key)); if (regOut.Storage is OutArgumentStorage && !ssa.Identifiers.TryGetValue(regOut, out var sidOut)) { // Ensure there are SSA identifiers for 'out' registers. ssa.Identifiers.Add(regOut, null, null, false); } } } foreach (var fpu in allLiveOut.Keys.OfType <FpuStackStorage>().OrderBy(r => r.FpuStackOffset)) { sb.AddOutParam(frame.EnsureFpuStackVariable(fpu.FpuStackOffset, fpu.DataType)); } var sig = sb.BuildSignature(); return(sig); }