Пример #1
0
 public override void VisitCallInstruction(CallInstruction ci)
 {
     base.VisitCallInstruction(ci);
     var pc = ci.Callee as ProcedureConstant;
     if (pc != null && ProcedureTerminates(pc.Procedure))
     {
         flow[curBlock].TerminatesProcess = true;
     }
 }
Пример #2
0
		/// <summary>
		/// Rewrites CALL instructions to function applications.
		/// </summary>
		/// <remarks>
		/// Converts an opcode:
		/// <code>
		///   call procExpr 
		/// </code>
		/// to one of:
		/// <code>
		///	 ax = procExpr(bindings);
		///  procEexpr(bindings);
		/// </code>
		/// </remarks>
		/// <param name="proc">Procedure in which the CALL instruction exists</param>
		/// <param name="stm">The particular statement of the call instruction</param>
		/// <param name="call">The actuall CALL instruction.</param>
		/// <returns>True if the conversion was possible, false if the procedure didn't have
		/// a signature yet.</returns>
		public bool RewriteCall(Procedure proc, Statement stm, CallInstruction call)
		{
            var callee = call.Callee as ProcedureConstant;
            if (callee == null)
                return false;          //$REVIEW: what happens with indirect calls?
			var procCallee = callee.Procedure;
			var sigCallee = GetProcedureSignature(procCallee);
			var fn = new ProcedureConstant(Program.Platform.PointerType, procCallee);
            if (sigCallee == null || !sigCallee.ParametersValid)
                return false;

            var ab = new ApplicationBuilder(Program.Architecture, proc.Frame, call.CallSite, fn, sigCallee, true);
			stm.Instruction = ab.CreateInstruction();
            return true;
		}
Пример #3
0
 private void RewriteCall(Statement stm, CallInstruction call)
 {
     var e = expander.Expand(call.Callee);
     var pt = e.Accept(asc) as Pointer;
     if (pt == null)
         return;
     var ft = pt.Pointee as FunctionType;
     if (ft == null)
         return;
     var returnId = ft.ReturnValue.DataType is VoidType ?
         null : ft.ReturnValue;
     var sigCallee = new FunctionType(returnId, ft.Parameters);
     var ab = new ApplicationBuilder(
         program.Architecture, proc.Frame, call.CallSite,
         call.Callee, sigCallee, true);
     stm.Instruction = ab.CreateInstruction();
     ssaIdTransformer.Transform(stm, call);
 }
Пример #4
0
 private void AddUseInstructions(CallInstruction ci)
 {
     var existing = ci.Uses.Select(u => u.Expression).ToHashSet();
     ci.Uses.UnionWith(rename.Values
         .Where(id => !existing.Contains(id))
         .Select(id => new UseInstruction(id)));
 }
Пример #5
0
            public override Instruction TransformCallInstruction(CallInstruction ci)
            {
                ci.Callee = ci.Callee.Accept(this);
                ProcedureConstant pc;
                if (ci.Callee.As(out pc))
                {
                    var procCallee = pc.Procedure as Procedure;
                    ProcedureFlow2 procFlow;
                    if (procCallee != null && programFlow.ProcedureFlows2.TryGetValue(procCallee, out procFlow))
                    {
                        AddUseInstructions(ci);
                        AddDefInstructions(ci, procFlow);
                    }
                    return ci;
                }

                // Hell node implementation - use all register variables.

                foreach (Identifier id in proc.Frame.Identifiers)
                {
                    if (id.Storage is RegisterStorage || id.Storage is FlagGroupStorage)
                    {
                        NewUse(id, stmCur);
                    }
                }
                return ci;
            }
Пример #6
0
        public override void VisitCallInstruction(CallInstruction ci)
        {
            FunctionType sig = GetProcedureSignature(ci.Callee);

            if (sig != null && sig.ParametersValid)
            {
                var procCallee = ((ProcedureConstant)ci.Callee).Procedure;
                var ab         = new ApplicationBuilder(
                    program.Architecture,
                    Procedure.Frame,
                    ci.CallSite,
                    new ProcedureConstant(program.Platform.PointerType, procCallee),
                    sig,
                    false);
                if (!sig.HasVoidReturn)
                {
                    varLive.Def(ab.Bind(sig.ReturnValue));
                }
                foreach (Identifier arg in sig.Parameters)
                {
                    if (arg.Storage is OutArgumentStorage)
                    {
                        varLive.Def(ab.Bind(arg));
                    }
                }

                foreach (Identifier arg in sig.Parameters)
                {
                    if (!(arg.Storage is OutArgumentStorage))
                    {
                        varLive.Use(ab.Bind(arg));
                    }
                }
            }
            else
            {
                var pc = ci.Callee as ProcedureConstant;
                if (pc == null)
                {
                    return;
                }
                var procCallee = pc.Procedure as Procedure;
                if (procCallee == null)
                {
                    return;
                }

                if (state.PropagateThroughExitNodes)
                {
                    PropagateToCalleeExitBlocks(stmCur);
                }

                // Update trash information.

                ProcedureFlow pi   = mpprocData[procCallee];
                ProcedureFlow item = mpprocData[Procedure];

                // The registers that are still live before a call are those
                // that were live after the call and were bypassed by the called function
                // or used by the called function.

                var ids = new HashSet <RegisterStorage>(pi.TrashedRegisters);
                ids.ExceptWith(pi.ByPass);
                varLive.Identifiers.ExceptWith(ids);
                varLive.Identifiers.UnionWith(pi.MayUse);
                // varLive.BitSet = pi.MayUse | ((pi.ByPass    | ~pi.TrashedRegisters) & varLive.BitSet);
                varLive.Grf = pi.grfMayUse | ((pi.grfByPass | ~pi.grfTrashed) & varLive.Grf);
                // Any stack parameters are also considered live.
                MarkLiveStackParameters(ci);
            }
        }
Пример #7
0
		public override void VisitCallInstruction(CallInstruction ci)
		{
			isCritical = true;
		}
Пример #8
0
        TranslatedExpression HandleDelegateConstruction(CallInstruction inst)
        {
            ILInstruction func = inst.Arguments[1];
            IMethod       method;

            switch (func.OpCode)
            {
            case OpCode.LdFtn:
                method = ((LdFtn)func).Method;
                break;

            case OpCode.LdVirtFtn:
                method = ((LdVirtFtn)func).Method;
                break;

            case OpCode.ILFunction:
                method = ((ILFunction)func).Method;
                return(expressionBuilder.TranslateFunction(inst.Method.DeclaringType, (ILFunction)func));

            default:
                throw new ArgumentException($"Unknown instruction type: {func.OpCode}");
            }
            var invokeMethod = inst.Method.DeclaringType.GetDelegateInvokeMethod();
            TranslatedExpression target;
            IType targetType;

            if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count)
            {
                target     = expressionBuilder.Translate(inst.Arguments[0]);
                targetType = method.Parameters[0].Type;
            }
            else
            {
                target     = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn);
                targetType = method.DeclaringType;
            }
            var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);
            var or     = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type)));
            var result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);

            bool needsCast = true;

            if (result is MethodGroupResolveResult mgrr)
            {
                or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray());
                needsCast = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(method, or.BestCandidate, func.OpCode == OpCode.LdVirtFtn));
            }
            if (needsCast)
            {
                target = target.ConvertTo(targetType, expressionBuilder);
                result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);
            }

            var mre = new MemberReferenceExpression(target, method.Name);

            mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
            mre.WithRR(result);
            var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), mre)
                      .WithILInstruction(inst)
                      .WithRR(new ConversionResolveResult(
                                  inst.Method.DeclaringType,
                                  new MemberResolveResult(target.ResolveResult, method),
                                  Conversion.MethodGroupConversion(method, func.OpCode == OpCode.LdVirtFtn, false)));

            return(oce);
        }
Пример #9
0
 public Statement Call(string procedureName, int retSizeOnStack)
 {
     var ci = new CallInstruction(Constant.Invalid, new CallSite(retSizeOnStack, 0)); 
     unresolvedProcedures.Add(new ProcedureConstantUpdater(procedureName, ci));
     return Emit(ci);
 }
Пример #10
0
 public void Transform(Statement stm, CallInstruction call)
 {
     this.stm = stm;
     this.call = call;
     ssa.ReplaceDefinitions(stm, null);
     ssa.RemoveUses(stm);
     Transform(stm.Instruction);
 }
Пример #11
0
 public abstract void VisitCallInstruction(CallInstruction instruction);
Пример #12
0
 void InstructionVisitor.VisitCallInstruction(CallInstruction ci)
 {
     stms.Add(new AbsynSideEffect(new Application(ci.Callee, VoidType.Instance)));
 }
Пример #13
0
 void InstructionVisitor.VisitCallInstruction(CallInstruction ci)
 {
     throw new NotImplementedException();
 }
Пример #14
0
        public bool VisitCall(RtlCall call)
        {
            if ((call.Class & RtlClass.Delay) != 0)
            {
                // Get delay slot instruction cluster.
                rtlStream.MoveNext();
                ProcessRtlCluster(rtlStream.Current);
            }
            var                      site = OnBeforeCall(stackReg, call.ReturnAddressSize);
            FunctionType             sig;
            ProcedureCharacteristics chr  = null;
            Address                  addr = call.Target as Address;

            if (addr != null)
            {
                if (!program.SegmentMap.IsValidAddress(addr))
                {
                    scanner.Warn(ric.Address, "Call target address {0} is invalid.", addr);
                    sig = new FunctionType();
                    EmitCall(
                        CreateProcedureConstant(
                            new ExternalProcedure(Procedure.GenerateName(addr), sig)),
                        sig,
                        chr,
                        site);
                    return(OnAfterCall(sig, chr));
                }

                var impProc = scanner.GetImportedProcedure(addr, this.ric.Address);
                if (impProc != null && impProc.Characteristics.IsAlloca)
                {
                    return(ProcessAlloca(site, impProc));
                }

                var callee   = scanner.ScanProcedure(addr, null, state);
                var pcCallee = CreateProcedureConstant(callee);
                sig = callee.Signature;
                chr = callee.Characteristics;
                EmitCall(pcCallee, sig, chr, site);
                var pCallee = callee as Procedure;
                if (pCallee != null)
                {
                    program.CallGraph.AddEdge(blockCur.Statements.Last, pCallee);
                }
                return(OnAfterCall(sig, chr));
            }

            var procCallee = call.Target as ProcedureConstant;

            if (procCallee != null)
            {
                sig = procCallee.Procedure.Signature;
                chr = procCallee.Procedure.Characteristics;
                EmitCall(procCallee, sig, chr, site);
                return(OnAfterCall(sig, chr));
            }
            sig = scanner.GetCallSignatureAtAddress(ric.Address);
            if (sig != null)
            {
                EmitCall(call.Target, sig, chr, site);
                return(OnAfterCall(sig, chr));  //$TODO: make characteristics available
            }

            Identifier id;

            if (call.Target.As <Identifier>(out id))
            {
                var ppp = SearchBackForProcedureConstant(id);
                if (ppp != null)
                {
                    var e = CreateProcedureConstant(ppp);
                    sig = ppp.Signature;
                    chr = ppp.Characteristics;
                    EmitCall(e, sig, chr, site);
                    return(OnAfterCall(sig, chr));
                }
            }

            var imp = ImportedProcedureName(call.Target);

            if (imp != null)
            {
                sig = imp.Signature;
                chr = imp.Characteristics;
                EmitCall(CreateProcedureConstant(imp), sig, chr, site);
                //Emit(BuildApplication(CreateProcedureConstant(imp), sig, site));
                return(OnAfterCall(sig, chr));
            }

            var syscall = program.Platform.FindService(call, state);

            if (syscall != null)
            {
                return(!EmitSystemServiceCall(syscall));
            }

            ProcessIndirectControlTransfer(ric.Address, call);

            var ic = new CallInstruction(call.Target, site);

            Emit(ic);
            sig = GuessProcedureSignature(ic);
            return(OnAfterCall(sig, chr));
        }
Пример #15
0
        void Run(CallInstruction inst, ILTransformContext context)
        {
            if (inst.Method.IsStatic)
            {
                return;
            }
            if (inst.Method.MetadataToken.IsNil || inst.Method.MetadataToken.Kind != HandleKind.MethodDefinition)
            {
                return;
            }
            var handle = (MethodDefinitionHandle)inst.Method.MetadataToken;

            if (!IsDefinedInCurrentOrOuterClass(inst.Method, context.Function.Method.DeclaringTypeDefinition))
            {
                return;
            }
            if (!inst.Method.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
            {
                return;
            }
            var metadata = context.PEFile.Metadata;
            MethodDefinition methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)inst.Method.MetadataToken);

            if (!methodDef.HasBody())
            {
                return;
            }
            // Use the callee's generic context
            var genericContext = new GenericContext(inst.Method);
            // partially copied from CSharpDecompiler
            var ilReader         = context.CreateILReader();
            var body             = context.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
            var proxyFunction    = ilReader.ReadIL(handle, body, genericContext, ILFunctionKind.TopLevelFunction, context.CancellationToken);
            var transformContext = new ILTransformContext(context, proxyFunction);

            proxyFunction.RunTransforms(CSharp.CSharpDecompiler.EarlyILTransforms(), transformContext);
            if (!(proxyFunction.Body is BlockContainer blockContainer))
            {
                return;
            }
            if (blockContainer.Blocks.Count != 1)
            {
                return;
            }
            var           block = blockContainer.Blocks[0];
            Call          call;
            ILInstruction returnValue;

            switch (block.Instructions.Count)
            {
            case 1:
                // leave IL_0000 (call Test(ldloc this, ldloc A_1))
                if (!block.Instructions[0].MatchLeave(blockContainer, out returnValue))
                {
                    return;
                }
                call = returnValue as Call;
                break;

            case 2:
                // call Test(ldloc this, ldloc A_1)
                // leave IL_0000(nop)
                call = block.Instructions[0] as Call;
                if (!block.Instructions[1].MatchLeave(blockContainer, out returnValue))
                {
                    return;
                }
                if (!returnValue.MatchNop())
                {
                    return;
                }
                break;

            default:
                return;
            }
            if (call == null || call.Method.IsConstructor)
            {
                return;
            }
            if (call.Method.IsStatic || call.Method.Parameters.Count != inst.Method.Parameters.Count)
            {
                return;
            }
            // check if original arguments are only correct ldloc calls
            for (int i = 0; i < call.Arguments.Count; i++)
            {
                var originalArg = call.Arguments[i];
                if (!originalArg.MatchLdLoc(out ILVariable var) ||
                    var.Kind != VariableKind.Parameter ||
                    var.Index != i - 1)
                {
                    return;
                }
            }
            context.Step("Replace proxy: " + inst.Method.Name + " with " + call.Method.Name, inst);
            // Apply the wrapper call's substitution to the actual method call.
            Call newInst = new Call(call.Method.Specialize(inst.Method.Substitution));

            // copy flags
            newInst.ConstrainedTo   = call.ConstrainedTo;
            newInst.ILStackWasEmpty = inst.ILStackWasEmpty;
            newInst.IsTail          = call.IsTail & inst.IsTail;
            // copy IL ranges
            newInst.AddILRange(inst);
            newInst.Arguments.ReplaceList(inst.Arguments);
            inst.ReplaceWith(newInst);
        }
Пример #16
0
 public void VisitCallInstruction(CallInstruction call)
 {
     call.Callee.Accept(asc);
     desc.MeetDataType(
                   call.Callee,
                   new Pointer(
                       new CodeType(),
                       program.Platform.PointerType.Size));
     call.Callee.Accept(desc, call.Callee.TypeVariable);
 }
Пример #17
0
        private Func <CallSite, TSelfType, CodeContext, object> MakeGetMemberTarget <TSelfType>(string name, object target)
        {
            Type type = CompilerHelpers.GetType(target);

            // needed for GetMember call until DynamicAction goes away
            if (typeof(TypeTracker).IsAssignableFrom(type))
            {
                // no fast path for TypeTrackers
                PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast TypeTracker");
                return(null);
            }

            MemberGroup members = Context.Binder.GetMember(MemberRequestKind.Get, type, name);

            if (members.Count == 0 && type.IsInterface)
            {
                // all interfaces have object members
                type    = typeof(object);
                members = Context.Binder.GetMember(MemberRequestKind.Get, type, name);
            }

            if (members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type))
            {
                // no fast path for strong box access
                PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast StrongBox");
                return(null);
            }

            MethodInfo getMem = Context.Binder.GetMethod(type, "GetCustomMember");

            if (getMem != null && getMem.IsSpecialName)
            {
                // no fast path for custom member access
                PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast GetCustomMember " + type);
                return(null);
            }

            Expression   error;
            TrackerTypes memberType = Context.Binder.GetMemberType(members, out error);

            if (error == null)
            {
                PythonType argType  = DynamicHelpers.GetPythonTypeFromType(type);
                bool       isHidden = argType.IsHiddenMember(name);
                if (isHidden)
                {
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast FilteredMember " + memberType);
                    return(null);
                }

                switch (memberType)
                {
                case TrackerTypes.TypeGroup:
                case TrackerTypes.Type:
                    object typeObj;
                    if (members.Count == 1)
                    {
                        typeObj = DynamicHelpers.GetPythonTypeFromType(((TypeTracker)members[0]).Type);
                    }
                    else
                    {
                        TypeTracker typeTracker = (TypeTracker)members[0];
                        for (int i = 1; i < members.Count; i++)
                        {
                            typeTracker = TypeGroup.UpdateTypeEntity(typeTracker, (TypeTracker)members[i]);
                        }
                        typeObj = typeTracker;
                    }

                    return(new FastTypeGet <TSelfType>(type, typeObj).GetTypeObject);

                case TrackerTypes.Method:
                    PythonTypeSlot slot = PythonTypeOps.GetSlot(members, name, _context.DomainManager.Configuration.PrivateBinding);
                    if (slot is BuiltinMethodDescriptor)
                    {
                        return(new FastMethodGet <TSelfType>(type, (BuiltinMethodDescriptor)slot).GetMethod);
                    }
                    else if (slot is BuiltinFunction)
                    {
                        return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(type)).GetRetSlot);
                    }
                    return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(type)).GetBindSlot);

                case TrackerTypes.Event:
                    if (members.Count == 1 && !((EventTracker)members[0]).IsStatic)
                    {
                        slot = PythonTypeOps.GetSlot(members, name, _context.DomainManager.Configuration.PrivateBinding);
                        return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(((EventTracker)members[0]).DeclaringType)).GetBindSlot);
                    }
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast Event " + members.Count + " " + ((EventTracker)members[0]).IsStatic);
                    return(null);

                case TrackerTypes.Property:
                    if (members.Count == 1)
                    {
                        PropertyTracker pt = (PropertyTracker)members[0];
                        if (!pt.IsStatic && pt.GetIndexParameters().Length == 0)
                        {
                            MethodInfo      prop = pt.GetGetMethod();
                            ParameterInfo[] parameters;

                            if (prop != null && (parameters = prop.GetParameters()).Length == 0)
                            {
                                if (prop.ReturnType == typeof(bool))
                                {
                                    return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetPropertyBool);
                                }
                                else if (prop.ReturnType == typeof(int))
                                {
                                    return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetPropertyInt);
                                }
                                else
                                {
                                    return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetProperty);
                                }
                            }
                        }
                    }
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast Property " + members.Count + " " + ((PropertyTracker)members[0]).IsStatic);
                    return(null);

                case TrackerTypes.All:
                    getMem = Context.Binder.GetMethod(type, "GetBoundMember");
                    if (getMem != null && getMem.IsSpecialName)
                    {
                        PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast GetBoundMember " + type);
                        return(null);
                    }

                    if (IsNoThrow)
                    {
                        return(new FastErrorGet <TSelfType>(type, name).GetErrorNoThrow);
                    }
                    else
                    {
                        return(new FastErrorGet <TSelfType>(type, name).GetError);
                    }

                default:
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast " + memberType);
                    return(null);
                }
            }
            else
            {
                StringBuilder sb = new StringBuilder();
                foreach (MemberTracker mi in members)
                {
                    if (sb.Length != 0)
                    {
                        sb.Append(", ");
                    }
                    sb.Append(mi.MemberType);
                    sb.Append(" : ");
                    sb.Append(mi.ToString());
                }

                return(new FastErrorGet <TSelfType>(type, sb.ToString()).GetAmbiguous);
            }
        }
Пример #18
0
 private Procedure GetUserProcedure(CallInstruction ci)
 {
     var pc = ci.Callee as ProcedureConstant;
     if (pc == null)
         return null;
     return pc.Procedure as Procedure;
 }
Пример #19
0
		public void VisitCallInstruction(CallInstruction ci)
		{
			writer.Indent();
			writer.WriteKeyword("call");
            writer.Write(" ");
            ci.Callee.Accept(this);
            writer.Write(" ({0})", ci.CallSite);
			writer.Terminate();
            if (ci.Uses.Count > 0)
            {
                writer.Indentation += writer.TabSize;
                writer.Indent();
                writer.Write("uses: ");
                writer.Write(string.Join(",", ci.Uses.OrderBy(u => ((Identifier)(u.Expression)).Name).Select(u => u.Expression)));
                writer.Terminate();
                writer.Indentation -= writer.TabSize;
            }
            if (ci.Definitions.Count > 0)
            {
                writer.Indentation += writer.TabSize;
                writer.Indent();
                writer.Write("defs: ");
                writer.Write(string.Join(",", ci.Definitions.OrderBy(d => ((Identifier)d.Expression).Name).Select(d => d.Expression)));
                writer.Terminate();
                writer.Indentation -= writer.TabSize;
            }
		}
Пример #20
0
        static bool MatchingGetterAndSetterCalls(CallInstruction getterCall, CallInstruction setterCall, out Action <ILTransformContext> finalizeMatch)
        {
            finalizeMatch = null;
            if (getterCall == null || setterCall == null || !IsSameMember(getterCall.Method.AccessorOwner, setterCall.Method.AccessorOwner))
            {
                return(false);
            }
            if (setterCall.OpCode != getterCall.OpCode)
            {
                return(false);
            }
            var owner = getterCall.Method.AccessorOwner as IProperty;

            if (owner == null || !IsSameMember(getterCall.Method, owner.Getter) || !IsSameMember(setterCall.Method, owner.Setter))
            {
                return(false);
            }
            if (setterCall.Arguments.Count != getterCall.Arguments.Count + 1)
            {
                return(false);
            }
            // Ensure that same arguments are passed to getterCall and setterCall:
            for (int j = 0; j < getterCall.Arguments.Count; j++)
            {
                if (setterCall.Arguments[j].MatchStLoc(out var v) && v.IsSingleDefinition && v.LoadCount == 1)
                {
                    if (getterCall.Arguments[j].MatchLdLoc(v))
                    {
                        // OK, setter call argument is saved in temporary that is re-used for getter call
                        if (finalizeMatch == null)
                        {
                            finalizeMatch = AdjustArguments;
                        }
                        continue;
                    }
                }
                if (!SemanticHelper.IsPure(getterCall.Arguments[j].Flags))
                {
                    return(false);
                }
                if (!getterCall.Arguments[j].Match(setterCall.Arguments[j]).Success)
                {
                    return(false);
                }
            }
            return(true);

            void AdjustArguments(ILTransformContext context)
            {
                Debug.Assert(setterCall.Arguments.Count == getterCall.Arguments.Count + 1);
                for (int j = 0; j < getterCall.Arguments.Count; j++)
                {
                    if (setterCall.Arguments[j].MatchStLoc(out var v, out var value))
                    {
                        Debug.Assert(v.IsSingleDefinition && v.LoadCount == 1);
                        Debug.Assert(getterCall.Arguments[j].MatchLdLoc(v));
                        getterCall.Arguments[j] = value;
                    }
                }
            }
        }
Пример #21
0
 public Instruction VisitCallInstruction(CallInstruction ci)
 {
     ci.Callee = ci.Callee.Accept(eval);
     return(ci);
 }
Пример #22
0
 public Instruction VisitCallInstruction(CallInstruction ci)
 {
     return(ci);
 }
Пример #23
0
 public Statement Call(Expression e, int retSizeOnstack)
 {
     CallInstruction ci = new CallInstruction(e, new CallSite(retSizeOnstack, 0));
     return Emit(ci);
 }
		public void Rl_CallToProcedureWithValidSignature()
		{
			Procedure callee = new Procedure("callee", null);
			callee.Signature = new ProcedureSignature(
				f.EnsureRegister(Registers.eax),
				new Identifier[] {
					f.EnsureRegister(Registers.ebx),
					f.EnsureRegister(Registers.ecx),
					f.EnsureOutArgument(f.EnsureRegister(Registers.edi), PrimitiveType.Pointer32)
				});
			
			rl.IdentifierLiveness.Identifiers.Add(Registers.eax);
			rl.IdentifierLiveness.Identifiers.Add(Registers.esi);
			rl.IdentifierLiveness.Identifiers.Add(Registers.edi);
			CallInstruction ci = new CallInstruction(new ProcedureConstant(PrimitiveType.Pointer32, callee), new CallSite(4, 0));
			rl.VisitCallInstruction(ci);
			Assert.AreEqual(" ebx ecx esi", Dump(rl.IdentifierLiveness));
		}
Пример #25
0
 public override Instruction TransformCallInstruction(CallInstruction ci)
 {
     //var proc = ci.Callee.Accept(new TypedMemoryExpressionRewriter(arch, store, globals));
     return new SideEffect(
         new Application(ci.Callee, VoidType.Instance));
 }
Пример #26
0
 void InstructionVisitor.VisitCallInstruction(CallInstruction ci)
 {
     stms.Add(new AbsynSideEffect(new Application(ci.Callee, VoidType.Instance)));
 }
Пример #27
0
 public void VisitCallInstruction(CallInstruction ci)
 {
     throw new NotImplementedException();
 }
Пример #28
0
        public TranslatedExpression Build(CallInstruction inst)
        {
            IMethod method = inst.Method;
            // Used for Call, CallVirt and NewObj
            TranslatedExpression target;

            if (inst.OpCode == OpCode.NewObj)
            {
                if (IL.Transforms.DelegateConstruction.IsDelegateConstruction((NewObj)inst, true))
                {
                    return(HandleDelegateConstruction(inst));
                }
                target = default(TranslatedExpression);                 // no target
            }
            else
            {
                target = expressionBuilder.TranslateTarget(method, inst.Arguments.FirstOrDefault(), inst.OpCode == OpCode.Call);
            }

            int firstParamIndex = (method.IsStatic || inst.OpCode == OpCode.NewObj) ? 0 : 1;

            // Translate arguments to the expected parameter types
            var arguments = new List <TranslatedExpression>(method.Parameters.Count);

            Debug.Assert(inst.Arguments.Count == firstParamIndex + method.Parameters.Count);
            var  expectedParameters = method.Parameters.ToList();
            bool isExpandedForm     = false;

            for (int i = 0; i < method.Parameters.Count; i++)
            {
                var parameter = expectedParameters[i];
                var arg       = expressionBuilder.Translate(inst.Arguments[firstParamIndex + i]);
                if (parameter.IsParams && i + 1 == method.Parameters.Count)
                {
                    // Parameter is marked params
                    // If the argument is an array creation, inline all elements into the call and add missing default values.
                    // Otherwise handle it normally.
                    if (arg.ResolveResult is ArrayCreateResolveResult acrr &&
                        acrr.SizeArguments.Count == 1 &&
                        acrr.SizeArguments[0].IsCompileTimeConstant &&
                        acrr.SizeArguments[0].ConstantValue is int length)
                    {
                        var expandedParameters = expectedParameters.Take(expectedParameters.Count - 1).ToList();
                        var expandedArguments  = new List <TranslatedExpression>(arguments);
                        if (length > 0)
                        {
                            var arrayElements = ((ArrayCreateExpression)arg.Expression).Initializer.Elements.ToArray();
                            var elementType   = ((ArrayType)acrr.Type).ElementType;
                            for (int j = 0; j < length; j++)
                            {
                                expandedParameters.Add(new DefaultParameter(elementType, parameter.Name + j));
                                if (j < arrayElements.Length)
                                {
                                    expandedArguments.Add(new TranslatedExpression(arrayElements[j]));
                                }
                                else
                                {
                                    expandedArguments.Add(expressionBuilder.GetDefaultValueExpression(elementType).WithoutILInstruction());
                                }
                            }
                        }
                        if (IsUnambiguousCall(inst, target, method, Array.Empty <IType>(), expandedArguments) == OverloadResolutionErrors.None)
                        {
                            isExpandedForm     = true;
                            expectedParameters = expandedParameters;
                            arguments          = expandedArguments.SelectList(a => new TranslatedExpression(a.Expression.Detach()));
                            continue;
                        }
                    }
                }

                arguments.Add(arg.ConvertTo(parameter.Type, expressionBuilder, allowImplicitConversion: true));

                if (parameter.IsOut && arguments[i].Expression is DirectionExpression dirExpr)
                {
                    dirExpr.FieldDirection = FieldDirection.Out;
                }
            }

            if (method is VarArgInstanceMethod)
            {
                int regularParameterCount = ((VarArgInstanceMethod)method).RegularParameterCount;
                var argListArg            = new UndocumentedExpression();
                argListArg.UndocumentedExpressionType = UndocumentedExpressionType.ArgList;
                int paramIndex = regularParameterCount;
                var builder    = expressionBuilder;
                argListArg.Arguments.AddRange(arguments.Skip(regularParameterCount).Select(arg => arg.ConvertTo(expectedParameters[paramIndex++].Type, builder).Expression));
                var argListRR = new ResolveResult(SpecialType.ArgList);
                arguments = arguments.Take(regularParameterCount)
                            .Concat(new[] { argListArg.WithoutILInstruction().WithRR(argListRR) }).ToList();
                method             = (IMethod)method.MemberDefinition;
                expectedParameters = method.Parameters.ToList();
            }

            var argumentResolveResults = arguments.Select(arg => arg.ResolveResult).ToList();

            ResolveResult rr = new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm);

            if (inst.OpCode == OpCode.NewObj)
            {
                if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType())
                {
                    var argumentExpressions            = arguments.SelectArray(arg => arg.Expression);
                    AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
                    if (CanInferAnonymousTypePropertyNamesFromArguments(argumentExpressions, expectedParameters))
                    {
                        atce.Initializers.AddRange(argumentExpressions);
                    }
                    else
                    {
                        for (int i = 0; i < argumentExpressions.Length; i++)
                        {
                            atce.Initializers.Add(
                                new NamedExpression {
                                Name       = expectedParameters[i].Name,
                                Expression = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder)
                            });
                        }
                    }
                    return(atce
                           .WithILInstruction(inst)
                           .WithRR(rr));
                }
                else
                {
                    if (IsUnambiguousCall(inst, target, method, Array.Empty <IType>(), arguments) != OverloadResolutionErrors.None)
                    {
                        for (int i = 0; i < arguments.Count; i++)
                        {
                            if (!settings.AnonymousTypes || !expectedParameters[i].Type.ContainsAnonymousType())
                            {
                                arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder);
                            }
                        }
                    }
                    return(new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), arguments.SelectArray(arg => arg.Expression))
                           .WithILInstruction(inst).WithRR(rr));
                }
            }
            else
            {
                int allowedParamCount = (method.ReturnType.IsKnownType(KnownTypeCode.Void) ? 1 : 0);
                if (method.IsAccessor && (method.AccessorOwner.SymbolKind == SymbolKind.Indexer || expectedParameters.Count == allowedParamCount))
                {
                    return(HandleAccessorCall(inst, target, method, arguments.ToList()));
                }
                else if (method.Name == "Invoke" && method.DeclaringType.Kind == TypeKind.Delegate)
                {
                    return(new InvocationExpression(target, arguments.Select(arg => arg.Expression)).WithILInstruction(inst).WithRR(rr));
                }
                else
                {
                    bool    requireTypeArguments = false;
                    bool    targetCasted         = false;
                    bool    argumentsCasted      = false;
                    IType[] typeArguments        = Array.Empty <IType>();

                    OverloadResolutionErrors errors;
                    while ((errors = IsUnambiguousCall(inst, target, method, typeArguments, arguments)) != OverloadResolutionErrors.None)
                    {
                        switch (errors)
                        {
                        case OverloadResolutionErrors.TypeInferenceFailed:
                        case OverloadResolutionErrors.WrongNumberOfTypeArguments:
                            if (requireTypeArguments)
                            {
                                goto default;
                            }
                            requireTypeArguments = true;
                            typeArguments        = method.TypeArguments.ToArray();
                            continue;

                        default:
                            if (!argumentsCasted)
                            {
                                argumentsCasted = true;
                                for (int i = 0; i < arguments.Count; i++)
                                {
                                    if (!settings.AnonymousTypes || !expectedParameters[i].Type.ContainsAnonymousType())
                                    {
                                        arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder);
                                    }
                                }
                            }
                            else if (!targetCasted)
                            {
                                targetCasted = true;
                                target       = target.ConvertTo(method.DeclaringType, expressionBuilder);
                            }
                            else if (!requireTypeArguments)
                            {
                                requireTypeArguments = true;
                                typeArguments        = method.TypeArguments.ToArray();
                            }
                            else
                            {
                                break;
                            }
                            continue;
                        }
                        break;
                    }

                    Expression targetExpr = target.Expression;
                    string     methodName = method.Name;
                    // HACK : convert this.Dispose() to ((IDisposable)this).Dispose(), if Dispose is an explicitly implemented interface method.
                    if (inst.Method.IsExplicitInterfaceImplementation && targetExpr is ThisReferenceExpression)
                    {
                        targetExpr = new CastExpression(expressionBuilder.ConvertType(method.ImplementedInterfaceMembers[0].DeclaringType), targetExpr);
                        methodName = method.ImplementedInterfaceMembers[0].Name;
                    }
                    var mre = new MemberReferenceExpression(targetExpr, methodName);
                    if (requireTypeArguments && (!settings.AnonymousTypes || !method.TypeArguments.Any(a => a.ContainsAnonymousType())))
                    {
                        mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
                    }
                    var argumentExpressions = arguments.Select(arg => arg.Expression);
                    return(new InvocationExpression(mre, argumentExpressions).WithILInstruction(inst).WithRR(rr));
                }
            }
        }
		public void Rl_MarkLiveStackParameters()
		{
            var callee = new Procedure("callee", program.Architecture.CreateFrame());
			callee.Frame.ReturnAddressSize = 4;
            callee.Frame.ReturnAddressKnown = true;
			callee.Frame.EnsureStackArgument(0, PrimitiveType.Word32);
			callee.Frame.EnsureStackArgument(4, PrimitiveType.Word32);
			Assert.AreEqual(8, callee.Frame.GetStackArgumentSpace());
			ProcedureFlow pf = new ProcedureFlow(callee, program.Architecture);
			mpprocflow[callee] = pf;

			Identifier loc08 = m.Frame.EnsureStackLocal(-8, PrimitiveType.Word32);
			Identifier loc0C = m.Frame.EnsureStackLocal(-12, PrimitiveType.Word32);
			Identifier loc10 = m.Frame.EnsureStackLocal(-16, PrimitiveType.Word32);
			rl.CurrentState = new RegisterLiveness.ByPassState(program.Architecture);
            var ci = new CallInstruction(
                new ProcedureConstant(PrimitiveType.Pointer32, callee),
                new CallSite(4, 0) { StackDepthOnEntry = 16 });
			rl.Procedure = m.Procedure;
			rl.MarkLiveStackParameters(ci);
			Assert.AreEqual(" Local -000C Local -0010", Dump(rl.IdentifierLiveness));
		}
Пример #30
0
 private void AdjustStackPointerAfterCall(
     Statement stm,
     CallInstruction call,
     int stackDelta)
 {
     // Locate the post-call definition of the stack pointer, if any
     var defSpBinding = call.Definitions.Where(
         d => d.Expression is Identifier).Where(
         d => ((Identifier)d.Expression).Storage ==
             program.Architecture.StackRegister)
         .FirstOrDefault();
     if (defSpBinding == null)
         return;
     var defSpId = defSpBinding.Expression as Identifier;
     if (defSpId == null)
         return;
     var usedSpExp = call.Uses.Select(u => u.Expression).
         OfType<Identifier>().Where(
         u => u.Storage == program.Architecture.StackRegister)
         .FirstOrDefault();
     if (usedSpExp == null)
         return;
     var retSize = call.CallSite.SizeOfReturnAddressOnStack;
     var offset = stackDelta - retSize;
     Expression src;
     if (offset == 0)
         src = usedSpExp;
     else
         src = m.IAdd(usedSpExp, Constant.Word32(offset));
     // Generate a statement that adjusts the stack pointer according to
     // the calling convention.
     var ass = new Assignment(defSpId, src);
     var defSid = ssa.Identifiers[defSpId];
     var stackStm = InsertStatement(stm, ass);
     defSid.DefExpression = src;
     defSid.DefStatement = stackStm;
     call.Definitions.Remove(defSpBinding);
     Use(stackStm, src);
 }
Пример #31
0
		public void TrcoIcall()
		{
			ProcedureBuilder m = new ProcedureBuilder();
			Identifier pfn = m.Local32("pfn");
			Expression l = m.Load(PrimitiveType.Word32, pfn);
			CallInstruction icall = new CallInstruction(l, new CallSite(0, 0));

            coll = CreateCollector();
			icall.Accept(eqb);
			icall.Accept(coll);
			StringWriter sw = new StringWriter();
			handler.Traits.Write(sw);
            string exp =
                "T_1 (in pfn : word32)" + nl +
                "\ttrait_primitive(word32)" + nl +
                "\ttrait_mem(T_2, 0)" + nl +
                "T_2 (in Mem0[pfn:word32] : word32)" + nl +
                "\ttrait_primitive((ptr code))" + nl +
                "\ttrait_primitive(word32)" + nl;
            Console.WriteLine(sw.ToString());
			Assert.AreEqual(exp, sw.ToString());
		}
Пример #32
0
 private void RewriteCall(Statement stm, CallInstruction call)
 {
     var e = expander.Expand(call.Callee);
     var pt = e.Accept(asc) as Pointer;
     if (pt == null)
         return;
     var ft = pt.Pointee as FunctionType;
     if (ft == null)
         return;
     AdjustStackPointerAfterCall(stm, call, ft.StackDelta);
     var ab = new ApplicationBuilder(
         program.Architecture, proc.Frame, call.CallSite,
         call.Callee, ft, false);
     stm.Instruction = ab.CreateInstruction();
     ssaIdTransformer.Transform(stm, call);
     changed = true;
 }
Пример #33
0
 private void AddDefInstructions(CallInstruction ci, ProcedureFlow2 flow)
 {
     var existing = ci.Definitions.Select(d => ssa.Identifiers[(Identifier)d.Expression].OriginalIdentifier).ToHashSet();
     var ab = new ApplicationBuilder(null, proc.Frame, null, null, null, true);
     foreach (var idDef in flow.Trashed)
     {
         var idLocal = proc.Frame.EnsureIdentifier(idDef);
         if (!existing.Contains(idLocal))
         {
             ci.Definitions.Add(new DefInstruction(idLocal));
         }
     }
     foreach (var def in ci.Definitions)
     {
         var idNew = NewDef((Identifier) def.Expression, null, false);
         def.Expression = idNew;
     }
 }
Пример #34
0
 private ApplicationBuilder CreateApplicationBuilder(SsaState ssaCaller, Statement stmCaller, CallInstruction call, Expression fn)
 {
     return(new CallApplicationBuilder(ssaCaller, stmCaller, call, fn, false));
 }
Пример #35
0
 /// <summary>
 /// Unresolved calls can be "hell nodes". A hell node is an indirect calls or indirect
 /// jump that prior passes of the decompiler have been unable to resolve.
 /// </summary>
 /// <param name="ci"></param>
 /// <returns></returns>
 public override void VisitCallInstruction(CallInstruction ci)
 {
     Procedure callee = GetUserProcedure(ci);
     ProcedureFlow2 flow;
     if (callee != null && programFlow.ProcedureFlows2.TryGetValue(callee, out flow))
     {
         foreach (var def in flow.Trashed)
         {
             var idDef = callee.Frame.EnsureIdentifier(def);
             MarkDefined(idDef);
         }
     }
     else
     {
         // Hell node implementation - define all register variables.
         foreach (Identifier id in proc.Frame.Identifiers)
         {
             if (id.Storage is RegisterStorage || id.Storage is FlagGroupStorage)
             {
                 MarkDefined(id);
             }
         }
     }
 }
Пример #36
0
        public override Instruction TransformCallInstruction(CallInstruction ci)
        {
            var exp = Rewrite(ci.Callee, true);

            return(new SideEffect(new Application(exp, VoidType.Instance)));
        }
Пример #37
0
 public void BlockCloner_CloneCall()
 {
     var call = new CallInstruction(new ProcedureConstant(arch.PointerType, procCalling), new CallSite(0, 0));
     var cloner = new BlockCloner(null, procCalling, callgraph);
     var block = new Block(procCalling, "test");
     cloner.Statement = new Statement(42, call, block);
     var newCall = (CallInstruction) call.Accept(cloner);
     Assert.AreEqual(call.Callee, newCall.Callee);
     Assert.AreEqual(1, callgraph.CallerStatements(procCalling).Count(), "Should've added a call to the callgraph");
 }
Пример #38
0
        TranslatedExpression HandleDelegateConstruction(CallInstruction inst)
        {
            ILInstruction func = inst.Arguments[1];
            IMethod       method;

            switch (func.OpCode)
            {
            case OpCode.LdFtn:
                method = ((LdFtn)func).Method;
                break;

            case OpCode.LdVirtFtn:
                method = ((LdVirtFtn)func).Method;
                break;

            default:
                throw new ArgumentException($"Unknown instruction type: {func.OpCode}");
            }
            var invokeMethod = inst.Method.DeclaringType.GetDelegateInvokeMethod();
            TranslatedExpression target;
            IType targetType;
            bool  requireTarget;

            if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count)
            {
                targetType    = method.Parameters[0].Type;
                target        = expressionBuilder.Translate(inst.Arguments[0], targetType);
                target        = ExpressionBuilder.UnwrapBoxingConversion(target);
                requireTarget = true;
            }
            else
            {
                targetType    = method.DeclaringType;
                target        = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn);
                target        = ExpressionBuilder.UnwrapBoxingConversion(target);
                requireTarget = expressionBuilder.HidesVariableWithName(method.Name) ||
                                (method.IsStatic ? !expressionBuilder.IsCurrentOrContainingType(method.DeclaringTypeDefinition) : !(target.Expression is ThisReferenceExpression));
            }
            var expectedTargetDetails = new ExpectedTargetDetails {
                CallOpCode = inst.OpCode
            };
            bool          needsCast = false;
            ResolveResult result    = null;
            var           or        = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type)));

            if (!requireTarget)
            {
                result = resolver.ResolveSimpleName(method.Name, method.TypeArguments, isInvocationTarget: false);
                if (result is MethodGroupResolveResult mgrr)
                {
                    or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray());
                    requireTarget = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate));
                }
                else
                {
                    requireTarget = true;
                }
            }
            MemberLookup lookup = null;

            if (requireTarget)
            {
                lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);
                var rr = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);
                needsCast = true;
                result    = rr;
                if (rr is MethodGroupResolveResult mgrr)
                {
                    or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray());
                    needsCast = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate));
                }
            }
            if (needsCast)
            {
                Debug.Assert(requireTarget);
                target = target.ConvertTo(targetType, expressionBuilder);
                result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);
            }
            Expression targetExpression;

            if (requireTarget)
            {
                var mre = new MemberReferenceExpression(target, method.Name);
                mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
                mre.WithRR(result);
                targetExpression = mre;
            }
            else
            {
                var ide = new IdentifierExpression(method.Name)
                          .WithRR(result);
                targetExpression = ide;
            }
            var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), targetExpression)
                      .WithILInstruction(inst)
                      .WithRR(new ConversionResolveResult(
                                  inst.Method.DeclaringType,
                                  new MemberResolveResult(target.ResolveResult, method),
                                  Conversion.MethodGroupConversion(method, func.OpCode == OpCode.LdVirtFtn, false)));

            return(oce);
        }
Пример #39
0
 public void VisitCallInstruction(CallInstruction ci)
 {
     d.VisitCallInstruction(ci);
 }
Пример #40
0
 public AbsynStatement VisitCallInstruction(CallInstruction ci)
 {
     return(new AbsynSideEffect(
                new Application(ci.Callee, VoidType.Instance)));
 }
Пример #41
0
 private Identifier FindUsedId(CallInstruction call, Storage storage)
 {
     return call.Uses.Select(u => u.Expression).
         OfType<Identifier>().
         Where(usedId => usedId.Storage.Equals(storage)).
         FirstOrDefault();
 }
Пример #42
0
        public Statement Call(Expression e, int retSizeOnstack)
        {
            var ci = new CallInstruction(e, new CallSite(retSizeOnstack, 0));

            return(Emit(ci));
        }
Пример #43
0
		public ProcedureConstantUpdater(string name, CallInstruction ci) : base(name)
		{
			this.ci = ci;
		}
Пример #44
0
        /// <summary>
        /// Determines whether <paramref name="enumerator"/> is only used once inside <paramref name="loopBody"/> for accessing the Current property.
        /// </summary>
        /// <param name="usingContainer">The using body container. This is only used for variable usage checks.</param>
        /// <param name="loopBody">The loop body. The first statement of this block is analyzed.</param>
        /// <param name="enumerator">The current enumerator.</param>
        /// <param name="moveNextUsage">The call MoveNext(ldloc enumerator) pattern.</param>
        /// <param name="singleGetter">Returns the call instruction invoking Current's getter.</param>
        /// <param name="foreachVariable">Returns the the foreach variable, if a suitable was found. This variable is only assigned once and its assignment is the first statement in <paramref name="loopBody"/>.</param>
        /// <returns><see cref="RequiredGetCurrentTransformation"/> for details.</returns>
        RequiredGetCurrentTransformation DetectGetCurrentTransformation(BlockContainer usingContainer, Block loopBody, ILVariable enumerator, ILInstruction moveNextUsage, out CallInstruction singleGetter, out ILVariable foreachVariable)
        {
            singleGetter    = null;
            foreachVariable = null;
            var loads = (enumerator.LoadInstructions.OfType <ILInstruction>().Concat(enumerator.AddressInstructions.OfType <ILInstruction>())).Where(ld => !ld.IsDescendantOf(moveNextUsage)).ToArray();

            // enumerator is used in multiple locations or not in conjunction with get_Current
            // => no foreach
            if (loads.Length != 1 || !ParentIsCurrentGetter(loads[0]))
            {
                return(RequiredGetCurrentTransformation.NoForeach);
            }
            singleGetter = (CallInstruction)loads[0].Parent;
            // singleGetter is not part of the first instruction in body or cannot be uninlined
            // => no foreach
            if (!(singleGetter.IsDescendantOf(loopBody.Instructions[0]) && ILInlining.CanUninline(singleGetter, loopBody.Instructions[0])))
            {
                return(RequiredGetCurrentTransformation.NoForeach);
            }
            ILInstruction inst = singleGetter;

            // in some cases, i.e. foreach variable with explicit type different from the collection-item-type,
            // the result of call get_Current is casted.
            while (inst.Parent is UnboxAny || inst.Parent is CastClass)
            {
                inst = inst.Parent;
            }
            // Gather all nested assignments to determine the foreach variable.
            List <StLoc> nestedStores = new List <StLoc>();

            while (inst.Parent is StLoc stloc)
            {
                nestedStores.Add(stloc);
                inst = stloc;
            }
            // No variable was found: we need a new one.
            if (nestedStores.Count == 0)
            {
                return(RequiredGetCurrentTransformation.IntroduceNewVariable);
            }
            // One variable was found.
            if (nestedStores.Count == 1)
            {
                // Must be a plain assignment expression and variable must only be used in 'body' + only assigned once.
                if (nestedStores[0].Parent == loopBody && VariableIsOnlyUsedInBlock(nestedStores[0], usingContainer))
                {
                    foreachVariable = nestedStores[0].Variable;
                    return(RequiredGetCurrentTransformation.UseExistingVariable);
                }
            }
            else
            {
                // Check if any of the variables is usable as foreach variable.
                foreach (var store in nestedStores)
                {
                    if (VariableIsOnlyUsedInBlock(store, usingContainer))
                    {
                        foreachVariable = store.Variable;
                        return(RequiredGetCurrentTransformation.UninlineAndUseExistingVariable);
                    }
                }
            }
            // No suitable variable found.
            return(RequiredGetCurrentTransformation.IntroduceNewVariable);
        }
Пример #45
0
 public Statement Call(ProcedureBase callee, int retSizeOnStack)
 {
     ProcedureConstant c = new ProcedureConstant(PrimitiveType.Pointer32, callee);
     CallInstruction ci = new CallInstruction(c, new CallSite(retSizeOnStack, 0));  
     return Emit(ci);
 }
Пример #46
0
 public override Instruction TransformCallInstruction(CallInstruction ci)
 {
     var exp = Rewrite(ci.Callee, true);
     return new SideEffect(new Application(exp, VoidType.Instance));
 }
Пример #47
0
		public virtual void VisitCallInstruction(CallInstruction ci)
		{
            ci.Callee.Accept(this);
		}
Пример #48
0
        void Run(CallInstruction inst, ILTransformContext context)
        {
            if (inst.Method.MetadataToken.IsNil || inst.Method.MetadataToken.Kind != HandleKind.MethodDefinition)
            {
                return;
            }
            var handle = (MethodDefinitionHandle)inst.Method.MetadataToken;

            if (!IsDefinedInCurrentOrOuterClass(inst.Method, context.Function.Method.DeclaringTypeDefinition))
            {
                return;
            }
            if (!inst.Method.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
            {
                return;
            }
            var metadata = context.PEFile.Metadata;
            MethodDefinition methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)inst.Method.MetadataToken);

            if (!methodDef.HasBody())
            {
                return;
            }
            var genericContext = DelegateConstruction.GenericContextFromTypeArguments(inst.Method.Substitution);

            if (genericContext == null)
            {
                return;
            }
            // partially copied from CSharpDecompiler
            var ilReader         = context.CreateILReader();
            var body             = context.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
            var proxyFunction    = ilReader.ReadIL(handle, body, genericContext.Value, context.CancellationToken);
            var transformContext = new ILTransformContext(context, proxyFunction);

            proxyFunction.RunTransforms(CSharp.CSharpDecompiler.EarlyILTransforms(), transformContext);
            if (!(proxyFunction.Body is BlockContainer blockContainer))
            {
                return;
            }
            if (blockContainer.Blocks.Count != 1)
            {
                return;
            }
            var  block = blockContainer.Blocks[0];
            Call call  = null;

            if (block.Instructions.Count == 1)
            {
                // leave IL_0000 (call Test(ldloc this, ldloc A_1))
                if (!block.Instructions[0].MatchLeave(blockContainer, out ILInstruction returnValue))
                {
                    return;
                }
                call = returnValue as Call;
            }
            else if (block.Instructions.Count == 2)
            {
                // call Test(ldloc this, ldloc A_1)
                // leave IL_0000(nop)
                call = block.Instructions[0] as Call;
                if (!block.Instructions[1].MatchLeave(blockContainer, out ILInstruction returnValue))
                {
                    return;
                }
                if (!returnValue.MatchNop())
                {
                    return;
                }
            }
            if (call == null)
            {
                return;
            }
            if (call.Method.IsConstructor)
            {
                return;
            }

            // check if original arguments are only correct ldloc calls
            for (int i = 0; i < call.Arguments.Count; i++)
            {
                var originalArg = call.Arguments[i];
                if (!originalArg.MatchLdLoc(out ILVariable var) ||
                    var.Kind != VariableKind.Parameter ||
                    var.Index != i - 1)
                {
                    return;
                }
            }

            Call newInst = (Call)call.Clone();

            newInst.Arguments.ReplaceList(inst.Arguments);
            inst.ReplaceWith(newInst);
        }