示例#1
0
        /// <summary>
        /// Make a function signature based on use and def information.
        /// </summary>
        /// <param name="ssa"></param>
        /// <param name="uses"></param>
        /// <param name="definitions"></param>
        /// <returns></returns>
        public FunctionType MakeSignature(SsaState ssa, IEnumerable <CallBinding> uses, IEnumerable <CallBinding> definitions)
        {
            var implicitRegs = platform.CreateImplicitArgumentRegisters();

            var arch  = ssa.Procedure.Architecture;
            var frame = arch.CreateFrame();
            var sb    = new SignatureBuilder(frame, arch);

            var seqs = uses.Select(u => u.Storage as SequenceStorage)
                       .Where(s => s != null)
                       .OrderBy(s => s.Name);

            foreach (var seq in seqs)
            {
                sb.AddSequenceArgument(seq);
            }

            //$TODO: sort these by some ABI order?
            var regs = uses.Select(u => u.Storage as RegisterStorage)
                       .Where(r => r != null && !implicitRegs.Contains(r))
                       .OrderBy(r => r.Number);

            foreach (var reg in regs)
            {
                sb.AddRegisterArgument(reg);
            }

            var stargs = uses.Select(u => u.Storage as StackStorage)
                         .Where(s => s != null)
                         .OrderBy(r => r.StackOffset);

            foreach (var arg in stargs)
            {
                var id = frame.EnsureIdentifier(arg);
                sb.AddInParam(id);
            }

            var outs = definitions.Select(d => d.Storage)
                       .OfType <RegisterStorage>()
                       .Where(r => !implicitRegs.Contains(r))
                       .OrderBy(r => r.Number);

            foreach (var o in outs)
            {
                var id = frame.EnsureIdentifier(o);
                sb.AddOutParam(id);
            }
            var sig = sb.BuildSignature();

            return(sig);
        }
示例#2
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)
        {
            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);
        }