public void AddMethod(MessageContext ctxt, CST.MethodDef methodDef) { var trace = Parent.Parent; var name = methodDef.QualifiedMemberName(trace.Parent.Env.Global, Parent.Assembly, Type); if (trace.Parent.FirstOccuranceOfMethod(ctxt, name, trace)) { Methods.Add(methodDef.MethodSignature); } }
private void Collect(CST.Global global, CST.MethodDef methodDef) { var instructions = methodDef.Instructions(global); if (instructions != null) { foreach (var inst in instructions.Body) { if (inst.Flavor == CST.InstructionFlavor.LdString) { var ldstri = (CST.LdStringInstruction)inst; Seen(ldstri.Value); } } } }
public bool CouldBeInlinableBasedOnHeaderAlone(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef) { if (methodDef.IsVirtualOrAbstract || typeDef.Style is CST.InterfaceTypeStyle) { // No virtuals or interface methods return(false); } if (typeDef.Style is CST.MultiDimArrayTypeStyle) { // Implemented by runtime return(false); } if (typeDef.IsAttributeType(env.Global, assemblyDef)) { // Don't inline attribute property methods since we invoke them directly when building attributes return(false); } var level = default(ReflectionLevel); env.AttributeHelper.GetValueFromType (assemblyDef, typeDef, env.AttributeHelper.ReflectionAttributeRef, env.AttributeHelper.TheReflectionLevelProperty, true, true, ref level); if (level >= ReflectionLevel.Full) { // No inlining in classes needing full reflection since need to support dynamic invokes return(false); } // NOTE: Method may be used in a delegate, in which case it's fine to inline but we'll still // need to emit the definition if (assemblyDef.EntryPoint != null && assemblyDef.EntryPoint.QualifiedMemberName.Equals (methodDef.QualifiedMemberName(env.Global, assemblyDef, typeDef))) { // Entry points are called directly by startup code return(false); } return(true); }
public void AddMethod(MessageContext ctxt, CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef) { var assemblyTrace = ResolveAssemblyTrace(assemblyDef); assemblyTrace.AddMethod(ctxt, typeDef, methodDef); }
public void AddMethod(MessageContext ctxt, CST.TypeDef typeDef, CST.MethodDef methodDef) { var typeTrace = ResolveTypeTrace(typeDef); typeTrace.AddMethod(ctxt, methodDef); }
public string ResolveMethodDefToSlot(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef) { return(TypeMappingFor(assemblyDef, typeDef).ResolveMethodToSlot (methodDef.QualifiedMemberName(env.Global, assemblyDef, typeDef))); }
public ControlFlowRecovery(MethodEnvironment methEnv, Func<JST.Identifier> gensym, int nextInstructionId, CSTWriter tracer) { this.methEnv = methEnv; method = methEnv.Method; this.gensym = gensym; this.tracer = tracer; targets = new Set<int>(); nextBlockId = 0; NextInstructionId = nextInstructionId; }
public abstract bool MethodAlwaysUsed(AssemblyDef assemblyDef, TypeDef typeDef, MethodDef methodDef);
public abstract bool IgnoreMethodDefBody(AssemblyDef assemblyDef, TypeDef typeDef, MethodDef methodDef);
public override CST.InvalidInfo ImplementableInstruction(MessageContext ctxt, CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef, CST.Instruction instruction) { switch (instruction.Flavor) { case CST.InstructionFlavor.Try: { var tryi = (CST.TryInstruction)instruction; if (tryi.Handlers.Any(h => h.Flavor == CST.HandlerFlavor.Filter)) { Log (new CST.InvalidInstruction (ctxt, instruction, "Exception filter blocks are not supported")); return(new CST.InvalidInfo(CST.MessageContextBuilders.Instruction(Global, instruction))); } break; } default: break; } return(null); }
public abstract bool IsAlternateEntryPoint(AssemblyDef assemblyDef, TypeDef typeDef, MethodDef methodDef);
public override bool IgnoreMethodDefBody(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef) { return(env.AttributeHelper.MethodHasAttribute(assemblyDef, typeDef, methodDef, env.AttributeHelper.InteropGeneratedAttributeRef, false, false)); }
// NOTE: May be called on invalid definitions public override bool IsAlternateEntryPoint(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef) { return(env.AttributeHelper.MethodHasAttribute (assemblyDef, typeDef, methodDef, env.AttributeHelper.EntryPointAttributeRef, false, false)); }
// NOTE: May be called on invalid definitions public override bool MethodAlwaysUsed(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef) { if (typeDef.Style is CST.DelegateTypeStyle) { // All the magic delegate methods are inlined by the compiler return(false); } #if false if (env.AttributeHelper.MethodHasAttribute(assemblyDef, typeDef, methodDef, env.Global.CompilerGeneratedAttributeRef, false)) { return(false); } #endif if (env.AttributeHelper.MethodHasAttribute (assemblyDef, typeDef, methodDef, env.AttributeHelper.IgnoreAttributeRef, true, true)) { return(false); } if (typeDef.IsModule && methodDef.IsStatic && methodDef.IsConstructor) { return(true); } if (HasFullReflection(assemblyDef, typeDef)) { return(true); } var isUsed = default(bool); env.AttributeHelper.GetValueFromMethod (assemblyDef, typeDef, methodDef, env.AttributeHelper.UsedAttributeRef, env.AttributeHelper.TheIsUsedProperty, true, false, ref isUsed); if (isUsed) { return(true); } if (env.InteropManager.IsExported(assemblyDef, typeDef, methodDef)) { // Exported methods always used return(true); } return(false); }
public bool IsInlinable(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef) { var s = MethodBodySize(methodDef.QualifiedMemberName(env.Global, assemblyDef, typeDef)); return(s >= 0 && s <= env.InlineThreshold); }
public abstract InvalidInfo ImplementableInstruction(MessageContext ctxt, AssemblyDef assemblyDef, TypeDef typeDef, MethodDef methodDef, Instruction instruction);
// See also: InteropManager::IsInlinable private bool PrimIsInlinable(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef) { if (!CouldBeInlinableBasedOnHeaderAlone(assemblyDef, typeDef, methodDef)) { return(false); } if (methodDef.IsRecursive) { // No recursive methods return(false); } if (methodDef.IsConstructor) { // No instance constructors (since we can't enline NewExpressions yet), and // no static constructors (since we can't inline calls emitted in assembly Initialize) return(false); } if (env.InteropManager.IsImported(assemblyDef, typeDef, methodDef) || env.InteropManager.IsExported(assemblyDef, typeDef, methodDef)) { // No imported methods (we inline separately), and // no exported methods (we need the definition around to be able to export it) return(false); } if (methodDef.MethodBody == null || methodDef.MethodBody.Instructions.Length == 0) { // No empty methods or imported methods return(false); } var numReturns = 0; var instructions = methodDef.Instructions(env.Global); if (!instructions.IsInlinable(ref numReturns) || numReturns != 1) { // Non-inlinable instructions return(false); } var code = instructions.Body[instructions.Body.Count - 1].Code; if (code != CST.InstructionCode.Ret && code != CST.InstructionCode.RetVal) { // Last instruction is not return return(false); } // NOTE: Even though instructions have a single return, it is still possible the translated statatements // won't have a unique result, so unfortunately we need to check that below var isInline = default(bool); var overrideInline = env.AttributeHelper.GetValueFromMethod (assemblyDef, typeDef, methodDef, env.AttributeHelper.InlineAttributeRef, env.AttributeHelper.TheIsInlinedProperty, true, false, ref isInline); if (overrideInline && !isInline) { // User has supressed inlining return(false); } if (!overrideInline && instructions.Size > env.InlineThreshold) { // Method too large return(false); } var methEnv = env.Global.Environment().AddAssembly(assemblyDef).AddType(typeDef).AddSelfTypeBoundArguments(). AddMethod(methodDef).AddSelfMethodBoundArguments(); var cstmethod = CST.CSTMethod.Translate(methEnv, new JST.NameSupply(), null); var body = new Seq <CST.Statement>(); var retres = cstmethod.Body.ToReturnResult(body); if (retres.Status != CST.ReturnStatus.One) { // More than one return return(false); } return(true); }
public MachineStateInference(MethodEnvironment methEnv, CSTWriter tracer) { this.methEnv = methEnv; global = methEnv.Global; method = methEnv.Method; this.tracer = tracer; offsetToBeforeState = new Map<int, MachineState>(); offsetToAfterState = new Map<int, MachineState>(); }