protected override void ProcessMethod(TypeDesc type, XPathNavigator methodNav, object customData) { string signature = GetSignature(methodNav); if (string.IsNullOrEmpty(signature)) { return; } MethodDesc method = FindMethod(type, signature); if (method == null) { // LogWarning(methodNav, DiagnosticId.XmlCouldNotFindMethodOnType, signature, type.GetDisplayName()); return; } string action = GetAttribute(methodNav, "body"); switch (action) { case "remove": _methodSubstitutions.Add(method, BodySubstitution.ThrowingBody); break; case "stub": BodySubstitution stubBody; if (method.Signature.ReturnType.IsVoid) { stubBody = BodySubstitution.EmptyBody; } else { stubBody = BodySubstitution.Create(TryCreateSubstitution(method.Signature.ReturnType, GetAttribute(methodNav, "value"))); } if (stubBody != null) { _methodSubstitutions[method] = stubBody; } else { // Context.LogWarning ($"Invalid value for '{method.GetDisplayName ()}' stub", 2010, _xmlDocumentLocation); } break; default: //Context.LogWarning($"Unknown body modification '{action}' for '{method.GetDisplayName()}'", 2011, _xmlDocumentLocation); break; } }
public override MethodIL GetMethodIL(MethodDesc method) { BodySubstitution substitution = GetSubstitution(method); if (substitution != null) { return(substitution.EmitIL(method)); } // BEGIN TEMPORARY WORKAROUND // // The following lines should just be: // return _nestedILProvider.GetMethodIL(method); // But we want to allow this to be used as a general-purpose IL provider. // // Rewriting all IL has compilation throughput hit we don't want. MethodIL result = _nestedILProvider.GetMethodIL(method); if (result != null) { var resultDef = result.GetMethodILDefinition(); if (resultDef != result) { MethodIL newBodyDef = GetMethodILWithInlinedSubstitutions(resultDef); // If we didn't rewrite the body, we can keep the existing result. if (newBodyDef != resultDef) { result = new InstantiatedMethodIL(method, newBodyDef); } } else { result = GetMethodILWithInlinedSubstitutions(result); } } return(result); // END TEMPORARY WORKAROUND }
private bool TryGetConstantArgument(MethodIL methodIL, byte[] body, OpcodeFlags[] flags, int offset, int argIndex, out int constant) { if ((flags[offset] & OpcodeFlags.BasicBlockStart) != 0) { constant = 0; return(false); } for (int currentOffset = offset - 1; currentOffset >= 0; currentOffset--) { if ((flags[currentOffset] & OpcodeFlags.InstructionStart) == 0) { continue; } ILReader reader = new ILReader(body, currentOffset); ILOpcode opcode = reader.ReadILOpcode(); if (opcode == ILOpcode.call || opcode == ILOpcode.callvirt) { MethodDesc method = (MethodDesc)methodIL.GetObject(reader.ReadILToken()); if (argIndex == 0) { BodySubstitution substitution = GetSubstitution(method); if (substitution != null && substitution.Value is int && (opcode != ILOpcode.callvirt || !method.IsVirtual)) { constant = (int)substitution.Value; return(true); } else { constant = 0; return(false); } } argIndex--; if (method.Signature.Length > 0 || !method.Signature.IsStatic) { // We don't know how to skip over the parameters break; } } else if (opcode == ILOpcode.ldsfld) { FieldDesc field = (FieldDesc)methodIL.GetObject(reader.ReadILToken()); if (argIndex == 0) { object substitution = GetSubstitution(field); if (substitution is int) { constant = (int)substitution; return(true); } else { constant = 0; return(false); } } argIndex--; } else if (opcode >= ILOpcode.ldc_i4_0 && opcode <= ILOpcode.ldc_i4_8) { if (argIndex == 0) { constant = opcode - ILOpcode.ldc_i4_0; return(true); } argIndex--; } else if (opcode == ILOpcode.ldc_i4) { if (argIndex == 0) { constant = (int)reader.ReadILUInt32(); return(true); } argIndex--; } else if (opcode == ILOpcode.ldc_i4_s) { if (argIndex == 0) { constant = (int)(sbyte)reader.ReadILByte(); return(true); } argIndex--; } else if ((opcode == ILOpcode.ldloc || opcode == ILOpcode.ldloc_s || (opcode >= ILOpcode.ldloc_0 && opcode <= ILOpcode.ldloc_3)) && ((flags[currentOffset] & OpcodeFlags.BasicBlockStart) == 0)) { // Paired stloc/ldloc that the C# compiler generates in debug code? int locIndex = opcode switch { ILOpcode.ldloc => reader.ReadILUInt16(), ILOpcode.ldloc_s => reader.ReadILByte(), _ => opcode - ILOpcode.ldloc_0, }; for (int potentialStlocOffset = currentOffset - 1; potentialStlocOffset >= 0; potentialStlocOffset--) { if ((flags[potentialStlocOffset] & OpcodeFlags.InstructionStart) == 0) { continue; } ILReader nestedReader = new ILReader(body, potentialStlocOffset); ILOpcode otherOpcode = nestedReader.ReadILOpcode(); if ((otherOpcode == ILOpcode.stloc || otherOpcode == ILOpcode.stloc_s || (otherOpcode >= ILOpcode.stloc_0 && otherOpcode <= ILOpcode.stloc_3)) && otherOpcode switch { ILOpcode.stloc => nestedReader.ReadILUInt16(), ILOpcode.stloc_s => nestedReader.ReadILByte(), _ => otherOpcode - ILOpcode.stloc_0, } == locIndex)