Ejemplo n.º 1
0
        /// <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);
        }