public override bool Rewrite( CodeDescriptor decompilee, MethodBase callee, StackElement[] args, IDecompiler stack, IFunctionBuilder builder) { if (args.Length < 2) throw new InvalidOperationException("The attribute SignalIndexer was applied to the wrong method"); LiteralReference refExpr = args[0].Expr as LiteralReference; if (refExpr == null) throw new InvalidOperationException("Unable to resolve port/signal reference expression"); DimSpec[] dimSamples = new DimSpec[args.Length - 1]; Expression[] indices = args.Skip(1).Select(arg => arg.Expr).ToArray(); bool isStatic = true; for (int i = 1; i < args.Length; i++) { var convidx = TypeConversions.ConvertValue(args[i].Sample, typeof(int)); if (convidx != null) { dimSamples[i - 1] = (int)convidx; } else if (args[i].Sample is Range) { dimSamples[i - 1] = (Range)args[i].Sample; } else { dimSamples = null; break; } // EVariability.LocalVariable is not static as well, since variables // inside for loops will have that variability. if (args[i].Variability != EVariability.Constant) isStatic = false; } IndexSpec indexSpec = null; indexSpec = new IndexSpec(dimSamples); SignalRef sigRef = null; LambdaLiteralVisitor llv = new LambdaLiteralVisitor() { OnVisitConstant = x => { sigRef = new SignalRef( ((SignalBase)x.ConstantValue).Descriptor, SignalRef.EReferencedProperty.Instance, new Expression[][] { indices }, indexSpec, isStatic); }, OnVisitFieldRef = x => { throw new InvalidOperationException(); }, OnVisitSignalRef = x => { sigRef = new SignalRef( x.Desc, x.Prop, x.Indices.Concat(new Expression[][] { indices }), indexSpec.Project(x.IndexSample), x.IsStaticIndex && isStatic); }, OnVisitVariable = x => { throw new InvalidOperationException(); }, OnVisitThisRef = x => { throw new InvalidOperationException(); } }; refExpr.ReferencedObject.Accept(llv); object rsample = null; Type[] argTypes = args .Skip(1) .Select(a => a.Expr.ResultType.CILType) .ToArray(); object[] argSamples = args .Select(a => a.Sample) .ToArray(); MethodInfo indexerSampleMethod = callee.DeclaringType.GetMethod( "GetIndexerSample", BindingFlags.Instance | BindingFlags.NonPublic, null, argTypes, null); if (indexerSampleMethod != null && argSamples.All(a => a != null)) { rsample = indexerSampleMethod.Invoke(argSamples); } else { try { rsample = callee.Invoke(args.Select(x => x.Sample).ToArray()); } catch (TargetInvocationException) { } } stack.Push(sigRef, rsample); return true; }
public override bool Rewrite( CodeDescriptor decompilee, MethodBase callee, StackElement[] args, IDecompiler stack, IFunctionBuilder builder) { if (args.Length == 0) throw new InvalidOperationException("The attribute SignalProperty was applied to the wrong method"); LiteralReference refExpr = args[0].Expr as LiteralReference; if (refExpr == null) throw new InvalidOperationException("Unable to resolve port/signal reference expression"); ISignal sigSample = args[0].Sample as ISignal; SignalRef sigRef = null; LambdaLiteralVisitor llv = new LambdaLiteralVisitor() { OnVisitConstant = x => { sigRef = ((ISignal)x.ConstantValue).ToSignalRef(Prop); }, OnVisitSignalRef = x => { sigRef = new SignalRef(x.Desc, Prop, x.Indices, x.IndexSample, x.IsStaticIndex); }, OnVisitVariable = x => { SignalArgumentDescriptor desc = decompilee.GetSignalArguments().Where(y => y.Name.Equals(x.Name)).Single(); sigRef = new SignalRef(desc, Prop); }, OnVisitFieldRef = x => { sigRef = ((ISignal)x.FieldDesc.ConstantValue).ToSignalRef(Prop); }, OnVisitThisRef = x => { throw new InvalidOperationException(); }, OnVisitArrayRef = x => { throw new InvalidOperationException(); } }; refExpr.ReferencedObject.Accept(llv); ParameterInfo[] pis = callee.GetParameters(); switch (Prop) { case SignalRef.EReferencedProperty.ChangedEvent: case SignalRef.EReferencedProperty.Cur: case SignalRef.EReferencedProperty.FallingEdge: case SignalRef.EReferencedProperty.Pre: case SignalRef.EReferencedProperty.RisingEdge: //if (pis.Length != 0 || callee.IsStatic) // throw new InvalidOperationException("The attribute SignalProperty was applied to the wrong method."); switch (Prop) { case SignalRef.EReferencedProperty.Cur: case SignalRef.EReferencedProperty.Pre: stack.Push( sigRef, sigSample != null ? sigSample.InitialValueObject : null); break; case SignalRef.EReferencedProperty.ChangedEvent: stack.Push( sigRef, null); break; case SignalRef.EReferencedProperty.FallingEdge: case SignalRef.EReferencedProperty.RisingEdge: stack.Push( sigRef, false); break; default: throw new NotImplementedException(); } break; case SignalRef.EReferencedProperty.Next: if (pis.Length != 1 || callee.IsStatic) throw new InvalidOperationException("The attribute SignalProperty was applied to the wrong method."); builder.Store(sigRef, args[1].Expr); decompilee.AddDrivenSignal(sigRef.Desc); break; default: throw new NotImplementedException(); } return true; }