public static IsFeatureSupportedConditional Create(BasicBlockScanner scanner, ref BasicBlock bb, ref int index) { if (bb.Instructions.Count == 1) { throw new OptimizerAssertionException(); } if (index + 1 >= scanner.Body.Instructions.Count) { throw new OptimizerAssertionException(); } /* * `bool MonoLinkerSupport.IsFeatureSupported (MonoLinkerFeature feature)` * */ if (bb.Instructions.Count > 2) { scanner.BlockList.SplitBlockAt(ref bb, bb.Instructions.Count - 2); } var feature = (MonoLinkerFeature)CecilHelper.GetFeatureArgument(bb.FirstInstruction); var instance = new IsFeatureSupportedConditional(scanner, feature); bb.LinkerConditional = instance; LookAheadAfterConditional(scanner.BlockList, ref bb, ref index); return(instance); }
public static bool Scan(BasicBlockScanner scanner, ref BasicBlock bb, ref int index, Instruction instruction) { var reference = (MethodReference)instruction.Operand; if (!scanner.Context.TryFastResolve(reference, out var target)) { return(false); } if (target == null) { if (reference.DeclaringType.Name.Contains("...")) { // FIXME: we don't support Ranges yet. return(false); } scanner.Context.LogMessage(MessageImportance.High, $"Cannot resolve call target: {CecilHelper.Format (instruction)}"); if (scanner.Context.Options.IgnoreResolutionErrors) { return(false); } throw new ResolutionException(reference); } scanner.LogDebug(2, $" CALL: {target}"); if (instruction.Operand is GenericInstanceMethod genericInstance) { if (scanner.Context.IsWeakInstanceOfMethod(target)) { var conditionalType = genericInstance.GenericArguments [0].Resolve(); if (conditionalType == null) { throw new ResolutionException(genericInstance.GenericArguments [0]); } IsWeakInstanceOfConditional.Create(scanner, ref bb, ref index, conditionalType); return(true); } else if (scanner.Context.AsWeakInstanceOfMethod(target)) { var conditionalType = genericInstance.GenericArguments [0].Resolve(); if (conditionalType == null) { throw new ResolutionException(genericInstance.GenericArguments [0]); } AsWeakInstanceOfConditional.Create(scanner, ref bb, ref index, conditionalType); return(true); } else if (scanner.Context.IsTypeAvailableMethod(target)) { var conditionalType = genericInstance.GenericArguments [0].Resolve(); if (conditionalType == null) { throw new ResolutionException(genericInstance.GenericArguments [0]); } IsTypeAvailableConditional.Create(scanner, ref bb, ref index, conditionalType); return(true); } return(false); } if (scanner.Context.IsFeatureSupportedMethod(target)) { IsFeatureSupportedConditional.Create(scanner, ref bb, ref index); return(true); } if (scanner.Context.IsTypeNameAvailableMethod(target)) { IsTypeAvailableConditional.Create(scanner, ref bb, ref index); return(true); } if (scanner.Context.IsRequireFeatureMethod(target)) { RequireFeatureConditional.Create(scanner, ref bb, ref index); return(true); } if (scanner.Context.TryGetConstantMethod(target, out var constant)) { ConstantCallConditional.Create(scanner, ref bb, ref index, target, constant); return(true); } return(false); }