public static ConstantCallConditional Create(BasicBlockScanner scanner, ref BasicBlock bb, ref int index, MethodDefinition target, ConstantValue constant) { if (index + 1 >= scanner.Body.Instructions.Count) { throw new OptimizerAssertionException(); } /* * Calling a constant property. * */ int stackDepth; int size = 1; if (target.IsStatic) { stackDepth = 0; } else if (bb.Count == 1) { stackDepth = 1; } else { var previous = scanner.Body.Instructions [index - 1]; if (CecilHelper.IsSimpleLoad(previous) || previous.OpCode.Code == Code.Nop) { stackDepth = 0; size++; } else { stackDepth = 1; } } if (bb.Instructions.Count > size) { scanner.BlockList.SplitBlockAt(ref bb, bb.Instructions.Count - size); } var instance = new ConstantCallConditional(scanner, target, stackDepth, constant); 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); }