--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props))" />
+
+ <PropertyGroup>
+ <SkipValidatePackage>true</SkipValidatePackage>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\tools\ILVerification\ILVerification.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageFile Include="$(ArtifactsDir)bin\ILVerification\$(TargetArchitecture)\$(Configuration)\ILVerification.dll">
+ <TargetPath>lib\netstandard2.0\ILVerification.dll</TargetPath>
+ </PackageFile>
+ <Dependency Include="System.Reflection.Metadata">
+ <Version>1.8.1</Version>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ <Exclude>Build,Analyzers</Exclude>
+ </Dependency>
+ </ItemGroup>
+
+ <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.targets))" />
+</Project>
<ItemGroup Condition="'$(TargetsWindows)'=='true' OR '$(DotNetBuildFromSource)'=='true'">
<ProjectReference Include="Microsoft.NET.Sdk.IL\Microsoft.NET.Sdk.IL.pkgproj" />
+ <ProjectReference Include="Microsoft.ILVerification\Microsoft.ILVerification.pkgproj" />
+ <ProjectReference Include="dotnet-ilverify\dotnet-ilverify.pkgproj" />
</ItemGroup>
<ItemGroup>
"Name": "Microsoft.NET.Sdk.IL",
"Description": "Provides support for building IL projects.",
"CommonTypes": [ ]
+ },
+ {
+ "Name": "Microsoft.ILVerification",
+ "Description": "IL verification library.",
+ "CommonTypes": [ ]
+ },
+ {
+ "Name": "dotnet-ilverify",
+ "Description": "ILVerify tool.",
+ "CommonTypes": [ ]
}
]
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<DotNetCliTool Version="1">
+ <Commands>
+ <Command Name="ilverify" EntryPoint="ILVerify.dll" Runner="dotnet" />
+ </Commands>
+</DotNetCliTool>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props))" />
+
+ <PropertyGroup>
+ <SkipValidatePackage>true</SkipValidatePackage>
+ <PackageType>DotnetTool</PackageType>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\tools\ILVerify\ILVerify.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageFile Include="DotnetToolSettings.xml">
+ <TargetPath>tools\netcoreapp3.1\any\DotnetToolSettings.xml</TargetPath>
+ </PackageFile>
+ <PackageFile Include="$(ArtifactsDir)bin\ILVerify\$(TargetArchitecture)\$(Configuration)\ILVerify.dll">
+ <TargetPath>tools\netcoreapp3.1\any\ILVerify.dll</TargetPath>
+ </PackageFile>
+ <PackageFile Include="$(ArtifactsDir)bin\ILVerify\$(TargetArchitecture)\$(Configuration)\ILVerification.dll">
+ <TargetPath>tools\netcoreapp3.1\any\ILVerification.dll</TargetPath>
+ </PackageFile>
+ <PackageFile Include="$(ArtifactsDir)bin\ILVerify\$(TargetArchitecture)\$(Configuration)\System.CommandLine.dll">
+ <TargetPath>tools\netcoreapp3.1\any\System.CommandLine.dll</TargetPath>
+ </PackageFile>
+ <PackageFile Include="$(ArtifactsDir)bin\ILVerify\$(TargetArchitecture)\$(Configuration)\ILVerify.deps.json">
+ <TargetPath>tools\netcoreapp3.1\any\ILVerify.deps.json</TargetPath>
+ </PackageFile>
+ <PackageFile Include="$(ArtifactsDir)bin\ILVerify\$(TargetArchitecture)\$(Configuration)\ILVerify.runtimeconfig.json">
+ <TargetPath>tools\netcoreapp3.1\any\ILVerify.runtimeconfig.json</TargetPath>
+ </PackageFile>
+ </ItemGroup>
+
+ <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.targets))" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Internal.TypeSystem
+{
+ // Dummy implementation of diagnostic names that just forwards to Name/Namespace
+ abstract partial class DefType
+ {
+ /// <summary>
+ /// Gets the Name of a type. This must not throw
+ /// </summary>
+ public string DiagnosticName => Name;
+
+ /// <summary>
+ /// Gets the Namespace of a type. This must not throw
+ /// </summary>
+ public string DiagnosticNamespace => Namespace;
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Internal.TypeSystem
+{
+ // Dummy implementation of diagnostic names that just forwards to Name
+ public abstract partial class GenericParameterDesc
+ {
+ /// <summary>
+ /// Gets the name of the generic parameter as defined in the metadata. This must not throw
+ /// </summary>
+ public string DiagnosticName => Name;
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Internal.TypeSystem
+{
+ // Dummy implementation of diagnostic names that just forwards to Name
+ partial class MethodDesc
+ {
+ public string DiagnosticName => Name;
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Internal.TypeSystem
+{
+ public class InstantiationContext
+ {
+ public readonly Instantiation TypeInstantiation;
+ public readonly Instantiation MethodInstantiation;
+
+ public InstantiationContext(Instantiation typeInstantiation, Instantiation methodInstantiation)
+ {
+ TypeInstantiation = typeInstantiation;
+ MethodInstantiation = methodInstantiation;
+ }
+ }
+
+ public static class TypeSystemConstraintsHelpers
+ {
+ private static bool VerifyGenericParamConstraint(InstantiationContext genericParamContext, GenericParameterDesc genericParam,
+ InstantiationContext instantiationParamContext, TypeDesc instantiationParam)
+ {
+ GenericConstraints constraints = genericParam.Constraints;
+
+ // Check class constraint
+ if ((constraints & GenericConstraints.ReferenceTypeConstraint) != 0)
+ {
+ if (!instantiationParam.IsGCPointer
+ && !CheckGenericSpecialConstraint(instantiationParam, GenericConstraints.ReferenceTypeConstraint))
+ return false;
+ }
+
+ // Check default constructor constraint
+ if ((constraints & GenericConstraints.DefaultConstructorConstraint) != 0)
+ {
+ if (!instantiationParam.HasExplicitOrImplicitDefaultConstructor()
+ && !CheckGenericSpecialConstraint(instantiationParam, GenericConstraints.DefaultConstructorConstraint))
+ return false;
+ }
+
+ // Check struct constraint
+ if ((constraints & GenericConstraints.NotNullableValueTypeConstraint) != 0)
+ {
+ if ((!instantiationParam.IsValueType || instantiationParam.IsNullable)
+ && !CheckGenericSpecialConstraint(instantiationParam, GenericConstraints.NotNullableValueTypeConstraint))
+ return false;
+ }
+
+ var instantiatedConstraints = new ArrayBuilder<TypeDesc>();
+ GetInstantiatedConstraintsRecursive(instantiationParamContext, instantiationParam, ref instantiatedConstraints);
+
+ foreach (var constraintType in genericParam.TypeConstraints)
+ {
+ var instantiatedType = constraintType.InstantiateSignature(genericParamContext.TypeInstantiation, genericParamContext.MethodInstantiation);
+ if (CanCastConstraint(ref instantiatedConstraints, instantiatedType))
+ continue;
+
+ if (!instantiationParam.CanCastTo(instantiatedType))
+ return false;
+ }
+
+ return true;
+ }
+
+ // Used to determine whether a type parameter used to instantiate another type parameter with a specific special
+ // constraint satisfies that constraint.
+ private static bool CheckGenericSpecialConstraint(TypeDesc type, GenericConstraints specialConstraint)
+ {
+ if (!type.IsGenericParameter)
+ return false;
+
+ var genericType = (GenericParameterDesc)type;
+
+ GenericConstraints constraints = genericType.Constraints;
+
+ // Check if type has specialConstraint on its own
+ if ((constraints & specialConstraint) != 0)
+ return true;
+
+ // Value type always has default constructor
+ if (specialConstraint == GenericConstraints.DefaultConstructorConstraint && (constraints & GenericConstraints.NotNullableValueTypeConstraint) != 0)
+ return true;
+
+ // The special constraints did not match, check if there is a primary type constraint,
+ // that would always satisfy the special constraint
+ foreach (var constraint in genericType.TypeConstraints)
+ {
+ if (constraint.IsGenericParameter || constraint.IsInterface)
+ continue;
+
+ switch (specialConstraint)
+ {
+ case GenericConstraints.NotNullableValueTypeConstraint:
+ if (constraint.IsValueType && !constraint.IsNullable)
+ return true;
+ break;
+ case GenericConstraints.ReferenceTypeConstraint:
+ if (!constraint.IsValueType)
+ return true;
+ break;
+ case GenericConstraints.DefaultConstructorConstraint:
+ // As constraint is only ancestor, can only be sure whether type has public default constructor if it is a value type
+ if (constraint.IsValueType)
+ return true;
+ break;
+ default:
+ Debug.Assert(false);
+ break;
+ }
+ }
+
+ // type did not satisfy special constraint in any way
+ return false;
+ }
+
+ private static void GetInstantiatedConstraintsRecursive(InstantiationContext typeContext, TypeDesc type, ref ArrayBuilder<TypeDesc> instantiatedConstraints)
+ {
+ if (!type.IsGenericParameter || typeContext == null)
+ return;
+
+ GenericParameterDesc genericParam = (GenericParameterDesc)type;
+
+ foreach (var constraint in genericParam.TypeConstraints)
+ {
+ var instantiatedType = constraint.InstantiateSignature(typeContext.TypeInstantiation, typeContext.MethodInstantiation);
+
+ if (instantiatedType.IsGenericParameter)
+ {
+ // Make sure it is save to call this method recursively
+ if (!instantiatedConstraints.Contains(instantiatedType))
+ {
+ instantiatedConstraints.Add(instantiatedType);
+
+ // Constraints of this constraint apply to 'genericParam' too
+ GetInstantiatedConstraintsRecursive(typeContext, instantiatedType, ref instantiatedConstraints);
+ }
+ }
+ else
+ {
+ instantiatedConstraints.Add(instantiatedType);
+ }
+ }
+ }
+
+ private static bool CanCastConstraint(ref ArrayBuilder<TypeDesc> instantiatedConstraints, TypeDesc instantiatedType)
+ {
+ for (int i = 0; i < instantiatedConstraints.Count; ++i)
+ {
+ if (instantiatedConstraints[i].CanCastTo(instantiatedType))
+ return true;
+ }
+
+ return false;
+ }
+
+ public static bool CheckValidInstantiationArguments(this Instantiation instantiation)
+ {
+ foreach(var arg in instantiation)
+ {
+ if (arg.IsPointer || arg.IsByRef || arg.IsGenericParameter || arg.IsVoid)
+ return false;
+
+ if (arg.HasInstantiation)
+ {
+ if (!CheckValidInstantiationArguments(arg.Instantiation))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static bool CheckConstraints(this TypeDesc type, InstantiationContext context = null)
+ {
+ TypeDesc uninstantiatedType = type.GetTypeDefinition();
+
+ // Non-generic types always pass constraints check
+ if (uninstantiatedType == type)
+ return true;
+
+ var paramContext = new InstantiationContext(type.Instantiation, default(Instantiation));
+ for (int i = 0; i < uninstantiatedType.Instantiation.Length; i++)
+ {
+ if (!VerifyGenericParamConstraint(paramContext, (GenericParameterDesc)uninstantiatedType.Instantiation[i], context, type.Instantiation[i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ public static bool CheckConstraints(this MethodDesc method, InstantiationContext context = null)
+ {
+ if (!method.OwningType.CheckConstraints(context))
+ return false;
+
+ // Non-generic methods always pass constraints check
+ if (!method.HasInstantiation)
+ return true;
+
+ var paramContext = new InstantiationContext(method.OwningType.Instantiation, method.Instantiation);
+ MethodDesc uninstantiatedMethod = method.GetMethodDefinition();
+ for (int i = 0; i < uninstantiatedMethod.Instantiation.Length; i++)
+ {
+ if (!VerifyGenericParamConstraint(paramContext, (GenericParameterDesc)uninstantiatedMethod.Instantiation[i], context, method.Instantiation[i]))
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+using Internal.TypeSystem;
+using Internal.IL;
+
+namespace Internal.IL
+{
+ internal partial class ILImporter
+ {
+ private BasicBlock[] _basicBlocks; // Maps IL offset to basic block
+
+ private BasicBlock _currentBasicBlock;
+ private int _currentOffset;
+
+ private BasicBlock _pendingBasicBlocks;
+
+ //
+ // IL stream reading
+ //
+
+ private byte ReadILByte()
+ {
+ if (_currentOffset >= _ilBytes.Length)
+ ReportMethodEndInsideInstruction();
+
+ return _ilBytes[_currentOffset++];
+ }
+
+ private UInt16 ReadILUInt16()
+ {
+ if (_currentOffset + 1 >= _ilBytes.Length)
+ ReportMethodEndInsideInstruction();
+
+ UInt16 val = (UInt16)(_ilBytes[_currentOffset] + (_ilBytes[_currentOffset + 1] << 8));
+ _currentOffset += 2;
+ return val;
+ }
+
+ private UInt32 ReadILUInt32()
+ {
+ if (_currentOffset + 3 >= _ilBytes.Length)
+ ReportMethodEndInsideInstruction();
+
+ UInt32 val = (UInt32)(_ilBytes[_currentOffset] + (_ilBytes[_currentOffset + 1] << 8) + (_ilBytes[_currentOffset + 2] << 16) + (_ilBytes[_currentOffset + 3] << 24));
+ _currentOffset += 4;
+ return val;
+ }
+
+ private int ReadILToken()
+ {
+ return (int)ReadILUInt32();
+ }
+
+ private ulong ReadILUInt64()
+ {
+ ulong value = ReadILUInt32();
+ value |= (((ulong)ReadILUInt32()) << 32);
+ return value;
+ }
+
+ private unsafe float ReadILFloat()
+ {
+ uint value = ReadILUInt32();
+ return *(float*)(&value);
+ }
+
+ private unsafe double ReadILDouble()
+ {
+ ulong value = ReadILUInt64();
+ return *(double*)(&value);
+ }
+
+ private void SkipIL(int bytes)
+ {
+ if (_currentOffset + (bytes - 1) >= _ilBytes.Length)
+ ReportMethodEndInsideInstruction();
+
+ _currentOffset += bytes;
+ }
+
+ //
+ // Basic block identification
+ //
+
+ private void FindBasicBlocks()
+ {
+ _basicBlocks = new BasicBlock[_ilBytes.Length];
+
+ CreateBasicBlock(0);
+
+ FindJumpTargets();
+
+ FindEHTargets();
+ }
+
+ private BasicBlock CreateBasicBlock(int offset)
+ {
+ BasicBlock basicBlock = _basicBlocks[offset];
+ if (basicBlock == null)
+ {
+ basicBlock = new BasicBlock() { StartOffset = offset };
+ _basicBlocks[offset] = basicBlock;
+ }
+
+ return basicBlock;
+ }
+
+ private void FindJumpTargets()
+ {
+ _currentOffset = 0;
+
+ while (_currentOffset < _ilBytes.Length)
+ {
+ MarkInstructionBoundary();
+
+ ILOpcode opCode = (ILOpcode)ReadILByte();
+
+ again:
+ switch (opCode)
+ {
+ case ILOpcode.ldarg_s:
+ case ILOpcode.ldarga_s:
+ case ILOpcode.starg_s:
+ case ILOpcode.ldloc_s:
+ case ILOpcode.ldloca_s:
+ case ILOpcode.stloc_s:
+ case ILOpcode.ldc_i4_s:
+ case ILOpcode.unaligned:
+ case ILOpcode.no:
+ SkipIL(1);
+ break;
+ case ILOpcode.ldarg:
+ case ILOpcode.ldarga:
+ case ILOpcode.starg:
+ case ILOpcode.ldloc:
+ case ILOpcode.ldloca:
+ case ILOpcode.stloc:
+ SkipIL(2);
+ break;
+ case ILOpcode.ldc_i4:
+ case ILOpcode.ldc_r4:
+ SkipIL(4);
+ break;
+ case ILOpcode.ldc_i8:
+ case ILOpcode.ldc_r8:
+ SkipIL(8);
+ break;
+ case ILOpcode.jmp:
+ case ILOpcode.call:
+ case ILOpcode.calli:
+ case ILOpcode.callvirt:
+ case ILOpcode.cpobj:
+ case ILOpcode.ldobj:
+ case ILOpcode.ldstr:
+ case ILOpcode.newobj:
+ case ILOpcode.castclass:
+ case ILOpcode.isinst:
+ case ILOpcode.unbox:
+ case ILOpcode.ldfld:
+ case ILOpcode.ldflda:
+ case ILOpcode.stfld:
+ case ILOpcode.ldsfld:
+ case ILOpcode.ldsflda:
+ case ILOpcode.stsfld:
+ case ILOpcode.stobj:
+ case ILOpcode.box:
+ case ILOpcode.newarr:
+ case ILOpcode.ldelema:
+ case ILOpcode.ldelem:
+ case ILOpcode.stelem:
+ case ILOpcode.unbox_any:
+ case ILOpcode.refanyval:
+ case ILOpcode.mkrefany:
+ case ILOpcode.ldtoken:
+ case ILOpcode.ldftn:
+ case ILOpcode.ldvirtftn:
+ case ILOpcode.initobj:
+ case ILOpcode.constrained:
+ case ILOpcode.sizeof_:
+ SkipIL(4);
+ break;
+ case ILOpcode.prefix1:
+ opCode = (ILOpcode)(0x100 + ReadILByte());
+ goto again;
+ case ILOpcode.br_s:
+ case ILOpcode.leave_s:
+ {
+ int delta = (sbyte)ReadILByte();
+ int target = _currentOffset + delta;
+ if ((uint)target < (uint)_basicBlocks.Length)
+ CreateBasicBlock(target);
+ else
+ ReportInvalidBranchTarget(target);
+ }
+ break;
+ case ILOpcode.brfalse_s:
+ case ILOpcode.brtrue_s:
+ case ILOpcode.beq_s:
+ case ILOpcode.bge_s:
+ case ILOpcode.bgt_s:
+ case ILOpcode.ble_s:
+ case ILOpcode.blt_s:
+ case ILOpcode.bne_un_s:
+ case ILOpcode.bge_un_s:
+ case ILOpcode.bgt_un_s:
+ case ILOpcode.ble_un_s:
+ case ILOpcode.blt_un_s:
+ {
+ int delta = (sbyte)ReadILByte();
+ int target = _currentOffset + delta;
+ if ((uint)target < (uint)_basicBlocks.Length)
+ CreateBasicBlock(target);
+ else
+ ReportInvalidBranchTarget(target);
+ CreateBasicBlock(_currentOffset);
+ }
+ break;
+ case ILOpcode.br:
+ case ILOpcode.leave:
+ {
+ int delta = (int)ReadILUInt32();
+ int target = _currentOffset + delta;
+ if ((uint)target < (uint)_basicBlocks.Length)
+ CreateBasicBlock(target);
+ else
+ ReportInvalidBranchTarget(target);
+ }
+ break;
+ case ILOpcode.brfalse:
+ case ILOpcode.brtrue:
+ case ILOpcode.beq:
+ case ILOpcode.bge:
+ case ILOpcode.bgt:
+ case ILOpcode.ble:
+ case ILOpcode.blt:
+ case ILOpcode.bne_un:
+ case ILOpcode.bge_un:
+ case ILOpcode.bgt_un:
+ case ILOpcode.ble_un:
+ case ILOpcode.blt_un:
+ {
+ int delta = (int)ReadILUInt32();
+ int target = _currentOffset + delta;
+ if ((uint)target < (uint)_basicBlocks.Length)
+ CreateBasicBlock(target);
+ else
+ ReportInvalidBranchTarget(target);
+ CreateBasicBlock(_currentOffset);
+ }
+ break;
+ case ILOpcode.switch_:
+ {
+ uint count = ReadILUInt32();
+ int jmpBase = _currentOffset + (int)(4 * count);
+ for (uint i = 0; i < count; i++)
+ {
+ int delta = (int)ReadILUInt32();
+ int target = jmpBase + delta;
+ if ((uint)target < (uint)_basicBlocks.Length)
+ CreateBasicBlock(target);
+ else
+ ReportInvalidBranchTarget(target);
+ }
+ CreateBasicBlock(_currentOffset);
+ }
+ break;
+ default:
+ continue;
+ }
+ }
+ }
+
+ private void FindEHTargets()
+ {
+ for (int i = 0; i < _exceptionRegions.Length; i++)
+ {
+ var r = _exceptionRegions[i];
+
+ CreateBasicBlock(r.ILRegion.TryOffset).TryStart = true;
+ if (r.ILRegion.Kind == ILExceptionRegionKind.Filter)
+ CreateBasicBlock(r.ILRegion.FilterOffset).FilterStart = true;
+ CreateBasicBlock(r.ILRegion.HandlerOffset).HandlerStart = true;
+ }
+ }
+
+ //
+ // Basic block importing
+ //
+
+ private void ImportBasicBlocks()
+ {
+ _pendingBasicBlocks = _basicBlocks[0];
+ _basicBlocks[0].State = BasicBlock.ImportState.IsPending;
+ while (_pendingBasicBlocks != null)
+ {
+ BasicBlock basicBlock = _pendingBasicBlocks;
+ _pendingBasicBlocks = basicBlock.Next;
+
+ StartImportingBasicBlock(basicBlock);
+ ImportBasicBlock(basicBlock);
+ EndImportingBasicBlock(basicBlock);
+ }
+ }
+
+ private void MarkBasicBlock(BasicBlock basicBlock)
+ {
+ if (basicBlock.State == BasicBlock.ImportState.Unmarked)
+ {
+ // Link
+ basicBlock.Next = _pendingBasicBlocks;
+ _pendingBasicBlocks = basicBlock;
+
+ basicBlock.State = BasicBlock.ImportState.IsPending;
+ }
+ }
+
+ private void ImportBasicBlock(BasicBlock basicBlock)
+ {
+ _currentBasicBlock = basicBlock;
+ _currentOffset = basicBlock.StartOffset;
+
+ for (;;)
+ {
+ StartImportingInstruction();
+
+ ILOpcode opCode = (ILOpcode)ReadILByte();
+
+ again:
+ switch (opCode)
+ {
+ case ILOpcode.nop:
+ ImportNop();
+ break;
+ case ILOpcode.break_:
+ ImportBreak();
+ break;
+ case ILOpcode.ldarg_0:
+ case ILOpcode.ldarg_1:
+ case ILOpcode.ldarg_2:
+ case ILOpcode.ldarg_3:
+ ImportLoadVar(opCode - ILOpcode.ldarg_0, true);
+ break;
+ case ILOpcode.ldloc_0:
+ case ILOpcode.ldloc_1:
+ case ILOpcode.ldloc_2:
+ case ILOpcode.ldloc_3:
+ ImportLoadVar(opCode - ILOpcode.ldloc_0, false);
+ break;
+ case ILOpcode.stloc_0:
+ case ILOpcode.stloc_1:
+ case ILOpcode.stloc_2:
+ case ILOpcode.stloc_3:
+ ImportStoreVar(opCode - ILOpcode.stloc_0, false);
+ break;
+ case ILOpcode.ldarg_s:
+ ImportLoadVar(ReadILByte(), true);
+ break;
+ case ILOpcode.ldarga_s:
+ ImportAddressOfVar(ReadILByte(), true);
+ break;
+ case ILOpcode.starg_s:
+ ImportStoreVar(ReadILByte(), true);
+ break;
+ case ILOpcode.ldloc_s:
+ ImportLoadVar(ReadILByte(), false);
+ break;
+ case ILOpcode.ldloca_s:
+ ImportAddressOfVar(ReadILByte(), false);
+ break;
+ case ILOpcode.stloc_s:
+ ImportStoreVar(ReadILByte(), false);
+ break;
+ case ILOpcode.ldnull:
+ ImportLoadNull();
+ break;
+ case ILOpcode.ldc_i4_m1:
+ ImportLoadInt(-1, StackValueKind.Int32);
+ break;
+ case ILOpcode.ldc_i4_0:
+ case ILOpcode.ldc_i4_1:
+ case ILOpcode.ldc_i4_2:
+ case ILOpcode.ldc_i4_3:
+ case ILOpcode.ldc_i4_4:
+ case ILOpcode.ldc_i4_5:
+ case ILOpcode.ldc_i4_6:
+ case ILOpcode.ldc_i4_7:
+ case ILOpcode.ldc_i4_8:
+ ImportLoadInt(opCode - ILOpcode.ldc_i4_0, StackValueKind.Int32);
+ break;
+ case ILOpcode.ldc_i4_s:
+ ImportLoadInt((sbyte)ReadILByte(), StackValueKind.Int32);
+ break;
+ case ILOpcode.ldc_i4:
+ ImportLoadInt((int)ReadILUInt32(), StackValueKind.Int32);
+ break;
+ case ILOpcode.ldc_i8:
+ ImportLoadInt((long)ReadILUInt64(), StackValueKind.Int64);
+ break;
+ case ILOpcode.ldc_r4:
+ ImportLoadFloat(ReadILFloat());
+ break;
+ case ILOpcode.ldc_r8:
+ ImportLoadFloat(ReadILDouble());
+ break;
+ case ILOpcode.dup:
+ ImportDup();
+ break;
+ case ILOpcode.pop:
+ ImportPop();
+ break;
+ case ILOpcode.jmp:
+ ImportJmp(ReadILToken());
+ EndImportingInstruction();
+ return;
+ case ILOpcode.call:
+ ImportCall(opCode, ReadILToken());
+ break;
+ case ILOpcode.calli:
+ ImportCalli(ReadILToken());
+ break;
+ case ILOpcode.ret:
+ ImportReturn();
+ EndImportingInstruction();
+ return;
+ case ILOpcode.br_s:
+ case ILOpcode.brfalse_s:
+ case ILOpcode.brtrue_s:
+ case ILOpcode.beq_s:
+ case ILOpcode.bge_s:
+ case ILOpcode.bgt_s:
+ case ILOpcode.ble_s:
+ case ILOpcode.blt_s:
+ case ILOpcode.bne_un_s:
+ case ILOpcode.bge_un_s:
+ case ILOpcode.bgt_un_s:
+ case ILOpcode.ble_un_s:
+ case ILOpcode.blt_un_s:
+ {
+ int delta = (sbyte)ReadILByte();
+ ImportBranch(opCode + (ILOpcode.br - ILOpcode.br_s),
+ _basicBlocks[_currentOffset + delta], (opCode != ILOpcode.br_s) ? _basicBlocks[_currentOffset] : null);
+ }
+ EndImportingInstruction();
+ return;
+ case ILOpcode.br:
+ case ILOpcode.brfalse:
+ case ILOpcode.brtrue:
+ case ILOpcode.beq:
+ case ILOpcode.bge:
+ case ILOpcode.bgt:
+ case ILOpcode.ble:
+ case ILOpcode.blt:
+ case ILOpcode.bne_un:
+ case ILOpcode.bge_un:
+ case ILOpcode.bgt_un:
+ case ILOpcode.ble_un:
+ case ILOpcode.blt_un:
+ {
+ int delta = (int)ReadILUInt32();
+ ImportBranch(opCode,
+ _basicBlocks[_currentOffset + delta], (opCode != ILOpcode.br) ? _basicBlocks[_currentOffset] : null);
+ }
+ EndImportingInstruction();
+ return;
+ case ILOpcode.switch_:
+ {
+ uint count = ReadILUInt32();
+ int jmpBase = _currentOffset + (int)(4 * count);
+ int[] jmpDelta = new int[count];
+ for (uint i = 0; i < count; i++)
+ jmpDelta[i] = (int)ReadILUInt32();
+
+ ImportSwitchJump(jmpBase, jmpDelta, _basicBlocks[_currentOffset]);
+ }
+ EndImportingInstruction();
+ return;
+ case ILOpcode.ldind_i1:
+ ImportLoadIndirect(WellKnownType.SByte);
+ break;
+ case ILOpcode.ldind_u1:
+ ImportLoadIndirect(WellKnownType.Byte);
+ break;
+ case ILOpcode.ldind_i2:
+ ImportLoadIndirect(WellKnownType.Int16);
+ break;
+ case ILOpcode.ldind_u2:
+ ImportLoadIndirect(WellKnownType.UInt16);
+ break;
+ case ILOpcode.ldind_i4:
+ ImportLoadIndirect(WellKnownType.Int32);
+ break;
+ case ILOpcode.ldind_u4:
+ ImportLoadIndirect(WellKnownType.UInt32);
+ break;
+ case ILOpcode.ldind_i8:
+ ImportLoadIndirect(WellKnownType.Int64);
+ break;
+ case ILOpcode.ldind_i:
+ ImportLoadIndirect(WellKnownType.IntPtr);
+ break;
+ case ILOpcode.ldind_r4:
+ ImportLoadIndirect(WellKnownType.Single);
+ break;
+ case ILOpcode.ldind_r8:
+ ImportLoadIndirect(WellKnownType.Double);
+ break;
+ case ILOpcode.ldind_ref:
+ ImportLoadIndirect(null);
+ break;
+ case ILOpcode.stind_ref:
+ ImportStoreIndirect(null);
+ break;
+ case ILOpcode.stind_i1:
+ ImportStoreIndirect(WellKnownType.SByte);
+ break;
+ case ILOpcode.stind_i2:
+ ImportStoreIndirect(WellKnownType.Int16);
+ break;
+ case ILOpcode.stind_i4:
+ ImportStoreIndirect(WellKnownType.Int32);
+ break;
+ case ILOpcode.stind_i8:
+ ImportStoreIndirect(WellKnownType.Int64);
+ break;
+ case ILOpcode.stind_r4:
+ ImportStoreIndirect(WellKnownType.Single);
+ break;
+ case ILOpcode.stind_r8:
+ ImportStoreIndirect(WellKnownType.Double);
+ break;
+ case ILOpcode.add:
+ case ILOpcode.sub:
+ case ILOpcode.mul:
+ case ILOpcode.div:
+ case ILOpcode.div_un:
+ case ILOpcode.rem:
+ case ILOpcode.rem_un:
+ case ILOpcode.and:
+ case ILOpcode.or:
+ case ILOpcode.xor:
+ ImportBinaryOperation(opCode);
+ break;
+ case ILOpcode.shl:
+ case ILOpcode.shr:
+ case ILOpcode.shr_un:
+ ImportShiftOperation(opCode);
+ break;
+ case ILOpcode.neg:
+ case ILOpcode.not:
+ ImportUnaryOperation(opCode);
+ break;
+ case ILOpcode.conv_i1:
+ ImportConvert(WellKnownType.SByte, false, false);
+ break;
+ case ILOpcode.conv_i2:
+ ImportConvert(WellKnownType.Int16, false, false);
+ break;
+ case ILOpcode.conv_i4:
+ ImportConvert(WellKnownType.Int32, false, false);
+ break;
+ case ILOpcode.conv_i8:
+ ImportConvert(WellKnownType.Int64, false, false);
+ break;
+ case ILOpcode.conv_r4:
+ ImportConvert(WellKnownType.Single, false, false);
+ break;
+ case ILOpcode.conv_r8:
+ ImportConvert(WellKnownType.Double, false, false);
+ break;
+ case ILOpcode.conv_u4:
+ ImportConvert(WellKnownType.UInt32, false, false);
+ break;
+ case ILOpcode.conv_u8:
+ ImportConvert(WellKnownType.UInt64, false, true);
+ break;
+ case ILOpcode.callvirt:
+ ImportCall(opCode, ReadILToken());
+ break;
+ case ILOpcode.cpobj:
+ ImportCpOpj(ReadILToken());
+ break;
+ case ILOpcode.ldobj:
+ ImportLoadIndirect(ReadILToken());
+ break;
+ case ILOpcode.ldstr:
+ ImportLoadString(ReadILToken());
+ break;
+ case ILOpcode.newobj:
+ ImportCall(opCode, ReadILToken());
+ break;
+ case ILOpcode.castclass:
+ case ILOpcode.isinst:
+ ImportCasting(opCode, ReadILToken());
+ break;
+ case ILOpcode.conv_r_un:
+ ImportConvert(WellKnownType.Double, false, true);
+ break;
+ case ILOpcode.unbox:
+ ImportUnbox(ReadILToken(), opCode);
+ break;
+ case ILOpcode.throw_:
+ ImportThrow();
+ EndImportingInstruction();
+ return;
+ case ILOpcode.ldfld:
+ ImportLoadField(ReadILToken(), false);
+ break;
+ case ILOpcode.ldflda:
+ ImportAddressOfField(ReadILToken(), false);
+ break;
+ case ILOpcode.stfld:
+ ImportStoreField(ReadILToken(), false);
+ break;
+ case ILOpcode.ldsfld:
+ ImportLoadField(ReadILToken(), true);
+ break;
+ case ILOpcode.ldsflda:
+ ImportAddressOfField(ReadILToken(), true);
+ break;
+ case ILOpcode.stsfld:
+ ImportStoreField(ReadILToken(), true);
+ break;
+ case ILOpcode.stobj:
+ ImportStoreIndirect(ReadILToken());
+ break;
+ case ILOpcode.conv_ovf_i1_un:
+ ImportConvert(WellKnownType.SByte, true, true);
+ break;
+ case ILOpcode.conv_ovf_i2_un:
+ ImportConvert(WellKnownType.Int16, true, true);
+ break;
+ case ILOpcode.conv_ovf_i4_un:
+ ImportConvert(WellKnownType.Int32, true, true);
+ break;
+ case ILOpcode.conv_ovf_i8_un:
+ ImportConvert(WellKnownType.Int64, true, true);
+ break;
+ case ILOpcode.conv_ovf_u1_un:
+ ImportConvert(WellKnownType.Byte, true, true);
+ break;
+ case ILOpcode.conv_ovf_u2_un:
+ ImportConvert(WellKnownType.UInt16, true, true);
+ break;
+ case ILOpcode.conv_ovf_u4_un:
+ ImportConvert(WellKnownType.UInt32, true, true);
+ break;
+ case ILOpcode.conv_ovf_u8_un:
+ ImportConvert(WellKnownType.UInt64, true, true);
+ break;
+ case ILOpcode.conv_ovf_i_un:
+ ImportConvert(WellKnownType.IntPtr, true, true);
+ break;
+ case ILOpcode.conv_ovf_u_un:
+ ImportConvert(WellKnownType.UIntPtr, true, true);
+ break;
+ case ILOpcode.box:
+ ImportBox(ReadILToken());
+ break;
+ case ILOpcode.newarr:
+ ImportNewArray(ReadILToken());
+ break;
+ case ILOpcode.ldlen:
+ ImportLoadLength();
+ break;
+ case ILOpcode.ldelema:
+ ImportAddressOfElement(ReadILToken());
+ break;
+ case ILOpcode.ldelem_i1:
+ ImportLoadElement(WellKnownType.SByte);
+ break;
+ case ILOpcode.ldelem_u1:
+ ImportLoadElement(WellKnownType.Byte);
+ break;
+ case ILOpcode.ldelem_i2:
+ ImportLoadElement(WellKnownType.Int16);
+ break;
+ case ILOpcode.ldelem_u2:
+ ImportLoadElement(WellKnownType.UInt16);
+ break;
+ case ILOpcode.ldelem_i4:
+ ImportLoadElement(WellKnownType.Int32);
+ break;
+ case ILOpcode.ldelem_u4:
+ ImportLoadElement(WellKnownType.UInt32);
+ break;
+ case ILOpcode.ldelem_i8:
+ ImportLoadElement(WellKnownType.Int64);
+ break;
+ case ILOpcode.ldelem_i:
+ ImportLoadElement(WellKnownType.IntPtr);
+ break;
+ case ILOpcode.ldelem_r4:
+ ImportLoadElement(WellKnownType.Single);
+ break;
+ case ILOpcode.ldelem_r8:
+ ImportLoadElement(WellKnownType.Double);
+ break;
+ case ILOpcode.ldelem_ref:
+ ImportLoadElement(null);
+ break;
+ case ILOpcode.stelem_i:
+ ImportStoreElement(WellKnownType.IntPtr);
+ break;
+ case ILOpcode.stelem_i1:
+ ImportStoreElement(WellKnownType.SByte);
+ break;
+ case ILOpcode.stelem_i2:
+ ImportStoreElement(WellKnownType.Int16);
+ break;
+ case ILOpcode.stelem_i4:
+ ImportStoreElement(WellKnownType.Int32);
+ break;
+ case ILOpcode.stelem_i8:
+ ImportStoreElement(WellKnownType.Int64);
+ break;
+ case ILOpcode.stelem_r4:
+ ImportStoreElement(WellKnownType.Single);
+ break;
+ case ILOpcode.stelem_r8:
+ ImportStoreElement(WellKnownType.Double);
+ break;
+ case ILOpcode.stelem_ref:
+ ImportStoreElement(null);
+ break;
+ case ILOpcode.ldelem:
+ ImportLoadElement(ReadILToken());
+ break;
+ case ILOpcode.stelem:
+ ImportStoreElement(ReadILToken());
+ break;
+ case ILOpcode.unbox_any:
+ ImportUnbox(ReadILToken(), opCode);
+ break;
+ case ILOpcode.conv_ovf_i1:
+ ImportConvert(WellKnownType.SByte, true, false);
+ break;
+ case ILOpcode.conv_ovf_u1:
+ ImportConvert(WellKnownType.Byte, true, false);
+ break;
+ case ILOpcode.conv_ovf_i2:
+ ImportConvert(WellKnownType.Int16, true, false);
+ break;
+ case ILOpcode.conv_ovf_u2:
+ ImportConvert(WellKnownType.UInt16, true, false);
+ break;
+ case ILOpcode.conv_ovf_i4:
+ ImportConvert(WellKnownType.Int32, true, false);
+ break;
+ case ILOpcode.conv_ovf_u4:
+ ImportConvert(WellKnownType.UInt32, true, false);
+ break;
+ case ILOpcode.conv_ovf_i8:
+ ImportConvert(WellKnownType.Int64, true, false);
+ break;
+ case ILOpcode.conv_ovf_u8:
+ ImportConvert(WellKnownType.UInt64, true, false);
+ break;
+ case ILOpcode.refanyval:
+ ImportRefAnyVal(ReadILToken());
+ break;
+ case ILOpcode.ckfinite:
+ ImportCkFinite();
+ break;
+ case ILOpcode.mkrefany:
+ ImportMkRefAny(ReadILToken());
+ break;
+ case ILOpcode.ldtoken:
+ ImportLdToken(ReadILToken());
+ break;
+ case ILOpcode.conv_u2:
+ ImportConvert(WellKnownType.UInt16, false, false);
+ break;
+ case ILOpcode.conv_u1:
+ ImportConvert(WellKnownType.Byte, false, false);
+ break;
+ case ILOpcode.conv_i:
+ ImportConvert(WellKnownType.IntPtr, false, false);
+ break;
+ case ILOpcode.conv_ovf_i:
+ ImportConvert(WellKnownType.IntPtr, true, false);
+ break;
+ case ILOpcode.conv_ovf_u:
+ ImportConvert(WellKnownType.UIntPtr, true, false);
+ break;
+ case ILOpcode.add_ovf:
+ case ILOpcode.add_ovf_un:
+ case ILOpcode.mul_ovf:
+ case ILOpcode.mul_ovf_un:
+ case ILOpcode.sub_ovf:
+ case ILOpcode.sub_ovf_un:
+ ImportBinaryOperation(opCode);
+ break;
+ case ILOpcode.endfinally: //both endfinally and endfault
+ ImportEndFinally();
+ EndImportingInstruction();
+ return;
+ case ILOpcode.leave:
+ {
+ int delta = (int)ReadILUInt32();
+ ImportLeave(_basicBlocks[_currentOffset + delta]);
+ }
+ EndImportingInstruction();
+ return;
+ case ILOpcode.leave_s:
+ {
+ int delta = (sbyte)ReadILByte();
+ ImportLeave(_basicBlocks[_currentOffset + delta]);
+ }
+ EndImportingInstruction();
+ return;
+ case ILOpcode.stind_i:
+ ImportStoreIndirect(WellKnownType.IntPtr);
+ break;
+ case ILOpcode.conv_u:
+ ImportConvert(WellKnownType.UIntPtr, false, false);
+ break;
+ case ILOpcode.prefix1:
+ opCode = (ILOpcode)(0x100 + ReadILByte());
+ goto again;
+ case ILOpcode.arglist:
+ ImportArgList();
+ break;
+ case ILOpcode.ceq:
+ case ILOpcode.cgt:
+ case ILOpcode.cgt_un:
+ case ILOpcode.clt:
+ case ILOpcode.clt_un:
+ ImportCompareOperation(opCode);
+ break;
+ case ILOpcode.ldftn:
+ case ILOpcode.ldvirtftn:
+ ImportLdFtn(ReadILToken(), opCode);
+ break;
+ case ILOpcode.ldarg:
+ ImportLoadVar(ReadILUInt16(), true);
+ break;
+ case ILOpcode.ldarga:
+ ImportAddressOfVar(ReadILUInt16(), true);
+ break;
+ case ILOpcode.starg:
+ ImportStoreVar(ReadILUInt16(), true);
+ break;
+ case ILOpcode.ldloc:
+ ImportLoadVar(ReadILUInt16(), false);
+ break;
+ case ILOpcode.ldloca:
+ ImportAddressOfVar(ReadILUInt16(), false);
+ break;
+ case ILOpcode.stloc:
+ ImportStoreVar(ReadILUInt16(), false);
+ break;
+ case ILOpcode.localloc:
+ ImportLocalAlloc();
+ break;
+ case ILOpcode.endfilter:
+ ImportEndFilter();
+ EndImportingInstruction();
+ return;
+ case ILOpcode.unaligned:
+ ImportUnalignedPrefix(ReadILByte());
+ continue;
+ case ILOpcode.volatile_:
+ ImportVolatilePrefix();
+ continue;
+ case ILOpcode.tail:
+ ImportTailPrefix();
+ continue;
+ case ILOpcode.initobj:
+ ImportInitObj(ReadILToken());
+ break;
+ case ILOpcode.constrained:
+ ImportConstrainedPrefix(ReadILToken());
+ continue;
+ case ILOpcode.cpblk:
+ ImportCpBlk();
+ break;
+ case ILOpcode.initblk:
+ ImportInitBlk();
+ break;
+ case ILOpcode.no:
+ ImportNoPrefix(ReadILByte());
+ continue;
+ case ILOpcode.rethrow:
+ ImportRethrow();
+ EndImportingInstruction();
+ return;
+ case ILOpcode.sizeof_:
+ ImportSizeOf(ReadILToken());
+ break;
+ case ILOpcode.refanytype:
+ ImportRefAnyType();
+ break;
+ case ILOpcode.readonly_:
+ ImportReadOnlyPrefix();
+ continue;
+ default:
+ ReportInvalidInstruction(opCode);
+ EndImportingInstruction();
+ return;
+ }
+
+ EndImportingInstruction();
+
+ // Check if control falls through the end of method.
+ if (_currentOffset == _basicBlocks.Length)
+ {
+ ReportFallthroughAtEndOfMethod();
+ return;
+ }
+
+ BasicBlock nextBasicBlock = _basicBlocks[_currentOffset];
+ if (nextBasicBlock != null)
+ {
+ ImportFallthrough(nextBasicBlock);
+ return;
+ }
+ }
+ }
+
+ private void ImportLoadIndirect(WellKnownType wellKnownType)
+ {
+ ImportLoadIndirect(GetWellKnownType(wellKnownType));
+ }
+
+ private void ImportStoreIndirect(WellKnownType wellKnownType)
+ {
+ ImportStoreIndirect(GetWellKnownType(wellKnownType));
+ }
+
+ private void ImportLoadElement(WellKnownType wellKnownType)
+ {
+ ImportLoadElement(GetWellKnownType(wellKnownType));
+ }
+
+ private void ImportStoreElement(WellKnownType wellKnownType)
+ {
+ ImportStoreElement(GetWellKnownType(wellKnownType));
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Internal.IL
+{
+ //
+ // Corresponds to "I.12.3.2.1 The evaluation stack" in ECMA spec
+ //
+ internal enum StackValueKind
+ {
+ /// <summary>An unknow type.</summary>
+ Unknown,
+ /// <summary>Any signed or unsigned integer values that can be represented as a 32-bit entity.</summary>
+ Int32,
+ /// <summary>Any signed or unsigned integer values that can be represented as a 64-bit entity.</summary>
+ Int64,
+ /// <summary>Underlying platform pointer type represented as an integer of the appropriate size.</summary>
+ NativeInt,
+ /// <summary>Any float value.</summary>
+ Float,
+ /// <summary>A managed pointer.</summary>
+ ByRef,
+ /// <summary>An object reference.</summary>
+ ObjRef,
+ /// <summary>A value type which is not any of the primitive one.</summary>
+ ValueType
+ }
+}
<Import Project="../Directory.Build.props" />
<PropertyGroup>
<IsShipping>false</IsShipping>
+ <SignAssembly>false</SignAssembly>
</PropertyGroup>
</Project>
--- /dev/null
+<Project>
+ <Import Project="../Directory.Build.targets" />
+
+ <!--
+ Provide default stub targets for packaging tasks, if not defined. Allows freer use of
+ ProjectReferences in pkgproj.
+ -->
+ <Target Name="GetFilesToPackage" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+namespace ILVerify
+{
+ internal static class AccessVerificationHelpers
+ {
+ /// <summary>
+ /// Returns whether the class <paramref name="currentClass"/> can access the class <paramref name="targetClass"/>.
+ /// </summary>
+ internal static bool CanAccess(this TypeDesc currentClass, TypeDesc targetClass)
+ {
+ if (targetClass.IsGenericParameter || targetClass.IsSignatureVariable)
+ return true; // Generic parameters are always accessible
+
+ if (targetClass.IsParameterizedType)
+ return currentClass.CanAccess(((ParameterizedType)targetClass).ParameterType);
+
+#if false
+ // perform transparency check on the type, if the caller is transparent
+ if ((NULL != pCurrentMD) && Security::IsTransparentMethod(pCurrentMD))
+ {
+ // check if type is visible outside the assembly
+ if (!IsTypeVisibleOutsideAssembly(pTargetClass))
+ {
+ // check transparent/critical on type
+ if (!Security::CheckNonPublicCriticalAccess(pCurrentMD, NULL, NULL, pTargetClass))
+ return FALSE;
+ }
+ }
+#endif
+
+ // Check access to class instantiations if generic class
+ if (targetClass.HasInstantiation && !currentClass.CanAccessInstantiation(targetClass.Instantiation))
+ return false;
+
+ var currentTypeDef = (MetadataType)currentClass.GetTypeDefinition();
+ var targetTypeDef = (EcmaType)targetClass.GetTypeDefinition();
+
+ var targetContainingType = targetTypeDef.ContainingType;
+ if (targetContainingType == null)
+ {
+ // a non-nested class can be either all public or accessible only from its own assembly (and friends)
+ if ((targetTypeDef.Attributes & TypeAttributes.Public) != 0)
+ return true;
+ else
+ return currentTypeDef.Module == targetTypeDef.Module || targetTypeDef.Module.GrantsFriendAccessTo(currentTypeDef.Module);
+ }
+
+ // Target class is nested
+ MethodAttributes visibility = NestedToMethodAccessAttribute(targetTypeDef.Attributes);
+
+ // Translate access check into member access check, i.e. check whether the current class can access
+ // a member of the enclosing class with the visibility of target class
+ return currentTypeDef.CanAccessMember(targetContainingType, visibility, null);
+ }
+
+ /// <summary>
+ /// Returns whether the class '<paramref name="currentClass"/>' can access the method '<paramref name="targetMethod"/>' through
+ /// the instance '<paramref name="instance"/>'. The instance can be null, if the method to be accessed is static.
+ /// </summary>
+ internal static bool CanAccess(this TypeDesc currentType, MethodDesc targetMethod, TypeDesc instance = null)
+ {
+ // If generic method, check instantiation access
+ if (targetMethod.HasInstantiation && !currentType.CanAccessInstantiation(targetMethod.Instantiation))
+ return false;
+
+ var targetMethodDef = targetMethod.GetTypicalMethodDefinition() as EcmaMethod;
+ var currentTypeDef = (MetadataType)currentType.GetTypeDefinition();
+
+ if (targetMethodDef != null) // Non metadata methods, such as ArrayMethods, may be null at this point
+ {
+ if (!currentTypeDef.CanAccessMember(targetMethod.OwningType, targetMethodDef.Attributes & MethodAttributes.MemberAccessMask, instance))
+ return false;
+ }
+
+ return currentTypeDef.CanAccessMethodSignature(targetMethod);
+ }
+
+ /// <summary>
+ /// Returns whether the class '<paramref name="currentClass"/>' can access the field '<paramref name="targetField"/>' through
+ /// the instance '<paramref name="instance"/>'. The instance can be null, if the field to be accessed is static.
+ /// </summary>
+ internal static bool CanAccess(this TypeDesc currentType, FieldDesc targetField, TypeDesc instance = null)
+ {
+ // Check access to field owning type
+ var targetFieldDef = (EcmaField)targetField.GetTypicalFieldDefinition();
+ var currentTypeDef = (MetadataType)currentType.GetTypeDefinition();
+
+ var targetFieldAccess = FieldToMethodAccessAttribute(targetFieldDef.Attributes);
+
+ if (!currentTypeDef.CanAccessMember(targetField.OwningType, targetFieldAccess, instance))
+ return false;
+
+ // Check access to field type itself
+ return currentType.CanAccess(targetField.FieldType);
+ }
+
+ private static bool CanAccessMember(this MetadataType currentType, TypeDesc targetType, MethodAttributes memberVisibility, TypeDesc instance)
+ {
+ if (instance == null)
+ instance = currentType;
+
+ // Check access to class defining member
+ if (!currentType.CanAccess(targetType))
+ return false;
+
+ var targetTypeDef = (MetadataType)targetType.GetTypeDefinition();
+
+ if (memberVisibility == MethodAttributes.Public)
+ return true;
+
+ // This is module-scope checking, to support C++ file & function statics.
+ if (memberVisibility == MethodAttributes.PrivateScope)
+ return currentType.Module == targetTypeDef.Module;
+
+ if (memberVisibility == MethodAttributes.Assembly)
+ return currentType.Module == targetTypeDef.Module || targetTypeDef.Module.GrantsFriendAccessTo(currentType.Module);
+
+ if (memberVisibility == MethodAttributes.FamANDAssem)
+ {
+ if (currentType.Module != targetTypeDef.Module && !targetTypeDef.Module.GrantsFriendAccessTo(currentType.Module))
+ return false;
+ }
+
+ // Nested classes can access all members of their parent class.
+ do
+ {
+ // Classes have access to all of their own members
+ if (currentType == targetTypeDef)
+ return true;
+
+ switch (memberVisibility)
+ {
+ case MethodAttributes.FamORAssem:
+ if (currentType.Module == targetTypeDef.Module || targetTypeDef.Module.GrantsFriendAccessTo(currentType.Module))
+ return true;
+
+ // Check if current class is subclass of target
+ if (CanAccessFamily(currentType, targetTypeDef, instance))
+ return true;
+ break;
+ case MethodAttributes.Family:
+ case MethodAttributes.FamANDAssem:
+ // Assembly access was already checked earlier, so only need to check family access
+ if (CanAccessFamily(currentType, targetTypeDef, instance))
+ return true;
+ break;
+ case MethodAttributes.Private:
+ break; // Already handled by loop
+ default:
+ Debug.Assert(false);
+ break;
+ }
+
+ var containingType = currentType.ContainingType;
+ if (containingType != null)
+ currentType = (MetadataType)containingType.GetTypeDefinition();
+ else
+ currentType = null;
+ } while (currentType != null);
+
+ return false;
+ }
+
+ private static bool CanAccessInstantiation(this TypeDesc currentType, Instantiation instantiation)
+ {
+ foreach (var inst in instantiation)
+ {
+ if (!currentType.CanAccess(inst))
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool CanAccessMethodSignature(this TypeDesc currentType, MethodDesc targetMethod)
+ {
+ var methodSig = targetMethod.Signature;
+
+ // Check return type
+ var returnType = methodSig.ReturnType;
+ if (returnType.IsParameterizedType)
+ returnType = ((ParameterizedType)returnType).ParameterType;
+
+ if (!returnType.IsGenericParameter && !returnType.IsSignatureVariable // Generic parameters are always accessible
+ && !returnType.IsVoid)
+ {
+ if (!currentType.CanAccess(returnType))
+ return false;
+ }
+
+ // Check arguments
+ for (int i = 0; i < methodSig.Length; ++i)
+ {
+ var param = methodSig[i];
+ if (param.IsByRef)
+ param = ((ByRefType)param).ParameterType;
+
+ if (param.IsGenericParameter || param.IsSignatureVariable)
+ continue; // Generic parameters are always accessible
+
+ if (!currentType.CanAccess(param))
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool CanAccessFamily(TypeDesc currentType, TypeDesc targetTypeDef, TypeDesc instanceType)
+ {
+ // if instanceType is generics and inherit from targetTypeDef members of targetTypeDef are accessible
+ if (instanceType.IsGenericParameter)
+ {
+ return instanceType.CanCastTo(targetTypeDef);
+ }
+
+ // Iterate through all containing types of instance
+ while (instanceType != null)
+ {
+ var curInstTypeDef = instanceType;
+ var currentTypeDef = currentType.GetTypeDefinition();
+ // Iterate through all super types of current instance type
+ while (curInstTypeDef != null)
+ {
+ if (currentTypeDef == curInstTypeDef.GetTypeDefinition())
+ {
+ // At this point we know that the instance type is able to access the same family fields as current type
+ // Now iterate through all super types of current type to see if current type can access family target type
+ while (currentTypeDef != null)
+ {
+ if (currentTypeDef == targetTypeDef)
+ return true;
+
+ currentTypeDef = currentTypeDef.BaseType;
+ if (currentTypeDef != null)
+ currentTypeDef = currentTypeDef.GetTypeDefinition();
+ }
+
+ return false;
+ }
+
+ curInstTypeDef = curInstTypeDef.BaseType;
+ }
+
+ instanceType = ((MetadataType)instanceType.GetTypeDefinition()).ContainingType;
+ }
+
+ return false;
+ }
+
+ private static EcmaAssembly ToEcmaAssembly(this ModuleDesc module)
+ {
+ return module.Assembly as EcmaAssembly;
+ }
+
+ private static bool GrantsFriendAccessTo(this ModuleDesc module, ModuleDesc friendModule)
+ {
+ var assembly = module.ToEcmaAssembly();
+ if (assembly != null)
+ {
+ var friendAssembly = friendModule.ToEcmaAssembly();
+ if (assembly == friendAssembly)
+ {
+ return true;
+ }
+ var friendName = friendAssembly.GetName();
+
+ foreach (var attribute in assembly.GetDecodedCustomAttributes("System.Runtime.CompilerServices", "InternalsVisibleToAttribute"))
+ {
+ AssemblyName friendAttributeName = new AssemblyName((string)attribute.FixedArguments[0].Value);
+ if (!friendName.Name.Equals(friendAttributeName.Name, StringComparison.OrdinalIgnoreCase))
+ continue;
+
+ // Comparing PublicKeyToken, since GetPublicKey returns null due to a bug
+ if (IsSamePublicKey(friendAttributeName.GetPublicKeyToken(), friendName.GetPublicKeyToken()))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static bool IsSamePublicKey(byte[] key1, byte[] key2)
+ {
+ if (key1 == null)
+ return key2 == null || key2.Length == 0;
+ if (key2 == null)
+ return key1 == null || key1.Length == 0;
+
+ if (key1.Length != key2.Length)
+ return false;
+
+ for (int i = 0; i < key1.Length; ++i)
+ {
+ if (key1[i] != key2[i])
+ return false;
+ }
+
+ return true;
+ }
+
+ private static MethodAttributes NestedToMethodAccessAttribute(TypeAttributes nestedVisibility)
+ {
+ switch (nestedVisibility & TypeAttributes.VisibilityMask)
+ {
+ case TypeAttributes.NestedAssembly:
+ return MethodAttributes.Assembly;
+ case TypeAttributes.NestedFamANDAssem:
+ return MethodAttributes.FamANDAssem;
+ case TypeAttributes.NestedFamily:
+ return MethodAttributes.Family;
+ case TypeAttributes.NestedFamORAssem:
+ return MethodAttributes.FamORAssem;
+ case TypeAttributes.NestedPrivate:
+ return MethodAttributes.Private;
+ case TypeAttributes.NestedPublic:
+ return MethodAttributes.Public;
+ default:
+ Debug.Assert(false);
+ return MethodAttributes.Public;
+ }
+ }
+
+ private static MethodAttributes FieldToMethodAccessAttribute(FieldAttributes attributes)
+ {
+ switch (attributes & FieldAttributes.FieldAccessMask)
+ {
+ case FieldAttributes.Assembly:
+ return MethodAttributes.Assembly;
+ case FieldAttributes.FamANDAssem:
+ return MethodAttributes.FamANDAssem;
+ case FieldAttributes.Family:
+ return MethodAttributes.Family;
+ case FieldAttributes.FamORAssem:
+ return MethodAttributes.FamORAssem;
+ case FieldAttributes.Private:
+ return MethodAttributes.Private;
+ case FieldAttributes.PrivateScope:
+ return MethodAttributes.PrivateScope;
+ case FieldAttributes.Public:
+ return MethodAttributes.Public;
+ default:
+ Debug.Assert(false);
+ return MethodAttributes.Public;
+ }
+ }
+ }
+}
--- /dev/null
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("ILVerification.Tests")]
+[assembly: InternalsVisibleTo("ILVerify")]
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+
+using Internal.TypeSystem;
+using ILVerify;
+
+namespace Internal.IL
+{
+ struct StackValue
+ {
+ [Flags]
+ public enum StackValueFlags
+ {
+ None = 0,
+ ReadOnly = 1 << 1,
+ PermanentHome = 1 << 2,
+ ThisPtr = 1 << 3,
+ }
+ private StackValueFlags Flags;
+
+ public readonly StackValueKind Kind;
+ public readonly TypeDesc Type;
+ public readonly MethodDesc Method;
+
+ private StackValue(StackValueKind kind, TypeDesc type = null, MethodDesc method = null, StackValueFlags flags = StackValueFlags.None)
+ {
+ this.Kind = kind;
+ this.Type = type;
+ this.Method = method;
+ this.Flags = flags;
+ }
+
+ public void SetIsReadOnly()
+ {
+ Debug.Assert(Kind == StackValueKind.ByRef);
+ Flags |= StackValueFlags.ReadOnly;
+ }
+
+ public void SetIsPermanentHome()
+ {
+ Debug.Assert(Kind == StackValueKind.ByRef);
+ Flags |= StackValueFlags.PermanentHome;
+ }
+
+ public void SetIsThisPtr()
+ {
+ Flags |= StackValueFlags.ThisPtr;
+ }
+
+ public bool IsReadOnly
+ {
+ get { return (Flags & StackValueFlags.ReadOnly) == StackValueFlags.ReadOnly; }
+ }
+
+ public bool IsPermanentHome
+ {
+ get { return (Flags & StackValueFlags.PermanentHome) == StackValueFlags.PermanentHome; }
+ }
+
+ public bool IsThisPtr
+ {
+ get { return (Flags & StackValueFlags.ThisPtr) == StackValueFlags.ThisPtr; }
+ }
+
+ public bool IsNullReference
+ {
+ get { return Kind == StackValueKind.ObjRef && Type == null; }
+ }
+
+ public bool IsMethod
+ {
+ get { return Kind == StackValueKind.NativeInt && Method != null; }
+ }
+
+ public bool IsBoxedValueType
+ {
+ get { return Kind == StackValueKind.ObjRef && Type.IsValueType; }
+ }
+
+ public StackValue DereferenceByRef()
+ {
+ Debug.Assert(Kind == StackValueKind.ByRef && Type != null, "Cannot dereference");
+ return CreateFromType(Type);
+ }
+
+ static public StackValue CreateUnknown()
+ {
+ return new StackValue(StackValueKind.Unknown);
+ }
+
+ static public StackValue CreatePrimitive(StackValueKind kind)
+ {
+ Debug.Assert(kind == StackValueKind.Int32 ||
+ kind == StackValueKind.Int64 ||
+ kind == StackValueKind.NativeInt ||
+ kind == StackValueKind.Float);
+
+ return new StackValue(kind);
+ }
+
+ static public StackValue CreateObjRef(TypeDesc type)
+ {
+ return new StackValue(StackValueKind.ObjRef, type);
+ }
+
+ static public StackValue CreateValueType(TypeDesc type)
+ {
+ return new StackValue(StackValueKind.ValueType, type);
+ }
+
+ static public StackValue CreateByRef(TypeDesc type, bool readOnly = false, bool permanentHome = false)
+ {
+ return new StackValue(StackValueKind.ByRef, type, null,
+ (readOnly ? StackValueFlags.ReadOnly : StackValueFlags.None) |
+ (permanentHome ? StackValueFlags.PermanentHome : StackValueFlags.None));
+ }
+
+ static public StackValue CreateMethod(MethodDesc method)
+ {
+ return new StackValue(StackValueKind.NativeInt, null, method);
+ }
+
+ static public StackValue CreateFromType(TypeDesc type)
+ {
+ switch (type.Category)
+ {
+ case TypeFlags.Boolean:
+ case TypeFlags.Char:
+ case TypeFlags.SByte:
+ case TypeFlags.Byte:
+ case TypeFlags.Int16:
+ case TypeFlags.UInt16:
+ case TypeFlags.Int32:
+ case TypeFlags.UInt32:
+ return CreatePrimitive(StackValueKind.Int32);
+ case TypeFlags.Int64:
+ case TypeFlags.UInt64:
+ return CreatePrimitive(StackValueKind.Int64);
+ case TypeFlags.Single:
+ case TypeFlags.Double:
+ return CreatePrimitive(StackValueKind.Float);
+ case TypeFlags.IntPtr:
+ case TypeFlags.UIntPtr:
+ case TypeFlags.Pointer:
+ return CreatePrimitive(StackValueKind.NativeInt);
+ case TypeFlags.Enum:
+ return CreateFromType(type.UnderlyingType);
+ case TypeFlags.ByRef:
+ return CreateByRef(((ByRefType)type).ParameterType);
+ default:
+ if (type.IsValueType || type.IsGenericParameter)
+ return CreateValueType(type);
+ else
+ return CreateObjRef(type);
+ }
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (Object.ReferenceEquals(this, obj))
+ return true;
+
+ if (!(obj is StackValue))
+ return false;
+
+ var value = (StackValue)obj;
+ return this.Kind == value.Kind && this.Flags == value.Flags && this.Type == value.Type;
+ }
+
+ public static bool operator ==(StackValue left, StackValue right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(StackValue left, StackValue right)
+ {
+ return !(left == right);
+ }
+
+ public override int GetHashCode()
+ {
+ const int prime = 17;
+ int hash = 23;
+ hash = (hash * prime) ^ Type.GetHashCode();
+ hash = (hash * prime) ^ Kind.GetHashCode();
+ hash = (hash * prime) ^ Flags.GetHashCode();
+ return hash;
+ }
+
+ // For now, match PEVerify type formating to make it easy to compare with baseline
+ static string TypeToStringForByRef(TypeDesc type)
+ {
+ switch (type.Category)
+ {
+ case TypeFlags.Boolean: return "Boolean";
+ case TypeFlags.Char: return "Char";
+ case TypeFlags.SByte: return "SByte";
+ case TypeFlags.Byte: return "Byte";
+ case TypeFlags.Int16: return "Int16";
+ case TypeFlags.UInt16: return "UInt16";
+ case TypeFlags.Int32: return "Int32";
+ case TypeFlags.UInt32: return "UInt32";
+ case TypeFlags.Int64: return "Int64";
+ case TypeFlags.UInt64: return "UInt64";
+ case TypeFlags.Single: return "Single";
+ case TypeFlags.Double: return "Double";
+ case TypeFlags.IntPtr: return "IntPtr";
+ case TypeFlags.UIntPtr: return "UIntPtr";
+ }
+
+ return "'" + type.ToString() + "'";
+ }
+
+ public override string ToString()
+ {
+ switch (Kind)
+ {
+ case StackValueKind.Int32:
+ return "Int32";
+ case StackValueKind.Int64:
+ return "Long";
+ case StackValueKind.NativeInt:
+ return "Native Int";
+ case StackValueKind.Float:
+ return "Double";
+ case StackValueKind.ByRef:
+ return (IsReadOnly ? "readonly " : "") + "address of " + TypeToStringForByRef(Type);
+ case StackValueKind.ObjRef:
+ return (Type != null) ? "ref '" + Type.ToString() + "'" : "Nullobjref 'NullReference'";
+ case StackValueKind.ValueType:
+ return "value '" + Type.ToString() + "'";
+ default:
+ return "unknown";
+ }
+ }
+ }
+
+ partial class ILImporter
+ {
+ /// <summary>
+ /// Merges two stack values to a common stack value as defined in the ECMA-335
+ /// standard III.1.8.1.3 (Merging stack states).
+ /// </summary>
+ /// <param name="valueA">The value to be merged with <paramref name="valueB"/>.</param>
+ /// <param name="valueB">The value to be merged with <paramref name="valueA"/>.</param>
+ /// <param name="merged">The resulting type of merging <paramref name="valueA"/> and <paramref name="valueB"/>.</param>
+ /// <returns>True if merge operation was successful, false if the merge operation failed.</returns>
+ public static bool TryMergeStackValues(StackValue valueA, StackValue valueB, out StackValue merged)
+ {
+ merged = valueA;
+
+ if (valueB.IsReadOnly)
+ merged.SetIsReadOnly();
+
+ // Same type
+ if (valueA.Kind == valueB.Kind && valueA.Type == valueB.Type)
+ return true;
+
+ if (valueA.IsNullReference)
+ {
+ //Null can be any reference type
+ if (valueB.Kind == StackValueKind.ObjRef)
+ {
+ merged = valueB;
+ return true;
+ }
+ }
+ else if (valueA.Kind == StackValueKind.ObjRef)
+ {
+ if (valueB.Kind != StackValueKind.ObjRef)
+ return false;
+
+ // Null can be any reference type
+ if (valueB.IsNullReference)
+ return true;
+
+ // Merging classes always succeeds since System.Object always works
+ merged = StackValue.CreateFromType(MergeObjectReferences(valueA.Type, valueB.Type));
+ return true;
+ }
+
+ return false;
+ }
+
+ // Used to merge stack states.
+ static TypeDesc MergeObjectReferences(TypeDesc classA, TypeDesc classB)
+ {
+ if (classA == classB)
+ return classA;
+
+ // Array case
+ if (classA.IsArray)
+ {
+ if (classB.IsArray)
+ return MergeArrayTypes((ArrayType)classA, (ArrayType)classB);
+ }
+
+ // Assumes generic parameters are boxed at this point.
+ // Return supertype, if related, otherwhise object
+ if (classA.IsGenericParameter || classB.IsGenericParameter)
+ {
+ if (classA.CanCastTo(classB))
+ return classB;
+ if (classB.CanCastTo(classA))
+ return classA;
+
+ return classA.Context.GetWellKnownType(WellKnownType.Object);
+ }
+
+ if (classB.IsInterface)
+ {
+ if (classA.IsInterface)
+ return MergeInterfaceWithInterface(classA, classB);
+ else
+ return MergeClassWithInterface(classA, classB);
+ }
+ else if (classA.IsInterface)
+ return MergeClassWithInterface(classB, classA);
+
+ return MergeClassWithClass(classA, classB);
+ }
+
+ static TypeDesc MergeInterfaceWithInterface(TypeDesc interfA, TypeDesc interfB)
+ {
+ foreach (var interf in interfA.RuntimeInterfaces)
+ {
+ if (interf == interfB)
+ return interfB; // Interface A extends interface B
+ }
+
+ foreach (var interf in interfB.RuntimeInterfaces)
+ {
+ if (interf == interfA)
+ return interfA; // Interface B extends interface A
+ }
+
+ // Get common supertype
+ foreach (var subInterfB in interfB.RuntimeInterfaces)
+ {
+ foreach (var subInterfA in interfA.RuntimeInterfaces)
+ {
+ if (subInterfA == subInterfB)
+ return subInterfA;
+ }
+ }
+
+ // No compatible interface found, return Object
+ return interfA.Context.GetWellKnownType(WellKnownType.Object);
+ }
+
+ static TypeDesc MergeClassWithClass(TypeDesc classA, TypeDesc classB)
+ {
+ // Find class hierarchy depth for both classes
+ int aDepth = 0;
+ int bDepth = 0;
+ TypeDesc curType;
+
+ for (curType = classA; curType != null; curType = curType.BaseType)
+ aDepth++;
+
+ for (curType = classB; curType != null; curType = curType.BaseType)
+ bDepth++;
+
+ // Walk up superclass chain until both classes at same level
+ while (aDepth > bDepth)
+ {
+ classA = classA.BaseType;
+ aDepth--;
+ }
+
+ while (bDepth > aDepth)
+ {
+ classB = classB.BaseType;
+ bDepth--;
+ }
+
+ while (classA != classB)
+ {
+ classA = classA.BaseType;
+ classB = classB.BaseType;
+ }
+
+ // At this point we should either have found a common supertype or end up at System.Object
+ Debug.Assert(classA != null);
+
+ return classA;
+ }
+
+ static TypeDesc MergeClassWithInterface(TypeDesc classType, TypeDesc interfaceType)
+ {
+ // Check if class implements interface
+ foreach (var interf in classType.RuntimeInterfaces)
+ {
+ if (interf == interfaceType)
+ return interfaceType;
+ }
+
+ // Check if class and interface implement common interface
+ foreach (var iInterf in interfaceType.RuntimeInterfaces)
+ {
+ foreach (var cInterf in classType.RuntimeInterfaces)
+ {
+ if (iInterf == cInterf)
+ return iInterf;
+ }
+ }
+
+ // No compatible merge, return Object
+ return classType.Context.GetWellKnownType(WellKnownType.Object);
+ }
+
+ static TypeDesc MergeArrayTypes(ArrayType arrayTypeA, ArrayType arrayTypeB)
+ {
+ if (arrayTypeA == arrayTypeB)
+ return arrayTypeA;
+
+ var basicArrayType = arrayTypeA.Context.GetWellKnownType(WellKnownType.Array);
+
+ // If non matching rank, common ancestor = System.Array
+ var rank = arrayTypeA.Rank;
+ var mergeCategory = arrayTypeA.Category;
+ if (rank != arrayTypeB.Rank)
+ return basicArrayType;
+
+ if (arrayTypeA.Category != arrayTypeB.Category)
+ {
+ if (rank == 1)
+ mergeCategory = TypeFlags.Array;
+ else
+ return basicArrayType;
+ }
+
+ // Determine merged array element type
+ TypeDesc mergedElementType;
+ if (arrayTypeA.ElementType == arrayTypeB.ElementType)
+ mergedElementType = arrayTypeA.ElementType;
+ else if (arrayTypeA.ElementType.IsArray && arrayTypeB.ElementType.IsArray)
+ {
+ // Array of arrays -> find merged type
+ mergedElementType = MergeArrayTypes(arrayTypeA, arrayTypeB);
+ }
+ //Both array element types are ObjRefs
+ else if ((!arrayTypeA.ElementType.IsValueType && !arrayTypeA.ElementType.IsByRef) &&
+ (!arrayTypeB.ElementType.IsValueType && !arrayTypeB.ElementType.IsByRef))
+ {
+ // Find common ancestor of the element types
+ mergedElementType = MergeObjectReferences(arrayTypeA.ElementType, arrayTypeB.ElementType);
+ }
+ else
+ {
+ // Array element types have nothing in common
+ return basicArrayType;
+ }
+
+ Debug.Assert(mergeCategory == TypeFlags.Array || mergeCategory == TypeFlags.SzArray);
+
+ if (mergeCategory == TypeFlags.SzArray)
+ return arrayTypeA.Context.GetArrayType(mergedElementType);
+ else
+ return arrayTypeA.Context.GetArrayType(mergedElementType, rank);
+ }
+
+ static bool IsSameReducedType(TypeDesc src, TypeDesc dst)
+ {
+ return src.GetReducedType() == dst.GetReducedType();
+ }
+
+ bool IsAssignable(TypeDesc src, TypeDesc dst, bool allowSizeEquivalence = false)
+ {
+ if (src == dst)
+ return true;
+
+ if (src.IsValueType || dst.IsValueType)
+ {
+ if (allowSizeEquivalence && IsSameReducedType(src, dst))
+ return true;
+
+ // TODO IsEquivalent
+ return false;
+ }
+
+ return CastingHelper.CanCastTo(src, dst);
+ }
+
+ bool IsAssignable(StackValue src, StackValue dst)
+ {
+ if (src.Kind == dst.Kind && src.Type == dst.Type && src.IsReadOnly == dst.IsReadOnly)
+ return true;
+
+ if (dst.Type == null)
+ return false;
+
+ switch (src.Kind)
+ {
+ case StackValueKind.ObjRef:
+ if (dst.Kind != StackValueKind.ObjRef)
+ return false;
+
+ // null is always assignable
+ if (src.Type == null)
+ return true;
+
+ return CastingHelper.CanCastTo(src.Type, dst.Type);
+
+ case StackValueKind.ValueType:
+
+ // TODO: Other cases - variance, etc.
+
+ return false;
+
+ case StackValueKind.ByRef:
+ if (dst.Kind == StackValueKind.ByRef && dst.IsReadOnly)
+ return src.Type == dst.Type;
+
+ // TODO: Other cases - variance, etc.
+
+ return false;
+
+ case StackValueKind.Int32:
+ return (dst.Kind == StackValueKind.Int64 || dst.Kind == StackValueKind.NativeInt);
+
+ case StackValueKind.Int64:
+ return false;
+
+ case StackValueKind.NativeInt:
+ return (dst.Kind == StackValueKind.Int64);
+
+ case StackValueKind.Float:
+ return false;
+
+ default:
+ // TODO:
+ // return false;
+ throw new NotImplementedException();
+ }
+
+#if false
+ if (child == parent)
+ {
+ return(TRUE);
+ }
+
+ // Normally we just let the runtime sort it out but we wish to be more strict
+ // than the runtime wants to be. For backwards compatibility, the runtime considers
+ // int32[] and nativeInt[] to be the same on 32-bit machines. It also is OK with
+ // int64[] and nativeInt[] on a 64-bit machine.
+
+ if (child.IsType(TI_REF) && parent.IsType(TI_REF)
+ && jitInfo->isSDArray(child.GetClassHandleForObjRef())
+ && jitInfo->isSDArray(parent.GetClassHandleForObjRef()))
+ {
+ BOOL runtime_OK;
+
+ // never be more lenient than the runtime
+ runtime_OK = jitInfo->canCast(child.m_cls, parent.m_cls);
+ if (!runtime_OK)
+ return false;
+
+ CORINFO_CLASS_HANDLE handle;
+ CorInfoType pType = jitInfo->getChildType(child.GetClassHandleForObjRef(), &handle);
+ CorInfoType cType = jitInfo->getChildType(parent.GetClassHandleForObjRef(), &handle);
+
+ // don't care whether it is signed
+ if (cType == CORINFO_TYPE_NATIVEUINT)
+ cType = CORINFO_TYPE_NATIVEINT;
+ if (pType == CORINFO_TYPE_NATIVEUINT)
+ pType = CORINFO_TYPE_NATIVEINT;
+
+ if (cType == CORINFO_TYPE_NATIVEINT)
+ return pType == CORINFO_TYPE_NATIVEINT;
+
+ if (pType == CORINFO_TYPE_NATIVEINT)
+ return cType == CORINFO_TYPE_NATIVEINT;
+
+ return runtime_OK;
+ }
+
+ if (parent.IsUnboxedGenericTypeVar() || child.IsUnboxedGenericTypeVar())
+ {
+ return (FALSE); // need to have had child == parent
+ }
+ else if (parent.IsType(TI_REF))
+ {
+ // An uninitialized objRef is not compatible to initialized.
+ if (child.IsUninitialisedObjRef() && !parent.IsUninitialisedObjRef())
+ return FALSE;
+
+ if (child.IsNullObjRef()) // NULL can be any reference type
+ return TRUE;
+ if (!child.IsType(TI_REF))
+ return FALSE;
+
+ return jitInfo->canCast(child.m_cls, parent.m_cls);
+
+ }
+ else if (parent.IsType(TI_METHOD))
+ {
+ if (!child.IsType(TI_METHOD))
+ return FALSE;
+
+ // Right now we don't bother merging method handles
+ return FALSE;
+ }
+ else if (parent.IsType(TI_STRUCT))
+ {
+ if (!child.IsType(TI_STRUCT))
+ return FALSE;
+
+ // Structures are compatible if they are equivalent
+ return jitInfo->areTypesEquivalent(child.m_cls, parent.m_cls);
+ }
+ else if (parent.IsByRef())
+ {
+ return tiCompatibleWithByRef(jitInfo, child, parent);
+ }
+
+ return FALSE;
+#endif
+ }
+
+
+ bool IsBinaryComparable(StackValue src, StackValue dst, ILOpcode op)
+ {
+ if (src.Kind == dst.Kind && src.Type == dst.Type)
+ return true;
+
+ switch (src.Kind)
+ {
+ case StackValueKind.ObjRef:
+ switch (dst.Kind)
+ {
+ case StackValueKind.ObjRef:
+ // ECMA-335 III.1.5 Operand type table, P. 303:
+ // __cgt.un__ is allowed and verifiable on ObjectRefs (O). This is commonly used when
+ // comparing an ObjectRef with null(there is no "compare - not - equal" instruction, which
+ // would otherwise be a more obvious solution)
+ return op == ILOpcode.beq || op == ILOpcode.beq_s ||
+ op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
+ op == ILOpcode.ceq || op == ILOpcode.cgt_un;
+ default:
+ return false;
+ }
+
+ case StackValueKind.ValueType:
+ return false;
+
+ case StackValueKind.ByRef:
+ switch (dst.Kind)
+ {
+ case StackValueKind.ByRef:
+ return true;
+ case StackValueKind.NativeInt:
+ return op == ILOpcode.beq || op == ILOpcode.beq_s ||
+ op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
+ op == ILOpcode.ceq;
+ default:
+ return false;
+ }
+
+ case StackValueKind.Int32:
+ return (dst.Kind == StackValueKind.Int64 || dst.Kind == StackValueKind.NativeInt);
+
+ case StackValueKind.Int64:
+ return (dst.Kind == StackValueKind.Int64);
+
+ case StackValueKind.NativeInt:
+ switch (dst.Kind)
+ {
+ case StackValueKind.Int32:
+ case StackValueKind.NativeInt:
+ return true;
+ case StackValueKind.ByRef:
+ return op == ILOpcode.beq || op == ILOpcode.beq_s ||
+ op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
+ op == ILOpcode.ceq;
+ default:
+ return false;
+ }
+
+ case StackValueKind.Float:
+ return dst.Kind == StackValueKind.Float;
+
+ default:
+ throw new NotImplementedException();
+ }
+ }
+
+ bool IsByRefLike(StackValue value)
+ {
+ if (value.Kind == StackValueKind.ByRef)
+ return true;
+
+ // TODO: Check for other by-ref like types Slice<T>, ArgIterator, TypedReference
+
+ return false;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+using ILVerify;
+
+namespace Internal.IL
+{
+ class VerificationException : Exception
+ {
+ public VerificationException()
+ {
+ }
+ }
+
+ class LocalVerificationException : VerificationException
+ {
+ public LocalVerificationException()
+ {
+ }
+ }
+
+ class VerifierException : Exception
+ {
+ internal VerifierException(string message) : base(message)
+ {
+ }
+ }
+
+ partial class ILImporter
+ {
+ readonly MethodDesc _method;
+ readonly MethodSignature _methodSignature;
+ readonly TypeSystemContext _typeSystemContext;
+
+ readonly TypeDesc _thisType;
+
+ readonly MethodIL _methodIL;
+ readonly byte[] _ilBytes;
+ readonly LocalVariableDefinition[] _locals;
+
+ readonly bool _initLocals;
+ readonly int _maxStack;
+
+ bool[] _instructionBoundaries; // For IL verification
+
+ static readonly StackValue[] s_emptyStack = new StackValue[0];
+ StackValue[] _stack = s_emptyStack;
+ int _stackTop = 0;
+
+ bool _isThisInitialized;
+ bool _modifiesThisPtr;
+ bool _trackObjCtorState;
+
+ bool[] _validTargetOffsets;
+
+ int? _delegateCreateStart;
+
+ class ExceptionRegion
+ {
+ public ILExceptionRegion ILRegion;
+ };
+ ExceptionRegion[] _exceptionRegions;
+
+ [Flags]
+ enum Prefix
+ {
+ ReadOnly = 0x01,
+ Unaligned = 0x02,
+ Volatile = 0x04,
+ Tail = 0x08,
+ Constrained = 0x10,
+ No = 0x20,
+ }
+ Prefix _pendingPrefix;
+ TypeDesc _constrained;
+
+ int _currentInstructionOffset;
+
+ class BasicBlock
+ {
+ // Common fields
+ public enum ImportState : byte
+ {
+ Unmarked,
+ IsPending,
+ WasVerified
+ }
+
+ public BasicBlock Next;
+
+ public int StartOffset;
+ public ImportState State = ImportState.Unmarked;
+
+ public StackValue[] EntryStack;
+ public bool IsThisInitialized = false;
+
+ public bool TryStart;
+ public bool FilterStart;
+ public bool HandlerStart;
+
+ //these point to the direct enclosing items in _exceptionRegions
+ public int? TryIndex;
+ public int? HandlerIndex;
+ public int? FilterIndex;
+
+ // Used for Backward Branch Constraint
+ public bool HasPredecessorWithLowerOffset = false;
+
+ public int ErrorCount
+ {
+ get;
+ private set;
+ }
+ public void IncrementErrorCount()
+ {
+ ErrorCount++;
+ }
+ };
+
+ void EmptyTheStack() => _stackTop = 0;
+
+ void Push(StackValue value)
+ {
+ FatalCheck(_stackTop < _maxStack, VerifierError.StackOverflow);
+
+ if (_stackTop >= _stack.Length)
+ Array.Resize(ref _stack, 2 * _stackTop + 3);
+ _stack[_stackTop++] = value;
+ }
+
+ StackValue Pop(bool allowUninitThis = false)
+ {
+ FatalCheck(_stackTop > 0, VerifierError.StackUnderflow);
+
+ var stackValue = _stack[--_stackTop];
+
+ if (!allowUninitThis)
+ Check(!_trackObjCtorState || !stackValue.IsThisPtr || _isThisInitialized, VerifierError.UninitStack, stackValue);
+
+ return stackValue;
+ }
+
+ public ILImporter(MethodDesc method, MethodIL methodIL)
+ {
+ _typeSystemContext = method.Context;
+
+ // Instantiate method and its owning type
+ var instantiatedType = method.OwningType;
+ var instantiatedMethod = method;
+ if (instantiatedType.HasInstantiation)
+ {
+ Instantiation genericTypeInstantiation = InstantiatedGenericParameter.CreateGenericTypeInstantiaton(instantiatedType.Instantiation);
+ instantiatedType = _typeSystemContext.GetInstantiatedType((MetadataType)instantiatedType, genericTypeInstantiation);
+ instantiatedMethod = _typeSystemContext.GetMethodForInstantiatedType(instantiatedMethod.GetTypicalMethodDefinition(), (InstantiatedType)instantiatedType);
+ }
+
+ if (instantiatedMethod.HasInstantiation)
+ {
+ Instantiation genericMethodInstantiation = InstantiatedGenericParameter.CreateGenericMethodInstantiation(
+ instantiatedType.Instantiation, instantiatedMethod.Instantiation);
+ instantiatedMethod = _typeSystemContext.GetInstantiatedMethod(instantiatedMethod, genericMethodInstantiation);
+ }
+ _method = instantiatedMethod;
+
+ _methodSignature = _method.Signature;
+ _methodIL = method == instantiatedMethod ? methodIL : new InstantiatedMethodIL(instantiatedMethod, methodIL);
+
+ // Determine this type
+ if (!_method.Signature.IsStatic)
+ {
+ _thisType = instantiatedType;
+
+ // ECMA-335 II.13.3 Methods of value types, P. 164:
+ // ... By contrast, instance and virtual methods of value types shall be coded to expect a
+ // managed pointer(see Partition I) to an unboxed instance of the value type. ...
+ if (_thisType.IsValueType)
+ _thisType = _thisType.MakeByRefType();
+ }
+
+ _initLocals = _methodIL.IsInitLocals;
+
+ _maxStack = _methodIL.MaxStack;
+
+ _isThisInitialized = false;
+ _trackObjCtorState = !_methodSignature.IsStatic && _method.IsConstructor && !method.OwningType.IsValueType;
+
+ _ilBytes = _methodIL.GetILBytes();
+ _locals = _methodIL.GetLocals();
+
+ var ilExceptionRegions = _methodIL.GetExceptionRegions();
+ _exceptionRegions = new ExceptionRegion[ilExceptionRegions.Length];
+ for (int i = 0; i < ilExceptionRegions.Length; i++)
+ {
+ _exceptionRegions[i] = new ExceptionRegion() { ILRegion = ilExceptionRegions[i] };
+ }
+ }
+
+ public Action<ErrorArgument[], VerifierError> ReportVerificationError
+ {
+ set;
+ private get;
+ }
+
+ public void Verify()
+ {
+ _instructionBoundaries = new bool[_ilBytes.Length];
+
+ FindBasicBlocks();
+ FindEnclosingExceptionRegions();
+ InitialPass();
+ ImportBasicBlocks();
+ }
+
+ private void FindEnclosingExceptionRegions()
+ {
+ for (int i = 0; i < _basicBlocks.Length; i++)
+ {
+ if (_basicBlocks[i] == null)
+ continue;
+
+ var basicBlock = _basicBlocks[i];
+ var offset = basicBlock.StartOffset;
+
+ for (int j = 0; j < _exceptionRegions.Length; j++)
+ {
+ var r = _exceptionRegions[j].ILRegion;
+ // Check if offset is within the range [TryOffset, TryOffset + TryLength[
+ if (r.TryOffset <= offset && offset < r.TryOffset + r.TryLength)
+ {
+ if (!basicBlock.TryIndex.HasValue)
+ {
+ basicBlock.TryIndex = j;
+ }
+ else
+ {
+ var currentlySelected = _exceptionRegions[basicBlock.TryIndex.Value].ILRegion;
+ var probeItem = _exceptionRegions[j].ILRegion;
+
+ if (currentlySelected.TryOffset < probeItem.TryOffset &&
+ currentlySelected.TryOffset + currentlySelected.TryLength > probeItem.TryOffset + probeItem.TryLength)
+ {
+ basicBlock.TryIndex = j;
+ }
+ }
+ }
+ // Check if offset is within the range [HandlerOffset, HandlerOffset + HandlerLength[
+ if (r.HandlerOffset <= offset && offset < r.HandlerOffset + r.HandlerLength)
+ {
+ if (!basicBlock.HandlerIndex.HasValue)
+ {
+ basicBlock.HandlerIndex = j;
+ }
+ else
+ {
+ var currentlySelected = _exceptionRegions[basicBlock.HandlerIndex.Value].ILRegion;
+ var probeItem = _exceptionRegions[j].ILRegion;
+
+ if (currentlySelected.HandlerOffset < probeItem.HandlerOffset &&
+ currentlySelected.HandlerOffset + currentlySelected.HandlerLength > probeItem.HandlerOffset + probeItem.HandlerLength)
+ {
+ basicBlock.HandlerIndex = j;
+ }
+ }
+ }
+ // Check if offset is within the range [FilterOffset, HandlerOffset[
+ if (r.FilterOffset != -1 && r.FilterOffset <= offset && offset < r.HandlerOffset )
+ {
+ if(!basicBlock.FilterIndex.HasValue)
+ {
+ basicBlock.FilterIndex = j;
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Checks whether the metod's il modifies the this pointer and builds up the
+ /// array of valid target offsets.
+ /// </summary>
+ private void InitialPass()
+ {
+ FatalCheck(_ilBytes.Length > 0, VerifierError.CodeSizeZero);
+
+ _modifiesThisPtr = false;
+ _validTargetOffsets = new bool[_ilBytes.Length];
+
+ bool previousWasPrefix = false;
+
+ _currentOffset = 0;
+
+ while (_currentOffset < _ilBytes.Length)
+ {
+ if (!previousWasPrefix) // The instruction following a prefix is not a valid branch target.
+ _validTargetOffsets[_currentOffset] = true;
+
+ ILOpcode opCode = (ILOpcode)ReadILByte();
+
+ previousWasPrefix = false;
+again:
+ switch (opCode)
+ {
+ // Check this pointer modification
+ case ILOpcode.starg_s:
+ case ILOpcode.ldarga_s:
+ if (ReadILByte() == 0)
+ {
+ _modifiesThisPtr = true;
+ break;
+ }
+ break;
+ case ILOpcode.starg:
+ case ILOpcode.ldarga:
+ if (ReadILUInt16() == 0)
+ {
+ _modifiesThisPtr = true;
+ break;
+ }
+ break;
+
+ // Keep track of prefixes
+ case ILOpcode.unaligned:
+ case ILOpcode.no:
+ previousWasPrefix = true;
+ SkipIL(1);
+ continue;
+ case ILOpcode.constrained:
+ previousWasPrefix = true;
+ SkipIL(4);
+ continue;
+ case ILOpcode.tail:
+ case ILOpcode.volatile_:
+ case ILOpcode.readonly_:
+ previousWasPrefix = true;
+ continue;
+
+ // Check for block predecessors with lower il offset
+ case ILOpcode.br:
+ case ILOpcode.leave:
+ MarkPredecessorWithLowerOffset((int)ReadILUInt32());
+ continue;
+ case ILOpcode.brfalse:
+ case ILOpcode.brtrue:
+ case ILOpcode.beq:
+ case ILOpcode.bge:
+ case ILOpcode.bgt:
+ case ILOpcode.ble:
+ case ILOpcode.blt:
+ case ILOpcode.bne_un:
+ case ILOpcode.bge_un:
+ case ILOpcode.bgt_un:
+ case ILOpcode.ble_un:
+ case ILOpcode.blt_un:
+ MarkPredecessorWithLowerOffset((int)ReadILUInt32());
+ break;
+ case ILOpcode.br_s:
+ case ILOpcode.leave_s:
+ MarkPredecessorWithLowerOffset((sbyte)ReadILByte());
+ continue;
+ case ILOpcode.brfalse_s:
+ case ILOpcode.brtrue_s:
+ case ILOpcode.beq_s:
+ case ILOpcode.bge_s:
+ case ILOpcode.bgt_s:
+ case ILOpcode.ble_s:
+ case ILOpcode.blt_s:
+ case ILOpcode.bne_un_s:
+ case ILOpcode.bge_un_s:
+ case ILOpcode.bgt_un_s:
+ case ILOpcode.ble_un_s:
+ case ILOpcode.blt_un_s:
+ MarkPredecessorWithLowerOffset((sbyte)ReadILByte());
+ break;
+ case ILOpcode.switch_:
+ {
+ uint count = ReadILUInt32();
+ int[] jmpDeltas = new int[count];
+ for (uint i = 0; i < count; i++)
+ jmpDeltas[i] = (int)ReadILUInt32();
+
+ foreach (int delta in jmpDeltas)
+ MarkPredecessorWithLowerOffset(delta);
+ }
+ break;
+
+ // Skip all other Opcodes
+ case ILOpcode.ret:
+ case ILOpcode.throw_:
+ case ILOpcode.rethrow:
+ case ILOpcode.endfinally:
+ case ILOpcode.endfilter:
+ continue;
+ case ILOpcode.ldarg_s:
+ case ILOpcode.ldloc_s:
+ case ILOpcode.ldloca_s:
+ case ILOpcode.stloc_s:
+ case ILOpcode.ldc_i4_s:
+ SkipIL(1);
+ break;
+ case ILOpcode.ldarg:
+ case ILOpcode.ldloc:
+ case ILOpcode.ldloca:
+ case ILOpcode.stloc:
+ SkipIL(2);
+ break;
+ case ILOpcode.ldc_i4:
+ case ILOpcode.ldc_r4:
+ case ILOpcode.call:
+ case ILOpcode.calli:
+ case ILOpcode.callvirt:
+ case ILOpcode.cpobj:
+ case ILOpcode.ldobj:
+ case ILOpcode.ldstr:
+ case ILOpcode.newobj:
+ case ILOpcode.castclass:
+ case ILOpcode.isinst:
+ case ILOpcode.unbox:
+ case ILOpcode.ldfld:
+ case ILOpcode.ldflda:
+ case ILOpcode.stfld:
+ case ILOpcode.ldsfld:
+ case ILOpcode.ldsflda:
+ case ILOpcode.stsfld:
+ case ILOpcode.stobj:
+ case ILOpcode.box:
+ case ILOpcode.newarr:
+ case ILOpcode.ldelema:
+ case ILOpcode.ldelem:
+ case ILOpcode.stelem:
+ case ILOpcode.unbox_any:
+ case ILOpcode.refanyval:
+ case ILOpcode.mkrefany:
+ case ILOpcode.ldtoken:
+ case ILOpcode.ldftn:
+ case ILOpcode.ldvirtftn:
+ case ILOpcode.initobj:
+ case ILOpcode.sizeof_:
+ SkipIL(4);
+ break;
+ case ILOpcode.jmp:
+ SkipIL(4);
+ continue;
+ case ILOpcode.ldc_i8:
+ case ILOpcode.ldc_r8:
+ SkipIL(8);
+ break;
+ case ILOpcode.prefix1:
+ opCode = (ILOpcode)(0x100 + ReadILByte());
+ goto again;
+ default:
+ break;
+ }
+
+ if (_currentOffset < _basicBlocks.Length)
+ {
+ var fallthrough = _basicBlocks[_currentOffset];
+ if (fallthrough != null)
+ MarkPredecessorWithLowerOffset(0);
+ }
+ }
+ }
+
+ void MarkPredecessorWithLowerOffset(int delta)
+ {
+ if (delta >= 0)
+ _basicBlocks[_currentOffset + delta].HasPredecessorWithLowerOffset = true;
+ }
+
+ void AbortBasicBlockVerification()
+ {
+ throw new LocalVerificationException();
+ }
+
+ void AbortMethodVerification()
+ {
+ throw new VerificationException();
+ }
+
+ // Check whether the condition is true. If not, terminate the verification of current method.
+ void FatalCheck(bool cond, VerifierError error)
+ {
+ if (!Check(cond, error))
+ AbortMethodVerification();
+ }
+
+ // Check whether the condition is true. If not, terminate the verification of current method.
+ void FatalCheck(bool cond, VerifierError error, StackValue found)
+ {
+ if (!Check(cond, error, found))
+ AbortMethodVerification();
+ }
+
+ // Check whether the condition is true. If not, terminate the verification of current method.
+ void FatalCheck(bool cond, VerifierError error, StackValue found, StackValue expected)
+ {
+ if (!Check(cond, error, found, expected))
+ AbortMethodVerification();
+ }
+
+ // If not, report verification error and continue verification.
+ void VerificationError(VerifierError error)
+ {
+ if (_currentBasicBlock != null)
+ _currentBasicBlock.IncrementErrorCount();
+
+ var args = new ErrorArgument[]
+ {
+ new ErrorArgument("Offset", _currentInstructionOffset)
+ };
+ ReportVerificationError(args, error);
+ }
+
+ void VerificationError(VerifierError error, object found)
+ {
+ if (_currentBasicBlock != null)
+ _currentBasicBlock.IncrementErrorCount();
+
+ var args = new ErrorArgument[]
+ {
+ new ErrorArgument("Offset", _currentInstructionOffset),
+ new ErrorArgument("Found", found.ToString())
+ };
+ ReportVerificationError(args, error);
+ }
+
+ void VerificationError(VerifierError error, object found, object expected)
+ {
+ if (_currentBasicBlock != null)
+ _currentBasicBlock.IncrementErrorCount();
+
+ var args = new ErrorArgument[]
+ {
+ new ErrorArgument("Offset", _currentInstructionOffset),
+ new ErrorArgument("Found", found.ToString())
+ };
+ ReportVerificationError(args, error);
+ }
+
+ // Check whether the condition is true. If not, report verification error and continue verification.
+ bool Check(bool cond, VerifierError error)
+ {
+ if (!cond)
+ VerificationError(error);
+ return cond;
+ }
+
+ bool Check(bool cond, VerifierError error, StackValue found)
+ {
+ if (!cond)
+ VerificationError(error, found);
+ return cond;
+ }
+
+ bool Check(bool cond, VerifierError error, StackValue found, StackValue expected)
+ {
+ if (!cond)
+ VerificationError(error, found, expected);
+ return cond;
+ }
+
+ void CheckIsNumeric(StackValue value)
+ {
+ if (!Check(StackValueKind.Int32 <= value.Kind && value.Kind <= StackValueKind.Float,
+ VerifierError.ExpectedNumericType, value))
+ {
+ AbortBasicBlockVerification();
+ }
+ }
+
+ void CheckIsInteger(StackValue value)
+ {
+ if (!Check(StackValueKind.Int32 <= value.Kind && value.Kind <= StackValueKind.NativeInt,
+ VerifierError.ExpectedIntegerType, value))
+ {
+ AbortBasicBlockVerification();
+ }
+ }
+
+ void CheckIsIndex(StackValue value)
+ {
+ if (!Check(value.Kind == StackValueKind.Int32 || value.Kind == StackValueKind.NativeInt,
+ VerifierError.StackUnexpected /* TODO: ExpectedIndex */, value))
+ {
+ AbortBasicBlockVerification();
+ }
+ }
+
+ void CheckIsByRef(StackValue value)
+ {
+ if (!Check(value.Kind == StackValueKind.ByRef, VerifierError.StackByRef, value))
+ {
+ AbortBasicBlockVerification();
+ }
+ }
+
+ void CheckIsArray(StackValue value)
+ {
+ Check((value.Kind == StackValueKind.ObjRef) && ((value.Type == null) || value.Type.IsSzArray),
+ VerifierError.ExpectedArray /* , value */);
+ }
+
+ void CheckIsAssignable(StackValue src, StackValue dst)
+ {
+ if (!IsAssignable(src, dst))
+ VerificationError(VerifierError.StackUnexpected, src, dst);
+ }
+
+ private void CheckIsValidLeaveTarget(BasicBlock src, BasicBlock target)
+ {
+ if (!_validTargetOffsets[target.StartOffset])
+ {
+ VerificationError(VerifierError.BadJumpTarget);
+ return;
+ }
+
+ // If the source is within filter, target shall be within the same
+ if (src.FilterIndex.HasValue && src.FilterIndex != target.FilterIndex)
+ {
+ VerificationError(VerifierError.LeaveOutOfFilter);
+ }
+
+ // If the source is within fault handler or finally handler, target shall be within the same
+ if (src.HandlerIndex.HasValue && src.HandlerIndex != target.HandlerIndex)
+ {
+ var regionKind = _exceptionRegions[src.HandlerIndex.Value].ILRegion.Kind;
+ if (regionKind == ILExceptionRegionKind.Fault)
+ VerificationError(VerifierError.LeaveOutOfFault);
+ else if (regionKind == ILExceptionRegionKind.Finally)
+ VerificationError(VerifierError.LeaveOutOfFinally);
+ }
+
+ // If the source is within a try block, target shall be within the same or an enclosing try block
+ // or the first instruction of a disjoint try block
+ // or not within any try block
+ bool invalidLeaveIntoTry = false;
+ if (src.TryIndex.HasValue && src.TryIndex != target.TryIndex)
+ {
+ if (target.TryIndex.HasValue)
+ {
+ ref var srcRegion = ref _exceptionRegions[src.TryIndex.Value].ILRegion;
+ ref var targetRegion = ref _exceptionRegions[target.TryIndex.Value].ILRegion;
+
+ // Target is not enclosing source
+ if (targetRegion.TryOffset > srcRegion.TryOffset ||
+ src.StartOffset >= targetRegion.TryOffset + targetRegion.TryLength)
+ {
+ // Target is not first instruction
+ if (target.StartOffset != targetRegion.TryOffset)
+ {
+ VerificationError(VerifierError.LeaveIntoTry);
+ invalidLeaveIntoTry = true;
+ }
+ else if (srcRegion.TryOffset <= targetRegion.TryOffset &&
+ srcRegion.TryOffset + srcRegion.TryLength > targetRegion.TryOffset) // Source is enclosing target
+ {
+ if (!IsDirectChildRegion(src, target))
+ {
+ VerificationError(VerifierError.LeaveIntoTry);
+ invalidLeaveIntoTry = true;
+ }
+ }
+ else if (!IsDisjointTryBlock(ref targetRegion, ref srcRegion))
+ {
+ VerificationError(VerifierError.LeaveIntoTry);
+ invalidLeaveIntoTry = true;
+ }
+ }
+ }
+ }
+
+ // If the source is within a catch or filtered handler, target shall be within same catch or filtered handler
+ // or within the associated try block
+ // or within a try block enclosing the catch / filtered handler
+ // or the first instruction of a disjoint try block
+ // or not within any try block
+ if (src.HandlerIndex.HasValue && src.HandlerIndex != target.HandlerIndex)
+ {
+ if (target.TryIndex.HasValue)
+ {
+ ref var srcRegion = ref _exceptionRegions[src.HandlerIndex.Value].ILRegion;
+ ref var targetRegion = ref _exceptionRegions[target.TryIndex.Value].ILRegion;
+
+ // If target is not associated try block, and not enclosing srcRegion
+ if (target.TryIndex != src.HandlerIndex &&
+ (targetRegion.TryOffset > srcRegion.HandlerOffset ||
+ targetRegion.TryOffset + targetRegion.TryLength < srcRegion.HandlerOffset))
+ {
+ // If target is not first instruction of try, or not a direct sibling
+ if (target.StartOffset != targetRegion.TryOffset || !IsDisjointTryBlock(ref targetRegion, ref srcRegion))
+ VerificationError(VerifierError.LeaveIntoTry);
+ }
+ }
+ }
+
+ // If the target is within a filter or handler, source shall be within same
+ if (target.HandlerIndex.HasValue && src.HandlerIndex != target.HandlerIndex)
+ {
+ ref var targetRegion = ref _exceptionRegions[target.HandlerIndex.Value].ILRegion;
+ // If target region is not enclosing source
+ if (targetRegion.HandlerOffset > src.StartOffset || targetRegion.HandlerOffset + targetRegion.HandlerLength < src.StartOffset)
+ VerificationError(VerifierError.LeaveIntoHandler);
+ }
+ if (target.FilterIndex.HasValue && src.FilterIndex != target.FilterIndex)
+ {
+ ref var targetRegion = ref _exceptionRegions[target.FilterIndex.Value].ILRegion;
+ var filterLength = targetRegion.HandlerOffset - targetRegion.FilterOffset;
+
+ // If target region is not enclosing source
+ if (targetRegion.FilterOffset > src.StartOffset || targetRegion.FilterOffset + filterLength < src.StartOffset)
+ VerificationError(VerifierError.LeaveIntoFilter);
+ }
+
+ // If the target is within a try block (except first instruction), source shall be within same
+ // or within associated handler
+ if (!invalidLeaveIntoTry && target.TryIndex.HasValue && src.TryIndex != target.TryIndex)
+ {
+ ref var targetRegion = ref _exceptionRegions[target.TryIndex.Value].ILRegion;
+
+ if (target.StartOffset != targetRegion.TryOffset && // Not first instruction
+ (!src.HandlerIndex.HasValue || src.HandlerIndex != target.TryIndex) && // Not associated handler
+ (targetRegion.TryOffset > src.StartOffset || targetRegion.TryOffset + targetRegion.TryLength < src.StartOffset)) // Target region does not enclose source
+ VerificationError(VerifierError.LeaveIntoTry);
+ }
+ }
+
+ bool IsValidBranchTarget(BasicBlock src, BasicBlock target, bool isFallthrough, bool reportErrors = true)
+ {
+ if (!_validTargetOffsets[target.StartOffset])
+ {
+ if (reportErrors)
+ VerificationError(VerifierError.BadJumpTarget);
+ return false;
+ }
+
+ bool isValid = true;
+
+ if (src.TryIndex != target.TryIndex)
+ {
+ if (src.TryIndex == null)
+ {
+ // Branching to first instruction of try-block is valid
+ if (target.StartOffset != _exceptionRegions[target.TryIndex.Value].ILRegion.TryOffset || !IsDirectChildRegion(src, target))
+ {
+ if (reportErrors)
+ {
+ Debug.Assert(!isFallthrough); // This should not be reachable by fallthrough
+ VerificationError(VerifierError.BranchIntoTry);
+ }
+ isValid = false;
+ }
+ }
+ else if (target.TryIndex == null)
+ {
+ if (reportErrors)
+ {
+ if (isFallthrough)
+ VerificationError(VerifierError.FallthroughException);
+ else
+ VerificationError(VerifierError.BranchOutOfTry);
+ }
+ isValid = false;
+ }
+ else
+ {
+ ref var srcRegion = ref _exceptionRegions[src.TryIndex.Value].ILRegion;
+ ref var targetRegion = ref _exceptionRegions[target.TryIndex.Value].ILRegion;
+ // If target is inside source region
+ if (srcRegion.TryOffset <= targetRegion.TryOffset &&
+ target.StartOffset < srcRegion.TryOffset + srcRegion.TryLength)
+ {
+ // Only branching to first instruction of try-block is valid
+ if (target.StartOffset != targetRegion.TryOffset || !IsDirectChildRegion(src, target))
+ {
+ if (reportErrors)
+ {
+ Debug.Assert(!isFallthrough); // This should not be reachable by fallthrough
+ VerificationError(VerifierError.BranchIntoTry);
+ }
+ isValid = false;
+ }
+ }
+ else
+ {
+ if (reportErrors)
+ {
+ if (isFallthrough)
+ VerificationError(VerifierError.FallthroughException);
+ else
+ VerificationError(VerifierError.BranchOutOfTry);
+ }
+ isValid = false;
+ }
+ }
+ }
+
+ if (src.FilterIndex != target.FilterIndex)
+ {
+ if (src.FilterIndex == null)
+ {
+ if (reportErrors)
+ {
+ if (isFallthrough)
+ VerificationError(VerifierError.FallthroughIntoFilter);
+ else
+ VerificationError(VerifierError.BranchIntoFilter);
+ }
+ isValid = false;
+ }
+ else if (target.HandlerIndex == null)
+ {
+ if (reportErrors)
+ {
+ if (isFallthrough)
+ VerificationError(VerifierError.FallthroughException);
+ else
+ VerificationError(VerifierError.BranchOutOfFilter);
+ }
+ isValid = false;
+ }
+ else
+ {
+ ref var srcRegion = ref _exceptionRegions[src.FilterIndex.Value].ILRegion;
+ ref var targetRegion = ref _exceptionRegions[target.FilterIndex.Value].ILRegion;
+ if (srcRegion.FilterOffset <= targetRegion.FilterOffset)
+ {
+ if (reportErrors)
+ {
+ if (isFallthrough)
+ VerificationError(VerifierError.FallthroughIntoFilter);
+ else
+ VerificationError(VerifierError.BranchIntoFilter);
+ }
+ isValid = false;
+ }
+ else
+ {
+ if (reportErrors)
+ {
+ if (isFallthrough)
+ VerificationError(VerifierError.FallthroughException);
+ else
+ VerificationError(VerifierError.BranchOutOfFilter);
+ }
+ isValid = false;
+ }
+ }
+ }
+
+ if (src.HandlerIndex != target.HandlerIndex)
+ {
+ if (src.HandlerIndex == null)
+ {
+ if (reportErrors)
+ {
+ if (isFallthrough)
+ VerificationError(VerifierError.FallthroughIntoHandler);
+ else
+ VerificationError(VerifierError.BranchIntoHandler);
+ }
+ isValid = false;
+ }
+ else if (target.HandlerIndex == null)
+ {
+ if (reportErrors)
+ {
+ if (isFallthrough)
+ VerificationError(VerifierError.FallthroughException);
+ else
+ {
+ if (_exceptionRegions[src.HandlerIndex.Value].ILRegion.Kind == ILExceptionRegionKind.Finally)
+ VerificationError(VerifierError.BranchOutOfFinally);
+ else
+ VerificationError(VerifierError.BranchOutOfHandler);
+ }
+ }
+ isValid = false;
+ }
+ else
+ {
+ ref var srcRegion = ref _exceptionRegions[src.HandlerIndex.Value].ILRegion;
+ ref var targetRegion = ref _exceptionRegions[target.HandlerIndex.Value].ILRegion;
+ if (srcRegion.HandlerOffset <= targetRegion.HandlerOffset)
+ {
+ if (reportErrors)
+ {
+ if (isFallthrough)
+ VerificationError(VerifierError.FallthroughIntoHandler);
+ else
+ VerificationError(VerifierError.BranchIntoHandler);
+ }
+ isValid = false;
+ }
+ else
+ {
+ if (reportErrors)
+ {
+ if (isFallthrough)
+ VerificationError(VerifierError.FallthroughException);
+ else
+ {
+ if (srcRegion.Kind == ILExceptionRegionKind.Finally)
+ VerificationError(VerifierError.BranchOutOfFinally);
+ else
+ VerificationError(VerifierError.BranchOutOfHandler);
+ }
+ }
+ isValid = false;
+ }
+ }
+ }
+
+ return isValid;
+ }
+
+ /// <summary>
+ /// Checks whether the given enclosed try block is a direct child try-region of
+ /// the given enclosing try block.
+ /// </summary>
+ /// <param name="enclosingBlock">The block enclosing the try block given by <paramref name="enclosedBlock"/>.</param>
+ /// <param name="enclosedBlock">The block to check whether it is a direct child try-region of <paramref name="enclosingBlock"/>.</param>
+ /// <returns>True if <paramref name="enclosedBlock"/> is a direct child try region of <paramref name="enclosingBlock"/>.</returns>
+ bool IsDirectChildRegion(BasicBlock enclosingBlock, BasicBlock enclosedBlock)
+ {
+ ref var enclosedRegion = ref _exceptionRegions[enclosedBlock.TryIndex.Value].ILRegion;
+
+ // Walk from enclosed try start backwards and check each BasicBlock whether it is a try-start
+ for (int i = enclosedRegion.TryOffset - 1; i > enclosingBlock.StartOffset; --i)
+ {
+ var block = _basicBlocks[i];
+ if (block == null)
+ continue;
+
+ if (block.TryStart && block.TryIndex != enclosingBlock.TryIndex)
+ {
+ ref var blockRegion = ref _exceptionRegions[block.TryIndex.Value].ILRegion;
+ // blockRegion is actually enclosing enclosedRegion
+ if (blockRegion.TryOffset + blockRegion.TryLength > enclosedRegion.TryOffset)
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Checks whether the try block <paramref name="disjoint"/> is a disjoint try block relative to <paramref name="source"/>.
+ /// </summary>
+ /// <returns>True if <paramref name="disjoint"/> is a disjoint try block relative to <paramref name="source"/>.</returns>
+ bool IsDisjointTryBlock(ref ILExceptionRegion disjoint, ref ILExceptionRegion source)
+ {
+ if (source.TryOffset <= disjoint.TryOffset && source.TryOffset + source.TryLength >= disjoint.TryOffset + disjoint.TryLength)
+ {
+ // source is enclosing disjoint
+ return false;
+ }
+
+ // Walk from disjoint region backwards and check for enclosing exception regions.
+ for (int i = disjoint.TryOffset - 1; i >= 0; --i)
+ {
+ var block = _basicBlocks[i];
+ if (block == null)
+ continue;
+
+ if (block.TryStart)
+ {
+ ref var blockRegion = ref _exceptionRegions[block.TryIndex.Value].ILRegion;
+ // blockRegion is enclosing disjoint, but not source
+ if (blockRegion.TryOffset + blockRegion.TryLength > disjoint.TryOffset &&
+ (blockRegion.TryOffset > source.TryOffset || blockRegion.TryOffset + blockRegion.TryLength <= source.TryOffset))
+ return false;
+ }
+
+ if (block.HandlerStart)
+ {
+ ref var blockRegion = ref _exceptionRegions[block.HandlerIndex.Value].ILRegion;
+ // blockRegion is enclosing secondRegion, but not source
+ if (blockRegion.HandlerOffset + blockRegion.HandlerLength > disjoint.TryOffset &&
+ (blockRegion.HandlerOffset > source.TryOffset || blockRegion.HandlerOffset + blockRegion.HandlerLength <= source.TryOffset))
+ return false;
+ }
+
+ if (block.FilterStart)
+ {
+ ref var blockRegion = ref _exceptionRegions[block.FilterIndex.Value].ILRegion;
+ // blockRegion is enclosing secondRegion, but not source
+ var filterLength = blockRegion.HandlerOffset - blockRegion.FilterOffset;
+ if (blockRegion.FilterOffset + filterLength > disjoint.TryOffset &&
+ (blockRegion.FilterOffset > source.TryOffset || blockRegion.FilterOffset + filterLength <= source.TryOffset))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // For now, match PEVerify type formating to make it easy to compare with baseline
+ static string TypeToStringForIsAssignable(TypeDesc type)
+ {
+ switch (type.Category)
+ {
+ case TypeFlags.Boolean: return "Boolean";
+ case TypeFlags.Char: return "Char";
+ case TypeFlags.SByte:
+ case TypeFlags.Byte: return "Byte";
+ case TypeFlags.Int16:
+ case TypeFlags.UInt16: return "Short";
+ case TypeFlags.Int32:
+ case TypeFlags.UInt32: return "Int32";
+ case TypeFlags.Int64:
+ case TypeFlags.UInt64: return "Long";
+ case TypeFlags.Single: return "Single";
+ case TypeFlags.Double: return "Double";
+ case TypeFlags.IntPtr:
+ case TypeFlags.UIntPtr: return "Native Int";
+ }
+
+ return StackValue.CreateFromType(type).ToString();
+ }
+
+ void CheckIsAssignable(TypeDesc src, TypeDesc dst)
+ {
+ if (!IsAssignable(src, dst))
+ {
+ VerificationError(VerifierError.StackUnexpected, TypeToStringForIsAssignable(src), TypeToStringForIsAssignable(dst));
+ }
+ }
+
+ void CheckIsArrayElementCompatibleWith(TypeDesc src, TypeDesc dst)
+ {
+ if (!IsAssignable(src, dst, true))
+ {
+ // TODO: Better error message
+ VerificationError(VerifierError.StackUnexpected, TypeToStringForIsAssignable(src));
+ }
+ }
+
+ void CheckIsPointerElementCompatibleWith(TypeDesc src, TypeDesc dst)
+ {
+ if (!(src == dst || IsSameReducedType(src, dst)))
+ {
+ // TODO: Better error message
+ // VerificationError(VerifierError.StackUnexpected, TypeToStringForIsAssignable(src), TypeToStringForIsAssignable(dst));
+ VerificationError(VerifierError.StackUnexpectedArrayType, TypeToStringForIsAssignable(src));
+ }
+ }
+
+ void CheckIsObjRef(TypeDesc type)
+ {
+ if (!IsAssignable(type, GetWellKnownType(WellKnownType.Object), false))
+ {
+ // TODO: Better error message
+ VerificationError(VerifierError.StackUnexpected, TypeToStringForIsAssignable(type));
+ }
+ }
+
+ void CheckIsObjRef(StackValue value)
+ {
+ if (value.Kind != StackValueKind.ObjRef)
+ VerificationError(VerifierError.StackObjRef, value);
+ }
+
+ private void CheckIsNotPointer(TypeDesc type)
+ {
+ if (type.IsPointer)
+ VerificationError(VerifierError.UnmanagedPointer);
+ }
+
+ void CheckIsComparable(StackValue a, StackValue b, ILOpcode op)
+ {
+ if (!IsBinaryComparable(a, b, op))
+ {
+ VerificationError(VerifierError.StackUnexpected, a, b);
+ }
+ }
+
+ void CheckDelegateCreation(StackValue ftn, StackValue obj)
+ {
+ if (!_delegateCreateStart.HasValue)
+ {
+ VerificationError(VerifierError.DelegatePattern);
+ return;
+ }
+
+ int delegateStart = _delegateCreateStart.Value;
+
+ if (_currentInstructionOffset - delegateStart == 6) // ldftn <tok> takes 6 bytes
+ {
+ if (GetOpcodeAt(delegateStart) != ILOpcode.ldftn)
+ {
+ VerificationError(VerifierError.DelegatePattern);
+ return;
+ }
+ else
+ {
+ // See "Rules for non-virtual call to a non-final virtual method" in ImportCall
+ if (ftn.Method.IsVirtual && !ftn.Method.IsFinal && !obj.IsBoxedValueType)
+ {
+ var methodTypeDef = ftn.Method.OwningType.GetTypeDefinition() as MetadataType; // Method is always considered final if owning type is sealed
+ if (methodTypeDef == null || !methodTypeDef.IsSealed)
+ Check(obj.IsThisPtr && !_modifiesThisPtr, VerifierError.LdftnNonFinalVirtual);
+ }
+ }
+ }
+ else if (_currentInstructionOffset - _delegateCreateStart == 7) // dup, ldvirtftn <tok> takes 7 bytes
+ {
+ if (GetOpcodeAt(delegateStart) != ILOpcode.dup ||
+ GetOpcodeAt(delegateStart + 1) != ILOpcode.ldvirtftn)
+ {
+ VerificationError(VerifierError.DelegatePattern);
+ return;
+ }
+ }
+ else
+ VerificationError(VerifierError.DelegatePattern);
+ }
+
+ void CheckIsDelegateAssignable(MethodDesc ftn, TypeDesc delegateType)
+ {
+ if (!IsDelegateAssignable(ftn, delegateType))
+ VerificationError(VerifierError.DelegateCtor);
+ }
+
+ bool IsDelegateAssignable(MethodDesc ftn, TypeDesc delegateType)
+ {
+ var invokeMethod = delegateType.GetMethod("Invoke", null);
+ if (invokeMethod == null)
+ return false;
+
+ var ftnSignature = ftn.Signature;
+ var delegateSignature = invokeMethod.Signature;
+
+ // Compare calling convention ignoring distinction between static and instance
+ if ((ftnSignature.Flags & ~MethodSignatureFlags.Static) != (delegateSignature.Flags & ~MethodSignatureFlags.Static))
+ return false;
+
+ // Compare signature parameters
+ if (ftnSignature.Length != delegateSignature.Length)
+ return false;
+
+ for (int i = 0; i < ftnSignature.Length; i++)
+ {
+ if (!IsAssignable(delegateSignature[i], ftnSignature[i]))
+ return false;
+ }
+
+ // Compare return type
+ return IsAssignable(ftnSignature.ReturnType, delegateSignature.ReturnType);
+ }
+
+ ILOpcode GetOpcodeAt(int instructionOffset)
+ {
+ var opCode = (ILOpcode)_ilBytes[instructionOffset];
+ if (opCode == ILOpcode.prefix1)
+ opCode = (ILOpcode)(0x100 + _ilBytes[instructionOffset + 1]);
+
+ return opCode;
+ }
+
+ void Unverifiable()
+ {
+ VerificationError(VerifierError.Unverifiable);
+ }
+
+ TypeDesc GetWellKnownType(WellKnownType wellKnownType)
+ {
+ return _typeSystemContext.GetWellKnownType(wellKnownType);
+ }
+
+ void HandleTokenResolveException(int token)
+ {
+ var args = new ErrorArgument[]
+ {
+ new ErrorArgument("Offset", _currentInstructionOffset),
+ new ErrorArgument("Token", token)
+ };
+ ReportVerificationError(args, VerifierError.TokenResolve);
+ AbortBasicBlockVerification();
+ }
+
+ Object ResolveToken(int token)
+ {
+ Object tokenObj = null;
+ try
+ {
+ tokenObj = _methodIL.GetObject(token);
+ }
+ catch (BadImageFormatException)
+ {
+ HandleTokenResolveException(token);
+ }
+ catch (ArgumentException)
+ {
+ HandleTokenResolveException(token);
+ }
+ return tokenObj;
+ }
+
+ TypeDesc ResolveTypeToken(int token)
+ {
+ object tokenObj = ResolveToken(token);
+ FatalCheck(tokenObj is TypeDesc, VerifierError.ExpectedTypeToken);
+ return (TypeDesc)tokenObj;
+ }
+
+ FieldDesc ResolveFieldToken(int token)
+ {
+ object tokenObj = ResolveToken(token);
+ FatalCheck(tokenObj is FieldDesc, VerifierError.ExpectedFieldToken);
+ return (FieldDesc)tokenObj;
+ }
+
+ MethodDesc ResolveMethodToken(int token)
+ {
+ object tokenObj = ResolveToken(token);
+ FatalCheck(tokenObj is MethodDesc, VerifierError.ExpectedMethodToken);
+ return (MethodDesc)tokenObj;
+ }
+
+ void MarkInstructionBoundary()
+ {
+ _instructionBoundaries[_currentOffset] = true;
+ }
+
+ void StartImportingInstruction()
+ {
+ _currentInstructionOffset = _currentOffset;
+ }
+
+ void EndImportingInstruction()
+ {
+ CheckPendingPrefix(_pendingPrefix);
+ ClearPendingPrefix(_pendingPrefix); // Make sure prefix is cleared
+ }
+
+ void StartImportingBasicBlock(BasicBlock basicBlock)
+ {
+ _delegateCreateStart = null;
+ _isThisInitialized = basicBlock.IsThisInitialized;
+
+ if (basicBlock.TryStart)
+ {
+ Check(basicBlock.EntryStack == null || basicBlock.EntryStack.Length == 0, VerifierError.TryNonEmptyStack);
+
+ for (int i = 0; i < _exceptionRegions.Length; i++)
+ {
+ var r = _exceptionRegions[i];
+
+ if (basicBlock.StartOffset != r.ILRegion.TryOffset)
+ continue;
+
+ if (r.ILRegion.Kind == ILExceptionRegionKind.Filter)
+ {
+ var filterBlock = _basicBlocks[r.ILRegion.FilterOffset];
+ PropagateThisState(basicBlock, filterBlock);
+ MarkBasicBlock(filterBlock);
+ }
+
+ var handlerBlock = _basicBlocks[r.ILRegion.HandlerOffset];
+ PropagateThisState(basicBlock, handlerBlock);
+ MarkBasicBlock(handlerBlock);
+ }
+ }
+
+ if (basicBlock.FilterStart || basicBlock.HandlerStart)
+ {
+ ExceptionRegion r;
+ if (basicBlock.HandlerIndex.HasValue)
+ {
+ r = _exceptionRegions[basicBlock.HandlerIndex.Value];
+ }
+ else if (basicBlock.FilterIndex.HasValue)
+ {
+ r = _exceptionRegions[basicBlock.FilterIndex.Value];
+ }
+ else
+ {
+ Debug.Fail("Block marked as filter / handler start but no filter / handler index set.");
+ return;
+ }
+
+ if (r.ILRegion.Kind == ILExceptionRegionKind.Filter || r.ILRegion.Kind == ILExceptionRegionKind.Catch)
+ {
+ // stack must uninit or 1 (exception object)
+ Check(basicBlock.EntryStack == null || basicBlock.EntryStack.Length == 1, VerifierError.FilterOrCatchUnexpectedStack);
+
+ if (basicBlock.EntryStack == null)
+ basicBlock.EntryStack = new StackValue[1];
+
+ if (r.ILRegion.Kind == ILExceptionRegionKind.Filter)
+ {
+ basicBlock.EntryStack[0] = StackValue.CreateObjRef(GetWellKnownType(WellKnownType.Object));
+ }
+ else
+ if (r.ILRegion.Kind == ILExceptionRegionKind.Catch)
+ {
+ var exceptionType = ResolveTypeToken(r.ILRegion.ClassToken);
+ Check(!exceptionType.IsByRef, VerifierError.CatchByRef);
+ basicBlock.EntryStack[0] = StackValue.CreateObjRef(exceptionType);
+ }
+ }
+ else
+ {
+ // stack must be uninit or empty
+ Check(basicBlock.EntryStack == null || basicBlock.EntryStack.Length == 0, VerifierError.FinOrFaultNonEmptyStack);
+ if (basicBlock.EntryStack == null)
+ basicBlock.EntryStack = s_emptyStack;
+ }
+ }
+
+ if (basicBlock.EntryStack?.Length > 0)
+ {
+ if (!basicBlock.TryStart && !basicBlock.HandlerStart && !basicBlock.FilterStart)
+ {
+ // ECMA III 1.7.5 Backward Branch Constraints
+ // if stack is not empty at beginning of this block,
+ // there must exist a predecessor block with lower IL offset.
+ Check(basicBlock.HasPredecessorWithLowerOffset, VerifierError.BackwardBranch);
+ }
+
+ // Copy stack state
+ if (_stack == null || _stack.Length < basicBlock.EntryStack.Length)
+ Array.Resize(ref _stack, basicBlock.EntryStack.Length);
+ Array.Copy(basicBlock.EntryStack, _stack, basicBlock.EntryStack.Length);
+ _stackTop = basicBlock.EntryStack.Length;
+ }
+ else
+ {
+ _stackTop = 0;
+ }
+ }
+
+ void EndImportingBasicBlock(BasicBlock basicBlock)
+ {
+ basicBlock.State = BasicBlock.ImportState.WasVerified;
+ }
+
+ void ImportNop()
+ {
+ // Always verifiable
+ }
+
+ void ImportBreak()
+ {
+ // Always verifiable
+ }
+
+ TypeDesc GetVarType(int index, bool argument)
+ {
+ if (argument)
+ {
+ if (_thisType != null)
+ {
+ if (index == 0)
+ return _thisType;
+ index--;
+ }
+ FatalCheck(index < _methodSignature.Length, VerifierError.UnrecognizedArgumentNumber);
+ return _methodSignature[index];
+ }
+ else
+ {
+ FatalCheck(index < _locals.Length, VerifierError.UnrecognizedLocalNumber);
+ return _locals[index].Type;
+ }
+ }
+
+ void ImportLoadVar(int index, bool argument)
+ {
+ var varType = GetVarType(index, argument);
+
+ if (!argument)
+ Check(_initLocals, VerifierError.InitLocals);
+
+ CheckIsNotPointer(varType);
+
+ var stackValue = StackValue.CreateFromType(varType);
+ if (index == 0 && argument && _thisType != null)
+ {
+ Debug.Assert(varType == _thisType);
+ stackValue.SetIsThisPtr();
+ }
+
+ Push(stackValue);
+ }
+
+ void ImportStoreVar(int index, bool argument)
+ {
+ var varType = GetVarType(index, argument);
+
+ var value = Pop();
+
+ if (_trackObjCtorState && !_isThisInitialized)
+ Check(index != 0 || !argument, VerifierError.ThisUninitStore);
+
+ CheckIsAssignable(value, StackValue.CreateFromType(varType));
+ }
+
+ void ImportAddressOfVar(int index, bool argument)
+ {
+ var varType = GetVarType(index, argument);
+
+ if (!argument)
+ Check(_initLocals, VerifierError.InitLocals);
+
+ Check(!varType.IsByRef, VerifierError.ByrefOfByref);
+
+ var stackValue = StackValue.CreateByRef(varType);
+ if (index == 0 && argument && _thisType != null)
+ {
+ Debug.Assert(varType == _thisType);
+ stackValue.SetIsThisPtr();
+
+ Check(!_trackObjCtorState || _isThisInitialized, VerifierError.ThisUninitStore);
+ }
+
+ Push(stackValue);
+ }
+
+ void ImportDup()
+ {
+ var value = Pop(allowUninitThis: true);
+
+ // this could be the beginning of a delegate create
+ _delegateCreateStart = _currentInstructionOffset;
+
+ Push(value);
+ Push(value);
+ }
+
+ void ImportPop()
+ {
+ Pop(allowUninitThis: true);
+ }
+
+ void ImportJmp(int token)
+ {
+ Unverifiable();
+
+ var method = ResolveMethodToken(token);
+ }
+
+ void ImportCasting(ILOpcode opcode, int token)
+ {
+ var type = ResolveTypeToken(token);
+
+ var value = Pop();
+
+ CheckIsObjRef(value);
+
+ Check(_method.OwningType.CanAccess(type), VerifierError.TypeAccess);
+
+ Push(StackValue.CreateObjRef(type));
+ }
+
+ void ImportCall(ILOpcode opcode, int token)
+ {
+ FatalCheck(opcode != ILOpcode.calli, VerifierError.Unverifiable);
+
+ TypeDesc constrained = null;
+ bool tailCall = false;
+
+ if (opcode != ILOpcode.newobj)
+ {
+ if (HasPendingPrefix(Prefix.Constrained) && opcode == ILOpcode.callvirt)
+ {
+ ClearPendingPrefix(Prefix.Constrained);
+ constrained = _constrained;
+ }
+
+ if (HasPendingPrefix(Prefix.Tail))
+ {
+ ClearPendingPrefix(Prefix.Tail);
+ tailCall = true;
+ }
+ }
+
+ // TODO: VarArgs
+ // if (sig.isVarArg())
+ // eeGetCallSiteSig(memberRef, getCurrentModuleHandle(), getCurrentContext(), &sig, false);
+
+ MethodDesc method = ResolveMethodToken(token);
+
+ MethodSignature sig = method.Signature;
+
+ TypeDesc methodType = sig.IsStatic ? null : method.OwningType;
+
+ if (opcode == ILOpcode.callvirt)
+ {
+ Check(methodType != null, VerifierError.CallVirtOnStatic);
+ Check(!methodType.IsValueType, VerifierError.CallVirtOnValueType);
+ }
+ else if (opcode != ILOpcode.newobj)
+ {
+ EcmaMethod ecmaMethod = method.GetTypicalMethodDefinition() as EcmaMethod;
+ if (ecmaMethod != null)
+ Check(!ecmaMethod.IsAbstract, VerifierError.CallAbstract);
+ }
+
+ if (opcode == ILOpcode.newobj && methodType.IsDelegate)
+ {
+ Check(sig.Length == 2, VerifierError.DelegateCtor);
+ var declaredObj = StackValue.CreateFromType(sig[0]);
+ var declaredFtn = StackValue.CreateFromType(sig[1]);
+
+ Check(declaredFtn.Kind == StackValueKind.NativeInt, VerifierError.DelegateCtorSigI, declaredFtn);
+
+ var actualFtn = Pop();
+ var actualObj = Pop();
+
+ Check(actualFtn.IsMethod, VerifierError.StackMethod);
+
+ CheckIsAssignable(actualObj, declaredObj);
+ Check(actualObj.Kind == StackValueKind.ObjRef, VerifierError.DelegateCtorSigO, actualObj);
+
+ CheckDelegateCreation(actualFtn, actualObj);
+
+ CheckIsDelegateAssignable(actualFtn.Method, methodType);
+ }
+ else
+ {
+ for (int i = sig.Length - 1; i >= 0; i--)
+ {
+ var actual = Pop(allowUninitThis: true);
+ var declared = StackValue.CreateFromType(sig[i]);
+
+ CheckIsAssignable(actual, declared);
+
+ // check that the argument is not a byref for tailcalls
+ if (tailCall)
+ Check(!IsByRefLike(declared), VerifierError.TailByRef, declared);
+ }
+ }
+
+ TypeDesc instance = null;
+
+ if (opcode == ILOpcode.newobj)
+ {
+ Check(method.IsConstructor, VerifierError.CtorExpected);
+ if (sig.IsStatic || methodType == null || method.IsAbstract)
+ {
+ VerificationError(VerifierError.CtorSig);
+ }
+ else
+ {
+ if (methodType.IsArray)
+ {
+ var arrayType = (ArrayType)methodType;
+ Check(!IsByRefLike(StackValue.CreateFromType(arrayType.ElementType)), VerifierError.ArrayByRef);
+ }
+ else
+ {
+ var metadataType = (MetadataType)methodType;
+ Check(!metadataType.IsAbstract, VerifierError.NewobjAbstractClass);
+ }
+ }
+ }
+ else
+ if (methodType != null)
+ {
+ var actualThis = Pop(allowUninitThis: true);
+ instance = actualThis.Type;
+ var declaredThis = methodType.IsValueType ?
+ StackValue.CreateByRef(methodType) : StackValue.CreateObjRef(methodType);
+
+ // If this is a call to the base class .ctor, set thisPtr Init for this block.
+ if (method.IsConstructor)
+ {
+ if (_trackObjCtorState && actualThis.IsThisPtr &&
+ (methodType == _thisType || methodType == _thisType.BaseType)) // Call to overloaded ctor or base ctor
+ {
+ _isThisInitialized = true;
+ }
+ else
+ {
+ // Allow direct calls to value type constructors
+ Check(actualThis.Kind == StackValueKind.ByRef && actualThis.Type.IsValueType, VerifierError.CallCtor);
+ }
+ }
+
+ if (constrained != null)
+ {
+ Check(actualThis.Kind == StackValueKind.ByRef, VerifierError.ConstrainedCallWithNonByRefThis);
+
+ // We just dereference this and test for equality
+ //todo: improve error - "this type mismatch with constrained type operand"
+ Check(actualThis.Type == constrained, VerifierError.StackUnexpected);
+
+ // Now pretend the this type is the boxed constrained type, for the sake of subsequent checks
+ actualThis = StackValue.CreateObjRef(constrained);
+ }
+
+ // To support direct calls on readonly byrefs, just pretend declaredThis is readonly too
+ if(declaredThis.Kind == StackValueKind.ByRef && (actualThis.Kind == StackValueKind.ByRef && actualThis.IsReadOnly))
+ {
+ declaredThis.SetIsReadOnly();
+ }
+ CheckIsAssignable(actualThis, declaredThis);
+
+ if (opcode == ILOpcode.call)
+ {
+ // Rules for non-virtual call to a non-final virtual method (ECMA III.3.19: Verifiability of 'call'):
+
+ // Define:
+ // The "this" pointer is considered to be "possibly written" if
+ // 1. Its address have been taken (LDARGA 0) anywhere in the method.
+ // (or)
+ // 2. It has been stored to (STARG.0) anywhere in the method.
+
+ // A non-virtual call to a non-final virtual method is only allowed if
+ // 1. The this pointer passed to the callee is an instance of a boxed value type.
+ // (or)
+ // 2. The this pointer passed to the callee is the current method's this pointer.
+ // (and) The current method's this pointer is not "possibly written".
+
+ // Thus the rule is that if you assign to this ANYWHERE you can't make "base" calls to
+ // virtual methods. (Luckily this does not affect .ctors, since they are not virtual).
+ // This is stronger than is strictly needed, but implementing a laxer rule is significantly
+ // harder and more error prone.
+ if (method.IsVirtual && !method.IsFinal && !actualThis.IsBoxedValueType)
+ {
+ var methodTypeDef = methodType.GetTypeDefinition() as MetadataType; // Method is always considered final if owning type is sealed
+ if (methodTypeDef == null || !methodTypeDef.IsSealed)
+ Check(actualThis.IsThisPtr && !_modifiesThisPtr, VerifierError.ThisMismatch);
+ }
+ }
+
+ if (tailCall)
+ {
+ // also check the special tailcall rule
+ Check(!IsByRefLike(declaredThis), VerifierError.TailByRef, declaredThis);
+
+ // Tail calls on constrained calls should be illegal too:
+ // when instantiated at a value type, a constrained call may pass the address of a stack allocated value
+ Check(constrained == null, VerifierError.TailByRef);
+ }
+ }
+
+ // Check any constraints on the callee's class and type parameters
+ if (!method.OwningType.CheckConstraints())
+ VerificationError(VerifierError.UnsatisfiedMethodParentInst, method.OwningType);
+ else if (!method.CheckConstraints())
+ VerificationError(VerifierError.UnsatisfiedMethodInst, method);
+
+ Check(_method.OwningType.CanAccess(method, instance), VerifierError.MethodAccess);
+
+ TypeDesc returnType = sig.ReturnType;
+
+ // special checks for tailcalls
+ if (tailCall)
+ {
+ TypeDesc callerReturnType = _methodSignature.ReturnType;
+
+ if (returnType.IsVoid || callerReturnType.IsVoid)
+ {
+ Check(returnType.IsVoid && callerReturnType.IsVoid, VerifierError.TailRetVoid);
+ }
+ // else
+ // if (returnType.IsValueType || callerReturnType.IsValueType)
+ // {
+ // TODO: Check exact match
+ // }
+ else
+ {
+ var retStackType = StackValue.CreateFromType(returnType);
+ var callerRetStackType = StackValue.CreateFromType(callerReturnType);
+ Check(IsAssignable(retStackType, callerRetStackType), VerifierError.TailRetType, retStackType, callerRetStackType);
+ }
+
+ // for tailcall, stack must be empty
+ Check(_stackTop == 0, VerifierError.TailStackEmpty);
+
+ // The instruction following a tail.call shall be a ret
+ Check(_currentOffset < _ilBytes.Length && (ILOpcode)_ilBytes[_currentOffset] == ILOpcode.ret, VerifierError.TailRet);
+ }
+
+ // now push on the result
+ if (opcode == ILOpcode.newobj)
+ {
+ Push(StackValue.CreateFromType(methodType));
+ }
+ else
+ if (!returnType.IsVoid)
+ {
+ var returnValue = StackValue.CreateFromType(returnType);
+
+ // "readonly." prefixed calls only allowed for the Address operation on arrays.
+ // The methods supported by array types are under the control of the EE
+ // so we can trust that only the Address operation returns a byref.
+ if (HasPendingPrefix(Prefix.ReadOnly))
+ {
+ if (method.OwningType.IsArray && sig.ReturnType.IsByRef)
+ returnValue.SetIsReadOnly();
+ else
+ VerificationError(VerifierError.ReadonlyUnexpectedCallee);
+
+ ClearPendingPrefix(Prefix.ReadOnly);
+ }
+
+ if (returnValue.Kind == StackValueKind.ByRef)
+ returnValue.SetIsPermanentHome();
+
+ Push(returnValue);
+ }
+ }
+
+ void ImportCalli(int token)
+ {
+ throw new NotImplementedException($"{nameof(ImportCalli)} not implemented");
+ }
+
+ void ImportLdFtn(int token, ILOpcode opCode)
+ {
+ MethodDesc method = ResolveMethodToken(token);
+ Check(!method.IsConstructor, VerifierError.LdftnCtor);
+
+#if false
+ if (sig.hasTypeArg())
+ NO_WAY("Currently do not support LDFTN of Parameterized functions");
+#endif
+
+ TypeDesc instance;
+
+ if (opCode == ILOpcode.ldftn)
+ {
+ _delegateCreateStart = _currentInstructionOffset;
+
+ instance = null;
+ }
+ else if (opCode == ILOpcode.ldvirtftn)
+ {
+ Check(!method.Signature.IsStatic, VerifierError.LdvirtftnOnStatic);
+
+ StackValue declaredType;
+ if (method.OwningType.IsValueType)
+ {
+ // Box value type for comparison
+ declaredType = StackValue.CreateObjRef(method.OwningType);
+ }
+ else
+ declaredType = StackValue.CreateFromType(method.OwningType);
+
+ var thisPtr = Pop();
+ instance = thisPtr.Type;
+
+ CheckIsObjRef(thisPtr);
+ CheckIsAssignable(thisPtr, declaredType);
+ }
+ else
+ {
+ Debug.Fail("Unexpected ldftn opcode: " + opCode.ToString());
+ return;
+ }
+
+ // Check any constraints on the callee's class and type parameters
+ if (!method.OwningType.CheckConstraints())
+ VerificationError(VerifierError.UnsatisfiedMethodParentInst, method.OwningType);
+ else if (!method.CheckConstraints())
+ VerificationError(VerifierError.UnsatisfiedMethodInst, method);
+
+ Check(_method.OwningType.CanAccess(method, instance), VerifierError.MethodAccess);
+
+ Push(StackValue.CreateMethod(method));
+ }
+
+ void ImportLoadInt(long value, StackValueKind kind)
+ {
+ Push(StackValue.CreatePrimitive(kind));
+ }
+
+ void ImportLoadFloat(double value)
+ {
+ Push(StackValue.CreatePrimitive(StackValueKind.Float));
+ }
+
+ void ImportLoadNull()
+ {
+ Push(StackValue.CreateObjRef(null));
+ }
+
+ void ImportReturn()
+ {
+ // 'this' must be init before return, unless System.Object
+ if (_trackObjCtorState)
+ Check(_isThisInitialized || _thisType.IsObject, VerifierError.ThisUninitReturn);
+
+ // Check current region type
+ Check(_currentBasicBlock.FilterIndex == null, VerifierError.ReturnFromFilter);
+ Check(_currentBasicBlock.TryIndex == null, VerifierError.ReturnFromTry);
+ Check(_currentBasicBlock.HandlerIndex == null, VerifierError.ReturnFromHandler);
+
+ var declaredReturnType = _method.Signature.ReturnType;
+
+ if (declaredReturnType.IsVoid)
+ {
+ Debug.Assert(_stackTop >= 0);
+
+ if (_stackTop > 0)
+ VerificationError(VerifierError.ReturnVoid, _stack[_stackTop - 1]);
+ }
+ else
+ {
+ if (_stackTop <= 0)
+ VerificationError(VerifierError.ReturnMissing);
+ else
+ {
+ Check(_stackTop == 1, VerifierError.ReturnEmpty);
+
+ var actualReturnType = Pop();
+ CheckIsAssignable(actualReturnType, StackValue.CreateFromType(declaredReturnType));
+
+ Check((!declaredReturnType.IsByRef && !declaredReturnType.IsByRefLike) || actualReturnType.IsPermanentHome, VerifierError.ReturnPtrToStack);
+ }
+ }
+ }
+
+ void ImportFallthrough(BasicBlock next)
+ {
+ PropagateControlFlow(next, isFallthrough: true);
+ }
+
+ void PropagateThisState(BasicBlock current, BasicBlock next)
+ {
+ if (next.State == BasicBlock.ImportState.Unmarked)
+ next.IsThisInitialized = _isThisInitialized;
+ else
+ {
+ if (next.IsThisInitialized && !_isThisInitialized)
+ {
+ // Next block has 'this' initialized, but current state has not
+ // therefore next block must be reverified with 'this' uninitialized
+ if (next.State == BasicBlock.ImportState.WasVerified && next.ErrorCount == 0)
+ next.State = BasicBlock.ImportState.Unmarked;
+ }
+
+ next.IsThisInitialized = next.IsThisInitialized && _isThisInitialized;
+ }
+ }
+
+ void ImportSwitchJump(int jmpBase, int[] jmpDelta, BasicBlock fallthrough)
+ {
+ var value = Pop();
+ CheckIsAssignable(value, StackValue.CreatePrimitive(StackValueKind.Int32));
+
+ for (int i = 0; i < jmpDelta.Length; i++)
+ {
+ BasicBlock target = _basicBlocks[jmpBase + jmpDelta[i]];
+ PropagateControlFlow(target, isFallthrough: false);
+ }
+
+ if (fallthrough != null)
+ ImportFallthrough(fallthrough);
+ }
+
+ void ImportBranch(ILOpcode opcode, BasicBlock target, BasicBlock fallthrough)
+ {
+ switch (opcode)
+ {
+ case ILOpcode.br:
+ break;
+ case ILOpcode.brfalse:
+ case ILOpcode.brtrue:
+ {
+ StackValue value = Pop();
+ Check(value.Kind >= StackValueKind.Int32 && value.Kind <= StackValueKind.NativeInt || value.Kind == StackValueKind.ObjRef || value.Kind == StackValueKind.ByRef, VerifierError.StackUnexpected);
+ }
+ break;
+ case ILOpcode.beq:
+ case ILOpcode.bge:
+ case ILOpcode.bgt:
+ case ILOpcode.ble:
+ case ILOpcode.blt:
+ case ILOpcode.bne_un:
+ case ILOpcode.bge_un:
+ case ILOpcode.bgt_un:
+ case ILOpcode.ble_un:
+ case ILOpcode.blt_un:
+ {
+ StackValue value1 = Pop();
+ StackValue value2 = Pop();
+
+ CheckIsComparable(value1, value2, opcode);
+ }
+ break;
+ default:
+ Debug.Fail("Unexpected branch opcode");
+ break;
+ }
+
+ PropagateControlFlow(target, isFallthrough: false);
+
+ if (fallthrough != null)
+ ImportFallthrough(fallthrough);
+ }
+
+ void PropagateControlFlow(BasicBlock next, bool isFallthrough)
+ {
+ if (!IsValidBranchTarget(_currentBasicBlock, next, isFallthrough) || _currentBasicBlock.ErrorCount > 0)
+ return;
+
+ PropagateThisState(_currentBasicBlock, next);
+
+ // Propagate stack across block bounds
+ StackValue[] entryStack = next.EntryStack;
+
+ if (entryStack != null)
+ {
+ FatalCheck(entryStack.Length == _stackTop, VerifierError.PathStackDepth);
+
+ for (int i = 0; i < entryStack.Length; i++)
+ {
+ // TODO: Do we need to allow conversions?
+ FatalCheck(entryStack[i].Kind == _stack[i].Kind, VerifierError.PathStackUnexpected, entryStack[i], _stack[i]);
+
+ if (entryStack[i].Type != _stack[i].Type)
+ {
+ if (!IsAssignable(_stack[i], entryStack[i]))
+ {
+ StackValue mergedValue;
+ if (!TryMergeStackValues(entryStack[i], _stack[i], out mergedValue))
+ FatalCheck(false, VerifierError.PathStackUnexpected, entryStack[i], _stack[i]);
+
+ // If merge actually changed entry stack
+ if (mergedValue != entryStack[i])
+ {
+ entryStack[i] = mergedValue;
+
+ if (next.ErrorCount == 0 && next.State != BasicBlock.ImportState.IsPending)
+ next.State = BasicBlock.ImportState.Unmarked; // Make sure block is reverified
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ entryStack = (_stackTop != 0) ? new StackValue[_stackTop] : s_emptyStack;
+
+ for (int i = 0; i < entryStack.Length; i++)
+ entryStack[i] = _stack[i];
+
+ next.EntryStack = entryStack;
+ }
+
+ MarkBasicBlock(next);
+ }
+
+ void ImportBinaryOperation(ILOpcode opcode)
+ {
+ var op1 = Pop();
+ var op2 = Pop();
+
+ switch (opcode)
+ {
+ case ILOpcode.add:
+ case ILOpcode.sub:
+ case ILOpcode.mul:
+ case ILOpcode.div:
+ case ILOpcode.rem:
+ CheckIsNumeric(op1);
+ CheckIsNumeric(op2);
+ break;
+ case ILOpcode.and:
+ case ILOpcode.or:
+ case ILOpcode.xor:
+ case ILOpcode.div_un:
+ case ILOpcode.rem_un:
+ case ILOpcode.add_ovf:
+ case ILOpcode.add_ovf_un:
+ case ILOpcode.mul_ovf:
+ case ILOpcode.mul_ovf_un:
+ case ILOpcode.sub_ovf:
+ case ILOpcode.sub_ovf_un:
+ CheckIsInteger(op1);
+ CheckIsInteger(op2);
+ break;
+ }
+
+ // StackValueKind is carefully ordered to make this work
+ StackValue result = (op1.Kind > op2.Kind) ? op1 : op2;
+
+ if ((op1.Kind != op2.Kind) && (result.Kind != StackValueKind.NativeInt))
+ {
+ VerificationError(VerifierError.StackUnexpected, op2, op1);
+ }
+
+ // The one exception from the above rule
+ if ((result.Kind == StackValueKind.ByRef) &&
+ (opcode == ILOpcode.sub || opcode == ILOpcode.sub_ovf || opcode == ILOpcode.sub_ovf_un))
+ {
+ result = StackValue.CreatePrimitive(StackValueKind.NativeInt);
+ }
+
+ Push(result);
+ }
+
+ void ImportShiftOperation(ILOpcode opcode)
+ {
+ var shiftBy = Pop();
+ var toBeShifted = Pop();
+
+ Check(shiftBy.Kind == StackValueKind.Int32 || shiftBy.Kind == StackValueKind.NativeInt, VerifierError.StackUnexpected, shiftBy);
+ CheckIsInteger(toBeShifted);
+
+ Push(StackValue.CreatePrimitive(toBeShifted.Kind));
+ }
+
+ void ImportCompareOperation(ILOpcode opcode)
+ {
+ var value1 = Pop();
+ var value2 = Pop();
+
+ CheckIsComparable(value1, value2, opcode);
+
+ Push(StackValue.CreatePrimitive(StackValueKind.Int32));
+ }
+
+ void ImportConvert(WellKnownType wellKnownType, bool checkOverflow, bool unsigned)
+ {
+ var value = Pop();
+
+ CheckIsNumeric(value);
+
+ Push(StackValue.CreateFromType(GetWellKnownType(wellKnownType)));
+ }
+
+ void ImportLoadField(int token, bool isStatic)
+ {
+ ClearPendingPrefix(Prefix.Unaligned);
+ ClearPendingPrefix(Prefix.Volatile);
+
+ var field = ResolveFieldToken(token);
+
+ TypeDesc instance;
+ if (isStatic)
+ {
+ Check(field.IsStatic, VerifierError.ExpectedStaticField);
+
+ instance = null;
+ }
+ else
+ {
+ var owningType = field.OwningType;
+
+ // Note that even if the field is static, we require that the this pointer
+ // satisfy the same constraints as a non-static field This happens to
+ // be simpler and seems reasonable
+ var actualThis = Pop(allowUninitThis: true);
+ if (actualThis.Kind == StackValueKind.ValueType)
+ actualThis = StackValue.CreateByRef(actualThis.Type);
+
+ var declaredThis = owningType.IsValueType ?
+ StackValue.CreateByRef(owningType) : StackValue.CreateObjRef(owningType);
+
+ CheckIsAssignable(actualThis, declaredThis);
+
+ instance = actualThis.Type;
+ }
+
+ Check(_method.OwningType.CanAccess(field, instance), VerifierError.FieldAccess);
+
+ Push(StackValue.CreateFromType(field.FieldType));
+ }
+
+ void ImportAddressOfField(int token, bool isStatic)
+ {
+ var field = ResolveFieldToken(token);
+ bool isPermanentHome = false;
+
+ TypeDesc instance;
+ if (isStatic)
+ {
+ Check(field.IsStatic, VerifierError.ExpectedStaticField);
+
+ isPermanentHome = true;
+ instance = null;
+
+ if (field.IsInitOnly)
+ Check(_method.IsStaticConstructor && field.OwningType == _method.OwningType, VerifierError.InitOnly);
+ }
+ else
+ {
+ var owningType = field.OwningType;
+
+ // Note that even if the field is static, we require that the this pointer
+ // satisfy the same constraints as a non-static field This happens to
+ // be simpler and seems reasonable
+ var actualThis = Pop(allowUninitThis: true);
+ if (actualThis.Kind == StackValueKind.ValueType)
+ actualThis = StackValue.CreateByRef(actualThis.Type);
+
+ var declaredThis = owningType.IsValueType ?
+ StackValue.CreateByRef(owningType) : StackValue.CreateObjRef(owningType);
+
+ CheckIsAssignable(actualThis, declaredThis);
+
+ isPermanentHome = actualThis.Kind == StackValueKind.ObjRef || actualThis.IsPermanentHome;
+ instance = actualThis.Type;
+
+ if (field.IsInitOnly)
+ Check(_method.IsConstructor && field.OwningType == _method.OwningType && actualThis.IsThisPtr, VerifierError.InitOnly);
+ }
+
+ Check(_method.OwningType.CanAccess(field, instance), VerifierError.FieldAccess);
+
+ Push(StackValue.CreateByRef(field.FieldType, false, isPermanentHome));
+ }
+
+ void ImportStoreField(int token, bool isStatic)
+ {
+ ClearPendingPrefix(Prefix.Unaligned);
+ ClearPendingPrefix(Prefix.Volatile);
+
+ var value = Pop();
+
+ var field = ResolveFieldToken(token);
+
+ TypeDesc instance;
+ if (isStatic)
+ {
+ Check(field.IsStatic, VerifierError.ExpectedStaticField);
+
+ instance = null;
+
+ if (field.IsInitOnly)
+ Check(_method.IsStaticConstructor && field.OwningType == _method.OwningType, VerifierError.InitOnly);
+ }
+ else
+ {
+ var owningType = field.OwningType;
+
+ // Note that even if the field is static, we require that the this pointer
+ // satisfy the same constraints as a non-static field This happens to
+ // be simpler and seems reasonable
+ var actualThis = Pop(allowUninitThis: true);
+ if (actualThis.Kind == StackValueKind.ValueType)
+ actualThis = StackValue.CreateByRef(actualThis.Type);
+
+ var declaredThis = owningType.IsValueType ?
+ StackValue.CreateByRef(owningType) : StackValue.CreateObjRef(owningType);
+
+ CheckIsAssignable(actualThis, declaredThis);
+
+ instance = actualThis.Type;
+
+ if (field.IsInitOnly)
+ Check(_method.IsConstructor && field.OwningType == _method.OwningType && actualThis.IsThisPtr, VerifierError.InitOnly);
+ }
+
+ // Check any constraints on the fields' class --- accessing the field might cause a class constructor to run.
+ Check(field.OwningType.CheckConstraints(), VerifierError.UnsatisfiedFieldParentInst);
+
+ Check(_method.OwningType.CanAccess(field, instance), VerifierError.FieldAccess);
+
+ CheckIsAssignable(value, StackValue.CreateFromType(field.FieldType));
+ }
+
+ void ImportLoadIndirect(int token)
+ {
+ ImportLoadIndirect(ResolveTypeToken(token));
+ }
+
+ void ImportLoadIndirect(TypeDesc type)
+ {
+ ClearPendingPrefix(Prefix.Unaligned);
+ ClearPendingPrefix(Prefix.Volatile);
+
+ var address = Pop();
+ CheckIsByRef(address);
+
+ if (type == null)
+ {
+ CheckIsObjRef(address.Type);
+ type = address.Type;
+ }
+ else
+ {
+ CheckIsAssignable(address.Type.GetVerificationType(), type.GetVerificationType());
+ }
+ Push(StackValue.CreateFromType(type));
+ }
+
+ void ImportStoreIndirect(int token)
+ {
+ ImportStoreIndirect(ResolveTypeToken(token));
+ }
+
+ void ImportStoreIndirect(TypeDesc type)
+ {
+ ClearPendingPrefix(Prefix.Unaligned);
+ ClearPendingPrefix(Prefix.Volatile);
+
+ var value = Pop();
+ var address = Pop();
+
+ Check(!address.IsReadOnly, VerifierError.ReadOnlyIllegalWrite);
+
+ CheckIsByRef(address);
+
+ if (type == null)
+ type = address.Type;
+
+ var typeVal = StackValue.CreateFromType(type);
+ var addressVal = StackValue.CreateFromType(address.Type);
+
+ CheckIsAssignable(typeVal, addressVal);
+ CheckIsAssignable(value, typeVal);
+ }
+
+ void ImportThrow()
+ {
+ var value = Pop();
+
+ CheckIsObjRef(value);
+
+ EmptyTheStack();
+ }
+
+ void ImportLoadString(int token)
+ {
+ object tokenObj = _methodIL.GetObject(token);
+ Check(tokenObj is String, VerifierError.StringOperand);
+
+ Push(StackValue.CreateObjRef(_typeSystemContext.GetWellKnownType(WellKnownType.String)));
+ }
+
+ void ImportInitObj(int token)
+ {
+ var type = ResolveTypeToken(token);
+
+ var value = Pop();
+
+ Check(value.Kind == StackValueKind.ByRef, VerifierError.StackByRef, value);
+
+ CheckIsAssignable(value, StackValue.CreateByRef(type));
+ }
+
+ void ImportBox(int token)
+ {
+ var type = ResolveTypeToken(token);
+
+ var value = Pop();
+
+ var targetType = StackValue.CreateFromType(type);
+
+ Check(!IsByRefLike(targetType), VerifierError.BoxByRef, targetType);
+
+ Check(type.IsPrimitive || targetType.Kind == StackValueKind.ObjRef ||
+ type.IsGenericParameter || type.IsValueType, VerifierError.ExpectedValClassObjRefVariable);
+
+ Check(type.CheckConstraints(), VerifierError.UnsatisfiedBoxOperand);
+
+ Check(_method.OwningType.CanAccess(type), VerifierError.TypeAccess);
+
+ CheckIsAssignable(value, targetType);
+
+ // for nullable<T> we push T
+ var typeForBox = type.IsNullable ? type.Instantiation[0] : type;
+
+ // even if type is a value type we want the ref
+ Push(StackValue.CreateObjRef(typeForBox));
+ }
+
+ static bool IsOffsetContained(int offset, int start, int length)
+ {
+ return start <= offset && offset < start + length;
+ }
+
+ void ImportLeave(BasicBlock target)
+ {
+ EmptyTheStack();
+
+ PropagateThisState(_currentBasicBlock, target);
+ MarkBasicBlock(target);
+
+ CheckIsValidLeaveTarget(_currentBasicBlock, target);
+ }
+
+ void ImportEndFinally()
+ {
+ Check(_currentBasicBlock.HandlerIndex.HasValue, VerifierError.Endfinally);
+ Check(_exceptionRegions[_currentBasicBlock.HandlerIndex.Value].ILRegion.Kind == ILExceptionRegionKind.Finally ||
+ _exceptionRegions[_currentBasicBlock.HandlerIndex.Value].ILRegion.Kind == ILExceptionRegionKind.Fault, VerifierError.Endfinally);
+
+ EmptyTheStack();
+ }
+
+ void ImportNewArray(int token)
+ {
+ var elementType = ResolveTypeToken(token);
+
+ var length = Pop();
+
+ Check(!IsByRefLike(StackValue.CreateFromType(elementType)), VerifierError.ArrayByRef);
+
+ Push(StackValue.CreateObjRef(elementType.Context.GetArrayType(elementType)));
+ }
+
+ void ImportLoadElement(int token)
+ {
+ ImportLoadElement(ResolveTypeToken(token));
+ }
+
+ void ImportLoadElement(TypeDesc elementType)
+ {
+ var index = Pop();
+ var array = Pop();
+
+ CheckIsIndex(index);
+ CheckIsArray(array);
+
+ if (array.Type != null)
+ {
+ var actualElementType = ((ArrayType)array.Type).ElementType;
+
+ if (elementType != null)
+ {
+ CheckIsArrayElementCompatibleWith(actualElementType.GetVerificationType(), elementType);
+ }
+ else
+ {
+ elementType = actualElementType;
+ CheckIsObjRef(elementType);
+ }
+ }
+
+ Push(StackValue.CreateFromType(elementType));
+ }
+
+ void ImportStoreElement(int token)
+ {
+ ImportStoreElement(ResolveTypeToken(token));
+ }
+
+ void ImportStoreElement(TypeDesc elementType)
+ {
+ var value = Pop();
+ var index = Pop();
+ var array = Pop();
+
+ CheckIsIndex(index);
+ CheckIsArray(array);
+
+ if (array.Type != null)
+ {
+ var actualElementType = ((ArrayType)array.Type).ElementType;
+
+ if (elementType != null)
+ {
+ CheckIsArrayElementCompatibleWith(elementType, actualElementType.GetVerificationType());
+ }
+ else
+ {
+ elementType = actualElementType;
+ CheckIsObjRef(elementType);
+ }
+ }
+
+ if (elementType != null)
+ {
+ // TODO: Change to CheckIsArrayElementCompatibleWith for two intermediate types
+ CheckIsAssignable(value, StackValue.CreateFromType(elementType));
+ }
+ }
+
+ void ImportAddressOfElement(int token)
+ {
+ var elementType = ResolveTypeToken(token);
+
+ var index = Pop();
+ var array = Pop();
+
+ CheckIsIndex(index);
+ CheckIsArray(array);
+
+ if (array.Type != null)
+ {
+ var actualElementType = ((ArrayType)array.Type).ElementType;
+
+ CheckIsPointerElementCompatibleWith(actualElementType, elementType);
+ }
+
+ // an array interior pointer is always on the heap, hence permanentHome = true
+ Push(StackValue.CreateByRef(elementType, HasPendingPrefix(Prefix.ReadOnly), true));
+ ClearPendingPrefix(Prefix.ReadOnly);
+ }
+
+ void ImportLoadLength()
+ {
+ var array = Pop();
+
+ CheckIsArray(array);
+
+ Push(StackValue.CreatePrimitive(StackValueKind.NativeInt));
+ }
+
+ void ImportUnaryOperation(ILOpcode opCode)
+ {
+ var operand = Pop();
+
+ switch (opCode)
+ {
+ case ILOpcode.neg:
+ CheckIsNumeric(operand);
+ break;
+ case ILOpcode.not:
+ CheckIsInteger(operand);
+ break;
+ default:
+ Debug.Fail("Unexpected branch opcode");
+ break;
+ }
+
+ Push(StackValue.CreatePrimitive(operand.Kind));
+ }
+
+ void ImportCpOpj(int token)
+ {
+ var type = ResolveTypeToken(token);
+
+ var src = Pop();
+ var dst = Pop();
+
+ Check(src.Kind == StackValueKind.ByRef, VerifierError.StackByRef, src);
+ Check(dst.Kind == StackValueKind.ByRef, VerifierError.StackByRef, dst);
+
+ // TODO !!!
+ // CheckIsAssignable(src.Type, type);
+ // CheckIsAssignable(type, dst.Type);
+ }
+
+ void ImportUnbox(int token, ILOpcode opCode)
+ {
+ var type = ResolveTypeToken(token);
+
+ CheckIsObjRef(Pop());
+
+ if (opCode == ILOpcode.unbox_any)
+ {
+ Push(StackValue.CreateFromType(type));
+ }
+ else
+ {
+ Check(type.IsValueType, VerifierError.ValueTypeExpected);
+
+ // We always come from an ObjRef, hence this is permanentHome
+ Push(StackValue.CreateByRef(type, true, true));
+ }
+ }
+
+ void ImportCkFinite()
+ {
+ var value = Pop();
+
+ Check(value.Kind == StackValueKind.Float, VerifierError.ExpectedFloatType);
+
+ Push(value);
+ }
+
+ void ImportLdToken(int token)
+ {
+ Object obj = ResolveToken(token);
+
+ WellKnownType handleKind;
+
+ if (obj is TypeDesc)
+ {
+ handleKind = WellKnownType.RuntimeTypeHandle;
+ }
+ else
+ if (obj is MethodDesc)
+ {
+ handleKind = WellKnownType.RuntimeMethodHandle;
+ }
+ else
+ if (obj is FieldDesc)
+ {
+ handleKind = WellKnownType.RuntimeFieldHandle;
+ }
+ else
+ {
+ throw new BadImageFormatException("Invalid token");
+ }
+
+ var handleType = _typeSystemContext.GetWellKnownType(handleKind);
+
+ Push(StackValue.CreateValueType(handleType));
+ }
+
+ void ImportLocalAlloc()
+ {
+ Unverifiable();
+
+ var size = Pop();
+
+ CheckIsInteger(size);
+
+ Push(StackValue.CreatePrimitive(StackValueKind.NativeInt));
+ }
+
+ void ImportEndFilter()
+ {
+ Check(_currentBasicBlock.FilterIndex.HasValue, VerifierError.Endfilter);
+ Check(_currentOffset == _exceptionRegions[_currentBasicBlock.FilterIndex.Value].ILRegion.HandlerOffset, VerifierError.Endfilter);
+
+ var result = Pop(allowUninitThis: true);
+ Check(result.Kind == StackValueKind.Int32, VerifierError.StackUnexpected, result);
+ Check(_stackTop == 0, VerifierError.EndfilterStack);
+ }
+
+ void ImportCpBlk()
+ {
+ ClearPendingPrefix(Prefix.Unaligned);
+ ClearPendingPrefix(Prefix.Volatile);
+
+ Unverifiable();
+
+ var size = Pop();
+ var srcaddr = Pop();
+ var dstaddr = Pop();
+
+ CheckIsInteger(size);
+
+ // TODO: Validate srcaddr, dstaddr
+ }
+
+ void ImportInitBlk()
+ {
+ ClearPendingPrefix(Prefix.Unaligned);
+ ClearPendingPrefix(Prefix.Volatile);
+
+ Unverifiable();
+
+ var size = Pop();
+ var value = Pop();
+ var addr = Pop();
+
+ CheckIsInteger(size);
+ CheckIsInteger(value);
+
+ // TODO: Validate addr
+ }
+
+ void ImportRethrow()
+ {
+ if (_currentBasicBlock.HandlerIndex.HasValue)
+ {
+ var eR = _exceptionRegions[_currentBasicBlock.HandlerIndex.Value].ILRegion;
+
+ //in case a simple catch
+ if (eR.Kind == ILExceptionRegionKind.Catch)
+ {
+ return;
+ }
+
+ //in case a filter make sure rethrow is within the handler
+ if (eR.Kind == ILExceptionRegionKind.Filter &&
+ _currentOffset >= eR.HandlerOffset &&
+ _currentOffset <= eR.HandlerOffset + eR.HandlerLength)
+ {
+ return;
+ }
+ }
+
+ VerificationError(VerifierError.Rethrow);
+ }
+
+ void ImportSizeOf(int token)
+ {
+ var type = ResolveTypeToken(token);
+
+ Push(StackValue.CreatePrimitive(StackValueKind.Int32));
+ }
+
+ //
+ // Prefix
+ //
+
+ void ImportUnalignedPrefix(byte alignment)
+ {
+ CheckPendingPrefix(_pendingPrefix & ~Prefix.Volatile);
+ _pendingPrefix |= Prefix.Unaligned;
+ }
+
+ void ImportVolatilePrefix()
+ {
+ CheckPendingPrefix(_pendingPrefix & ~Prefix.Unaligned);
+ _pendingPrefix |= Prefix.Volatile;
+ }
+
+ void ImportTailPrefix()
+ {
+ CheckPendingPrefix(_pendingPrefix);
+ _pendingPrefix |= Prefix.Tail;
+
+ Check(!_currentBasicBlock.TryIndex.HasValue && !_currentBasicBlock.FilterIndex.HasValue &&
+ !_currentBasicBlock.HandlerIndex.HasValue, VerifierError.TailCallInsideER);
+ }
+
+ void ImportConstrainedPrefix(int token)
+ {
+ CheckPendingPrefix(_pendingPrefix);
+ _pendingPrefix |= Prefix.Constrained;
+
+ _constrained = ResolveTypeToken(token);
+ }
+
+ void ImportNoPrefix(byte mask)
+ {
+ Unverifiable();
+
+ CheckPendingPrefix(_pendingPrefix);
+ _pendingPrefix |= Prefix.No;
+ }
+
+ void ImportReadOnlyPrefix()
+ {
+ CheckPendingPrefix(_pendingPrefix);
+ _pendingPrefix |= Prefix.ReadOnly;
+ }
+
+ void CheckPendingPrefix(Prefix mask)
+ {
+ if (mask == 0) return;
+
+ //illegal to stack prefixes
+ Check((mask & Prefix.Unaligned) == 0, VerifierError.Unaligned);
+ Check((mask & Prefix.Tail) == 0, VerifierError.TailCall);
+ Check((mask & Prefix.Volatile) == 0, VerifierError.Volatile);
+ Check((mask & Prefix.ReadOnly) == 0, VerifierError.ReadOnly);
+ Check((mask & Prefix.Constrained) == 0, VerifierError.Constrained);
+ }
+
+ bool HasPendingPrefix(Prefix prefix)
+ {
+ return (_pendingPrefix & prefix) != 0;
+ }
+
+ void ClearPendingPrefix(Prefix prefix)
+ {
+ _pendingPrefix &= ~prefix;
+ }
+
+ void ReportInvalidBranchTarget(int targetOffset)
+ {
+ VerificationError(VerifierError.BadBranch);
+ }
+
+ void ReportFallthroughAtEndOfMethod()
+ {
+ VerificationError(VerifierError.MethodFallthrough);
+ }
+
+ void ReportMethodEndInsideInstruction()
+ {
+ VerificationError(VerifierError.MethodEnd);
+ AbortMethodVerification();
+ }
+
+ void ReportInvalidInstruction(ILOpcode opcode)
+ {
+ VerificationError(VerifierError.UnknownOpcode);
+ }
+
+ //
+ // Deprecated
+ //
+
+ void ImportArgList()
+ {
+ throw new PlatformNotSupportedException("RuntimeArgumentHandle not supported in .NET Core");
+ }
+
+ void ImportRefAnyType()
+ {
+ throw new PlatformNotSupportedException("TypedReference not supported in .NET Core");
+ }
+
+ void ImportMkRefAny(int token)
+ {
+ throw new PlatformNotSupportedException("TypedReference not supported in .NET Core");
+ }
+
+ void ImportRefAnyVal(int token)
+ {
+ throw new PlatformNotSupportedException("TypedReference not supported in .NET Core");
+ }
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CLSCompliant>false</CLSCompliant>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="..\Common\TypeSystem\CodeGen\MethodDesc.CodeGen.cs">
+ <Link>TypeSystem\CodeGen\MethodDesc.CodeGen.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\AlignmentHelper.cs">
+ <Link>Utilities\AlignmentHelper.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\CastingHelper.cs">
+ <Link>TypeSystem\Common\CastingHelper.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\FunctionPointerType.cs">
+ <Link>TypeSystem\Common\FunctionPointerType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\IAssemblyDesc.cs">
+ <Link>TypeSystem\Common\IAssemblyDesc.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\Instantiation.cs">
+ <Link>TypeSystem\Common\Instantiation.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\ModuleDesc.cs">
+ <Link>TypeSystem\Common\ModuleDesc.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\TypeSystemEntity.cs">
+ <Link>TypeSystem\Common\TypeSystemEntity.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\TypeSystemException.cs">
+ <Link>TypeSystem\Common\TypeSystemException.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\Utilities\CustomAttributeTypeNameParser.cs">
+ <Link>Utilities\CustomAttributeTypeNameParser.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\Utilities\LockFreeReaderHashtable.cs">
+ <Link>Utilities\LockFreeReaderHashtable.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\ArrayType.cs">
+ <Link>TypeSystem\Common\ArrayType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\BaseTypeRuntimeInterfacesAlgorithm.cs">
+ <Link>TypeSystem\Common\BaseTypeRuntimeInterfacesAlgorithm.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\ByRefType.cs">
+ <Link>TypeSystem\Common\ByRefType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\GenericParameterDesc.cs">
+ <Link>TypeSystem\Common\GenericParameterDesc.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\GenericParameterDesc.Dummy.Diagnostic.cs">
+ <Link>TypeSystem\Common\GenericParameterDesc.Dummy.Diagnostic.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\ExceptionStringID.cs">
+ <Link>TypeSystem\Common\ExceptionStringID.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\Utilities\DebugNameFormatter.cs">
+ <Link>Utilities\DebugNameFormatter.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\FieldForInstantiatedType.cs">
+ <Link>TypeSystem\Common\FieldForInstantiatedType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\FieldDesc.cs">
+ <Link>TypeSystem\Common\FieldDesc.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\FieldDesc.FieldLayout.cs">
+ <Link>TypeSystem\Common\FieldDesc.FieldLayout.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\FieldDesc.ToString.cs">
+ <Link>TypeSystem\Common\FieldDesc.ToString.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\FieldLayoutAlgorithm.cs">
+ <Link>TypeSystem\Common\FieldLayoutAlgorithm.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\IModuleResolver.cs">
+ <Link>TypeSystem\Common\IModuleResolver.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\InstantiatedMethod.cs">
+ <Link>TypeSystem\Common\InstantiatedMethod.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\InstantiatedType.cs">
+ <Link>TypeSystem\Common\InstantiatedType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\InstantiatedType.Interfaces.cs">
+ <Link>TypeSystem\Common\InstantiatedType.Interfaces.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\InstantiatedType.MethodImpls.cs">
+ <Link>TypeSystem\Common\InstantiatedType.MethodImpls.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\LayoutInt.cs">
+ <Link>TypeSystem\Common\LayoutInt.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\MetadataType.cs">
+ <Link>TypeSystem\Common\MetadataType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\MetadataType.Interfaces.cs">
+ <Link>TypeSystem\Common\MetadataType.Interfaces.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\MetadataType.MethodImpls.cs">
+ <Link>TypeSystem\Common\MetadataType.MethodImpls.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\MetadataFieldLayoutAlgorithm.cs">
+ <Link>TypeSystem\Common\MetadataFieldLayoutAlgorithm.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\ExplicitLayoutValidator.cs">
+ <Link>TypeSystem\Common\ExplicitLayoutValidator.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\MetadataRuntimeInterfacesAlgorithm.cs">
+ <Link>TypeSystem\Common\MetadataRuntimeInterfacesAlgorithm.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\MetadataTypeSystemContext.cs">
+ <Link>TypeSystem\Common\MetadataTypeSystemContext.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\MethodForInstantiatedType.cs">
+ <Link>TypeSystem\Common\MethodForInstantiatedType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\ParameterizedType.cs">
+ <Link>TypeSystem\Common\ParameterizedType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\PointerType.cs">
+ <Link>TypeSystem\Common\PointerType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\PropertySignature.cs">
+ <Link>TypeSystem\Common\PropertySignature.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\SignatureVariable.cs">
+ <Link>TypeSystem\Common\SignatureVariable.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\TargetDetails.cs">
+ <Link>TypeSystem\Common\TargetDetails.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\ThreadSafeFlags.cs">
+ <Link>TypeSystem\Common\ThreadSafeFlags.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\TypeFlags.cs">
+ <Link>TypeSystem\Common\TypeFlags.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\TypeHashingAlgorithms.cs">
+ <Link>TypeSystem\Common\TypeHashingAlgorithms.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\TypeSystemContext.cs">
+ <Link>TypeSystem\Common\TypeSystemContext.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\TypeSystemHelpers.cs">
+ <Link>TypeSystem\Common\TypeSystemHelpers.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\Utilities\TypeNameFormatter.cs">
+ <Link>Utilities\TypeNameFormatter.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\WellKnownType.cs">
+ <Link>TypeSystem\Common\WellKnownType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\VirtualMethodAlgorithm.cs">
+ <Link>TypeSystem\Common\VirtualMethodAlgorithm.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\MethodDesc.cs">
+ <Link>TypeSystem\Common\MethodDesc.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\MethodDesc.ToString.cs">
+ <Link>TypeSystem\Common\MethodDesc.ToString.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\MethodDesc.Dummy.Diagnostic.cs">
+ <Link>TypeSystem\Common\MethodDesc.Dummy.Diagnostic.ToString.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\MetadataVirtualMethodAlgorithm.cs">
+ <Link>TypeSystem\Common\StandardVirtualMethodAlgorithm.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\TypeDesc.cs">
+ <Link>TypeSystem\Common\TypeDesc.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\TypeDesc.Interfaces.cs">
+ <Link>TypeSystem\Common\TypeDesc.Interfaces.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\TypeDesc.ToString.cs">
+ <Link>TypeSystem\Common\TypeDesc.ToString.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\DefType.cs">
+ <Link>TypeSystem\Common\DefType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\DefType.FieldLayout.cs">
+ <Link>TypeSystem\Common\DefType.FieldLayout.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\DefType.Dummy.Diagnostic.cs">
+ <Link>TypeSystem\Common\DefType.Dummy.Diagnostic.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\RuntimeInterfacesAlgorithm.cs">
+ <Link>TypeSystem\Common\RuntimeInterfacesAlgorithm.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\ThrowHelper.Common.cs">
+ <Link>TypeSystem\Common\ThrowHelper.Common.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\ThrowHelper.cs">
+ <Link>TypeSystem\Common\ThrowHelper.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\Utilities\ExceptionTypeNameFormatter.cs">
+ <Link>TypeSystem\Common\Utilities\ExceptionTypeNameFormatter.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\Utilities\ExceptionTypeNameFormatter.Metadata.cs">
+ <Link>TypeSystem\Common\Utilities\ExceptionTypeNameFormatter.Metadata.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\CustomAttributeTypeProvider.cs">
+ <Link>Ecma\CustomAttributeTypeProvider.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\EcmaAssembly.cs">
+ <Link>Ecma\EcmaAssembly.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\EcmaField.cs">
+ <Link>Ecma\EcmaField.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\EcmaGenericParameter.cs">
+ <Link>Ecma\EcmaGenericParameter.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\EcmaMethod.cs">
+ <Link>Ecma\EcmaMethod.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\EcmaModule.cs">
+ <Link>Ecma\EcmaModule.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\EcmaSignatureParser.cs">
+ <Link>Ecma\EcmaSignatureParser.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\EcmaType.cs">
+ <Link>Ecma\EcmaType.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\EcmaType.MethodImpls.cs">
+ <Link>Ecma\EcmaType.MethodImpls.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\EcmaType.Interfaces.cs">
+ <Link>Ecma\EcmaType.Interfaces.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\MetadataExtensions.cs">
+ <Link>Ecma\MetadataExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\IMetadataStringDecoderProvider.cs">
+ <Link>Ecma\IMetadataStringDecoderProvider.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\CachingMetadataStringDecoder.cs">
+ <Link>Ecma\CachingMetadataStringDecoder.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Ecma\PrimitiveTypeProvider.cs">
+ <Link>Ecma\PrimitiveTypeProvider.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\IL\EcmaMethodIL.cs">
+ <Link>IL\EcmaMethodIL.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\IL\MethodIL.cs">
+ <Link>IL\MethodIL.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\IL\MethodILDebugView.cs">
+ <Link>IL\MethodILDebugView.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\IL\ILDisassembler.cs">
+ <Link>IL\ILDisassembler.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\IL\InstantiatedMethodIL.cs">
+ <Link>IL\InstantiatedMethodIL.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\IL\ILOpcode.cs">
+ <Link>IL\ILOpcode.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\IL\ILImporter.cs">
+ <Link>IL\ILImporter.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\IL\StackValueKind.cs">
+ <Link>IL\StackValueKind.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Interop\InstantiatedType.Interop.cs">
+ <Link>Interop\InstantiatedType.Interop.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Interop\MetadataType.Interop.cs">
+ <Link>Interop\MetadataType.Interop.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Interop\MethodDesc.Interop.cs">
+ <Link>Interop\MethodDesc.Interop.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Interop\FieldDesc.Interop.cs">
+ <Link>Interop\FieldDesc.Interop.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Interop\MarshalAsDescriptor.cs">
+ <Link>TypeSystem\Interop\MarshalAsDescriptor.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\System\Collections\Generic\ArrayBuilder.cs">
+ <Link>Utilities\ArrayBuilder.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\LocalVariableDefinition.cs">
+ <Link>TypeSystem\Common\LocalVariableDefinition.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\System\FormattingHelpers.cs">
+ <Link>..\Common\System\FormattingHelpers.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\TypeSystem\Common\TypeSystemConstraintsHelpers.cs">
+ <Link>TypeSystem\Common\TypeSystemConstraintsHelpers.cs</Link>
+ </Compile>
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="System.Reflection.Metadata" Version="1.8.0" />
+ </ItemGroup>
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.PortableExecutable;
+using Internal.IL;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+namespace ILVerify
+{
+ class ILVerifyTypeSystemContext : MetadataTypeSystemContext
+ {
+ internal readonly IResolver _resolver;
+
+ private RuntimeInterfacesAlgorithm _arrayOfTRuntimeInterfacesAlgorithm;
+ private MetadataRuntimeInterfacesAlgorithm _metadataRuntimeInterfacesAlgorithm = new MetadataRuntimeInterfacesAlgorithm();
+ private MetadataVirtualMethodAlgorithm _metadataVirtualMethodAlgorithm = new MetadataVirtualMethodAlgorithm();
+
+ private readonly Dictionary<PEReader, EcmaModule> _modulesCache = new Dictionary<PEReader, EcmaModule>();
+
+ public ILVerifyTypeSystemContext(IResolver resolver)
+ {
+ _resolver = resolver;
+ }
+
+ public override ModuleDesc ResolveAssembly(AssemblyName name, bool throwIfNotFound = true)
+ {
+ // Note: we use simple names instead of full names to resolve, because we can't get a full name from an assembly without reading it
+ string simpleName = name.Name;
+ return ResolveAssemblyOrNetmodule(simpleName, simpleName, null, throwIfNotFound);
+ }
+
+ internal override ModuleDesc ResolveModule(IAssemblyDesc referencingModule, string fileName, bool throwIfNotFound = true)
+ {
+ // Referenced modules are stored without their extension (see CommandLineHelpers.cs), so we have to drop
+ // the extension here as well to find a match.
+ string simpleName = Path.GetFileNameWithoutExtension(fileName);
+ // The referencing module is not getting verified currently.
+ // However, netmodules are resolved in the context of assembly, not in the global context.
+ EcmaModule module = ResolveAssemblyOrNetmodule(simpleName, fileName, referencingModule as IAssemblyDesc, throwIfNotFound);
+ if (module.MetadataReader.IsAssembly)
+ {
+ throw new VerifierException($"The module '{fileName}' is not expected to be an assembly");
+ }
+ return module;
+ }
+
+ private EcmaModule ResolveAssemblyOrNetmodule(string simpleName, string verificationName, IAssemblyDesc containingAssembly, bool throwIfNotFound)
+ {
+ PEReader peReader = _resolver.Resolve(simpleName);
+ if (peReader == null && throwIfNotFound)
+ {
+ throw new VerifierException("Assembly or module not found: " + simpleName);
+ }
+ var module = GetModule(peReader, containingAssembly);
+ VerifyModuleName(verificationName, module);
+ return module;
+ }
+
+ private static void VerifyModuleName(string simpleName, EcmaModule module)
+ {
+ MetadataReader metadataReader = module.MetadataReader;
+ StringHandle nameHandle = metadataReader.IsAssembly
+ ? metadataReader.GetAssemblyDefinition().Name
+ : metadataReader.GetModuleDefinition().Name;
+
+ string actualSimpleName = metadataReader.GetString(nameHandle);
+ if (!actualSimpleName.Equals(simpleName, StringComparison.OrdinalIgnoreCase))
+ {
+ throw new VerifierException($"Actual PE name '{actualSimpleName}' does not match provided name '{simpleName}'");
+ }
+ }
+
+ protected override RuntimeInterfacesAlgorithm GetRuntimeInterfacesAlgorithmForNonPointerArrayType(ArrayType type)
+ {
+ if (_arrayOfTRuntimeInterfacesAlgorithm == null)
+ {
+ _arrayOfTRuntimeInterfacesAlgorithm = new SimpleArrayOfTRuntimeInterfacesAlgorithm(SystemModule);
+ }
+ return _arrayOfTRuntimeInterfacesAlgorithm;
+ }
+
+ protected override RuntimeInterfacesAlgorithm GetRuntimeInterfacesAlgorithmForDefType(DefType type)
+ {
+ return _metadataRuntimeInterfacesAlgorithm;
+ }
+
+ public override VirtualMethodAlgorithm GetVirtualMethodAlgorithmForType(TypeDesc type)
+ {
+ return _metadataVirtualMethodAlgorithm;
+ }
+
+ internal EcmaModule GetModule(PEReader peReader, IAssemblyDesc containingAssembly = null)
+ {
+ if (peReader == null)
+ {
+ return null;
+ }
+
+ if (_modulesCache.TryGetValue(peReader, out EcmaModule existingModule))
+ {
+ if (containingAssembly != null && existingModule.Assembly != containingAssembly)
+ {
+ throw new VerifierException($"Containing assembly for module '{existingModule}' must be '{containingAssembly}'");
+ }
+ return existingModule;
+ }
+
+ EcmaModule module = EcmaModule.Create(this, peReader, containingAssembly);
+ _modulesCache.Add(peReader, module);
+ return module;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.PortableExecutable;
+
+namespace ILVerify
+{
+ public interface IResolver
+ {
+ /// <summary>
+ /// This method should return the same instance when queried multiple times.
+ /// </summary>
+ PEReader Resolve(string simpleName);
+ }
+
+ /// <summary>
+ /// Provides caching logic for implementations of IResolver
+ /// </summary>
+ public abstract class ResolverBase : IResolver
+ {
+ private readonly Dictionary<string, PEReader> _resolverCache = new Dictionary<string, PEReader>();
+
+ public PEReader Resolve(string simpleName)
+ {
+ if (_resolverCache.TryGetValue(simpleName, out PEReader peReader))
+ {
+ return peReader;
+ }
+
+ PEReader result = ResolveCore(simpleName);
+ if (result != null)
+ {
+ _resolverCache.Add(simpleName, result);
+ return result;
+ }
+
+ return null;
+ }
+
+ protected abstract PEReader ResolveCore(string simpleName);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Internal.TypeSystem
+{
+ internal sealed partial class InstantiatedGenericParameter : GenericParameterDesc
+ {
+ private readonly GenericParameterDesc _genericParam;
+ private Instantiation _typeInstantiation;
+ private Instantiation _methodInstantiation;
+
+ public GenericParameterDesc GenericParameter
+ {
+ get
+ {
+ return _genericParam;
+ }
+ }
+
+ internal static Instantiation CreateGenericTypeInstantiaton(Instantiation instantiation)
+ {
+ if (instantiation.Length == 0)
+ return instantiation;
+
+ var genericInstantiation = CreateGenericInstantiation(instantiation);
+
+ foreach (var parameter in genericInstantiation)
+ ((InstantiatedGenericParameter)parameter)._typeInstantiation = genericInstantiation;
+
+ return genericInstantiation;
+ }
+
+ internal static Instantiation CreateGenericMethodInstantiation(Instantiation typeInstantiation, Instantiation methodInstantiation)
+ {
+ if (methodInstantiation.Length == 0)
+ return methodInstantiation;
+
+ var genericInstantiation = CreateGenericInstantiation(methodInstantiation);
+
+ foreach (var parameter in genericInstantiation)
+ {
+ var par = (InstantiatedGenericParameter)parameter;
+ par._typeInstantiation = typeInstantiation;
+ par._methodInstantiation = genericInstantiation;
+ }
+
+ return genericInstantiation;
+ }
+
+ private static Instantiation CreateGenericInstantiation(Instantiation fromInstantiation)
+ {
+ var parameters = new TypeDesc[fromInstantiation.Length];
+ for (int i = 0; i < fromInstantiation.Length; ++i)
+ parameters[i] = new InstantiatedGenericParameter((GenericParameterDesc)fromInstantiation[i]);
+
+ return new Instantiation(parameters);
+ }
+
+ private InstantiatedGenericParameter(GenericParameterDesc genericParam)
+ {
+ Debug.Assert(!(genericParam is InstantiatedGenericParameter));
+ _genericParam = genericParam;
+ }
+
+ public override GenericParameterKind Kind => _genericParam.Kind;
+
+ public override int Index => _genericParam.Index;
+
+ public override TypeSystemContext Context => _genericParam.Context;
+
+ public override GenericVariance Variance => _genericParam.Variance;
+
+ public override GenericConstraints Constraints => _genericParam.Constraints;
+
+ public override IEnumerable<TypeDesc> TypeConstraints
+ {
+ get
+ {
+ foreach (var constraint in _genericParam.TypeConstraints)
+ {
+ yield return constraint.InstantiateSignature(_typeInstantiation, _methodInstantiation);
+ }
+ }
+ }
+
+ public override string ToString()
+ {
+ return _genericParam.ToString();
+ }
+ }
+}
--- /dev/null
+# ILVerification
+
+The ILVerification library is part of the ILVerify project. See details under [src/coreclr/src/tools/ILVerify](../ILVerify).
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using Internal.IL;
+using Internal.TypeSystem;
+
+namespace ILVerify
+{
+ internal class SimpleArrayOfTRuntimeInterfacesAlgorithm : RuntimeInterfacesAlgorithm
+ {
+ private DefType[] _arrayRuntimeInterfaces;
+ private MetadataType[] _genericRuntimeInterfaces;
+ private ModuleDesc _systemModule;
+
+ private static readonly string[] s_genericRuntimeInterfacesNames =
+ {
+ "IEnumerable`1",
+ "ICollection`1",
+ "IList`1",
+ "IReadOnlyList`1",
+ "IReadOnlyCollection`1",
+ };
+
+ public SimpleArrayOfTRuntimeInterfacesAlgorithm(ModuleDesc systemModule)
+ {
+ _systemModule = systemModule;
+
+ // initialize interfaces
+ _arrayRuntimeInterfaces = _systemModule.GetType("System", "Array")?.RuntimeInterfaces
+ ?? Array.Empty<DefType>();
+
+ _genericRuntimeInterfaces = new MetadataType[s_genericRuntimeInterfacesNames.Length];
+ int count = 0;
+ for (int i = 0; i < s_genericRuntimeInterfacesNames.Length; ++i)
+ {
+ MetadataType runtimeInterface =_systemModule.GetType("System.Collections.Generic", s_genericRuntimeInterfacesNames[i], false);
+ if (runtimeInterface != null)
+ _genericRuntimeInterfaces[count++] = runtimeInterface;
+ };
+ Array.Resize(ref _genericRuntimeInterfaces, count);
+ }
+
+ public override DefType[] ComputeRuntimeInterfaces(TypeDesc type)
+ {
+ ArrayType arrayType = (ArrayType)type;
+ TypeDesc elementType = arrayType.ElementType;
+ Debug.Assert(arrayType.IsSzArray);
+
+ // first copy runtime interfaces from System.Array
+ var result = new DefType[_arrayRuntimeInterfaces.Length + _genericRuntimeInterfaces.Length];
+ Array.Copy(_arrayRuntimeInterfaces, result, _arrayRuntimeInterfaces.Length);
+
+ // then copy instantiated generic interfaces
+ int offset = _arrayRuntimeInterfaces.Length;
+ for (int i = 0; i < _genericRuntimeInterfaces.Length; ++i)
+ result[i + offset] = _genericRuntimeInterfaces[i].MakeInstantiatedType(elementType);
+
+ return result;
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="ArrayByRef" xml:space="preserve">
+ <value>Array of ELEMENT_TYPE_BYREF or ELEMENT_TYPE_TYPEDBYREF.</value>
+ </data>
+ <data name="BackwardBranch" xml:space="preserve">
+ <value>Stack height at all points must be determinable in a single forward scan of IL.</value>
+ </data>
+ <data name="BadBranch" xml:space="preserve">
+ <value>Branch out of the method.</value>
+ </data>
+ <data name="BadJumpTarget" xml:space="preserve">
+ <value>Branch / Leave into the middle of an instruction.</value>
+ </data>
+ <data name="BoxByRef" xml:space="preserve">
+ <value>Cannot box byref.</value>
+ </data>
+ <data name="BranchIntoFilter" xml:space="preserve">
+ <value>Branch into exception filter block.</value>
+ </data>
+ <data name="BranchIntoHandler" xml:space="preserve">
+ <value>Branch into exception handler block.</value>
+ </data>
+ <data name="BranchIntoTry" xml:space="preserve">
+ <value>Branch into try block.</value>
+ </data>
+ <data name="BranchOutOfFilter" xml:space="preserve">
+ <value>Branch out of exception filter block.</value>
+ </data>
+ <data name="BranchOutOfFinally" xml:space="preserve">
+ <value>Branch out of finally block.</value>
+ </data>
+ <data name="BranchOutOfHandler" xml:space="preserve">
+ <value>Branch out of exception handler block.</value>
+ </data>
+ <data name="BranchOutOfTry" xml:space="preserve">
+ <value>Branch out of try block.</value>
+ </data>
+ <data name="ByrefOfByref" xml:space="preserve">
+ <value>ByRef of ByRef.</value>
+ </data>
+ <data name="CallAbstract" xml:space="preserve">
+ <value>Call not allowed on abstract methods.</value>
+ </data>
+ <data name="CallCtor" xml:space="preserve">
+ <value>call to .ctor only allowed to initialize this pointer from within a .ctor. Try newobj.</value>
+ </data>
+ <data name="CallVirtOnStatic" xml:space="preserve">
+ <value>callvirt on static.</value>
+ </data>
+ <data name="CallVirtOnValueType" xml:space="preserve">
+ <value>Callvirt on a value type method.</value>
+ </data>
+ <data name="CatchByRef" xml:space="preserve">
+ <value>ByRef not allowed as catch type.</value>
+ </data>
+ <data name="CodeSizeZero" xml:space="preserve">
+ <value>Code size is zero.</value>
+ </data>
+ <data name="Constrained" xml:space="preserve">
+ <value>Missing callvirt following constrained prefix.</value>
+ </data>
+ <data name="ConstrainedCallWithNonByRefThis" xml:space="preserve">
+ <value>The 'this' argument to a constrained call must have ByRef type.</value>
+ </data>
+ <data name="CtorExpected" xml:space="preserve">
+ <value>.ctor expected.</value>
+ </data>
+ <data name="CtorSig" xml:space="preserve">
+ <value>newobj on static or abstract method.</value>
+ </data>
+ <data name="DelegateCtor" xml:space="preserve">
+ <value>Unrecognized arguments for delegate .ctor.</value>
+ </data>
+ <data name="DelegateCtorSigI" xml:space="preserve">
+ <value>Unrecognized delegate .ctor signature; expected Native Int.</value>
+ </data>
+ <data name="DelegateCtorSigO" xml:space="preserve">
+ <value>Unrecognized delegate .ctor signature; expected Object.</value>
+ </data>
+ <data name="DelegatePattern" xml:space="preserve">
+ <value>Dup, ldvirtftn, newobj delegate::.ctor() pattern expected (in the same basic block).</value>
+ </data>
+ <data name="Endfilter" xml:space="preserve">
+ <value>Endfilter from outside an exception filter block.</value>
+ </data>
+ <data name="EndfilterStack" xml:space="preserve">
+ <value>Stack not empty when leaving an exception filter.</value>
+ </data>
+ <data name="Endfinally" xml:space="preserve">
+ <value>Endfinally from outside a finally handler.</value>
+ </data>
+ <data name="ExpectedArray" xml:space="preserve">
+ <value>Expected single-dimension zero-based array.</value>
+ </data>
+ <data name="ExpectedFieldToken" xml:space="preserve">
+ <value>Expected field token.</value>
+ </data>
+ <data name="ExpectedFloatType" xml:space="preserve">
+ <value>Expected R, R4, or R8 on the stack.</value>
+ </data>
+ <data name="ExpectedIntegerType" xml:space="preserve">
+ <value>Expected I, I4, or I8 on the stack.</value>
+ </data>
+ <data name="ExpectedMethodToken" xml:space="preserve">
+ <value>Expected memberRef, memberDef or methodSpec token.</value>
+ </data>
+ <data name="ExpectedNumericType" xml:space="preserve">
+ <value>Expected numeric type on the stack.</value>
+ </data>
+ <data name="ExpectedStaticField" xml:space="preserve">
+ <value>Expected static field.</value>
+ </data>
+ <data name="ExpectedTypeToken" xml:space="preserve">
+ <value>Expected type token.</value>
+ </data>
+ <data name="ExpectedValClassObjRefVariable" xml:space="preserve">
+ <value>Value type, ObjRef type or variable type expected.</value>
+ </data>
+ <data name="FallthroughException" xml:space="preserve">
+ <value>Fallthrough the end of an exception block.</value>
+ </data>
+ <data name="FallthroughIntoFilter" xml:space="preserve">
+ <value>Fallthrough into an exception filter.</value>
+ </data>
+ <data name="FallthroughIntoHandler" xml:space="preserve">
+ <value>Fallthrough into an exception handler.</value>
+ </data>
+ <data name="FieldAccess" xml:space="preserve">
+ <value>Field is not visible.</value>
+ </data>
+ <data name="FilterOrCatchUnexpectedStack" xml:space="preserve">
+ <value>Attempt to enter a filter or catch block with unexpected stack state.</value>
+ </data>
+ <data name="FinOrFaultNonEmptyStack" xml:space="preserve">
+ <value>Attempt to enter a finally or fault block with nonempty stack.</value>
+ </data>
+ <data name="InitLocals" xml:space="preserve">
+ <value>initlocals must be set for verifiable methods with one or more local variables.</value>
+ </data>
+ <data name="InitOnly" xml:space="preserve">
+ <value>Cannot change initonly field outside its .ctor.</value>
+ </data>
+ <data name="LdftnConstructor" xml:space="preserve">
+ <value>ldftn/ldvirtftn not allowed on .ctor.</value>
+ </data>
+ <data name="LdftnNonFinalVirtual" xml:space="preserve">
+ <value>Cannot LDFTN a non-final virtual method for delegate creation if target object is potentially not the same type as the method class.</value>
+ </data>
+ <data name="LdvirtftnOnStatic" xml:space="preserve">
+ <value>ldvirtftn on static.</value>
+ </data>
+ <data name="LeaveIntoFilter" xml:space="preserve">
+ <value>Leave into filter block.</value>
+ </data>
+ <data name="LeaveIntoHandler" xml:space="preserve">
+ <value>Leave into exception handler block.</value>
+ </data>
+ <data name="LeaveIntoTry" xml:space="preserve">
+ <value>Leave into try block.</value>
+ </data>
+ <data name="LeaveOutOfFault" xml:space="preserve">
+ <value>Leave out of fault block.</value>
+ </data>
+ <data name="LeaveOutOfFilter" xml:space="preserve">
+ <value>Leave out of filter block.</value>
+ </data>
+ <data name="LeaveOutOfFinally" xml:space="preserve">
+ <value>Leave out of finally block.</value>
+ </data>
+ <data name="MethodAccess" xml:space="preserve">
+ <value>Method is not visible.</value>
+ </data>
+ <data name="MethodEnd" xml:space="preserve">
+ <value>Method ends in the middle of an instruction.</value>
+ </data>
+ <data name="MethodFallthrough" xml:space="preserve">
+ <value>Fall through end of the method without returning.</value>
+ </data>
+ <data name="NewobjAbstractClass" xml:space="preserve">
+ <value>Cannot construct an instance of abstract class.</value>
+ </data>
+ <data name="PathStackDepth" xml:space="preserve">
+ <value>Stack depth differs depending on path.</value>
+ </data>
+ <data name="PathStackUnexpected" xml:space="preserve">
+ <value>Non-compatible types on stack depending on path.</value>
+ </data>
+ <data name="ReadOnly" xml:space="preserve">
+ <value>Missing ldelema or call following readonly prefix.</value>
+ </data>
+ <data name="ReadOnlyIllegalWrite" xml:space="preserve">
+ <value>Illegal write to readonly ByRef.</value>
+ </data>
+ <data name="ReadonlyUnexpectedCallee" xml:space="preserve">
+ <value>The readonly prefix may only be applied to calls to array methods returning ByRefs.</value>
+ </data>
+ <data name="Rethrow" xml:space="preserve">
+ <value>Rethrow from outside a catch handler.</value>
+ </data>
+ <data name="ReturnEmpty" xml:space="preserve">
+ <value>Stack must contain only the return value.</value>
+ </data>
+ <data name="ReturnFromFilter" xml:space="preserve">
+ <value>Return out of exception filter block.</value>
+ </data>
+ <data name="ReturnFromHandler" xml:space="preserve">
+ <value>Return out of exception handler block.</value>
+ </data>
+ <data name="ReturnFromTry" xml:space="preserve">
+ <value>Return out of try block.</value>
+ </data>
+ <data name="ReturnMissing" xml:space="preserve">
+ <value>Return value missing on the stack.</value>
+ </data>
+ <data name="ReturnPtrToStack" xml:space="preserve">
+ <value>Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.</value>
+ </data>
+ <data name="ReturnVoid" xml:space="preserve">
+ <value>Stack must be empty on return from a void function.</value>
+ </data>
+ <data name="StackByRef" xml:space="preserve">
+ <value>Expected ByRef on the stack.</value>
+ </data>
+ <data name="StackMethod" xml:space="preserve">
+ <value>Expected pointer to function on the stack.</value>
+ </data>
+ <data name="StackNotEq" xml:space="preserve">
+ <value>Non-compatible types on the stack.</value>
+ </data>
+ <data name="StackObjRef" xml:space="preserve">
+ <value>Expected an ObjRef on the stack.</value>
+ </data>
+ <data name="StackOverflow" xml:space="preserve">
+ <value>Stack overflow.</value>
+ </data>
+ <data name="StackUnderflow" xml:space="preserve">
+ <value>Stack underflow.</value>
+ </data>
+ <data name="StackUnexpected" xml:space="preserve">
+ <value>Unexpected type on the stack.</value>
+ </data>
+ <data name="StackUnexpectedArrayType" xml:space="preserve">
+ <value>Unexpected array type on the stack.</value>
+ </data>
+ <data name="StringOperand" xml:space="preserve">
+ <value>Operand does not point to a valid string ref.</value>
+ </data>
+ <data name="TailByRef" xml:space="preserve">
+ <value>Cannot pass ByRef to a tail call.</value>
+ </data>
+ <data name="TailCall" xml:space="preserve">
+ <value>Missing call/callvirt/calli.</value>
+ </data>
+ <data name="TailCallInsideER" xml:space="preserve">
+ <value>The tail.call (or calli or callvirt) instruction cannot be used to transfer control out of a try, filter, catch, or finally block.</value>
+ </data>
+ <data name="TailRet" xml:space="preserve">
+ <value>tail.call may only be followed by ret.</value>
+ </data>
+ <data name="TailRetType" xml:space="preserve">
+ <value>Tail call return type not compatible.</value>
+ </data>
+ <data name="TailRetVoid" xml:space="preserve">
+ <value>Void ret type expected for tail call.</value>
+ </data>
+ <data name="ThisMismatch" xml:space="preserve">
+ <value>The 'this' parameter to the call must be the calling method's 'this' parameter.</value>
+ </data>
+ <data name="ThisUninitReturn" xml:space="preserve">
+ <value>Return from .ctor when this is uninitialized.</value>
+ </data>
+ <data name="ThisUninitStore" xml:space="preserve">
+ <value>Store into this when it is uninitialized.</value>
+ </data>
+ <data name="TokenResolve" xml:space="preserve">
+ <value>Unable to resolve token.</value>
+ </data>
+ <data name="TryNonEmptyStack" xml:space="preserve">
+ <value>Attempt to enter a try block with nonempty stack.</value>
+ </data>
+ <data name="TypeAccess" xml:space="preserve">
+ <value>Type is not visible.</value>
+ </data>
+ <data name="Unaligned" xml:space="preserve">
+ <value>Missing ldind, stind, ldfld, stfld, ldobj, stobj, initblk, cpblk.</value>
+ </data>
+ <data name="UninitStack" xml:space="preserve">
+ <value>Uninitialized item on stack.</value>
+ </data>
+ <data name="UnknownOpcode" xml:space="preserve">
+ <value>Unknown opcode.</value>
+ </data>
+ <data name="UnmanagedPointer" xml:space="preserve">
+ <value>Unmanaged pointers are not a verifiable type.</value>
+ </data>
+ <data name="UnrecognizedArgumentNumber" xml:space="preserve">
+ <value>Unrecognized argument number.</value>
+ </data>
+ <data name="UnrecognizedLocalNumber" xml:space="preserve">
+ <value>Unrecognized local variable number.</value>
+ </data>
+ <data name="UnsatisfiedBoxOperand" xml:space="preserve">
+ <value>Type operand of box instruction has unsatisfied class type parameter constraints.</value>
+ </data>
+ <data name="UnsatisfiedFieldParentInst" xml:space="preserve">
+ <value>Field parent instantiation has unsatisfied class type parameter constraints.</value>
+ </data>
+ <data name="UnsatisfiedMethodInst" xml:space="preserve">
+ <value>Method instantiation has unsatisfied method type parameter constraints.</value>
+ </data>
+ <data name="UnsatisfiedMethodParentInst" xml:space="preserve">
+ <value>Method parent instantiation has unsatisfied class type parameter constraints.</value>
+ </data>
+ <data name="Unverifiable" xml:space="preserve">
+ <value>Instruction cannot be verified.</value>
+ </data>
+ <data name="ValueTypeExpected" xml:space="preserve">
+ <value>Value type expected.</value>
+ </data>
+ <data name="Volatile" xml:space="preserve">
+ <value>Missing ldsfld, stsfld, ldind, stind, ldfld, stfld, ldobj, stobj, initblk, or cpblk.</value>
+ </data>
+ <data name="InterfaceImplHasDuplicate" xml:space="preserve">
+ <value>Interface implementation has a duplicate. Class '{0}' Interface: '{1}'</value>
+ </data>
+ <data name="InterfaceMethodNotImplemented" xml:space="preserve">
+ <value>Class implements interface but not method, Class: '{0}' Interface: '{1}' Missing method: '{2}'.</value>
+ </data>
+</root>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+namespace ILVerify
+{
+ internal static class TypeSystemHelpers
+ {
+ /// <summary>
+ /// Returns the "reduced type" based on the definition in the ECMA-335 standard (I.8.7).
+ /// </summary>
+ internal static TypeDesc GetReducedType(this TypeDesc type)
+ {
+ if (type == null)
+ return null;
+
+ var category = type.UnderlyingType.Category;
+
+ switch (category)
+ {
+ case TypeFlags.Byte:
+ return type.Context.GetWellKnownType(WellKnownType.SByte);
+ case TypeFlags.UInt16:
+ return type.Context.GetWellKnownType(WellKnownType.Int16);
+ case TypeFlags.UInt32:
+ return type.Context.GetWellKnownType(WellKnownType.Int32);
+ case TypeFlags.UInt64:
+ return type.Context.GetWellKnownType(WellKnownType.Int64);
+ case TypeFlags.UIntPtr:
+ return type.Context.GetWellKnownType(WellKnownType.IntPtr);
+
+ default:
+ return type.UnderlyingType; //Reduced type is type itself
+ }
+ }
+
+ /// <summary>
+ /// Returns the "verification type" based on the definition in the ECMA-335 standard (I.8.7).
+ /// </summary>
+ internal static TypeDesc GetVerificationType(this TypeDesc type)
+ {
+ if (type == null)
+ return null;
+
+ if (type.IsByRef)
+ {
+ var parameterVerificationType = GetVerificationType(type.GetParameterType());
+ return type.Context.GetByRefType(parameterVerificationType);
+ }
+ else
+ {
+ var reducedType = GetReducedType(type);
+ switch (reducedType.Category)
+ {
+ case TypeFlags.Boolean:
+ return type.Context.GetWellKnownType(WellKnownType.SByte);
+
+ case TypeFlags.Char:
+ return type.Context.GetWellKnownType(WellKnownType.Int16);
+
+ default:
+ return reducedType; // Verification type is reduced type
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the "intermediate type" based on the definition in the ECMA-335 standard (I.8.7).
+ /// </summary>
+ internal static TypeDesc GetIntermediateType(this TypeDesc type)
+ {
+ var verificationType = GetVerificationType(type);
+
+ if (verificationType == null)
+ return null;
+
+ switch (verificationType.Category)
+ {
+ case TypeFlags.SByte:
+ case TypeFlags.Int16:
+ case TypeFlags.Int32:
+ return type.Context.GetWellKnownType(WellKnownType.Int32);
+ case TypeFlags.Single:
+ case TypeFlags.Double:
+ return type.Context.GetWellKnownType(WellKnownType.Double);
+ default:
+ return verificationType;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+using ILVerify;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+namespace Internal.TypeVerifier
+{
+ internal class TypeVerifier
+ {
+ private readonly EcmaModule _module;
+ private readonly TypeDefinitionHandle _typeDefinitionHandle;
+ private readonly ILVerifyTypeSystemContext _typeSystemContext;
+ private readonly VerifierOptions _verifierOptions;
+
+ public Action<VerifierError, object[]> ReportVerificationError
+ {
+ set;
+ private get;
+ }
+
+ private void VerificationError(VerifierError error, params object[] args)
+ {
+ ReportVerificationError(error, args);
+ }
+
+ public TypeVerifier(EcmaModule module, TypeDefinitionHandle typeDefinitionHandle, ILVerifyTypeSystemContext typeSystemContext, VerifierOptions verifierOptions)
+ {
+ _module = module;
+ _typeDefinitionHandle = typeDefinitionHandle;
+ _typeSystemContext = typeSystemContext;
+ _verifierOptions = verifierOptions;
+ }
+
+ public void Verify()
+ {
+ VerifyInterfaces();
+ }
+
+ public void VerifyInterfaces()
+ {
+ TypeDefinition typeDefinition = _module.MetadataReader.GetTypeDefinition(_typeDefinitionHandle);
+ EcmaType type = (EcmaType)_module.GetType(_typeDefinitionHandle);
+
+ if (type.IsInterface)
+ {
+ return;
+ }
+
+ InterfaceImplementationHandleCollection interfaceHandles = typeDefinition.GetInterfaceImplementations();
+ int count = interfaceHandles.Count;
+ if (count == 0)
+ {
+ return;
+ }
+
+ // Look for duplicates and prepare distinct list of implemented interfaces to avoid
+ // subsequent error duplication
+ List<InterfaceMetadataObjects> implementedInterfaces = new List<InterfaceMetadataObjects>();
+ foreach (InterfaceImplementationHandle interfaceHandle in interfaceHandles)
+ {
+ InterfaceImplementation interfaceImplementation = _module.MetadataReader.GetInterfaceImplementation(interfaceHandle);
+ TypeDesc interfaceTypeDesc = _module.GetType(interfaceImplementation.Interface) as TypeDesc;
+ if (interfaceTypeDesc == null)
+ {
+ ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadBadFormat, type);
+ }
+
+ InterfaceMetadataObjects imo = new InterfaceMetadataObjects
+ {
+ InterfaceType = interfaceTypeDesc,
+ InterfaceImplementation = interfaceImplementation
+ };
+
+ if (!implementedInterfaces.Contains(imo))
+ {
+ implementedInterfaces.Add(imo);
+ }
+ else
+ {
+ VerificationError(VerifierError.InterfaceImplHasDuplicate, Format(type), Format(imo.InterfaceType, _module, imo.InterfaceImplementation));
+ }
+ }
+
+ foreach (InterfaceMetadataObjects implementedInterface in implementedInterfaces)
+ {
+ if (!type.IsAbstract)
+ {
+ // Look for missing method implementation
+ foreach (MethodDesc method in implementedInterface.InterfaceType.GetAllMethods())
+ {
+ if (method.Signature.IsStatic)
+ {
+ continue;
+ }
+
+ MethodDesc resolvedMethod = type.ResolveInterfaceMethodTarget(method);
+ if (resolvedMethod is null)
+ {
+ VerificationError(VerifierError.InterfaceMethodNotImplemented, Format(type), Format(implementedInterface.InterfaceType, _module, implementedInterface.InterfaceImplementation), Format(method));
+ }
+ }
+ }
+ }
+ }
+
+ private string Format(TypeDesc type)
+ {
+ if (_verifierOptions.IncludeMetadataTokensInErrorMessages)
+ {
+ TypeDesc typeDesc = type.GetTypeDefinition();
+ EcmaModule module = (EcmaModule)((MetadataType)typeDesc).Module;
+
+ return string.Format("{0}([{1}]0x{2:X8})", type, module, module.MetadataReader.GetToken(((EcmaType)type).Handle));
+ }
+ else
+ {
+ return type.ToString();
+ }
+ }
+
+ private string Format(TypeDesc interfaceTypeDesc, EcmaModule module, InterfaceImplementation interfaceImplementation)
+ {
+ if (_verifierOptions.IncludeMetadataTokensInErrorMessages)
+ {
+ return string.Format("{0}([{1}]0x{2:X8})", interfaceTypeDesc, module, module.MetadataReader.GetToken(interfaceImplementation.Interface));
+ }
+ else
+ {
+ return interfaceTypeDesc.ToString();
+ }
+ }
+
+ private string Format(MethodDesc methodDesc)
+ {
+ if (_verifierOptions.IncludeMetadataTokensInErrorMessages)
+ {
+ TypeDesc typeDesc = methodDesc.OwningType.GetTypeDefinition();
+ EcmaModule module = (EcmaModule)((MetadataType)typeDesc).Module;
+
+ return string.Format("{0}([{1}]0x{2:X8})", methodDesc, module, module.MetadataReader.GetToken(((EcmaMethod)methodDesc.GetTypicalMethodDefinition()).Handle));
+ }
+ else
+ {
+ return methodDesc.ToString();
+ }
+ }
+
+ private class InterfaceMetadataObjects : IEquatable<InterfaceMetadataObjects>
+ {
+ public TypeDesc InterfaceType { get; set; }
+ public InterfaceImplementation InterfaceImplementation { get; set; }
+ public bool Equals(InterfaceMetadataObjects other)
+ {
+ return other.InterfaceType == InterfaceType;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Reflection.Metadata;
+using Internal.TypeSystem;
+
+namespace ILVerify
+{
+ public class VerificationResult
+ {
+ public VerifierError Code { get; internal set; }
+ public ExceptionStringID? ExceptionID { get; internal set; }
+ public TypeDefinitionHandle Type { get; internal set; }
+ public MethodDefinitionHandle Method { get; internal set; }
+ public string Message { get; internal set; }
+ public object[] Args { get; internal set; }
+ public ErrorArgument[] ErrorArguments { get; set; }
+
+ public T GetArgumentValue<T>(string name)
+ {
+ TryGetArgumentValue<T>(name, out T argumentValue);
+ return argumentValue;
+ }
+
+ public bool TryGetArgumentValue<T>(string name,out T argumentValue)
+ {
+ argumentValue = default;
+
+ for (int i = 0; i < ErrorArguments.Length; i++)
+ {
+ if (ErrorArguments[i].Name == name)
+ {
+ argumentValue = (T)ErrorArguments[i].Value;
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public class ErrorArgument
+ {
+ public ErrorArgument() { }
+
+ public ErrorArgument(string name, object value)
+ {
+ Name = name;
+ Value = value;
+ }
+
+ public string Name { get; }
+ public object Value { get; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.PortableExecutable;
+using System.Resources;
+using Internal.IL;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+using Internal.TypeVerifier;
+
+namespace ILVerify
+{
+ public class Verifier
+ {
+ private Lazy<ResourceManager> _stringResourceManager =
+ new Lazy<ResourceManager>(() => new ResourceManager("ILVerification.Strings", typeof(Verifier).GetTypeInfo().Assembly));
+
+ private ILVerifyTypeSystemContext _typeSystemContext;
+ private VerifierOptions _verifierOptions;
+
+ public Verifier(IResolver resolver) : this(resolver, null){ }
+
+ public Verifier(IResolver resolver, VerifierOptions verifierOptions) : this(new ILVerifyTypeSystemContext(resolver), verifierOptions) { }
+
+ internal Verifier(ILVerifyTypeSystemContext context, VerifierOptions verifierOptions)
+ {
+ _typeSystemContext = context;
+ _verifierOptions = verifierOptions ?? new VerifierOptions();
+ }
+
+ public void SetSystemModuleName(AssemblyName name)
+ {
+ PEReader peReader = _typeSystemContext._resolver.Resolve(name.Name);
+ if (peReader is null)
+ {
+ throw new VerifierException("Assembly or module not found: " + name.FullName);
+ }
+ _typeSystemContext.SetSystemModule(_typeSystemContext.GetModule(peReader));
+ }
+
+ internal EcmaModule GetModule(PEReader peReader)
+ {
+ return _typeSystemContext.GetModule(peReader);
+ }
+
+ public IEnumerable<VerificationResult> Verify(PEReader peReader)
+ {
+ if (peReader == null)
+ {
+ throw new ArgumentNullException(nameof(peReader));
+ }
+
+ if (_typeSystemContext.SystemModule == null)
+ {
+ ThrowMissingSystemModule();
+ }
+
+ IEnumerable<VerificationResult> results;
+ try
+ {
+ EcmaModule module = GetModule(peReader);
+ results = VerifyMethods(module, module.MetadataReader.MethodDefinitions);
+ }
+ catch (VerifierException e)
+ {
+ results = new[] { new VerificationResult() { Message = e.Message } };
+ }
+
+ foreach (var result in results)
+ {
+ yield return result;
+ }
+ }
+
+ public IEnumerable<VerificationResult> Verify(PEReader peReader, TypeDefinitionHandle typeHandle, bool verifyMethods = false)
+ {
+ if (peReader == null)
+ {
+ throw new ArgumentNullException(nameof(peReader));
+ }
+
+ if (typeHandle.IsNil)
+ {
+ throw new ArgumentNullException(nameof(typeHandle));
+ }
+
+ if (_typeSystemContext.SystemModule == null)
+ {
+ ThrowMissingSystemModule();
+ }
+
+ IEnumerable<VerificationResult> results;
+ try
+ {
+ EcmaModule module = GetModule(peReader);
+ MetadataReader metadataReader = peReader.GetMetadataReader();
+
+ results = VerifyType(module, typeHandle);
+
+ if (verifyMethods)
+ {
+ TypeDefinition typeDef = metadataReader.GetTypeDefinition(typeHandle);
+ results = results.Union(VerifyMethods(module, typeDef.GetMethods()));
+ }
+ }
+ catch (VerifierException e)
+ {
+ results = new[] { new VerificationResult() { Message = e.Message } };
+ }
+
+ foreach (var result in results)
+ {
+ yield return result;
+ }
+ }
+
+ public IEnumerable<VerificationResult> Verify(PEReader peReader, MethodDefinitionHandle methodHandle)
+ {
+ if (peReader == null)
+ {
+ throw new ArgumentNullException(nameof(peReader));
+ }
+
+ if (methodHandle.IsNil)
+ {
+ throw new ArgumentNullException(nameof(methodHandle));
+ }
+
+ if (_typeSystemContext.SystemModule == null)
+ {
+ ThrowMissingSystemModule();
+ }
+
+ IEnumerable<VerificationResult> results;
+ try
+ {
+ EcmaModule module = GetModule(peReader);
+ results = VerifyMethods(module, new[] { methodHandle });
+ }
+ catch (VerifierException e)
+ {
+ results = new[] { new VerificationResult() { Message = e.Message } };
+ }
+
+ foreach (var result in results)
+ {
+ yield return result;
+ }
+ }
+
+ private IEnumerable<VerificationResult> VerifyMethods(EcmaModule module, IEnumerable<MethodDefinitionHandle> methodHandles)
+ {
+ foreach (var methodHandle in methodHandles)
+ {
+ var method = (EcmaMethod)module.GetMethod(methodHandle);
+ var methodIL = EcmaMethodIL.Create(method);
+
+ if (methodIL != null)
+ {
+ var results = VerifyMethod(module, methodIL, methodHandle);
+ foreach (var result in results)
+ {
+ yield return result;
+ }
+ }
+ }
+ }
+
+ private IEnumerable<VerificationResult> VerifyMethod(EcmaModule module, MethodIL methodIL, MethodDefinitionHandle methodHandle)
+ {
+ var builder = new ArrayBuilder<VerificationResult>();
+ MethodDesc method = methodIL.OwningMethod;
+
+ try
+ {
+ var importer = new ILImporter(method, methodIL);
+
+ importer.ReportVerificationError = (args, code) =>
+ {
+ var codeResource = _stringResourceManager.Value.GetString(code.ToString(), CultureInfo.InvariantCulture);
+
+ builder.Add(new VerificationResult()
+ {
+ Code = code,
+ Method = methodHandle,
+ ErrorArguments = args,
+ Message = string.IsNullOrEmpty(codeResource) ? code.ToString() : codeResource
+ });
+ };
+
+ importer.Verify();
+ }
+ catch (VerificationException)
+ {
+ // a result was reported already (before aborting)
+ }
+ catch (BadImageFormatException)
+ {
+ builder.Add(new VerificationResult()
+ {
+ Method = methodHandle,
+ Message = "Unable to resolve token"
+ });
+ }
+ catch (NotImplementedException e)
+ {
+ reportException(e);
+ }
+ catch (InvalidProgramException e)
+ {
+ reportException(e);
+ }
+ catch (PlatformNotSupportedException e)
+ {
+ reportException(e);
+ }
+ catch (VerifierException e)
+ {
+ reportException(e);
+ }
+ catch (TypeSystemException e)
+ {
+ reportTypeSystemException(e);
+ }
+
+ return builder.ToArray();
+
+ void reportException(Exception e)
+ {
+ builder.Add(new VerificationResult()
+ {
+ Method = methodHandle,
+ Message = e.Message
+ });
+ }
+
+ void reportTypeSystemException(TypeSystemException e)
+ {
+ builder.Add(new VerificationResult()
+ {
+ ExceptionID = e.StringID,
+ Method = methodHandle,
+ Message = e.Message
+ });
+ }
+ }
+
+ private IEnumerable<VerificationResult> VerifyType(EcmaModule module, TypeDefinitionHandle typeHandle)
+ {
+ var builder = new ArrayBuilder<VerificationResult>();
+
+ try
+ {
+ TypeVerifier typeVerifier = new TypeVerifier(module, typeHandle, _typeSystemContext, _verifierOptions);
+
+ typeVerifier.ReportVerificationError = (code, args) =>
+ {
+ builder.Add(new VerificationResult()
+ {
+ Code = code,
+ Message = $"[MD]: Error: {_stringResourceManager.Value.GetString(code.ToString(), CultureInfo.InvariantCulture)}",
+ Args = args
+ });
+ };
+
+ typeVerifier.Verify();
+ }
+ catch (BadImageFormatException)
+ {
+ builder.Add(new VerificationResult()
+ {
+ Type = typeHandle,
+ Message = "Unable to resolve token"
+ });
+ }
+ catch (NotImplementedException e)
+ {
+ reportException(e);
+ }
+ catch (InvalidProgramException e)
+ {
+ reportException(e);
+ }
+ catch (PlatformNotSupportedException e)
+ {
+ reportException(e);
+ }
+ catch (VerifierException e)
+ {
+ reportException(e);
+ }
+ catch (TypeSystemException e)
+ {
+ reportException(e);
+ }
+
+ return builder.ToArray();
+
+ void reportException(Exception e)
+ {
+ builder.Add(new VerificationResult()
+ {
+ Type = typeHandle,
+ Message = e.Message
+ });
+ }
+ }
+
+ private void ThrowMissingSystemModule()
+ {
+ throw new VerifierException("No system module specified");
+ }
+ }
+
+ public class VerifierOptions
+ {
+ public bool IncludeMetadataTokensInErrorMessages { get; set; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace ILVerify
+{
+ public enum VerifierError
+ {
+ None = 0,
+ //E_HRESULT "[HRESULT 0x%08X]"
+ //E_OFFSET "[offset 0x%08X]"
+ //E_OPCODE "[opcode %s]"
+ //E_OPERAND "[operand 0x%08X]"
+ //E_TOKEN "[token 0x%08X]"
+ //E_EXCEPT "[exception #0x%08X]"
+ //E_STACK_SLOT "[stack slot 0x%08X]"
+ //E_LOC "[local variable #0x%08X]"
+ //E_LOC_BYNAME "[local variable '%s']"
+ //E_ARG "[argument #0x%08x]"
+ //E_FOUND "[found %s]"
+ //E_EXPECTED "[expected %s]"
+
+ UnknownOpcode, // Unknown opcode.
+ //E_SIG_CALLCONV "Unknown calling convention [0x%08X]."
+ //E_SIG_ELEMTYPE "Unknown ELEMENT_TYPE [0x%08x]."
+
+ //E_RET_SIG "[return sig]"
+ //E_FIELD_SIG "[field sig]"
+
+ //E_INTERNAL "Internal error."
+ //E_STACK_TOO_LARGE "Stack is too large."
+ //E_ARRAY_NAME_LONG "Array name is too long."
+
+ MethodFallthrough, // Fall through end of the method without returning.
+ //E_TRY_GTEQ_END "try start >= try end."
+ //E_TRYEND_GT_CS "try end > code size."
+ //E_HND_GTEQ_END "handler start >= handler end."
+ //E_HNDEND_GT_CS "handler end > code size."
+ //E_TRY_START "Try starts in the middle of an instruction."
+ //E_HND_START "Handler starts in the middle of an instruction."
+ //E_TRY_OVERLAP "Try block overlap with another block."
+ //E_TRY_EQ_HND_FIL "Try and filter/handler blocks are equivalent."
+ //E_TRY_SHARE_FIN_FAL "Shared try has finally or fault handler."
+ //E_HND_EQ "Handler block is the same as another block."
+ //E_FIL_CONT_TRY "Filter contains try."
+ //E_FIL_CONT_HND "Filter contains handler."
+ //E_FIL_CONT_FIL "Nested filters."
+ //E_FIL_GTEQ_CS "filter >= code size."
+ FallthroughException, // Fallthrough the end of an exception block.
+ FallthroughIntoHandler, // Fallthrough into an exception handler.
+ FallthroughIntoFilter, // Fallthrough into an exception filter.
+ LeaveIntoTry, // Leave into try block.
+ LeaveIntoHandler, // Leave into exception handler block.
+ LeaveIntoFilter, // Leave into filter block.
+ LeaveOutOfFilter, // Leave out of filter block.
+ LeaveOutOfFinally, // Leave out of finally block.
+ LeaveOutOfFault, // Leave out of fault block.
+ Rethrow, // Rethrow from outside a catch handler.
+ Endfinally, // Endfinally from outside a finally handler.
+ Endfilter, // Endfilter from outside an exception filter block.
+ BranchIntoTry, // Branch into try block.
+ BranchIntoHandler, // Branch into exception handler block.
+ BranchIntoFilter, // Branch into exception filter block.
+ BranchOutOfTry, // Branch out of try block.
+ BranchOutOfHandler, // Branch out of exception handler block.
+ BranchOutOfFilter, // Branch out of exception filter block.
+ BranchOutOfFinally, // Branch out of finally block.
+ ReturnFromTry, // Return out of try block.
+ ReturnFromHandler, // Return out of exception handler block.
+ ReturnFromFilter, // Return out of exception filter block.
+ BadJumpTarget, // Branch / Leave into the middle of an instruction.
+ PathStackUnexpected, // Non-compatible types on stack depending on path.
+ PathStackDepth, // Stack depth differs depending on path.
+ //E_THIS_UNINIT_EXCEP "Uninitialized this on entering a try block."
+ ThisUninitStore, // Store into this when it is uninitialized.
+ ThisUninitReturn, // Return from .ctor when this is uninitialized.
+ LdftnCtor, // ldftn/ldvirtftn not allowed on .ctor.
+ //StackNotEq, // Non-compatible types on the stack.
+ StackUnexpected, // Unexpected type on the stack.
+ StackUnexpectedArrayType, // Unexpected array type on the stack.
+ StackOverflow, // Stack overflow.
+ StackUnderflow, // Stack underflow.
+ UninitStack, // Uninitialized item on stack.
+ ExpectedIntegerType, // Expected I, I4, or I8 on the stack.
+ ExpectedFloatType, // Expected R, R4, or R8 on the stack.
+ ExpectedNumericType, // Expected numeric type on the stack.
+ StackObjRef, // Expected an ObjRef on the stack.
+ StackByRef, // Expected ByRef on the stack.
+ StackMethod, // Expected pointer to function on the stack.
+ UnrecognizedLocalNumber, // Unrecognized local variable number.
+ UnrecognizedArgumentNumber, // Unrecognized argument number.
+ ExpectedTypeToken, // Expected type token.
+ TokenResolve, // Unable to resolve token.
+ //E_TOKEN_TYPE "Unable to resolve type of the token."
+ ExpectedMethodToken, // Expected memberRef, memberDef or methodSpec token.
+ ExpectedFieldToken, // Expected field token.
+ Unverifiable, // Instruction can not be verified.
+ StringOperand, // Operand does not point to a valid string ref.
+ ReturnPtrToStack, // Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
+ ReturnVoid, // Stack must be empty on return from a void function.
+ ReturnMissing, // Return value missing on the stack.
+ ReturnEmpty, // Stack must contain only the return value.
+ ExpectedArray, // Expected single-dimension zero-based array.
+ //E_ARRAY_SD_PTR "Expected single dimension array of pointer types."
+ //E_ARGLIST "Allowed only in vararg methods."
+ ValueTypeExpected, // Value type expected.
+ //E_OPEN_DLGT_PROT_ACC "Protected method access through an open instance delegate is not verifiable."
+ TypeAccess, // Type is not visible.
+ MethodAccess, // Method is not visible.
+ FieldAccess, // Field is not visible.
+ ExpectedStaticField, // Expected static field.
+ InitOnly, // Cannot change initonly field outside its .ctor.
+ //E_WRITE_RVA_STATIC "Cannot modify an imaged based (RVA) static"
+ CallVirtOnValueType, // Callvirt on a value type method.
+ CtorExpected, // .ctor expected.
+ CtorSig, // newobj on static or abstract method.
+ //E_SIG_ARRAY "Cannot resolve Array type."
+ ArrayByRef, // Array of ELEMENT_TYPE_BYREF or ELEMENT_TYPE_TYPEDBYREF.
+ ByrefOfByref, // ByRef of ByRef.
+ CodeSizeZero, // Code size is zero.
+ TailCall, // Missing call/callvirt/calli.
+ TailByRef, // Cannot pass ByRef to a tail call.
+ TailRet, // tail.call may only be followed by ret.
+ TailRetVoid, // Void ret type expected for tail call.
+ TailRetType, // Tail call return type not compatible.
+ TailStackEmpty, // Stack not empty after tail call.
+ MethodEnd, // Method ends in the middle of an instruction.
+ BadBranch, // Branch out of the method.
+ //E_LEXICAL_NESTING "Lexical nesting."
+ Volatile, // Missing ldsfld, stsfld, ldind, stind, ldfld, stfld, ldobj, stobj, initblk, or cpblk.
+ Unaligned, // Missing ldind, stind, ldfld, stfld, ldobj, stobj, initblk, cpblk.
+ //E_INNERMOST_FIRST "Innermost exception blocks should be declared first."
+ CallAbstract, // Call not allowed on abstract methods.
+ TryNonEmptyStack, // Attempt to enter a try block with nonempty stack.
+ FilterOrCatchUnexpectedStack, // Attempt to enter a filter or catch block with unexpected stack state.
+ FinOrFaultNonEmptyStack, // Attempt to enter a finally or fault block with nonempty stack.
+ DelegateCtor, // Unrecognized arguments for delegate .ctor.
+ DelegatePattern, // Dup, ldvirtftn, newobj delegate::.ctor() pattern expected (in the same basic block).
+ //E_SIG_C_VC "ELEMENT_TYPE_CLASS ValueClass in signature."
+ //E_SIG_VC_C "ELEMENT_TYPE_VALUETYPE non-ValueClass in signature."
+ //E_BOX_PTR_TO_STACK "Box operation on TypedReference, ArgHandle, or ArgIterator."
+ BoxByRef, // Cannot box byref.
+ //E_SIG_BYREF_TB_AH "ByRef of TypedReference, ArgHandle, or ArgIterator."
+ EndfilterStack, // Stack not empty when leaving an exception filter.
+ DelegateCtorSigI, // Unrecognized delegate .ctor signature; expected Native Int.
+ DelegateCtorSigO, // Unrecognized delegate .ctor signature; expected Object.
+ //E_RA_PTR_TO_STACK "Mkrefany on TypedReference, ArgHandle, or ArgIterator."
+ CatchByRef, // ByRef not allowed as catch type.
+ LdvirtftnOnStatic, // ldvirtftn on static.
+ CallVirtOnStatic, // callvirt on static.
+ InitLocals, // initlocals must be set for verifiable methods with one or more local variables.
+ CallCtor, // call to .ctor only allowed to initialize this pointer from within a .ctor. Try newobj.
+
+ ////@GENERICSVER: new generics related error messages
+ ExpectedValClassObjRefVariable, // Value type, ObjRef type or variable type expected.
+ ReadOnly, // Missing ldelema or call following readonly prefix.
+ Constrained, // Missing callvirt following constrained prefix.
+
+ //E_CIRCULAR_VAR_CONSTRAINTS "Method parent has circular class type parameter constraints."
+ //E_CIRCULAR_MVAR_CONSTRAINTS "Method has circular method type parameter constraints."
+
+ UnsatisfiedMethodInst, // Method instantiation has unsatisfied method type parameter constraints.
+ UnsatisfiedMethodParentInst, // Method parent instantiation has unsatisfied class type parameter constraints.
+ UnsatisfiedFieldParentInst, // Field parent instantiation has unsatisfied class type parameter constraints.
+ UnsatisfiedBoxOperand, // Type operand of box instruction has unsatisfied class type parameter constraints.
+ ConstrainedCallWithNonByRefThis, // The 'this' argument to a constrained call must have ByRef type.
+ //E_CONSTRAINED_OF_NON_VARIABLE_TYPE "The operand to a constrained prefix instruction must be a type parameter."
+ ReadonlyUnexpectedCallee, // The readonly prefix may only be applied to calls to array methods returning ByRefs.
+ ReadOnlyIllegalWrite, // Illegal write to readonly ByRef.
+ //E_READONLY_IN_MKREFANY "A readonly ByRef cannot be used with mkrefany."
+ //E_UNALIGNED_ALIGNMENT "Alignment specified for 'unaligned' prefix must be 1, 2, or 4."
+ TailCallInsideER, // The tail.call (or calli or callvirt) instruction cannot be used to transfer control out of a try, filter, catch, or finally block.
+ BackwardBranch, // Stack height at all points must be determinable in a single forward scan of IL.
+ //E_CALL_TO_VTYPE_BASE "Call to base type of valuetype."
+ NewobjAbstractClass, // Cannot construct an instance of abstract class.
+ UnmanagedPointer, // Unmanaged pointers are not a verifiable type.
+ LdftnNonFinalVirtual, // Cannot LDFTN a non-final virtual method for delegate creation if target object is potentially not the same type as the method class.
+ //E_FIELD_OVERLAP "Accessing type with overlapping fields."
+ ThisMismatch, // The 'this' parameter to the call must be the calling method's 'this' parameter.
+
+ //E_BAD_PE "Unverifiable PE Header/native stub."
+ //E_BAD_MD "Unrecognized metadata, unable to verify IL."
+ //E_BAD_APPDOMAIN "Unrecognized appdomain pointer."
+
+ //E_TYPELOAD "Type load failed."
+ //E_PE_LOAD "Module load failed."
+
+ //IDS_E_FORMATTING "Error formatting message."
+ //IDS_E_ILERROR "[IL]: Error: "
+ //IDS_E_GLOBAL "<GlobalFunction>"
+ //IDS_E_MDTOKEN "[mdToken=0x%x]"
+ InterfaceImplHasDuplicate, // InterfaceImpl has a duplicate
+ InterfaceMethodNotImplemented // Class implements interface but not method
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>netcoreapp3.1</TargetFramework>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="System.CommandLine" Version="$(SystemCommandLineVersion)" />
+ <ProjectReference Include="..\ILVerification\ILVerification.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="..\Common\CommandLine\CommandLineException.cs">
+ <Link>CommandLine\CommandLineException.cs</Link>
+ </Compile>
+ <Compile Include="..\Common\CommandLine\CommandLineHelpers.cs">
+ <Link>CommandLine\CommandLineHelpers.cs</Link>
+ </Compile>
+ </ItemGroup>
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.CommandLine;
+using System.CommandLine.Invocation;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.PortableExecutable;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Internal.CommandLine;
+using Internal.TypeSystem.Ecma;
+using static System.Console;
+
+namespace ILVerify
+{
+ class Program : ResolverBase
+ {
+ private Options _options;
+ private Dictionary<string, string> _inputFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); // map of simple name to file path
+ private Dictionary<string, string> _referenceFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); // map of simple name to file path
+ private IReadOnlyList<Regex> _includePatterns;
+ private IReadOnlyList<Regex> _excludePatterns;
+ private IReadOnlyList<Regex> _ignoreErrorPatterns;
+
+ private Verifier _verifier;
+
+ public static IReadOnlyList<Regex> StringPatternsToRegexList(IReadOnlyList<string> patterns)
+ {
+ List<Regex> patternList = new List<Regex>();
+ if (patterns != null)
+ {
+ foreach (var pattern in patterns)
+ patternList.Add(new Regex(pattern, RegexOptions.Compiled));
+ }
+ return patternList;
+ }
+
+ public class Options
+ {
+ public string[] InputFilePath { get; set; }
+ public string[] Reference { get; set; }
+ public string SystemModule { get; set; }
+ public string[] Include { get; set; }
+ public FileInfo IncludeFile { get; set; }
+ public string[] Exclude { get; set; }
+ public FileInfo ExcludeFile { get; set; }
+ public string[] IgnoreError { get; set; }
+ public FileInfo IgnoreErrorFile { get; set; }
+ public bool Statistics { get; set; }
+ public bool Verbose { get; set; }
+ public bool Tokens { get; set; }
+ }
+
+ public static RootCommand RootCommand()
+ {
+ RootCommand command = new RootCommand();
+ command.AddArgument(new Argument<string[]>("input-file-path", "Input file(s)") { Arity = new ArgumentArity(1, Int32.MaxValue) });
+ command.AddOption(new Option<string[]>(new[] { "--reference", "-r" }, "Reference metadata from the specified assembly"));
+ command.AddOption(new Option<string>(new[] { "--system-module", "-s" }, "System module name (default: mscorlib)"));
+ command.AddOption(new Option<string[]>(new[] { "--include", "-i" }, "Use only methods/types/namespaces, which match the given regular expression(s)"));
+ command.AddOption(new Option<FileInfo>(new[] { "--include-file" }, "Same as --include, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly());
+ command.AddOption(new Option<string[]>(new[] { "--exclude", "-e" }, "Skip methods/types/namespaces, which match the given regular expression(s)"));
+ command.AddOption(new Option<FileInfo>(new[] { "--exclude-file" }, "Same as --exclude, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly());
+ command.AddOption(new Option<string[]>(new[] { "--ignore-error", "-g" }, "Ignore errors, which match the given regular expression(s)"));
+ command.AddOption(new Option<FileInfo>(new[] { "--ignore-error-file" }, "Same as --ignore-error, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly());
+ command.AddOption(new Option<bool>(new[] { "--statistics" }, "Print verification statistics"));
+ command.AddOption(new Option<bool>(new[] { "--verbose", "-v" }, "Verbose output"));
+ command.AddOption(new Option<bool>(new[] { "--tokens", "-t" }, "Include metadata tokens in error messages"));
+ return command;
+ }
+
+ private Program(Options options)
+ {
+ _options = options;
+
+ if (options.InputFilePath != null)
+ {
+ foreach (var input in options.InputFilePath)
+ Helpers.AppendExpandedPaths(_inputFilePaths, input, true);
+ }
+
+ if (options.Reference != null)
+ {
+ foreach (var reference in options.Reference)
+ Helpers.AppendExpandedPaths(_referenceFilePaths, reference, false);
+ }
+
+ string[] includePatterns = options.Include;
+ if (options.IncludeFile != null)
+ {
+ if (options.Include.Length != 0)
+ WriteLine("[Warning] --include-file takes precedence over --include");
+ includePatterns = File.ReadAllLines(options.IncludeFile.FullName);
+ }
+ _includePatterns = StringPatternsToRegexList(includePatterns);
+
+ string[] excludePatterns = options.Exclude;
+ if (options.ExcludeFile != null)
+ {
+ if (options.Exclude.Length != 0)
+ WriteLine("[Warning] --exclude-file takes precedence over --exclude");
+ excludePatterns = File.ReadAllLines(options.ExcludeFile.FullName);
+ }
+ _excludePatterns = StringPatternsToRegexList(excludePatterns);
+
+ string[] ignoreErrorPatterns = options.IgnoreError;
+ if (options.IgnoreErrorFile != null)
+ {
+ if (options.IgnoreError.Length != 0)
+ WriteLine("[Warning] --ignore-error-file takes precedence over --ignore-error");
+ ignoreErrorPatterns = File.ReadAllLines(options.IgnoreErrorFile.FullName);
+ }
+ _ignoreErrorPatterns = StringPatternsToRegexList(ignoreErrorPatterns);
+
+ if (options.Verbose)
+ {
+ WriteLine();
+ foreach (var path in _inputFilePaths)
+ WriteLine($"Using input file '{path.Value}'");
+
+ WriteLine();
+ foreach (var path in _referenceFilePaths)
+ WriteLine($"Using reference file '{path.Value}'");
+
+ WriteLine();
+ foreach (var pattern in _includePatterns)
+ WriteLine($"Using include pattern '{pattern}'");
+
+ WriteLine();
+ foreach (var pattern in _excludePatterns)
+ WriteLine($"Using exclude pattern '{pattern}'");
+
+ WriteLine();
+ foreach (var pattern in _ignoreErrorPatterns)
+ WriteLine($"Using ignore error pattern '{pattern}'");
+ }
+ }
+
+ private int Run()
+ {
+ _verifier = new Verifier(this, GetVerifierOptions());
+ _verifier.SetSystemModuleName(new AssemblyName(_options.SystemModule ?? "mscorlib"));
+
+ int numErrors = 0;
+
+ foreach (var kvp in _inputFilePaths)
+ {
+ numErrors += VerifyAssembly(new AssemblyName(kvp.Key), kvp.Value);
+ }
+
+ if (numErrors > 0)
+ {
+ return 2;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private VerifierOptions GetVerifierOptions()
+ {
+ return new VerifierOptions { IncludeMetadataTokensInErrorMessages = _options.Tokens };
+ }
+
+ private void PrintVerifyMethodsResult(VerificationResult result, EcmaModule module, string pathOrModuleName)
+ {
+ Write("[IL]: Error [");
+ if (result.Code != VerifierError.None)
+ {
+ Write(result.Code);
+ }
+ else
+ {
+ Write(result.ExceptionID);
+ }
+ Write("]: ");
+
+ Write("[");
+ Write(pathOrModuleName);
+ Write(" : ");
+
+ MetadataReader metadataReader = module.MetadataReader;
+
+ TypeDefinition typeDef = metadataReader.GetTypeDefinition(metadataReader.GetMethodDefinition(result.Method).GetDeclaringType());
+ string typeNamespace = metadataReader.GetString(typeDef.Namespace);
+ Write(typeNamespace);
+ Write(".");
+ string typeName = metadataReader.GetString(typeDef.Name);
+ Write(typeName);
+
+ Write("::");
+ var method = (EcmaMethod)module.GetMethod(result.Method);
+ PrintMethod(method);
+ Write("]");
+
+ if (result.Code != VerifierError.None)
+ {
+ Write("[offset 0x");
+ Write(result.GetArgumentValue<int>("Offset").ToString("X8"));
+ Write("]");
+
+ if (result.TryGetArgumentValue("Found", out string found))
+ {
+ Write("[found ");
+ Write(found);
+ Write("]");
+ }
+
+ if (result.TryGetArgumentValue("Expected", out string expected))
+ {
+ Write("[expected ");
+ Write(expected);
+ Write("]");
+ }
+
+ if (result.TryGetArgumentValue("Token", out int token))
+ {
+ Write("[token 0x");
+ Write(token.ToString("X8"));
+ Write("]");
+ }
+ }
+
+ Write(" ");
+ WriteLine(result.Message);
+ }
+
+ private static void PrintMethod(EcmaMethod method)
+ {
+ Write(method.Name);
+ Write("(");
+ try
+ {
+ if (method.Signature.Length > 0)
+ {
+ bool first = true;
+ for (int i = 0; i < method.Signature.Length; i++)
+ {
+ Internal.TypeSystem.TypeDesc parameter = method.Signature[i];
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ Write(", ");
+ }
+
+ Write(parameter.ToString());
+ }
+ }
+ }
+ catch
+ {
+ Write("Error while getting method signature");
+ }
+ Write(")");
+ }
+
+ private int VerifyAssembly(AssemblyName name, string path)
+ {
+ PEReader peReader = Resolve(name.Name);
+ EcmaModule module = _verifier.GetModule(peReader);
+
+ return VerifyAssembly(peReader, module, path);
+ }
+
+ private int VerifyAssembly(PEReader peReader, EcmaModule module, string path)
+ {
+ int numErrors = 0;
+ int verifiedMethodCounter = 0;
+ int methodCounter = 0;
+ int verifiedTypeCounter = 0;
+ int typeCounter = 0;
+
+ VerifyMethods(peReader, module, path, ref numErrors, ref verifiedMethodCounter, ref methodCounter);
+ VerifyTypes(peReader, module, path, ref numErrors, ref verifiedTypeCounter, ref typeCounter);
+
+ if (numErrors > 0)
+ WriteLine(numErrors + " Error(s) Verifying " + path);
+ else
+ WriteLine("All Classes and Methods in " + path + " Verified.");
+
+ if (_options.Statistics)
+ {
+ WriteLine($"Types found: {typeCounter}");
+ WriteLine($"Types verified: {verifiedTypeCounter}");
+
+ WriteLine($"Methods found: {methodCounter}");
+ WriteLine($"Methods verified: {verifiedMethodCounter}");
+ }
+
+ return numErrors;
+ }
+
+ private void VerifyMethods(PEReader peReader, EcmaModule module, string path, ref int numErrors, ref int verifiedMethodCounter, ref int methodCounter)
+ {
+ numErrors = 0;
+ verifiedMethodCounter = 0;
+ methodCounter = 0;
+
+ MetadataReader metadataReader = peReader.GetMetadataReader();
+ foreach (var methodHandle in metadataReader.MethodDefinitions)
+ {
+ // get fully qualified method name
+ var methodName = GetQualifiedMethodName(metadataReader, methodHandle);
+
+ bool verifying = ShouldVerifyMemberName(methodName);
+ if (_options.Verbose)
+ {
+ Write(verifying ? "Verifying " : "Skipping ");
+ WriteLine(methodName);
+ }
+
+ if (verifying)
+ {
+ var results = _verifier.Verify(peReader, methodHandle);
+ foreach (var result in results)
+ {
+ if (ShouldIgnoreVerificationResult(result))
+ {
+ if (_options.Verbose)
+ {
+ Write("Ignoring ");
+ PrintVerifyMethodsResult(result, module, path);
+ }
+ }
+ else
+ {
+ PrintVerifyMethodsResult(result, module, path);
+ numErrors++;
+ }
+ }
+
+ verifiedMethodCounter++;
+ }
+
+ methodCounter++;
+ }
+ }
+
+ private void VerifyTypes(PEReader peReader, EcmaModule module, string path, ref int numErrors, ref int verifiedTypeCounter, ref int typeCounter)
+ {
+ MetadataReader metadataReader = peReader.GetMetadataReader();
+
+ foreach (TypeDefinitionHandle typeHandle in metadataReader.TypeDefinitions)
+ {
+ // get fully qualified type name
+ var className = GetQualifiedClassName(metadataReader, typeHandle);
+ bool verifying = ShouldVerifyMemberName(className);
+ if (_options.Verbose)
+ {
+ Write(verifying ? "Verifying " : "Skipping ");
+ WriteLine(className);
+ }
+ if (verifying)
+ {
+ var results = _verifier.Verify(peReader, typeHandle);
+ foreach (VerificationResult result in results)
+ {
+ if (ShouldIgnoreVerificationResult(result))
+ {
+ if (_options.Verbose)
+ {
+ Write("Ignoring ");
+ Console.WriteLine(result.Message, result.Args);
+ }
+ }
+ else
+ {
+ Console.WriteLine(result.Message, result.Args);
+ numErrors++;
+ }
+ }
+
+ typeCounter++;
+ }
+
+ verifiedTypeCounter++;
+ }
+ }
+
+ /// <summary>
+ /// This method returns the fully qualified class name.
+ /// </summary>
+ private string GetQualifiedClassName(MetadataReader metadataReader, TypeDefinitionHandle typeHandle)
+ {
+ var typeDef = metadataReader.GetTypeDefinition(typeHandle);
+ var typeName = metadataReader.GetString(typeDef.Name);
+
+ var namespaceName = metadataReader.GetString(typeDef.Namespace);
+ var assemblyName = metadataReader.GetString(metadataReader.IsAssembly ? metadataReader.GetAssemblyDefinition().Name : metadataReader.GetModuleDefinition().Name);
+
+ StringBuilder builder = new StringBuilder();
+ builder.Append($"[{assemblyName}]");
+ if (!string.IsNullOrEmpty(namespaceName))
+ builder.Append($"{namespaceName}.");
+ builder.Append($"{typeName}");
+
+ return builder.ToString();
+ }
+
+ /// <summary>
+ /// This method returns the fully qualified method name by concatenating assembly, type and method name.
+ /// This method exists to avoid additional assembly resolving, which might be triggered by calling
+ /// MethodDesc.ToString().
+ /// </summary>
+ private string GetQualifiedMethodName(MetadataReader metadataReader, MethodDefinitionHandle methodHandle)
+ {
+ var methodDef = metadataReader.GetMethodDefinition(methodHandle);
+ var typeDef = metadataReader.GetTypeDefinition(methodDef.GetDeclaringType());
+
+ var methodName = metadataReader.GetString(metadataReader.GetMethodDefinition(methodHandle).Name);
+ var typeName = metadataReader.GetString(typeDef.Name);
+ var namespaceName = metadataReader.GetString(typeDef.Namespace);
+ var assemblyName = metadataReader.GetString(metadataReader.IsAssembly ? metadataReader.GetAssemblyDefinition().Name : metadataReader.GetModuleDefinition().Name);
+
+ StringBuilder builder = new StringBuilder();
+ builder.Append($"[{assemblyName}]");
+ if (!string.IsNullOrEmpty(namespaceName))
+ builder.Append($"{namespaceName}.");
+ builder.Append($"{typeName}.{methodName}");
+
+ return builder.ToString();
+ }
+
+ private bool ShouldVerifyMemberName(string memberName)
+ {
+ if (_includePatterns.Count > 0 && !_includePatterns.Any(p => p.IsMatch(memberName)))
+ {
+ return false;
+ }
+
+ if (_excludePatterns.Any(p => p.IsMatch(memberName)))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private bool ShouldIgnoreVerificationResult(VerificationResult result)
+ {
+ var error = result.Code.ToStringInvariant();
+ if (result.Code == VerifierError.None && result.ExceptionID != null)
+ {
+ error = result.ExceptionID?.ToStringInvariant();
+ }
+
+ if (_ignoreErrorPatterns.Any(p => p.IsMatch(error)))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected override PEReader ResolveCore(string simpleName)
+ {
+ string path = null;
+ if (_inputFilePaths.TryGetValue(simpleName, out path) || _referenceFilePaths.TryGetValue(simpleName, out path))
+ {
+ return new PEReader(File.OpenRead(path));
+ }
+
+ return null;
+ }
+
+ private static int Run(Options options)
+ {
+ try
+ {
+ return new Program(options).Run();
+ }
+ catch (CommandLineException e)
+ {
+ Console.WriteLine("Error: " + e.Message);
+ return 1;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error: " + e.ToString());
+ return 1;
+ }
+ }
+
+ private static async Task<int> Main(string[] args)
+ {
+ var command = RootCommand();
+ command.Handler = CommandHandler.Create<Options>(Run);
+ return await command.InvokeAsync(args);
+ }
+ }
+}
--- /dev/null
+# ILVerify
+
+### This directory contains the implementation of ILVerify
+
+## Intention of this project:
+The goal is to create a standalone, cross platform, open-source tool that is capable of verifying MSIL code based on [ECMA-335](https://www.ecma-international.org/publications/standards/Ecma-335.htm).
+
+The main users of this tool are people working on software that emits MSIL code. These are typically compiler and profiler writers.
+
+## Other tools
+Historically on Full Framework IL generators used PEVerify to make sure that they generated correct IL. PEVerify has some major limitations (e.g. it is tied to the Full Framework, it cannot verify mscorlib.dll, etc.), which initiated this project.
+
+## Main properties of ILVerify:
+- No coupling with CoreLib: ILVerify can point to any assembly and verify it. This also includes the full framework base assemblies (especially mscorlib).
+- Cross-platform, Open-Source
+- It should be easy to add new verification rules
+- Fast spin up/tear down.
+
+## The codebase
+The project targets netcoreapp2.1 and uses the new .csproj based project format. If you want to open and compile it with Visual Studio then you need a version, which supports .NET Core 2.1 tooling. This is supported in Visual Studio 2017 Version 15.8 or later. The other option is to use command (with .NET Core 2.1 tooling).
+The code is split into three projects:
+- ILVerification is the library with the core verification logic,
+- ILVerification.Tests contains the tests for ILVerification,
+- ILVerify is an application that provides a command-line interface on top of ILVerification.
+
+## Tests
+
+To test the ILVerification library we have small methods checked in as .il files testing specific verification scenarios. These tests live under [src/ILVerification/tests/ILTests](../ILVerification/tests/ILTests). Tests are grouped into .il files based on functionalities they test. There is no strict policy here, the goal is to have a few dozen .il files instead of thousands containing each only a single method.
+
+The test project itself is under [src/coreclr/tests/src/ilverify](../../../tests/src/ilverify)
+
+ Method names in the .il files must follow the following naming convention:
+
+### Methods with Valid IL:
+
+```
+[FriendlyName]_Valid
+```
+The method must contain 1 '`_`'.
+ - The part before the `_` is a friendly name describing what the method does.
+ - The word after the `_` must be 'Valid' (Case sensitive)
+
+E.g.: ```SimpleAdd_Valid```
+
+### Methods with Invalid IL:
+```
+[FriendlyName]_Invalid_[ExpectedVerifierError1].[ExpectedVerifierError2]....[ExpectedVerifierErrorN]
+```
+
+The method name must contain 2 '`_`' characters.
+ 1. part: a friendly name
+ 2. part: must be the word 'Invalid' (Case sensitive)
+ 3. part: the expected [VerifierErrors](../ILVerification/src/VerifierError.cs) as string separated by '.'. We assert on these errors; the test fails if ILVerify does not report these errors.
+
+ E.g.: ```SimpleAdd_Invalid_ExpectedNumericType```
+
+### Methods with special names:
+
+In order to test methods with special names (e.g. '.ctor'), the specialname method is defined as usual and a separate empty method is added to the type:
+```
+special.[FriendlyName].[SpecialName]_[Valid | Invalid]_[ExpectedVerifierError1].[ExpectedVerifierError2]....[ExpectedVerifierErrorN]
+```
+
+The format of the special test method is equal to normal valid or invalid tests, except that the first part must contain 3 sub-parts separated by '`.`':
+ 1. part: the '`special`' prefix
+ 2. part: a friendly name
+ 3. part: the name of the specialname method to actually test
+
+Additionally the method signature of the special test method must be equal to the signature of the method that shall be tested.
+
+ E.g.: In order to test a specific invalid constructor method the specialname `.ctor` method is defined as usual, while an additional method ```'special.SimpleAdd..ctor_Invalid_StackUnexpected'``` is defined.
+
+
+The methods are automatically fed into appropriate XUnit theories based on the naming convention. Methods not following this naming conventions are ignored by the test scaffolding system.
+
+You can run the tests either in Visual Studio (in Test Explorer) or with the ```dotnet test ``` command from the command line.
+
+## How to contribute
+All ILVerify issues are labeled with [area-ILVerification](https://github.com/search?utf8=%E2%9C%93&q=label%3Aarea-ILVerification&type=).
+
+ILVerify basically runs through the IL commands in an assembly and does all the verification steps that are specified in ECMA-335.
+
+Currently every IL command falls into one of these categories:
+
+ - Not implemented: the implementation is completely missing. The easiest way is to pick one of them (look for NotImplentedException in the code) and implement it. First you should 100% understand the spec. (see [ECMA-335](https://www.ecma-international.org/publications/standards/Ecma-335.htm)), then try to port an existing implementation (sources below).
+ - Partially implemented: These are typically methods with TODOs in it. As the first phase we want to make sure that for every command the stack is correctly maintained, therefore for some commands we either have no verification or we have only a not complete verification. You can also pick one of these and finish it.
+ - Implemented: find and fix bugs ;) .
+
+Another option to contribute is to write tests (see Tests section).
+
+Useful sources:
+ - [PEVerify source code](https://github.com/lewischeng-ms/sscli/blob/master/clr/src/jit64/newverify.cpp)
+ - [RyuJIT source code](https://github.com/dotnet/runtime/tree/master/src/coreclr/src/jit), specifically: [exception handling specific part](https://github.com/dotnet/runtime/blob/master/src/coreclr/src/jit/jiteh.cpp), [importer.cpp](https://github.com/dotnet/runtime/blob/master/src/coreclr/src/jit/importer.cpp) (look for `Compiler::ver`, `Verify`, `VerifyOrReturn`, and `VerifyOrReturnSpeculative`), [_typeinfo.h](https://github.com/dotnet/runtime/blob/master/src/coreclr/src/jit/_typeinfo.h), [typeinfo.cpp](https://github.com/dotnet/runtime/blob/master/src/coreclr/src/jit/typeinfo.cpp)
+ - [ECMA-335 standard](https://www.ecma-international.org/publications/standards/Ecma-335.htm)
+ - [Expert .NET 2.0 IL Assembler book](http://www.apress.com/us/book/9781590596463) by Serge Lidin
</PropertyGroup>
<ItemGroup>
<Compile Include="ICustomMarshaler.cs" />
- <Compile Include="..\..\common\XunitBase.cs" />
+ <Compile Include="..\..\..\Common\XunitBase.cs" />
</ItemGroup>
<PropertyGroup>
<CLRTestNeedTarget>1</CLRTestNeedTarget>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+using ILVerify;
+using Internal.TypeSystem.Ecma;
+using Xunit;
+
+namespace ILVerification.Tests
+{
+ public class ILMethodTester
+ {
+ [Theory(DisplayName = "")]
+ [MemberData(nameof(TestDataLoader.GetMethodsWithValidIL), MemberType = typeof(TestDataLoader))]
+ [Trait("", "Valid IL Tests")]
+ void TestMethodsWithValidIL(ValidILTestCase validIL)
+ {
+ var results = Verify(validIL);
+ Assert.Empty(results);
+ }
+
+ [Theory(DisplayName = "")]
+ [MemberData(nameof(TestDataLoader.GetMethodsWithInvalidIL), MemberType = typeof(TestDataLoader))]
+ [Trait("", "Invalid IL Tests")]
+ void TestMethodsWithInvalidIL(InvalidILTestCase invalidIL)
+ {
+ IEnumerable<VerificationResult> results = null;
+
+ try
+ {
+ results = Verify(invalidIL);
+ }
+ catch
+ {
+ //in some cases ILVerify throws exceptions when things look too wrong to continue
+ //currently these are not caught. In tests we just catch these and do the asserts.
+ //Once these exceptions are better handled and ILVerify instead of crashing aborts the verification
+ //gracefully we can remove this empty catch block.
+ }
+ finally
+ {
+ Assert.NotNull(results);
+ Assert.Equal(invalidIL.ExpectedVerifierErrors.Count, results.Count());
+
+ foreach (var item in invalidIL.ExpectedVerifierErrors)
+ {
+ var actual = results.Select(e => e.Code.ToString());
+ Assert.True(results.Where(r => r.Code == item).Count() > 0, $"Actual errors where: {string.Join(",", actual)}");
+ }
+ }
+ }
+
+ private static IEnumerable<VerificationResult> Verify(TestCase testCase)
+ {
+ EcmaModule module = TestDataLoader.GetModuleForTestAssembly(testCase.ModuleName);
+ var methodHandle = (MethodDefinitionHandle) MetadataTokens.EntityHandle(testCase.MetadataToken);
+ var method = (EcmaMethod)module.GetMethod(methodHandle);
+ var verifier = new Verifier((ILVerifyTypeSystemContext)method.Context, new VerifierOptions() { IncludeMetadataTokensInErrorMessages = true });
+ return verifier.Verify(module.PEReader, methodHandle);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly extern AccessTestsFriend
+{
+}
+
+.assembly AccessTests
+{
+}
+
+.class private auto ansi beforefieldinit PrivateClass
+{
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit GenericClass<S, T>
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit SimpleClass
+ extends [System.Runtime]System.Object
+{
+ .field public static int32 publicField
+ .field private static int32 privateField
+ .field family static int32 familyField
+ .field assembly static int32 assemblyField
+ .field famorassem static int32 familyOrAssemblyField
+ .field famandassem static int32 familyAndAssemblyField
+
+ .field family int32 instanceFamilyField
+
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method private hidebysig static void PrivateMethod() cil managed
+ {
+ ret
+ }
+
+ .method family hidebysig static void FamilyMethod() cil managed
+ {
+ ret
+ }
+
+ .method assembly hidebysig static void AssemblyMethod() cil managed
+ {
+ ret
+ }
+
+ .method famorassem hidebysig static void FamilyOrAssemblyMethod() cil managed
+ {
+ ret
+ }
+
+ .method famandassem hidebysig static void FamilyAndAssemblyMethod() cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig static void InaccessibleParamMethod(class SimpleClass/PrivateNestedClass c) cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig static void GenericMethod<T>() cil managed
+ {
+ ret
+ }
+
+ .method family hidebysig instance void FamilyMethod() cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig static class SimpleClass/PrivateNestedClass InaccessibleReturnMethod() cil managed
+ {
+ newobj instance void SimpleClass/PrivateNestedClass::.ctor()
+ ret
+ }
+
+ .class nested public auto ansi beforefieldinit PublicNestedClass
+ extends [System.Runtime]System.Object
+ {
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig static void Instantiate.PrivateNestedClassFromNested_Valid() cil managed
+ {
+ newobj instance void SimpleClass/PrivateNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig static void Load.PrivateFieldFromNestedClass_Valid() cil managed
+ {
+ ldsfld int32 SimpleClass::privateField
+ pop
+ ret
+ }
+ }
+
+ .class nested private auto ansi beforefieldinit PrivateNestedClass
+ extends [System.Runtime]System.Object
+ {
+ .field public static int32 publicField
+
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+ }
+
+ .class nested assembly auto ansi beforefieldinit AssemblyNestedClass
+ extends [System.Runtime]System.Object
+ {
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+ }
+
+ .class nested famorassem auto ansi beforefieldinit FamilyOrAssemblyNestedClass
+ extends [System.Runtime]System.Object
+ {
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+ }
+
+ .class nested famandassem auto ansi beforefieldinit FamilyAndAssemblyNestedClass
+ extends [System.Runtime]System.Object
+ {
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+ }
+
+ .class nested family auto ansi beforefieldinit FamilyNestedClass
+ extends [System.Runtime]System.Object
+ {
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+ }
+
+ .method private hidebysig static void Call.PrivateClassParamIntern_Valid(class SimpleClass/PrivateNestedClass c) cil managed
+ {
+ ldarg.0
+ call void SimpleClass::InaccessibleParamMethod(class SimpleClass/PrivateNestedClass)
+ ret
+ }
+
+ .method private hidebysig static void Call.PrivateReturnTypeIntern_Valid() cil managed
+ {
+ call class SimpleClass/PrivateNestedClass SimpleClass::InaccessibleReturnMethod()
+ pop
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit AccessTestsType
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig instance void Instantiate.PublicNestedClass_Valid() cil managed
+ {
+ newobj instance void SimpleClass/PublicNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.PrivateNestedClass_Invalid_MethodAccess() cil managed
+ {
+ newobj instance void SimpleClass/PrivateNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.AssemNestedClass_Valid() cil managed
+ {
+ newobj instance void SimpleClass/AssemblyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.AssemOrFamNestedClass_Valid() cil managed
+ {
+ newobj instance void SimpleClass/FamilyOrAssemblyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.AssemAndFamNestedClass_Invalid_MethodAccess() cil managed
+ {
+ newobj instance void SimpleClass/FamilyAndAssemblyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.FamilyNestedClass_Invalid_MethodAccess() cil managed
+ {
+ newobj instance void SimpleClass/FamilyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.GenericWithPrivateNestedClass_Invalid_MethodAccess() cil managed
+ {
+ newobj instance void class GenericClass<class SimpleClass/PrivateNestedClass, class SimpleClass/PublicNestedClass>::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Call.PrivateClassParamExtern_Invalid_MethodAccess(class SimpleClass/PrivateNestedClass c) cil managed
+ {
+ ldarg.1
+ call void SimpleClass::InaccessibleParamMethod(class SimpleClass/PrivateNestedClass)
+ ret
+ }
+
+ .method public hidebysig instance void Call.PrivateReturnTypeExtern_Invalid_MethodAccess() cil managed
+ {
+ call class SimpleClass/PrivateNestedClass SimpleClass::InaccessibleReturnMethod()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Call.GenericMethodWithPrivateNestedClass_Invalid_MethodAccess() cil managed
+ {
+ call void class SimpleClass::GenericMethod<class SimpleClass/PrivateNestedClass>()
+ ret
+ }
+
+ .method public hidebysig instance void Load.PrivateFieldExtern_Invalid_FieldAccess() cil managed
+ {
+ ldsfld int32 SimpleClass::privateField
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Load.PublicFieldOfPrivateClass_Invalid_FieldAccess() cil managed
+ {
+ ldsfld int32 SimpleClass/PrivateNestedClass::publicField
+ pop
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit DerivedType
+ extends SimpleClass
+{
+ .method public hidebysig instance void Call.DerivedFamAndAssemblyMethod_Valid() cil managed
+ {
+ call void SimpleClass::FamilyAndAssemblyMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.FamOrAssemblyNestedClassFromDerived_Valid() cil managed
+ {
+ newobj instance void SimpleClass/FamilyOrAssemblyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.FamNestedClassFromDerived_Valid() cil managed
+ {
+ newobj instance void SimpleClass/FamilyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method private hidebysig instance void Load.FamFieldOfBaseWithBaseInstance_Invalid_FieldAccess(class SimpleClass c) cil managed
+ {
+ ldarg.1
+ ldfld int32 SimpleClass::instanceFamilyField
+ pop
+ ret
+ }
+
+ .method private hidebysig instance void Load.FamFieldOfBaseWithDerivedInstance_Valid() cil managed
+ {
+ ldarg.0
+ ldfld int32 SimpleClass::instanceFamilyField
+ pop
+ ret
+ }
+
+ .method private hidebysig instance void Call.FamMethodOfBaseWithBaseInstance_Invalid_MethodAccess(class SimpleClass c) cil managed
+ {
+ ldarg.1
+ call instance void SimpleClass::FamilyMethod()
+ ret
+ }
+
+ .method private hidebysig instance void Call.FamMethodOfBaseWithDerivedInstance_Valid() cil managed
+ {
+ ldarg.0
+ call instance void SimpleClass::FamilyMethod()
+ ret
+ }
+
+ .method private hidebysig instance void Load.AssemFieldOfFriendAssembly_Valid() cil managed
+ {
+ ldsfld int32 [AccessTestsFriend]AccessTestsFriendType::assemblyField
+ pop
+ ret
+ }
+
+ .method private hidebysig instance void Load.PrivateFieldOfFriendAssembly_Invalid_FieldAccess() cil managed
+ {
+ ldsfld int32 [AccessTestsFriend]AccessTestsFriendType::privateField
+ pop
+ ret
+ }
+}
+
+// Special case: Nested class trying to access family field of superclass of containing class
+
+.class private auto ansi beforefieldinit SuperClass
+ extends [System.Runtime]System.Object
+{
+ .field family static int32 familyField
+ .field family int32 instanceFamilyField
+
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+}
+
+.class private auto ansi beforefieldinit NestedClass
+ extends SuperClass
+{
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void SuperClass::.ctor()
+ ret
+ }
+
+ .class nested private auto ansi beforefieldinit NestedClass
+ extends [System.Runtime]System.Object
+ {
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method private hidebysig instance void Load.FamFieldOfSuperOfContaining_Valid() cil managed
+ {
+ ldsfld int32 SuperClass::familyField
+ pop
+ ret
+ }
+ }
+}
+
+// Test for bugfix https://github.com/dotnet/corert/issues/6693
+
+.class public auto ansi beforefieldinit Issue6693
+ extends [System.Runtime]System.Object
+{
+
+ .class nested public auto ansi abstract beforefieldinit InnerClass`1<(Issue6693) T>
+ extends class Issue6693Base`1<!T>
+ {
+ .method public hidebysig virtual
+ instance void BaseMethod_Valid (
+ int32 index,
+ !T item
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: nop
+ IL_0001: ldarg.2
+ IL_0002: box !T
+ IL_0007: callvirt instance void Issue6693::ParentMethod()
+ IL_000c: nop
+ IL_000d: ret
+ }
+
+ .method family hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void class Issue6693Base`1<!T>::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ }
+ }
+
+ .method family hidebysig
+ instance void ParentMethod () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: nop
+ IL_0001: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ }
+}
+
+.class public auto ansi beforefieldinit Issue6693Base`1<T>
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig newslot virtual
+ instance void BaseMethod_Valid (
+ int32 index,
+ !T item
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: nop
+ IL_0001: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly extern AccessTests
+{
+}
+
+.assembly extern AccessTestsFriend
+{
+}
+
+.assembly AccessTestsExtern
+{
+}
+
+.class public auto ansi beforefieldinit AccessTestsType
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig instance void Instantiate.PublicClass_Valid() cil managed
+ {
+ newobj instance void [AccessTests]SimpleClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.PrivateClass_Invalid_MethodAccess() cil managed
+ {
+ newobj instance void [AccessTests]PrivateClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.PublicNested_Valid() cil managed
+ {
+ newobj instance void [AccessTests]SimpleClass/PublicNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.PrivateNested_Invalid_MethodAccess() cil managed
+ {
+ newobj instance void [AccessTests]SimpleClass/PrivateNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.AssemblyNested_Invalid_MethodAccess() cil managed
+ {
+ newobj instance void [AccessTests]SimpleClass/AssemblyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.FamOrAssemNested_Invalid_MethodAccess() cil managed
+ {
+ newobj instance void [AccessTests]SimpleClass/FamilyOrAssemblyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.FamAndAssemNested_Invalid_MethodAccess() cil managed
+ {
+ newobj instance void [AccessTests]SimpleClass/FamilyAndAssemblyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.FamilyNested_Invalid_MethodAccess() cil managed
+ {
+ newobj instance void [AccessTests]SimpleClass/FamilyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Call.PrivateMethod_Invalid_MethodAccess() cil managed
+ {
+ call void [AccessTests]SimpleClass::PrivateMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Call.FamilyMethod_Invalid_MethodAccess() cil managed
+ {
+ call void [AccessTests]SimpleClass::FamilyMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Call.AssemblyMethod_Invalid_MethodAccess() cil managed
+ {
+ call void [AccessTests]SimpleClass::AssemblyMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Call.FamOrAssemMethod_Invalid_MethodAccess() cil managed
+ {
+ call void [AccessTests]SimpleClass::FamilyOrAssemblyMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Call.FamAndAssemMethod_Invalid_MethodAccess() cil managed
+ {
+ call void [AccessTests]SimpleClass::FamilyAndAssemblyMethod()
+ ret
+ }
+
+ .method private hidebysig instance void Load.AssemFieldOfFriendAssemblyWithSpace_Valid() cil managed
+ {
+ ldsfld int32 [AccessTestsFriend]AccessTestsFriendType::assemblyField
+ pop
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit DerivedType
+ extends [AccessTests]SimpleClass
+{
+ .method public hidebysig instance void Call.DerivedFamMethod_Valid() cil managed
+ {
+ call void [AccessTests]SimpleClass::FamilyMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Call.DerivedFamOrAssemMethod_Valid() cil managed
+ {
+ call void [AccessTests]SimpleClass::FamilyOrAssemblyMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Call.DerivedFamAndAssemMethod_Invalid_MethodAccess() cil managed
+ {
+ call void [AccessTests]SimpleClass::FamilyAndAssemblyMethod()
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit DerivedClass
+ extends [AccessTests]SimpleClass
+{
+ .method public hidebysig instance void Instantiate.FamAndAssemNestedClassFromDerived_Invalid_MethodAccess() cil managed
+ {
+ newobj instance void [AccessTests]SimpleClass/FamilyAndAssemblyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.FamOrAssemNestedClassFromDerived_Valid() cil managed
+ {
+ newobj instance void [AccessTests]SimpleClass/FamilyOrAssemblyNestedClass::.ctor()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Instantiate.FamNestedClassFromDerived_Valid() cil managed
+ {
+ newobj instance void [AccessTests]SimpleClass/FamilyNestedClass::.ctor()
+ pop
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly extern AccessTests
+{
+}
+
+.assembly AccessTestsFriend
+{
+ // InternalsVisibleTo("AccessTests")
+ .custom instance void [System.Runtime]System.Runtime.CompilerServices.InternalsVisibleToAttribute::.ctor(string) = (
+ 01 00 0b 41 63 63 65 73 73 54 65 73 74 73 00 00
+ )
+
+ // InternalsVisibleTo("AccessTestsExtern ")
+ // ^ purposeful space at the end
+ .custom instance void [System.Runtime]System.Runtime.CompilerServices.InternalsVisibleToAttribute::.ctor(string) = (
+ 01 00 12 41 63 63 65 73 73 54 65 73 74 73 45 78
+ 74 65 72 6e 20 00 00
+ )
+}
+
+.class private auto ansi beforefieldinit AccessTestsFriendType
+ extends [System.Runtime]System.Object
+{
+ .field private static int32 privateField
+ .field assembly static int32 assemblyField
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly ArrayTests
+{
+}
+
+.class public auto ansi beforefieldinit ArrayTestsType
+ extends [System.Runtime]System.Object
+{
+
+ .method public hidebysig instance void StoreElement.Int8IntoBoolArray_Valid() cil managed
+ {
+ // bool[] a = new bool[];
+ // a[0] = true;
+
+ ldc.i4.1
+ newarr [System.Runtime]System.Boolean
+ ldc.i4.0
+ ldc.i4.1
+ stelem.i1
+ ret
+ }
+
+ .method public hidebysig instance void StoreElement.Int16IntoCharArray_Valid() cil managed
+ {
+ // char[] a = new char[];
+ // a[0] = 'a';
+
+ ldc.i4.1
+ newarr [System.Runtime]System.Char
+ ldc.i4.0
+ ldc.i4.s 97
+ stelem.i2
+ ret
+ }
+
+ .method public hidebysig instance void LoadElement.UInt16FromCharArray_Valid() cil managed
+ {
+ .locals init (
+ [0] char[],
+ [1] char
+ )
+
+ // char[] a = new char[];
+ // a[0] = 'a';
+ // char b = a[0];
+
+ ldc.i4.1
+ newarr [System.Runtime]System.Char
+ stloc.0
+ ldloc.0
+ ldc.i4.0
+ ldc.i4.s 97
+ stelem.i2
+ ldloc.0
+ ldc.i4.0
+ ldelem.u2
+ stloc.1
+ ret
+ }
+
+ .method public hidebysig instance void LoadElement.UInt8FromBoolArray_Valid() cil managed
+ {
+ .locals init (
+ [0] bool[],
+ [1] bool
+ )
+
+ // bool[] a = new bool[];
+ // a[0] = true;
+ // bool b = a[0];
+
+ ldc.i4.1
+ newarr [System.Runtime]System.Boolean
+ stloc.0
+ ldloc.0
+ ldc.i4.0
+ ldc.i4.1
+ stelem.i1
+ ldloc.0
+ ldc.i4.0
+ ldelem.u1
+ stloc.1
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly BasicArithmeticTests
+{
+}
+
+.class public auto ansi beforefieldinit BasicArithmeticTestsType
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig instance int32
+ SimpleAdd_Valid(int32 a,
+ int32 b) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ add
+ ret
+ }
+
+ .method public hidebysig instance void SimpleAdd_Invalid_ExpectedNumericType() cil managed
+ {
+ ldstr "sfdsf"
+ ldc.i4.3
+ add
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly BranchingTests
+{
+}
+
+// Custom Comparer class implementing IEqualityComparer for testing
+.class private auto ansi beforefieldinit CustomComparer
+ extends [System.Runtime]System.Object
+ implements [System.Runtime]System.Collections.IEqualityComparer
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance bool Equals (
+ object x,
+ object y
+ ) cil managed
+ {
+ ldc.i4.0
+ ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance int32 GetHashCode (
+ object obj
+ ) cil managed
+ {
+ ldarg.1
+ callvirt instance int32 [System.Runtime]System.Object::GetHashCode()
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit BranchingTestsType
+ extends [System.Runtime]System.Object
+{
+ // Volatile field for testing
+ .field private static int32 modreq([System.Runtime]System.Runtime.CompilerServices.IsVolatile) volatileField
+
+ .method static public hidebysig void StaticMethod() cil managed
+ {
+ ret
+ }
+
+ .method static public hidebysig void Branching.NullConditional_Valid() cil managed
+ {
+ //object o = null;
+ //Type t = o != null ? o.GetType() : null;
+ //Type.GetTypeCode(t);
+
+ .maxstack 1
+ .locals init (
+ [0] object o
+ )
+
+ IL_0000: ldnull
+ IL_0001: stloc.0
+ IL_0002: ldloc.0
+ IL_0003: brtrue.s IL_0008
+
+ IL_0005: ldnull
+ IL_0006: br.s IL_000E
+
+ IL_0008: ldloc.0
+ IL_0009: callvirt instance class [System.Runtime]System.Type [System.Runtime]System.Object::GetType()
+
+ IL_000E: call valuetype [System.Runtime]System.TypeCode [System.Runtime]System.Type::GetTypeCode(class [System.Runtime]System.Type)
+ IL_0013: pop
+ IL_0014: ret
+ }
+
+ .method static public hidebysig void Branching.NullConditional_Invalid_StackUnexpected() cil managed
+ {
+ //object o = null;
+ //Type t = o != null ? o.GetType() : o;
+ //Type.GetTypeCode(t);
+
+ .maxstack 1
+ .locals init (
+ [0] object o
+ )
+
+ IL_0000: ldnull
+ IL_0001: stloc.0
+ IL_0002: ldloc.0
+ IL_0003: brtrue.s IL_0008
+
+ IL_0005: ldloc.0
+ IL_0006: br.s IL_000E
+
+ IL_0008: ldloc.0
+ IL_0009: callvirt instance class [System.Runtime]System.Type [System.Runtime]System.Object::GetType()
+
+ IL_000E: call valuetype [System.Runtime]System.TypeCode [System.Runtime]System.Type::GetTypeCode(class [System.Runtime]System.Type)
+ IL_0013: pop
+ IL_0014: ret
+ }
+
+ .method static public hidebysig void Branching.UnequalStackMerge_Valid(class [System.Runtime]System.Collections.IEqualityComparer equalityComparer,
+ class CustomComparer customComparer) cil managed
+ {
+ .maxstack 1
+ .locals init(
+ [0] class [System.Runtime]System.Collections.IEqualityComparer
+ )
+
+ ldc.i4.0
+ brfalse.s lbl_cComp
+
+ ldarg.0
+ br.s lbl_store
+
+ lbl_cComp:
+ ldarg.1
+
+ lbl_store:
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Branching.UnequalStackMergeConstrained_Valid<([System.Runtime]System.Collections.IEqualityComparer) T>
+ (class [System.Runtime]System.Collections.IEqualityComparer equalityComparer, !!T customComparer) cil managed
+ {
+ .maxstack 1
+ .locals init(
+ [0] class [System.Runtime]System.Collections.IEqualityComparer
+ )
+
+ ldc.i4.0
+ brfalse.s lbl_cComp
+
+ ldarg.0
+ br.s lbl_store
+
+ lbl_cComp:
+ ldarg.1
+ box !!T
+
+ lbl_store:
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Branching.UnequalStackMergeArrays_Valid(class CustomComparer[] comparers,
+ class [System.Runtime]System.Collections.IEqualityComparer[] customComparer) cil managed
+ {
+ .maxstack 1
+ .locals init(
+ [0] class [System.Runtime]System.Collections.IEqualityComparer[]
+ )
+
+ ldarg.0
+ brfalse.s lbl_cComp
+
+ ldarg.0
+ br.s lbl_store
+
+ lbl_cComp:
+ ldarg.1
+
+ lbl_store:
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Branching.UnequalStackMergeArrays_Invalid_StackUnexpected(class CustomComparer[] comparers,
+ class [System.Runtime]System.Collections.IEqualityComparer[] customComparer) cil managed
+ {
+ .maxstack 1
+ .locals init(
+ [0] class CustomComparer[]
+ )
+
+ ldarg.0
+ brfalse.s lbl_cComp
+
+ ldarg.0
+ br.s lbl_store
+
+ lbl_cComp:
+ ldarg.1
+
+ lbl_store:
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Branching.UnequalStackMergeGeneric_Invalid_PathStackUnexpected<T>(!!T generic,
+ object obj) cil managed
+ {
+ .maxstack 1
+ .locals init(
+ [0] object obj
+ )
+
+ ldarg.1
+ brfalse.s lbl_gen
+
+ ldarg.1
+ br.s lbl_store
+
+ lbl_gen:
+ ldarg.0
+
+ lbl_store:
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Branching.UnequalStackMergeGenericArrayConstrain_Valid<(int32[]) T>(!!T generic,
+ int32[] arr) cil managed
+ {
+ .maxstack 1
+ .locals init(
+ [0] int32[] dest
+ )
+
+ ldarg.1
+ brfalse.s lbl_arr
+
+ ldarg.0
+ box !!T
+ br.s lbl_store
+
+ lbl_arr:
+ ldarg.1
+
+ lbl_store:
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Branching.InsideTry_Valid() cil managed
+ {
+ .maxstack 2
+
+ .try
+ {
+ ldc.i4.s 10
+ ldc.i4.s 5
+ bne.un.s lbl_true
+
+ nop
+ br.s lbl_leave
+
+ lbl_true: nop
+
+ lbl_leave: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branching.OutOfTry_Invalid_BranchOutOfTry() cil managed
+ {
+ .maxstack 2
+
+ .try
+ {
+ ldc.i4.s 10
+ ldc.i4.s 5
+ bne.un.s lbl_true
+
+ nop
+ br.s lbl_ret
+
+ lbl_true: nop
+
+ lbl_leave: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branching.IntoTryStart_Valid() cil managed
+ {
+ .maxstack 2
+
+ ldc.i4.s 10
+ ldc.i4.s 5
+ bne.un.s lbl_true
+
+ nop
+ br.s lbl_ret
+
+ .try
+ {
+ lbl_true: nop
+
+ leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branching.IntoTryMiddle_Invalid_BranchIntoTry() cil managed
+ {
+ .maxstack 2
+
+ ldc.i4.s 10
+ ldc.i4.s 5
+ bne.un.s lbl_true
+
+ nop
+ br.s lbl_ret
+
+ .try
+ {
+ nop
+ lbl_true: nop
+
+ leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branching.IntoNestedTryStart_Valid() cil managed
+ {
+ .maxstack 2
+
+ .try
+ {
+ ldc.i4.s 10
+ ldc.i4.s 5
+ bne.un.s lbl_true
+
+ nop
+ br.s lbl_leave
+ .try
+ {
+ lbl_true: nop
+
+ leave.s lbl_leave
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_leave
+ }
+
+ lbl_leave: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branching.IntoDoubleNestedTryStart_Invalid_BranchIntoTry() cil managed
+ {
+ .try
+ {
+ nop
+ br Inner
+
+ .try
+ {
+ nop
+
+ .try
+ {
+ Inner:
+ leave.s A
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s A
+ }
+ A:
+
+ leave.s B
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s B
+ }
+ B:
+
+ leave.s C
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s C
+ }
+ C:
+
+ ret
+ }
+
+ .method static public hidebysig void Branching.IntoDoubleNestedTryStartStart_Valid() cil managed
+ {
+ .try
+ {
+ nop
+ br Inner
+
+ .try
+ {
+ .try
+ {
+ Inner:
+ leave.s A
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s A
+ }
+ A:
+
+ leave.s B
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s B
+ }
+ B:
+
+ leave.s C
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s C
+ }
+ C:
+
+ ret
+ }
+
+ .method static public hidebysig void Branching.IntoDoubleNestedTryStartFromOutside_Invalid_BranchIntoTry() cil managed
+ {
+ br Inner
+
+ .try
+ {
+ nop
+
+ .try
+ {
+ Inner:
+ leave.s A
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s A
+ }
+ A:
+
+ leave.s B
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s B
+ }
+ B:
+
+ ret
+ }
+
+ .method static public hidebysig void Branching.IntoTryStartWithPredecessor_Valid() cil managed
+ {
+ .try
+ {
+ nop
+ br Inner
+
+ .try
+ {
+ leave.s A
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s A
+ }
+
+ .try
+ {
+ Inner:
+ leave.s A
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s A
+ }
+
+ A:
+
+ leave.s C
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s C
+ }
+ C:
+
+ ret
+ }
+
+ .method static public hidebysig void Branching.IntoNestedTryMiddle_Invalid_BranchIntoTry() cil managed
+ {
+ .maxstack 2
+
+ .try
+ {
+ ldc.i4.s 10
+ ldc.i4.s 5
+ bne.un.s lbl_true
+
+ nop
+ br.s lbl_leave
+ .try
+ {
+ nop
+ lbl_true: nop
+
+ leave.s lbl_leave
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_leave
+ }
+
+ lbl_leave: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branching.FromTryIntoCatch_Invalid_BranchOutOfTry.BranchIntoHandler() cil managed
+ {
+ .maxstack 2
+
+ .try
+ {
+ ldc.i4.s 10
+ ldc.i4.s 5
+ bne.un.s lbl_true
+
+ nop
+ leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ lbl_true: nop
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branching.FromTryIntoFilter_Invalid_BranchOutOfTry.BranchIntoFilter() cil managed
+ {
+ .try
+ {
+ br.s lbl_filter
+ }
+ filter
+ {
+ lbl_filter: pop
+ ldc.i4.0
+ endfilter
+ }
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branching.FromTryIntoFinally_Invalid_BranchOutOfTry.BranchIntoHandler() cil managed
+ {
+ .maxstack 2
+
+ .try
+ {
+ ldc.i4.s 10
+ ldc.i4.s 5
+ bne.un.s lbl_finally
+
+ nop
+ leave.s lbl_ret
+ }
+ finally
+ {
+ lbl_finally: nop
+ endfinally
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branching.OutOfFinally_Invalid_BranchOutOfFinally() cil managed
+ {
+ .maxstack 2
+
+ .try
+ {
+ leave.s lbl_ret
+ }
+ finally
+ {
+ br lbl_ret
+ endfinally
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branching.FromTryIntoOtherTryStart_Invalid_BranchOutOfTry() cil managed
+ {
+ .maxstack 2
+
+ .try
+ {
+ ldc.i4.s 10
+ ldc.i4.s 5
+ bne.un.s lbl_try2
+
+ nop
+ leave.s lbl_try
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_try
+ }
+
+ lbl_try: nop
+ .try
+ {
+ lbl_try2: nop
+ leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branching.OutOfTrySameStart_Invalid_BranchOutOfTry() cil managed
+ {
+ .try
+ {
+ .try
+ {
+ br A
+
+ leave.s A
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s A
+ }
+ A:
+
+ leave.s B
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s B
+ }
+ B:
+
+ ret
+ }
+
+ .method static public hidebysig void Branching.FromTryIntoOtherTryMiddle_Invalid_BranchOutOfTry() cil managed
+ {
+ .maxstack 2
+
+ .try
+ {
+ ldc.i4.s 10
+ ldc.i4.s 5
+ bne.un.s lbl_try2
+
+ nop
+ leave.s lbl_try
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_try
+ }
+
+ lbl_try: nop
+ .try
+ {
+ nop
+ lbl_try2: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Fallthrough.OutOfTryIntoFinally_Invalid_FallthroughException.FallthroughIntoHandler() cil managed
+ {
+ .try
+ {
+ nop
+ }
+ finally
+ {
+ endfinally
+ }
+ }
+
+ .method static public hidebysig void Fallthrough.OutOfTryIntoCatch_Invalid_FallthroughException.FallthroughIntoHandler() cil managed
+ {
+ .try
+ {
+ nop
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Fallthrough.OutOfCatch_Invalid_FallthroughException() cil managed
+ {
+ .try
+ {
+ nop
+ leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Fallthrough.OutOfTryIntoFilter_Invalid_FallthroughException.FallthroughIntoFilter() cil managed
+ {
+ .try
+ {
+ nop
+ }
+ filter
+ {
+ pop
+ ldc.i4.0
+ endfilter
+ }
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Branch.BeforeReadonlyInstruction_Valid(object[] objectArray) cil managed
+ {
+ // objectArray[0];
+
+ ldarg.0
+ ldc.i4.0
+ br BeforeInstr
+
+ BeforeInstr:
+ readonly.
+ ldelema [System.Runtime]System.Object
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Branch.IntoReadonlyInstruction_Invalid_BadJumpTarget(object[] objectArray) cil managed
+ {
+ // objectArray[0];
+
+ ldarg.0
+ ldc.i4.0
+ br MidInstr
+
+ readonly.
+ MidInstr:
+ ldelema [System.Runtime]System.Object
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Branch.IntoConstrainedInstruction_Invalid_BadJumpTarget<T>(!!T arg) cil managed
+ {
+ // arg.ToString();
+ ldarga.s arg
+ br MidInstr
+
+ constrained. !!T
+ MidInstr:
+ callvirt instance string [System.Runtime]System.Object::ToString()
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Branch.AfterConstrainedInstruction_Valid<T>(!!T arg) cil managed
+ {
+ // arg.ToString();
+ ldarga.s arg
+ br AfterInstr
+
+ constrained. !!T
+ callvirt instance string [System.Runtime]System.Object::ToString()
+ AfterInstr:
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Branch.IntoVolatileInstruction_Invalid_BadJumpTarget() cil managed
+ {
+ // volatileField = 0;
+
+ ldc.i4.0
+ br MidInstr
+
+ volatile.
+ MidInstr:
+ stsfld int32 modreq([System.Runtime]System.Runtime.CompilerServices.IsVolatile) BranchingTestsType::volatileField
+ ret
+ }
+
+ .method static public hidebysig void Branch.IntoUnalignedInstruction_Invalid_BadJumpTarget() cil managed
+ {
+ .locals init (
+ int32&
+ )
+
+ ldloc.0
+ br MidInstr
+
+ unaligned. 4
+ MidInstr:
+ ldind.i4
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Branch.IntoUnalignedVolatileInstruction_Invalid_BadJumpTarget() cil managed
+ {
+ .locals init (
+ int32&
+ )
+
+ ldloc.0
+ br MidInstr
+
+ unaligned. 4
+ volatile.
+ MidInstr:
+ ldind.i4
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Branch.IntoTailInstruction_Invalid_BadJumpTarget() cil managed
+ {
+ br MidInstr
+
+ tail.
+ MidInstr:
+ call void BranchingTestsType::StaticMethod()
+ ret
+ }
+
+ .method static public hidebysig void Branch.BackwardWithPredecessor_Valid() cil managed
+ {
+ ldnull
+ ldc.i4.0
+ brfalse MethodEnd
+
+ BackwardBranch:
+ pop
+
+ ldnull
+ ldc.i4.1
+ brtrue BackwardBranch
+
+ MethodEnd:
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Branch.BackwardWithoutPredecessor_Invalid_BackwardBranch() cil managed
+ {
+ br MethodEnd
+
+ BackwardBranch:
+ pop
+
+ MethodEnd:
+ ldnull
+ ldc.i4.1
+ brtrue BackwardBranch
+
+ pop
+ ret
+ }
+
+ .method static public hidebysig void BrFalseS.Backward_Valid() cil managed
+ {
+ BackwardBranch:
+ // Note: additional nops to increase branch delta
+ nop
+ nop
+ ldc.i4.0
+ brfalse.s BackwardBranch
+
+ ret
+ }
+
+ .method static public hidebysig void Branch.BackwardEmptyStack_Valid() cil managed
+ {
+ br MethodEnd
+
+ BackwardBranch:
+ nop
+
+ MethodEnd:
+ ldc.i4.1
+ brtrue BackwardBranch
+
+ ret
+ }
+
+ .method static public hidebysig void Branch.BackwardWithComplexPredecessor_Valid() cil managed
+ {
+ ldnull
+ br MethodEnd
+
+ Predecessor:
+ ldnull
+
+ BackwardBranch:
+ pop
+
+ ldnull
+ ldc.i4.1
+ brtrue BackwardBranch
+
+ MethodEnd:
+ pop
+ ldc.i4.1
+ brtrue Predecessor
+
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly CallTests
+{
+}
+
+.class public auto ansi beforefieldinit SimpleClass
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig newslot virtual instance void VirtualMethod() cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig static void InObjectMethod([in] object&) cil managed
+ {
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit DerivedClass
+ extends SimpleClass
+{
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void SimpleClass::.ctor()
+ ret
+ }
+
+ .method public hidebysig virtual instance void VirtualMethod() cil managed
+ {
+ ldarg.0
+ call instance void SimpleClass::VirtualMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Call.BaseMethod_Valid() cil managed
+ {
+ ldarg.0
+ call instance void SimpleClass::VirtualMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Call.BaseMethodModThisLdarga_Invalid_ThisMismatch() cil managed
+ {
+ ldarg.0
+ call instance void SimpleClass::VirtualMethod()
+ ldarga 0
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Call.BaseMethodModThisStarg_Invalid_ThisMismatch() cil managed
+ {
+ ldarg.0
+ call instance void SimpleClass::VirtualMethod()
+ ldarg.0
+ starg 0
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit CallTestsType
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig instance void Call.IntToStringManagedPtr_Valid() cil managed
+ {
+ .locals init (
+ [0] int32
+ )
+
+ ldc.i4.0
+ stloc.0
+ ldloca.s 0
+ call instance string [System.Runtime]System.Int32::ToString()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Call.IntToStringBoxed_Valid() cil managed
+ {
+ .locals init (
+ [0] int32
+ )
+
+ ldc.i4.0
+ box [System.Runtime]System.Int32
+ call instance string [System.Runtime]System.Object::ToString()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Callvirt.IntToStringBoxed_Valid() cil managed
+ {
+ .locals init (
+ [0] int32
+ )
+
+ ldc.i4.0
+ box [System.Runtime]System.Int32
+ callvirt instance string [System.Runtime]System.Object::ToString()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Call.IntToStringUnboxed_Invalid_StackUnexpected() cil managed
+ {
+ .locals init (
+ [0] int32
+ )
+
+ ldc.i4.0
+ call instance string [System.Runtime]System.Int32::ToString()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Call.ExternBaseMethod_Invalid_ThisMismatch(class DerivedClass c) cil managed
+ {
+ ldarg.1
+ call instance void SimpleClass::VirtualMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Call.ReadonlyByRefForInArg_Invalid_StackUnexpected(object[] objectArray) cil managed
+ {
+ // SimpleClass.InObjectMethod(objectArray[0]);
+
+ ldarg.1
+ ldc.i4.0
+ readonly.
+ ldelema [System.Runtime]System.Object
+ call void SimpleClass::InObjectMethod(object&)
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly CastingTests
+{
+}
+
+// Provides tests for casting arrays
+.class public auto ansi beforefieldinit ArrayCastingTestsType
+ extends [System.Runtime]System.Object
+{
+ // Array<T> tests
+ .method static public hidebysig void Casting.ArrayOfTToEnumerableOfT_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.Generic.IEnumerable`1<int32> V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToEnumerable_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.IEnumerable V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToICollectionOfT_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.Generic.ICollection`1<int32> V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToICollection_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.ICollection V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToIListOfT_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.Generic.IList`1<int32> V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToIList_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.IList V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToIReadOnlyCollectionOfT_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.Generic.IReadOnlyCollection`1<int32> V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToIReadOnlyListOfT_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.Generic.IReadOnlyList`1<int32> V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToArray_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Array V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Assign.ConstrainedGenericToComparable_Valid<(class [System.Runtime]System.IComparable`1<!!T>) T>(!!T t)
+ {
+ .locals init (
+ class [System.Runtime]System.IComparable`1<!!T> c
+ )
+
+ ldarg.0
+ box !!T
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Assign.ComplexConstrainedGenericToComparable_Valid<(!!S) T, (class [System.Runtime]System.IComparable`1<!!T>) S>(!!T t)
+ {
+ .locals init (
+ class [System.Runtime]System.IComparable`1<!!T> c
+ )
+
+ ldarg.0
+ box !!T
+ stloc.0
+ ret
+ }
+}
+
+.class public sequential ansi sealed beforefieldinit GenericOtherFieldsType`1<T>
+ extends [System.Runtime]System.ValueType
+{
+ .field public !T GenericField;
+ .field int32 IntField;
+}
+
+.class public sequential ansi beforefieldinit GenericTypeWithConstrained<class ([System.Runtime]System.IComparable) TValueType>
+ extends [System.Runtime]System.Object
+{
+ .property !TValueType Value()
+ {
+ .get instance !0 GenericTypeWithConstrained::get_Value()
+ }
+ .method public !TValueType get_Value()
+ {
+ ldc.i4 0x00000000
+ ret
+ }
+}
+
+// Provides casting logic tests for stfld, ldfld, call, callvirt
+.class public auto ansi beforefieldinit GenericCastingTestsType`1<T>
+ extends [System.Runtime]System.Object
+{
+ .field private int32 ThisIntField
+ .method public hidebysig instance void Casting.StorePlainFieldInThisGenericType_Valid(int32 v) cil managed
+ {
+ ldarg.0
+ ldarg.1
+ stfld int32 class GenericCastingTestsType`1<!T>::ThisIntField
+ ret
+ }
+
+ .method public hidebysig instance void Casting.StorePlainFieldInOtherGenericType_Valid(int32 v) cil managed
+ {
+ .locals init (
+ class GenericOtherFieldsType`1<!T> V_0
+ )
+
+ ldloc.0
+ ldarg.1
+ stfld !0 class GenericOtherFieldsType`1<!T>::IntField
+ ret
+ }
+
+ .field private !T ThisGenericField
+ .method public hidebysig instance void Casting.StoreGenericFieldInThisGenericType_Valid(!T v) cil managed
+ {
+ ldarg.0
+ ldarg.1
+ stfld !0 class GenericCastingTestsType`1<!T>::ThisGenericField
+ ret
+ }
+
+ .method public hidebysig instance void Casting.StoreGenericFieldInOtherGenericType_Valid(!T v) cil managed
+ {
+ .locals init (
+ class GenericOtherFieldsType`1<!T> V_0
+ )
+ ldloc.0
+ ldarg.1
+ stfld !0 class GenericOtherFieldsType`1<!T>::GenericField
+ ret
+ }
+
+ .method public hidebysig instance void Casting.CallPlainFunctionFromThisGenericType_Valid(int32 v) cil managed
+ {
+ ldarg.0
+ ldarg.1
+ callvirt instance void class GenericCastingTestsType`1<!T>::Casting.StorePlainFieldInThisGenericType_Valid(int32)
+ ret
+ }
+
+ .method public hidebysig instance void Casting.CallGenericFunctionFromThisGenericType_Valid(!T v) cil managed
+ {
+ ldarg.0
+ ldarg.1
+ callvirt instance void class GenericCastingTestsType`1<!T>::Casting.CallGenericFunctionFromOtherGenericType_Valid(!0)
+ ret
+ }
+
+ .method public hidebysig instance void Casting.CallGenericFunctionFromOtherGenericType_Valid(!T v) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Func`1<!T> V_0
+ )
+
+ ldloc.0
+ callvirt instance !0 class [System.Runtime]System.Func`1<!T>::Invoke()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Casting.AssignVariantInterfaceToObject_Valid(class [System.Runtime]System.Collections.Generic.IEnumerable`1<string> e) cil managed
+ {
+ .locals init (
+ object o
+ )
+
+ ldarg.1
+ stloc.0
+ ret
+ }
+
+ .method public hidebysig instance void Casting.AssignThisToSameTypeWithOtherGenericArgs_Invalid_StackUnexpected() cil managed
+ {
+ .locals init (
+ class GenericCastingTestsType`1<int32> V_0
+ )
+
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method public hidebysig instance void Casting.AssignGenericToObject_Valid(!T v) cil managed
+ {
+ .locals init (
+ object
+ )
+
+ ldarg.1
+ box !T
+ stloc.0
+ ret
+ }
+
+ .method public hidebysig static void Casting.AssignToSameTypeWithOtherGenericArgs_Invalid_StackUnexpected() cil managed
+ {
+ .locals init (
+ class GenericCastingTestsType`1<int32> V_0,
+ class GenericCastingTestsType`1<string> V_1
+ )
+
+ ldloc.0
+ stloc.1
+ ret
+ }
+
+ .method public static void Casting.AssignReturnValueFromConstrainedProperty_Valid<class ([System.Runtime]System.IComparable) TValueType>(class GenericTypeWithConstrained<!!TValueType> wrapper) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.IComparable V_0
+ )
+
+ ldarg.0
+ callvirt instance !0 class GenericTypeWithConstrained<!!TValueType>::get_Value()
+ box !!TValueType
+ stloc.0
+ ret
+ }
+}
+
+// Class with private nested class
+.class public auto ansi beforefieldinit ContainingClass
+ extends [System.Runtime]System.Object
+{
+ .class nested private auto ansi beforefieldinit PrivateNestedClass
+ extends [System.Runtime]System.Object
+ {
+ }
+}
+
+
+// Test enum
+.class public auto ansi sealed Enum
+ extends [System.Runtime]System.Enum
+{
+ .field public static literal valuetype Enum EnumValue1 = int32(0)
+ .field public static literal valuetype Enum EnumValue2 = int32(1)
+
+ .field public specialname rtspecialname int32 value__
+}
+
+.class public auto ansi beforefieldinit CastingTestsType
+ extends [System.Runtime]System.Object
+{
+ .method public static void Casting.AssignPrimitiveToIComparable_Valid(int32 arg) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.IComparable
+ )
+
+ ldarg.0
+ box [System.Runtime]System.Int32
+ stloc.0
+ ret
+ }
+
+ .method public static void Casting.CastToInaccessibleType_Invalid_TypeAccess() cil managed
+ {
+ ldnull
+ castclass ContainingClass/PrivateNestedClass
+ pop
+ ret
+ }
+
+ .method public static void Casting.CastClassInt_Invalid_StackObjRef() cil managed
+ {
+ ldc.i4.0
+ castclass CastingTestsType
+ pop
+ ret
+ }
+
+ .method public static void Casting.BoxInaccesibleType_Invalid_TypeAccess(class ContainingClass/PrivateNestedClass c) cil managed
+ {
+ ldarg.0
+ box ContainingClass/PrivateNestedClass
+ pop
+ ret
+ }
+
+ .method public static void Casting.BoxByRefInt_Invalid_BoxByRef.ExpectedValClassObjRefVariable(int32& i) cil managed
+ {
+ ldarg.0
+ box int32&
+ pop
+ ret
+ }
+
+ .method public static void Casting.BoxToUnsatisfiedConstraint_Invalid_UnsatisfiedBoxOperand(class GenericTypeWithConstrained<class [System.Runtime]System.Object> c) cil managed
+ {
+ ldarg.0
+ box class GenericTypeWithConstrained<class [System.Runtime]System.Object>
+ pop
+ ret
+ }
+
+ .method public static void Casting.BoxEnum_Valid(valuetype Enum e) cil managed
+ {
+ ldarg.0
+ box Enum
+ pop
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly ComparisonTests
+{
+}
+
+.class public auto ansi beforefieldinit ComparisonTestsType
+ extends [System.Runtime]System.Object
+{
+ .method static public hidebysig void Comparison.NullWithObjRef_Valid() cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Object V_0
+ )
+ ldnull
+ ldloc.0
+ cgt.un
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Comparison.ObjRefWithNull_Valid() cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Object V_0
+ )
+ ldloc.0
+ ldnull
+ cgt.un
+ pop
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly DelegateTests
+{
+}
+
+.class public auto ansi sealed ByteEnum
+ extends [System.Runtime]System.Enum
+{
+ .field public specialname rtspecialname uint8 value__
+ .field public static literal valuetype ByteEnum A = uint8(0)
+ .field public static literal valuetype ByteEnum B = uint8(0)
+}
+
+.class private auto ansi beforefieldinit DelegateTestsType
+ extends [System.Runtime]System.Object
+{
+ // assignment from Func<int, string> to Func<int, object> is valid
+ .method private hidebysig instance class [System.Runtime]System.Func`2<int32,object>
+ DelegateAssignmentReturn_Valid(class [System.Runtime]System.Func`2<int32,string> input) cil managed
+ {
+ ldarg.1
+ ret
+ }
+
+ // assignment from Func<object, int> to Func<string, int> is valid
+ .method private hidebysig instance class [System.Runtime]System.Func`2<string,int32>
+ DelegateAssignmentParameter_Valid(class [System.Runtime]System.Func`2<object,int32> input) cil managed
+ {
+ ldarg.1
+ ret
+ }
+
+ // assignment from Func<string, int> to Func<object, int> is invalid
+ .method private hidebysig instance class [System.Runtime]System.Func`2<object,int32>
+ DelegateAssignmentParameter_Invalid_StackUnexpected(class [System.Runtime]System.Func`2<string,int32> input) cil managed
+ {
+ ldarg.1
+ ret
+ }
+
+ // assignment from Func<int, object> to Func<int, string> is invalid
+ .method private hidebysig instance class [System.Runtime]System.Func`2<int32,string>
+ DelegateAssignment_Invalid_StackUnexpected(class [System.Runtime]System.Func`2<int32,object> input) cil managed
+ {
+ ldarg.1
+ ret
+ }
+
+ // assignment from Func<int> to Func<byte> is invalid
+ .method private hidebysig instance class [System.Runtime]System.Func`1<uint8>
+ AssignIntFuncToByteFunc_Invalid_StackUnexpected(class [System.Runtime]System.Func`2<int32> input) cil managed
+ {
+ ldarg.1
+ ret
+ }
+
+ // assignment from Func<byte> to Func<int> is invalid
+ .method private hidebysig instance class [System.Runtime]System.Func`1<int32>
+ AssignByteFuncToIntFunc_Invalid_StackUnexpected(class [System.Runtime]System.Func`1<uint8> input) cil managed
+ {
+ ldarg.1
+ ret
+ }
+
+ // assignment from Func<ByteEnum> to Func<byte> is invalid
+ .method private hidebysig instance class [System.Runtime]System.Func`1<uint8>
+ AssignByteActionToIntAction_Invalid_StackUnexpected(class [System.Runtime]System.Func`1<valuetype ByteEnum> input) cil managed
+ {
+ ldarg.1
+ ret
+ }
+
+ // assignment from Action<byte> to Action<int> is invalid
+ .method private hidebysig instance class [System.Runtime]System.Action`1<int32>
+ AssignByteActionToIntAction_Invalid_StackUnexpected(class [System.Runtime]System.Action`1<uint8> input) cil managed
+ {
+ ldarg.1
+ ret
+ }
+
+ // assignment from Action<ByteEnum> to Action<byte> is invalid
+ .method private hidebysig instance class [System.Runtime]System.Action`1<uint8>
+ AssignByteActionToByteEnumAction_Invalid_StackUnexpected(class [System.Runtime]System.Action`1<valuetype ByteEnum> input) cil managed
+ {
+ ldarg.1
+ ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly ExceptionRegionTests
+{
+}
+
+.class public sequential ansi sealed beforefieldinit ExceptionRegionTests
+ extends [System.Runtime]System.Object
+{
+ .method public instance void ExceptionRegion.NestedTryFinally_Valid() cil managed
+ {
+ .try
+ {
+ nop
+ leave EndTryCatch
+ }
+ finally
+ {
+ .try
+ {
+ nop
+ leave EndFinally
+ }
+ catch [System.Runtime]System.Exception
+ {
+ nop
+ leave EndFinally
+ }
+ EndFinally:
+ endfinally
+ }
+ EndTryCatch:
+ ret
+ }
+
+ .method public instance void Leave.ToSameFilter_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ filter
+ {
+ pop
+ leave SameFilter
+
+ SameFilter:
+ ldc.i4.0
+ endfilter
+ }
+ {
+ pop
+ leave MethodEnd
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToOtherFilter_Invalid_LeaveOutOfFilter.LeaveIntoFilter() cil managed
+ {
+ .try
+ {
+ leave AfterTry
+ }
+ filter
+ {
+ pop
+ leave OtherFilter
+
+ ldc.i4.0
+ endfilter
+ }
+ {
+ pop
+ leave MethodEnd
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ leave MethodEnd
+ }
+ filter
+ {
+ pop
+
+ OtherFilter:
+ ldc.i4.0
+ endfilter
+ }
+ {
+ pop
+ leave MethodEnd
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.OutOfFilter_Invalid_LeaveOutOfFilter() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ filter
+ {
+ pop
+ leave MethodEnd
+
+ ldc.i4.0
+ endfilter
+ }
+ {
+ pop
+ leave MethodEnd
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToSameFault_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ fault
+ {
+ leave SameFault
+
+ SameFault:
+ endfault
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToSameFinally_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ finally
+ {
+ leave SameFinally
+
+ SameFinally:
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToOtherFinally_Invalid_LeaveOutOfFinally.LeaveIntoHandler() cil managed
+ {
+ .try
+ {
+ leave AfterTry
+ }
+ finally
+ {
+ leave OtherFinally
+ endfinally
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ leave MethodEnd
+ }
+ finally
+ {
+ OtherFinally:
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToOtherFault_Invalid_LeaveOutOfFault.LeaveIntoFault.LeaveIntoHandler() cil managed
+ {
+ .try
+ {
+ leave AfterTry
+ }
+ fault
+ {
+ leave OtherFault
+ endfault
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ leave MethodEnd
+ }
+ fault
+ {
+ OtherFault:
+ endfault
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.OutOfFinally_Invalid_LeaveOutOfFinally() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ finally
+ {
+ leave MethodEnd
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.OutOfFault_Invalid_LeaveOutOfFault() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ fault
+ {
+ leave MethodEnd
+ endfault
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToSameTry_Valid() cil managed
+ {
+ .try
+ {
+ leave SameTry
+
+ SameTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToEnclosingTry_Valid() cil managed
+ {
+ .try
+ {
+ .try
+ {
+ leave EnclosingTry
+ }
+ finally
+ {
+ endfinally
+ }
+ EnclosingTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToFirstInstrOfDisjointTry_Valid() cil managed
+ {
+ .try
+ {
+ leave DisjointTry
+ }
+ finally
+ {
+ endfinally
+ }
+
+ .try
+ {
+ DisjointTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToFirstInstrOfNestedDisjointTry_Valid() cil managed
+ {
+ .try
+ {
+ leave DisjointTry
+ }
+ finally
+ {
+ endfinally
+ }
+
+ .try
+ {
+ .try
+ {
+ DisjointTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.IntoOtherTry_Invalid_LeaveIntoTry() cil managed
+ {
+ .try
+ {
+ leave OtherTry
+ }
+ finally
+ {
+ endfinally
+ }
+
+ .try
+ {
+ nop
+ OtherTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToSecondInstrOfNestedDisjointTry_Invalid_LeaveIntoTry() cil managed
+ {
+ .try
+ {
+ leave DisjointTry
+ }
+ finally
+ {
+ endfinally
+ }
+
+ .try
+ {
+ nop
+ .try
+ {
+ DisjointTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToFirstInstrOfEnclosedTry_Valid() cil managed
+ {
+ .try
+ {
+ leave EnclosedTry
+
+ .try
+ {
+ EnclosedTry:
+ leave TryEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ TryEnd:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromCatchIntoAssociatedTry_Valid() cil managed
+ {
+ .try
+ {
+ TryStart:
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave TryStart
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToSameCatch_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave SameCatch
+
+ SameCatch:
+ leave MethodEnd
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.OutOfCatch_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave MethodEnd
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.CatchToFirstInstrOfDisjointTry_Valid() cil managed
+ {
+ .try
+ {
+ leave AfterTry
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave DisjointTry
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ DisjointTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.CatchToFirstInstrOfNestedTry_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave NestedTry
+
+ .try
+ {
+ NestedTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ leave MethodEnd
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.CatchToSecondInstrOfNestedTry_Invalid_LeaveIntoTry() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave NestedTry
+
+ .try
+ {
+ nop
+ NestedTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ leave MethodEnd
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.TryToEnclosingCatch_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ .try
+ {
+ leave EnclosingCatch
+ }
+ finally
+ {
+ endfinally
+ }
+
+ EnclosingCatch:
+ leave MethodEnd
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.CatchToEnclosingTry_Valid() cil managed
+ {
+ .try
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave EnclosingTry
+ }
+
+ EnclosingTry:
+ leave MethodEnd
+ }
+ filter
+ {
+ pop
+ ldc.i4.0
+ endfilter
+ }
+ {
+ leave MethodEnd
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromOutsideIntoFilter_Invalid_LeaveIntoFilter() cil managed
+ {
+ leave IntoFilter
+
+ .try
+ {
+ leave MethodEnd
+ }
+ filter
+ {
+ pop
+ IntoFilter:
+ ldc.i4.0
+ endfilter
+ }
+ {
+ leave MethodEnd
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromOutsideIntoHandler_Invalid_LeaveIntoHandler() cil managed
+ {
+ leave IntoHandler
+
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ IntoHandler:
+ leave MethodEnd
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromOutsideIntoTry_Invalid_LeaveIntoTry() cil managed
+ {
+ leave IntoTry
+
+ .try
+ {
+ nop
+ IntoTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromNestedTryToDisjointTry_Valid() cil managed
+ {
+ .try
+ {
+ .try
+ {
+ leave DisjointTry
+ }
+ finally
+ {
+ endfinally
+ }
+ leave AfterTry
+ }
+ finally
+ {
+ endfinally
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ DisjointTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromNestedTryToDisjointTryBackward_Valid() cil managed
+ {
+ .try
+ {
+ DisjointTry:
+ leave AfterTry
+ }
+ finally
+ {
+ endfinally
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ .try
+ {
+ leave DisjointTry
+ }
+ finally
+ {
+ endfinally
+ }
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ MethodEnd:
+ ret
+ }
+}
+
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly FieldTests
+{
+}
+
+.class private auto ansi beforefieldinit ConstrainedClass`1<([System.Runtime]System.Collections.IEnumerable) T>
+ extends [System.Runtime]System.Object
+{
+ .field public static int32 StaticField
+
+ .method public hidebysig specialname rtspecialname instance void .ctor () cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit FieldTestsType
+ extends [System.Runtime]System.Object
+{
+ .field public initonly int32 InstanceInitonlyField
+ .field public static initonly int32 StaticInitonlyField
+
+ .method public instance void Stsfld.UnsatisfiedParentConstraints_Invalid_UnsatisfiedFieldParentInst() cil managed
+ {
+ ldc.i4.0
+ stsfld int32 class ConstrainedClass`1<int32>::StaticField
+ ret
+ }
+
+ .method public instance void Stfld.InitonlyFieldOutsideCtor_Invalid_InitOnly() cil managed
+ {
+ ldarg.0
+ ldc.i4.0
+ stfld int32 FieldTestsType::InstanceInitonlyField
+ ret
+ }
+
+ .method public instance void Ldflda.InitonlyFieldOutsideCtor_Invalid_InitOnly() cil managed
+ {
+ ldarg.0
+ ldflda int32 FieldTestsType::InstanceInitonlyField
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void 'special.StoreInitonlyField..ctor_Valid'() cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ldarg.0
+ ldc.i4.0
+ stfld int32 FieldTestsType::InstanceInitonlyField
+ ret
+ }
+
+ .method public hidebysig instance void 'special.LoadAddrInitonlyField..ctor_Valid'(int32) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(int32) cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ldarg.0
+ ldflda int32 FieldTestsType::InstanceInitonlyField
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void 'special.LoadAddrInitonlyField..ctor_Valid'(int64) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(int64) cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ldarg.0
+ ldflda int32 FieldTestsType::InstanceInitonlyField
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void 'special.StoreInitonlyFieldOtherType..ctor_Invalid_InitOnly'(class OtherType c) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(class OtherType c) cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ldarg.1
+ ldc.i4.0
+ stfld int32 OtherType::InstanceInitonlyField
+ ret
+ }
+
+ .method public hidebysig instance void 'special.StoreInitonlyFieldOtherInstance..ctor_Invalid_InitOnly'(class FieldTestsType c) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(class FieldTestsType c) cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ldarg.1
+ ldc.i4.0
+ stfld int32 FieldTestsType::InstanceInitonlyField
+ ret
+ }
+
+ .method public hidebysig instance void 'special.StsfldInitonlyInCtor..ctor_Invalid_InitOnly'(bool) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(bool) cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ldc.i4.0
+ stsfld int32 FieldTestsType::StaticInitonlyField
+ ret
+ }
+
+ .method public hidebysig instance void 'special.LdsfldInitonlyInCtor..ctor_Invalid_InitOnly'(char) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(char) cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ldsflda int32 FieldTestsType::StaticInitonlyField
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void 'special.LdsfldStslfdInitonlyCctor..cctor_Valid'() cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .cctor() cil managed
+ {
+ ldsflda int32 FieldTestsType::StaticInitonlyField
+ pop
+ ldc.i4.0
+ stsfld int32 FieldTestsType::StaticInitonlyField
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit OtherType
+ extends [System.Runtime]System.Object
+{
+ .field public static class OtherType Instance
+
+ .field public initonly int32 InstanceInitonlyField
+ .field public static initonly int32 StaticInitonlyField
+
+ .method public hidebysig instance void 'special.LdfldStlfdInitonlyCctor..cctor_Invalid_InitOnly.InitOnly'() cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .cctor() cil managed
+ {
+ ldsfld class OtherType OtherType::Instance
+ ldflda int32 OtherType::InstanceInitonlyField
+ pop
+ ldsfld class OtherType OtherType::Instance
+ ldc.i4.0
+ stfld int32 OtherType::InstanceInitonlyField
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly FtnTests
+{
+}
+
+// Generic test class with class constraint
+.class public auto ansi beforefieldinit GenericTestClass`1<class T>
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig instance void InstanceMethod() cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig static void StaticMethod() cil managed
+ {
+ ret
+ }
+}
+
+// Generic test class with default ctor constraint
+.class public auto ansi beforefieldinit GenericCtor`1<.ctor T>
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+}
+
+// Generic test class with default valuetype constraint
+.class public auto ansi beforefieldinit GenericValueType`1<valuetype T>
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+}
+
+// Test class with generic methods with constraints and private default ctor
+.class public auto ansi beforefieldinit TestClass
+ extends [System.Runtime]System.Object
+{
+ .method private hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method private hidebysig specialname rtspecialname instance void .ctor(int32 i) cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig instance void InstanceMethodRefConstr<class T>() cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig instance void InstanceMethod() cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig newslot virtual instance void VirtInstanceMethod() cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig static void StaticMethod() cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig static int32 StaticIntMethod() cil managed
+ {
+ ldc.i4.0
+ ret
+ }
+
+ .method public hidebysig static void StaticMethodRefConstr<class T>() cil managed
+ {
+ ret
+ }
+}
+
+// Type containing test methods for delegate-assignment
+.class public auto ansi beforefieldinit TestMethodsType
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig static uint8 ByteReturnMethod() cil managed
+ {
+ ldc.i4.0
+ ret
+ }
+
+ .method public hidebysig static valuetype ByteEnum ByteEnumReturnMethod() cil managed
+ {
+ ldc.i4.0
+ box ByteEnum
+ ret
+ }
+
+ .method public hidebysig static int32 IntReturnMethod() cil managed
+ {
+ ldc.i4.0
+ ret
+ }
+
+ .method public hidebysig static string StringReturnMethod() cil managed
+ {
+ ldnull
+ ret
+ }
+
+ .method public hidebysig static object ObjectReturnMethod() cil managed
+ {
+ ldnull
+ ret
+ }
+
+ .method public hidebysig static void ByteParamMethod(uint8 param) cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig static void ByteEnumParamMethod(valuetype ByteEnum param) cil managed
+ {
+ ret
+ }
+}
+
+.class public auto ansi sealed ByteEnum
+ extends [System.Runtime]System.Enum
+{
+ .field public specialname rtspecialname uint8 value__
+ .field public static literal valuetype ByteEnum A = uint8(0)
+ .field public static literal valuetype ByteEnum B = uint8(0)
+}
+
+.class public auto ansi beforefieldinit FtnTestsType
+ extends [System.Runtime]System.Object
+{
+ .method static public hidebysig void LdFtn.StaticClassRefConstraint_Valid() cil managed
+ {
+ // var a = new System.Action(GenericTestClass<TestClass>.StaticMethod);
+ // a();
+
+ ldnull
+ ldftn void class GenericTestClass`1<class TestClass>::StaticMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.InstanceClassRefConstraint_Valid(class GenericTestClass`1<class TestClass> c) cil managed
+ {
+ // (GenericTestClass<TestClass> c)
+ // var a = new System.Action(c.InstanceMethod);
+ // a();
+
+ ldarg.0
+ ldftn instance void class GenericTestClass`1<class TestClass>::InstanceMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.IntForStaticClassRefConstraint_Invalid_UnsatisfiedMethodParentInst() cil managed
+ {
+ // var a = new System.Action(GenericTestClass<int>.StaticMethod);
+ // a();
+
+ ldnull
+ ldftn void class GenericTestClass`1<int32>::StaticMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.IntForStaticMethodRefConstraint_Invalid_UnsatisfiedMethodInst() cil managed
+ {
+ // var a = new System.Action(TestClass.StaticMethod<int>);
+ // a();
+
+ ldnull
+ ldftn void TestClass::StaticMethodRefConstr<int32>()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdvirtFtn.InstanceMethod_Valid(class TestClass c) cil managed
+ {
+ // (TestClass c)
+ // var a = new System.Action(c.InstanceMethod);
+ // a();
+
+ ldarg.0
+ dup
+ ldvirtftn instance void TestClass::InstanceMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdvirtFtn.VirtInstanceMethod_Valid(class TestClass c) cil managed
+ {
+ // (TestClass c)
+ // var a = new System.Action(c.InstanceMethod);
+ // a();
+
+ ldarg.0
+ dup
+ ldvirtftn instance void TestClass::VirtInstanceMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdvirtFtn.ValueTypeInstanceMethod_Valid(int32 i) cil managed
+ {
+ // (int i)
+ // var f = new System.Func<int, int>(i.CompareTo);
+ // f(0);
+
+ ldarg.0
+ box [System.Runtime]System.Int32
+ dup
+ ldvirtftn instance int32 [System.Runtime]System.Int32::CompareTo(int32)
+ newobj instance void class [System.Runtime]System.Func`2<int32, int32>::.ctor(object, native int)
+ ldc.i4.0
+ callvirt instance !1 class [System.Runtime]System.Func`2<int32, int32>::Invoke(!0)
+ pop
+ ret
+ }
+
+ .method static public hidebysig void LdvirtFtn.StaticMethod_Invalid_LdvirtftnOnStatic() cil managed
+ {
+ ldnull
+ dup
+ ldvirtftn void TestClass::StaticMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdvirtFtn.ValueTypeNoBox_Invalid_StackObjRef.StackUnexpected.StackUnexpected.DelegateCtorSigO(int32 i) cil managed
+ {
+ // (int i)
+ // var f = new System.Func<int, int>(i.CompareTo);
+ // f(0);
+
+ ldarg.0
+ dup
+ ldvirtftn instance int32 [System.Runtime]System.Int32::CompareTo(int32)
+ newobj instance void class [System.Runtime]System.Func`2<int32, int32>::.ctor(object, native int)
+ ldc.i4.0
+ callvirt instance !1 class [System.Runtime]System.Func`2<int32, int32>::Invoke(!0)
+ pop
+ ret
+ }
+
+ .method static public hidebysig void LdvirtFtn.ValueTypeWrongBox_Invalid_StackUnexpected.DelegateCtorSigO.DelegatePattern(int32 i) cil managed
+ {
+ // (int i)
+ // var f = new System.Func<int, int>(i.CompareTo);
+ // f(0);
+
+ ldarg.0
+ dup
+ box [System.Runtime]System.Int32
+ ldvirtftn instance int32 [System.Runtime]System.Int32::CompareTo(int32)
+ newobj instance void class [System.Runtime]System.Func`2<int32, int32>::.ctor(object, native int)
+ ldc.i4.0
+ callvirt instance !1 class [System.Runtime]System.Func`2<int32, int32>::Invoke(!0)
+ pop
+ ret
+ }
+
+ .method static public hidebysig void LdvirtFtn.ObjectForTestClassInstance_Invalid_StackUnexpected(object c) cil managed
+ {
+ // (object c)
+ // var a = new System.Action(c.InstanceMethod);
+
+ ldarg.0
+ dup
+ ldvirtftn instance void TestClass::InstanceMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ pop
+ ret
+ }
+
+ .method static public hidebysig void NewObj.RefGenericForRefConstraint_Valid<class T>() cil managed
+ {
+ // var c = new GenericTestClass`1<T>();
+
+ newobj instance void class GenericTestClass`1<!!T>::.ctor()
+ pop
+ ret
+ }
+
+ .method static public hidebysig void NewObj.IntForRefConstraint_Invalid_UnsatisfiedMethodParentInst() cil managed
+ {
+ // GenericTestClass<int> c = new GenericTestClass<int>();
+
+ newobj instance void class GenericTestClass`1<int32>::.ctor()
+ pop
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.NopInDelegatePattern_Invalid_DelegatePattern() cil managed
+ {
+ // var a = new System.Action(TestClass.StaticMethod);
+ // a();
+
+ ldnull
+ ldftn void TestClass::StaticMethod()
+ nop
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdvirtFtn.NopInDelegatePattern_Invalid_DelegatePattern(class TestClass c) cil managed
+ {
+ // (TestClass c)
+ // var a = new System.Action(c.InstanceMethod);
+ // a();
+
+ ldarg.0
+ dup
+ nop
+ ldvirtftn instance void TestClass::InstanceMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.BranchIntoDelegatePattern_Invalid_DelegatePattern() cil managed
+ {
+ ldnull
+ ldftn void TestClass::StaticMethod()
+ br lbl_newobj
+
+ ldnull
+ ldftn void TestClass::StaticMethod()
+
+ lbl_newobj:
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdvirtFtn.BranchIntoDelegatePattern_Invalid_DelegatePattern(class TestClass t) cil managed
+ {
+ ldarg.0
+ dup
+ br lbl_ldvirt
+
+ ldarg.0
+ dup
+
+ lbl_ldvirt:
+ ldvirtftn instance void TestClass::InstanceMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.DelegateMissingArgument_Invalid_DelegateCtor() cil managed
+ {
+ ldnull
+ ldftn void TestClass::StaticMethod()
+ newobj instance void class [System.Runtime]System.Action`1<int32>::.ctor(object, native int)
+ ldc.i4.0
+ callvirt instance void class [System.Runtime]System.Action`1<int32>::Invoke(!0)
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.DelegateWrongReturnType_Invalid_DelegateCtor() cil managed
+ {
+ ldnull
+ ldftn int32 TestClass::StaticIntMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.VirtualMethodNonThisPtr_Invalid_LdftnNonFinalVirtual(class TestClass c) cil managed
+ {
+ ldarg.0
+ ldftn instance void TestClass::VirtInstanceMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ // creating a Func<object> from a string return method is valid
+ .method private hidebysig instance void ObjectFuncFromStringMethod_Valid() cil managed
+ {
+ ldnull
+ ldftn string TestMethodsType::StringReturnMethod()
+ newobj instance void class [System.Runtime]System.Func`1<object>::.ctor(object, native int)
+ pop
+ ret
+ }
+
+ // creating a Func<string> from a object return method is invalid
+ .method private hidebysig instance void StringFuncFromObjectMethod_Invalid_DelegateCtor() cil managed
+ {
+ ldnull
+ ldftn object TestMethodsType::ObjectReturnMethod()
+ newobj instance void class [System.Runtime]System.Func`1<string>::.ctor(object, native int)
+ pop
+ ret
+ }
+
+ // creating a Func<byte> from an int return method is invalid
+ .method private hidebysig instance void ByteFuncFromIntMethod_Invalid_DelegateCtor() cil managed
+ {
+ ldnull
+ ldftn int32 TestMethodsType::IntReturnMethod()
+ newobj instance void class [System.Runtime]System.Func`1<uint8>::.ctor(object, native int)
+ pop
+ ret
+ }
+
+ // creating a Func<int> from a byte return method is invalid
+ .method private hidebysig instance void IntFuncFromByteMethod_Invalid_DelegateCtor() cil managed
+ {
+ ldnull
+ ldftn uint8 TestMethodsType::ByteReturnMethod()
+ newobj instance void class [System.Runtime]System.Func`1<int32>::.ctor(object, native int)
+ pop
+ ret
+ }
+
+ // creating a Func<byte> from a ByteEnum return method is invalid
+ .method private hidebysig instance void IntFuncFromByteEnumMethod_Invalid_DelegateCtor() cil managed
+ {
+ ldnull
+ ldftn valuetype ByteEnum TestMethodsType::ByteEnumReturnMethod()
+ newobj instance void class [System.Runtime]System.Func`1<int32>::.ctor(object, native int)
+ pop
+ ret
+ }
+
+ // creating an Action<int> from a method with byte parameter is invalid
+ .method private hidebysig instance void IntActionFromByteMethod_Invalid_DelegateCtor() cil managed
+ {
+ ldnull
+ ldftn void TestMethodsType::ByteParamMethod(uint8)
+ newobj instance void class [System.Runtime]System.Action`1<int32>::.ctor(object, native int)
+ pop
+ ret
+ }
+
+ // creating an Action<byte> from a method with an enum (with underlying type byte) as parameter is invalid
+ .method private hidebysig instance void ByteActionFromByteEnum_Invalid_DelegateCtor() cil managed
+ {
+ ldnull
+ ldftn void TestMethodsType::ByteEnumParamMethod(valuetype ByteEnum)
+ newobj instance void class [System.Runtime]System.Action`1<uint8>::.ctor(object, native int)
+ pop
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly GenericInterface
+{
+}
+
+.assembly extern System.Runtime
+{
+}
+
+.class interface public auto ansi abstract IGeneric`2<TIN, TOUT>
+{
+ .method public hidebysig newslot abstract virtual
+ instance !TOUT M1 (
+ !TIN par,
+ !TIN par2
+ ) cil managed
+ {
+ }
+}
+
+.class public auto ansi beforefieldinit GenericImplementationInt32_ValidType_Valid
+ extends [System.Runtime]System.Object
+ implements class IGeneric`2<int32, int32>
+{
+ .method public final hidebysig newslot virtual
+ instance int32 M1 (
+ int32 par,
+ int32 par2
+ ) cil managed
+ {
+ .maxstack 1
+ .locals init (
+ [0] int32
+ )
+
+ IL_0000: nop
+ IL_0001: ldc.i4.0
+ IL_0002: stloc.0
+ IL_0003: br.s IL_0005
+
+ IL_0005: ldloc.0
+ IL_0006: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ }
+
+}
+
+.class public auto ansi beforefieldinit GenericsMissingMethod_InvalidType_InterfaceMethodNotImplemented
+ extends [System.Runtime]System.Object
+ implements class IGeneric`2<int32, int32>
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ }
+
+}
+
+.class public auto ansi beforefieldinit GenericsInvalidReturnParameter_InvalidType_InterfaceMethodNotImplemented
+ extends [System.Runtime]System.Object
+ implements class IGeneric`2<int32, int32>
+{
+ .method public final hidebysig newslot virtual
+ instance int64 M1 (
+ int32 par,
+ int32 par2
+ ) cil managed
+ {
+ .maxstack 1
+ .locals init (
+ [0] int32
+ )
+
+ IL_0000: nop
+ IL_0001: ldc.i4.0
+ IL_0002: stloc.0
+ IL_0003: br.s IL_0005
+
+ IL_0005: ldloc.0
+ IL_0006: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ }
+}
+
+.class public auto ansi beforefieldinit GenericsMissingParameter_InvalidType_InterfaceMethodNotImplemented
+ extends [System.Runtime]System.Object
+ implements class IGeneric`2<int32, int32>
+{
+ .method public final hidebysig newslot virtual
+ instance int32 M1 (int32 par2) cil managed
+ {
+ .maxstack 1
+ .locals init (
+ [0] int32
+ )
+
+ IL_0000: nop
+ IL_0001: ldc.i4.0
+ IL_0002: stloc.0
+ IL_0003: br.s IL_0005
+
+ IL_0005: ldloc.0
+ IL_0006: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ }
+}
+
+.class public auto ansi beforefieldinit GenericsInvalidInTypeParameter_InvalidType_InterfaceMethodNotImplemented
+ extends [System.Runtime]System.Object
+ implements class IGeneric`2<int32, int32>
+{
+ .method public final hidebysig newslot virtual
+ instance int64 M1 (
+ int64 par,
+ int32 par2
+ ) cil managed
+ {
+ .maxstack 1
+ .locals init (
+ [0] int32
+ )
+
+ IL_0000: nop
+ IL_0001: ldc.i4.0
+ IL_0002: stloc.0
+ IL_0003: br.s IL_0005
+
+ IL_0005: ldloc.0
+ IL_0006: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk.IL">
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+ <OutputPath>$(BaseOutputPathWithConfig)ilverify\Tests</OutputPath>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="$(MSBuildProjectName).il" />
+ </ItemGroup>
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly InterfaceDefinition
+{
+}
+
+.assembly extern System.Runtime
+{
+}
+
+.class interface public auto ansi abstract Interface
+{
+ .method public hidebysig newslot abstract virtual
+ instance void M1 () cil managed
+ {
+ }
+
+ .method public hidebysig newslot abstract virtual
+ instance void M2 () cil managed
+ {
+ }
+
+ .method public hidebysig newslot abstract virtual
+ instance void M3 (
+ int32 i
+ ) cil managed
+ {
+ }
+
+ .method public hidebysig newslot abstract virtual
+ instance int32 M4 (
+ int32 i
+ ) cil managed
+ {
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly InterfaceImplementation
+{
+}
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly extern InterfaceDefinition
+{
+}
+
+.class public auto ansi beforefieldinit Valid_ValidType_Valid
+ extends [System.Runtime]System.Object
+ implements [InterfaceDefinition]Interface
+{
+ .method public final hidebysig newslot virtual
+ instance void M1 () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance void M2 () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance void M3 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance int32 M4 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: ret
+ }
+}
+
+.class public auto ansi beforefieldinit InterfaceImplHasDuplicate_InvalidType_InterfaceImplHasDuplicate
+ extends [System.Runtime]System.Object
+ implements [InterfaceDefinition]Interface, [InterfaceDefinition]Interface
+{
+ .method public final hidebysig newslot virtual
+ instance void M1 () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance void M2 () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance void M3 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance int32 M4 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: ret
+ }
+}
+
+.class public auto ansi beforefieldinit MissingMethod_InvalidType_InterfaceMethodNotImplemented
+ extends [System.Runtime]System.Object
+ implements [InterfaceDefinition]Interface
+{
+ .method public final hidebysig newslot virtual
+ instance void M2 () cil managed
+ {
+ .maxstack 8
+ IL_0000: ret
+ }
+ .method public final hidebysig newslot virtual
+ instance void M3 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+ IL_0000: ret
+ }
+ .method public final hidebysig newslot virtual
+ instance int32 M4 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ }
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: ret
+ }
+}
+
+.class public auto ansi abstract beforefieldinit MissingMethod_ValidType_AbstractClass
+ extends [System.Runtime]System.Object
+ implements [InterfaceDefinition]Interface
+{
+ .method public final hidebysig newslot virtual
+ instance void M2 () cil managed
+ {
+ .maxstack 8
+ IL_0000: ret
+ }
+ .method public final hidebysig newslot virtual
+ instance void M3 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+ IL_0000: ret
+ }
+ .method public final hidebysig newslot virtual
+ instance int32 M4 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ }
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: ret
+ }
+}
+
+.class public auto ansi beforefieldinit InterfaceImplHasDuplicateAndMissingMethod_InvalidType_InterfaceImplHasDuplicate@InterfaceMethodNotImplemented
+ extends [System.Runtime]System.Object
+ implements [InterfaceDefinition]Interface, [InterfaceDefinition]Interface
+{
+ .method public final hidebysig newslot virtual
+ instance void M2 () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance void M3 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance int32 M4 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: ret
+ }
+}
+
+.class public auto ansi beforefieldinit InvalidReturnTypeM1_InvalidType_InterfaceMethodNotImplemented
+ extends [System.Runtime]System.Object
+ implements [InterfaceDefinition]Interface
+{
+ .method public final hidebysig newslot virtual
+ instance int32 M1 () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance void M2 () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance void M3 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance int32 M4 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: ret
+ }
+}
+
+.class public auto ansi beforefieldinit InvalidParameterTypeM3_InvalidType_InterfaceMethodNotImplemented
+ extends [System.Runtime]System.Object
+ implements [InterfaceDefinition]Interface
+{
+ .method public final hidebysig newslot virtual
+ instance void M1 () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance void M2 () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance void M3 (
+ int64 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance int32 M4 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: ret
+ }
+}
+
+.class public auto ansi beforefieldinit InvalidMethodNameM10_InvalidType_InterfaceMethodNotImplemented
+ extends [System.Runtime]System.Object
+ implements [InterfaceDefinition]Interface
+{
+ .method public final hidebysig newslot virtual
+ instance void M10 () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance void M2 () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance void M3 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ret
+ }
+
+ .method public final hidebysig newslot virtual
+ instance int32 M4 (
+ int32 i
+ ) cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: ret
+ }
+}
+
+.class public auto ansi beforefieldinit BaseClass
+ extends [System.Runtime]System.Object
+ implements IInterface
+{
+ .method public final hidebysig newslot virtual
+ instance void InterfaceMethod () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: nop
+ IL_0001: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ }
+}
+
+.class public auto ansi beforefieldinit ChildClass_ValidType_Valid
+ extends BaseClass
+ implements IInterface
+{
+ .method public hidebysig
+ instance void ChildMethod () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: nop
+ IL_0001: ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void BaseClass::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ }
+}
+
+.class interface public auto ansi abstract IInterface
+{
+ .method public hidebysig newslot abstract virtual
+ instance void InterfaceMethod () cil managed
+ {
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly LoadStoreIndirectTests
+{
+}
+
+.class public auto ansi beforefieldinit LoadStoreIndirectTestsType
+ extends [System.Runtime]System.Object
+{
+ .method static public hidebysig void LoadIndirectRef.FromStringRef_Valid(string&) cil managed
+ {
+ ldarg.0
+ ldind.ref
+ pop
+ ret
+ }
+
+ .method static public hidebysig void LoadIndirect.FromInt32Ref_Valid(int32&) cil managed
+ {
+ ldarg.0
+ ldind.i4
+ pop
+ ret
+ }
+
+ .method static public hidebysig void LoadIndirect.FromInt64Ref_Invalid_StackUnexpected(int64&) cil managed
+ {
+ ldarg.0
+ ldind.i4
+ pop
+ ret
+ }
+
+ .method static public hidebysig void LoadIndirectRef.FromInt64Ref_Invalid_StackUnexpected(int64&) cil managed
+ {
+ ldarg.0
+ ldind.ref
+ pop
+ ret
+ }
+
+ .method static public hidebysig void LoadIndirectRef.AssignRefStringToString_Valid(string&) cil managed
+ {
+ .locals init (
+ string V_0)
+ ldarg.0
+ ldind.ref
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void StoreIndirect.AssignToInt_Valid(int32&) cil managed
+ {
+ // arg = 0;
+ ldarg.0
+ ldc.i4.0
+ stind.i4
+ ret
+ }
+
+ .method static public hidebysig void StoreIndirect.AssignToRefBase_Valid(object&) cil managed
+ {
+ .locals init (string V_0)
+
+ // ref object a;
+ // string b;
+ // a = b;
+
+ ldarg.0
+ ldloc.0
+ stind.ref
+ ret
+ }
+
+ .method static public hidebysig void StoreIndirect.AssignToRefString_Invalid_StackUnexpected(string&) cil managed
+ {
+ .locals init (object V_0)
+
+ // ref string x;
+ // object y;
+ // x = y;
+
+ ldarg.0
+ ldloc.0
+ stind.ref
+ ret
+ }
+
+ .method static public hidebysig void StoreIndirect.AssignNullToRefString_Valid(string&) cil managed
+ {
+ // ref string x;
+ // x = null;
+
+ ldarg.0
+ ldnull
+ stind.ref
+ ret
+ }
+
+ .method static public hidebysig void StoreIndirect.AssignStringToRefString_Valid(string&) cil managed
+ {
+ // ref string x;
+ // string y = "a";
+ // x = y;
+
+ ldarg.0
+ ldstr "a"
+ stind.ref
+ ret
+ }
+
+ .method static public hidebysig void StoreObject.AssignStringToRefStringAsObject_Invalid_StackUnexpected(string&) cil managed
+ {
+ // ref string x;
+ // string y = "a";
+ // x = y;
+
+ ldarg.0
+ ldstr "a"
+ stobj [System.Runtime]System.Object
+ ret
+ }
+
+ .method static public hidebysig void StoreIndirect.AssignByteToBoolRef_Valid(bool&) cil managed
+ {
+ ldarg.0
+ ldc.i4.0
+ stind.i1
+ ret
+ }
+
+ .method static public hidebysig void StoreObject.ValidTypeToken_Valid() cil managed
+ {
+ .locals init (object V_0)
+
+ ldloca.s V_0
+ ldstr "Hello"
+ stobj string
+ ret
+ }
+
+ .method static public hidebysig void StoreObject.InvalidTypeToken_Invalid_StackUnexpected() cil managed
+ {
+ .locals init (object V_0)
+
+ ldloca.s V_0
+ ldstr "Hello"
+ stobj [System.Runtime]System.IO.Stream
+ ret
+ }
+
+ .method static public hidebysig void LoadIndirect.AssignInt8ToBool_Valid(bool&) cil managed
+ {
+ .locals init (bool)
+
+ // ref bool a;
+ // bool b;
+ // b = a;
+
+ ldarg.0
+ ldind.i1
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void LoadIndirect.AssignUInt8ToBool_Valid(bool&) cil managed
+ {
+ .locals init (bool)
+
+ // ref bool a;
+ // bool b;
+ // b = a;
+
+ ldarg.0
+ ldind.u1
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void LoadIndirect.AssignInt16ToChar_Valid(char&) cil managed
+ {
+ .locals init (char)
+
+ // ref char a;
+ // char b;
+ // b = a;
+
+ ldarg.0
+ ldind.i2
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void LoadIndirect.AssignUInt16ToChar_Valid(char&) cil managed
+ {
+ .locals init (char)
+
+ // ref char a;
+ // char b;
+ // b = a;
+
+ ldarg.0
+ ldind.u2
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void StoreIndirect.AssignInt32ToCharRef_Valid(char&) cil managed
+ {
+ .locals init (char)
+
+ // ref char a;
+ // a = 'a';
+
+ ldarg.0
+ ldc.i4.s 97
+ stind.i2
+ ret
+ }
+
+ .method static public hidebysig void StoreIndirect.AssignInt32ToBoolRef_Valid(bool&) cil managed
+ {
+ .locals init (bool)
+
+ // ref bool a;
+ // a = true;
+
+ ldarg.0
+ ldc.i4.1
+ stind.i1
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly NewobjTests
+{
+}
+
+.class public auto ansi abstract beforefieldinit AbstractClass
+{
+ .method public hidebysig newslot abstract virtual instance void AbstractMethod() cil managed
+ {
+ }
+}
+
+.class public auto ansi beforefieldinit NewobjTestsType
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig instance void InstanceMethod() cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig static void StaticMethod() cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig instance void Newobj.InstanceMethod_Invalid_CtorExpected() cil managed
+ {
+ newobj instance void NewobjTestsType::InstanceMethod()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Newobj.AbstractMethod_Invalid_CtorSig.CtorExpected() cil managed
+ {
+ newobj instance void AbstractClass::AbstractMethod()
+ pop
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly PrefixTests
+{
+}
+
+.class public auto ansi beforefieldinit PrefixTestsType
+ extends [System.Runtime]System.Object
+{
+ .method static public hidebysig void StaticMethod() cil managed
+ {
+ ret
+ }
+
+ .method static public hidebysig void Readonly.Ldelema_Valid() cil managed
+ {
+ .locals init (int32[] V_0)
+
+ //int[] array = new int[2];
+ ldc.i4.2
+ newarr [System.Runtime]System.Int32
+ stloc.0
+ ldloc.0
+ // array[1].ToString();
+ ldc.i4.1
+ readonly.
+ ldelema [System.Runtime]System.Int32
+ call instance string [System.Runtime]System.Int32::ToString()
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Readonly.Ldelem_Invalid_ReadOnly() cil managed
+ {
+ .locals init (int32[] V_0)
+
+ //int[] array = new int[2];
+ ldc.i4.2
+ newarr [System.Runtime]System.Int32
+ stloc.0
+ ldloc.0
+ ldc.i4.1
+
+ readonly.
+ ldelem [System.Runtime]System.Int32
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Readonly.ArrayAddress_Valid() cil managed
+ {
+ //int[,] array = new int[1, 1];
+ ldc.i4.1
+ ldc.i4.1
+ newobj instance void int32[0..., 0...]::.ctor(int32, int32)
+ ldc.i4.0
+ ldc.i4.0
+ readonly.
+ call instance int32& int32[0..., 0...]::Address(int32, int32)
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Readonly.ArrayGet_Invalid_ReadonlyUnexpectedCallee() cil managed
+ {
+ //int[,] array = new int[1, 1];
+ ldc.i4.1
+ ldc.i4.1
+ newobj instance void int32[0..., 0...]::.ctor(int32, int32)
+ ldc.i4.0
+ ldc.i4.0
+ readonly.
+ call instance int32 int32[0..., 0...]::Get(int32, int32)
+ pop
+ ret
+ }
+
+ .method static public hidebysig void Prefix.UnalignedAndVolatile_Valid() cil managed
+ {
+ .locals init (int32& V_0, int32 V_1)
+ // ref int x;
+ // int y;
+ // y = *x;
+ ldloc.0
+ volatile.
+ unaligned. 4
+ ldind.i4
+ stloc.1
+ ret
+ }
+
+ .method static public hidebysig void Tail.FromTry_Invalid_TailCallInsideER.TailRet() cil managed
+ {
+ .try
+ {
+ tail.
+ call void PrefixTestsType::StaticMethod()
+
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method static public hidebysig void Tail.FollowedByRet_Valid() cil managed
+ {
+ tail.
+ call void PrefixTestsType::StaticMethod()
+ ret
+ }
+
+ .method static public hidebysig void Tail.NoRet_Invalid_TailRet.MethodFallthrough() cil managed
+ {
+ tail.
+ call void PrefixTestsType::StaticMethod()
+ }
+
+ .method static public hidebysig void Tail.DoubleCall_Invalid_TailRet() cil managed
+ {
+ tail.
+ call void PrefixTestsType::StaticMethod()
+ call void PrefixTestsType::StaticMethod()
+ ret
+ }
+
+ .method static public hidebysig void Tail.BranchToRet_Valid() cil managed
+ {
+ ldc.i4.0
+ brfalse MethodEnd
+
+ tail.
+ call void PrefixTestsType::StaticMethod()
+
+ MethodEnd:
+ ret
+ }
+
+ .method static public hidebysig void Tail.ComplexBranchToRet_Valid() cil managed
+ {
+ br AfterTail
+
+ TailCall:
+ tail.
+ call void PrefixTestsType::StaticMethod()
+
+ MethodEnd:
+ ret
+
+ AfterTail:
+ ldc.i4.0
+ brfalse TailCall
+
+ br MethodEnd
+ }
+
+ .method static public hidebysig void Tail.BranchToNopRet_Invalid_TailRet() cil managed
+ {
+ ldc.i4.0
+ brfalse MethodEnd
+
+ tail.
+ call void PrefixTestsType::StaticMethod()
+
+ MethodEnd:
+ nop
+ ret
+ }
+
+ .method static public hidebysig void Tail.Ret_Invalid_TailCall() cil managed
+ {
+ tail.
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly ReturnTests
+{
+}
+
+.class public sequential ansi sealed beforefieldinit Struct
+ extends [System.Runtime]System.ValueType
+{
+ .field public int32 instanceField
+}
+
+.class public auto ansi beforefieldinit ReturnTestsType
+ extends [System.Runtime]System.Object
+{
+ .field private int32 instanceField
+ .field private static int32 staticField
+
+ .field private valuetype Struct instanceStruct
+
+ .method public hidebysig instance void Return.Void_Valid() cil managed
+ {
+ ldarg.0
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Return.VoidNonEmptyStack_Invalid_ReturnVoid() cil managed
+ {
+ ldarg.0
+ ret
+ }
+
+ .method public hidebysig instance int32 Return.Int32_Valid() cil managed
+ {
+ ldc.i4.0
+ ret
+ }
+
+ .method public hidebysig instance int32 Return.Int32EmptyStack_Invalid_ReturnMissing() cil managed
+ {
+ ret
+ }
+
+ .method public hidebysig instance int32 Return.Int32StackLeft_Invalid_ReturnEmpty() cil managed
+ {
+ ldc.i4.0
+ ldc.i4.0
+ ret
+ }
+
+ .method public hidebysig instance void Return.FromTry_Invalid_ReturnFromTry() cil managed
+ {
+ .try
+ {
+ ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret:
+ ret
+ }
+
+ .method public hidebysig instance void Return.FromCatch_Invalid_ReturnFromHandler() cil managed
+ {
+ .try
+ {
+ leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ ret
+ }
+
+ lbl_ret:
+ ret
+ }
+
+ .method public hidebysig instance void Return.FromFilter_Invalid_ReturnFromFilter() cil managed
+ {
+ .try
+ {
+ leave.s lbl_ret
+ }
+ filter
+ {
+ pop
+ ret
+
+ endfilter
+ }
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret:
+ ret
+ }
+
+ .method public hidebysig instance int32 Return.ObjectForInt32_Invalid_StackUnexpected(object o) cil managed
+ {
+ ldarg.1
+ ret
+ }
+
+ .method public hidebysig instance int32& Return.LocalArgByRef_Invalid_ReturnPtrToStack(int32 i) cil managed
+ {
+ ldarga.s i
+ ret
+ }
+
+ .method public hidebysig instance int32& Return.InstanceFieldByRef_Valid(int32 i) cil managed
+ {
+ ldarg.0
+ ldflda int32 ReturnTestsType::instanceField
+ ret
+ }
+
+ .method public hidebysig instance int32& Return.StaticFieldByRef_Valid(int32 i) cil managed
+ {
+ ldsflda int32 ReturnTestsType::staticField
+ ret
+ }
+
+ .method public hidebysig instance int32& Return.LocalStructFieldByRef_Invalid_ReturnPtrToStack(valuetype Struct s) cil managed
+ {
+ ldarg.1
+ ldflda int32 Struct::instanceField
+ ret
+ }
+
+ .method public hidebysig instance int32& Return.FieldStructFieldByRef_Valid() cil managed
+ {
+ ldarg.0
+ ldflda valuetype Struct ReturnTestsType::instanceStruct
+ ldflda int32 Struct::instanceField
+ ret
+ }
+
+ .method public hidebysig instance void MissingReturn_Invalid_MethodFallthrough() cil managed
+ {
+ ldarg.0
+ }
+
+ .method public hidebysig instance void 'special.ReturnAfterBaseCtor..ctor_Valid'() cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig instance void 'special.ReturnBeforeBaseCtor..ctor_Invalid_ThisUninitReturn'(int32) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(int32) cil managed
+ {
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly ShiftTests
+{
+}
+
+.class public auto ansi beforefieldinit ShiftTestsType
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig instance int32 ShiftLeft.Int32ByInt32_Valid(int32 toBeShifted, int32 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int32 ShiftRight.Int32ByInt32_Valid(int32 toBeShifted, int32 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shr
+ ret
+ }
+
+ .method public hidebysig instance int32 ShiftRightUn.Int32ByInt32_Valid(int32 toBeShifted, int32 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shr.un
+ ret
+ }
+
+ .method public hidebysig instance int32 ShiftLeft.Int32ByNativeInt_Valid(int32 toBeShifted, native int shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int64 ShiftLeft.Int64ByInt32_Valid(int64 toBeShifted, int32 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int64 ShiftLeft.Int64ByNativeInt_Valid(int64 toBeShifted, native int shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance native int ShiftLeft.NativeIntByInt32_Valid(native int toBeShifted, int32 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance native int ShiftLeft.NativeIntByNativeInt_Valid(native int toBeShifted, native int shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int32 ShiftLeft.Int32ByInt64_Invalid_StackUnexpected(int32 toBeShifted, int64 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int32 ShiftLeft.Int32ByFloat64_Invalid_StackUnexpected(int32 toBeShifted, float64 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int32 ShiftLeft.Int32ByInt32Ref_Invalid_StackUnexpected(int32 toBeShifted, int32& shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int32 ShiftLeft.Int32ByObject_Invalid_StackUnexpected(int32 toBeShifted, object shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int64 ShiftLeft.Int64ByInt64_Invalid_StackUnexpected(int64 toBeShifted, int64 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int64 ShiftLeft.Int64ByFloat64_Invalid_StackUnexpected(int64 toBeShifted, float64 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int64 ShiftLeft.Int64ByInt32Ref_Invalid_StackUnexpected(int64 toBeShifted, int32& shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int64 ShiftLeft.Int64ByObject_Invalid_StackUnexpected(int64 toBeShifted, object shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance native int ShiftLeft.NativeIntByInt64_Invalid_StackUnexpected(native int toBeShifted, int64 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance native int ShiftLeft.NativeIntByFloat64_Invalid_StackUnexpected(native int toBeShifted, float64 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance native int ShiftLeft.NativeIntByInt32Ref_Invalid_StackUnexpected(native int toBeShifted, int32& shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance native int ShiftLeft.NativeIntByObject_Invalid_StackUnexpected(native int toBeShifted, object shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance float64 ShiftLeft.Float64ByInt32_Invalid_ExpectedIntegerType(float64 toBeShifted, int32 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance int32& ShiftLeft.Int32RefByInt32_Invalid_ExpectedIntegerType(int32& toBeShifted, int32 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+
+ .method public hidebysig instance object ShiftLeft.ObjectByInt32_Invalid_ExpectedIntegerType(object toBeShifted, int32 shiftBy) cil managed
+ {
+ ldarg.1
+ ldarg.2
+ shl
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly SwitchTests
+{
+}
+
+.class public auto ansi beforefieldinit SwitchTestsType
+ extends [System.Runtime]System.Object
+{
+ .method static public hidebysig void Switch.Int32Value_Valid() cil managed
+ {
+ .maxstack 1
+
+ ldc.i4.s 10
+ switch (lbl_ret, lbl_a, lbl_a, lbl_b, lbl_b)
+
+ br.s lbl_ret
+
+ lbl_a: nop
+ br.s lbl_ret
+
+ lbl_b: nop
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Switch.Int64Value_Invalid_StackUnexpected() cil managed
+ {
+ .maxstack 1
+
+ ldc.i8 10
+ switch (lbl_ret, lbl_a, lbl_a, lbl_b, lbl_b)
+
+ br.s lbl_ret
+
+ lbl_a: nop
+ br.s lbl_ret
+
+ lbl_b: nop
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Switch.InsideTry_Valid() cil managed
+ {
+ .maxstack 1
+
+ .try
+ {
+ ldc.i4.s 10
+ switch (lbl_leave, lbl_a, lbl_a, lbl_b, lbl_b)
+
+ br.s lbl_leave
+
+ lbl_a: nop
+ br.s lbl_leave
+
+ lbl_b: nop
+
+ lbl_leave: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ nop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Switch.IntoTryStart_Valid() cil managed
+ {
+ .maxstack 1
+
+ ldc.i4.s 10
+ switch (lbl_ret, lbl_a)
+
+ br.s lbl_ret
+
+ .try
+ {
+ lbl_a: nop
+ br.s lbl_leave
+
+ lbl_leave: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ nop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Switch.IntoTryMiddle_Invalid_BranchIntoTry() cil managed
+ {
+ .maxstack 1
+
+ ldc.i4.s 10
+ switch (lbl_ret, lbl_a)
+
+ br.s lbl_ret
+
+ .try
+ {
+ nop
+ lbl_a: br.s lbl_leave
+
+ lbl_leave: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ nop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Switch.OutOfTry_Invalid_BranchOutOfTry() cil managed
+ {
+ .maxstack 1
+
+ .try
+ {
+ ldc.i4.s 10
+ switch (lbl_ret, lbl_a)
+
+ br.s lbl_leave
+
+ lbl_a: nop
+ br.s lbl_leave
+
+ lbl_leave: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ nop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Switch.NestedOutOfTry_Invalid_BranchOutOfTry() cil managed
+ {
+ .maxstack 1
+
+ .try
+ {
+ .try
+ {
+ ldc.i4.s 10
+ switch (lbl_leave, lbl_a, lbl_leave2)
+
+ br.s lbl_leave
+
+ lbl_a: nop
+ br.s lbl_leave
+
+ lbl_leave: leave.s lbl_leave2
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_leave2
+ }
+
+ lbl_leave2: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Switch.NestedIntoTryStart_Valid() cil managed
+ {
+ .maxstack 1
+
+ .try
+ {
+ ldc.i4.s 10
+ switch (lbl_leave, lbl_a, lbl_b)
+
+ br.s lbl_leave
+
+ lbl_a: nop
+ br.s lbl_leave
+
+ .try
+ {
+ lbl_b: nop
+ leave.s lbl_leave
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_leave
+ }
+
+ lbl_leave: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Switch.NestedIntoTryMiddle_Invalid_BranchIntoTry() cil managed
+ {
+ .maxstack 1
+
+ .try
+ {
+ ldc.i4.s 10
+ switch (lbl_leave, lbl_a, lbl_b)
+
+ br.s lbl_leave
+
+ lbl_a: nop
+ br.s lbl_leave
+
+ .try
+ {
+ nop
+ lbl_b: leave.s lbl_leave
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_leave
+ }
+
+ lbl_leave: leave.s lbl_ret
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ leave.s lbl_ret
+ }
+
+ lbl_ret: ret
+ }
+
+ .method static public hidebysig void Switch.ObjectValue_Invalid_StackUnexpected() cil managed
+ {
+ .maxstack 1
+
+ ldnull
+ switch (lbl_ret, lbl_a, lbl_a, lbl_b, lbl_b)
+
+ br.s lbl_ret
+
+ lbl_a: nop
+ br.s lbl_ret
+
+ lbl_b: nop
+
+ lbl_ret: ret
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly ThisStateTests
+{
+}
+
+.class public auto ansi beforefieldinit FieldTestsType
+ extends [System.Runtime]System.Object
+{
+ .field private int32 instanceField
+ .field private static int32 staticField
+
+ .method public hidebysig instance void 'special.LoadFieldThisInit..ctor_Valid'() cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ldarg.0
+ ldfld int32 FieldTestsType::instanceField
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void 'special.LoadFieldThisUninit..ctor_Valid'(int32) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(int32) cil managed
+ {
+ ldarg.0
+ dup
+ ldfld int32 FieldTestsType::instanceField
+ pop
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig instance void 'special.LoadSFieldThisUninit..ctor_Valid'(float64) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(float64) cil managed
+ {
+ ldarg.0
+ ldsfld int32 FieldTestsType::staticField
+ pop
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig instance void 'special.StoreFieldThisInit..ctor_Valid'(int64) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(int64) cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ldarg.0
+ ldc.i4.0
+ stfld int32 FieldTestsType::instanceField
+ ret
+ }
+
+ .method public hidebysig instance void 'special.StoreFieldThisUninit..ctor_Valid'(int32, int32) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(int32, int32) cil managed
+ {
+ ldarg.0
+ dup
+ ldc.i4.0
+ stfld int32 FieldTestsType::instanceField
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig instance void 'special.StoreSFieldThisUninit..ctor_Valid'(native int) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(native int) cil managed
+ {
+ ldc.i4.0
+ stsfld int32 FieldTestsType::staticField
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit ThisStateTestsType
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig instance void 'special.ThrowThisUninit..ctor_Invalid_UninitStack'() cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ throw
+ ret
+ }
+
+ .method public hidebysig instance void 'special.CallCtorOverload..ctor_Valid'(int32) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(int32) cil managed
+ {
+ ldarg.0
+ call instance void ThisStateTestsType::.ctor()
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit LoadStoreVarTestsType
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig instance void 'special.StoreLocUninit..ctor_Invalid_StackUninit'() cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ .locals init (
+ [0] int32
+ )
+
+ ldc.i4.0
+ stloc.0
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig instance void 'special.StoreThisUninit..ctor_Invalid_ThisUninitStore'(int32) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(int32) cil managed
+ {
+ newobj instance void LoadStoreVarTestsType::.ctor()
+ starg 0
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig instance void 'special.LoadAddrOfThisUninit..ctor_Invalid_ThisUninitStore'(int64) cil managed { ret }
+ .method public hidebysig specialname rtspecialname instance void .ctor(int64) cil managed
+ {
+ ldarga 0
+ pop
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+}
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly ValueTypeTests
+{
+}
+
+.class public sequential ansi sealed beforefieldinit ValueTypeTests
+ extends [System.Runtime]System.ValueType
+{
+ .size 1
+ .method public instance void CallThis() cil managed
+ {
+ ret
+ }
+
+ .method public instance void ValueType.CallMethod_Valid() cil managed
+ {
+ ldarg.0
+ call instance void ValueTypeTests::CallThis()
+ ret
+ }
+}
+
--- /dev/null
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+using ILVerify;
+using Internal.TypeSystem.Ecma;
+using Xunit;
+
+namespace ILVerification.Tests
+{
+ public class ILTypeVerificationTester : XunitBase
+ {
+ [Theory(DisplayName = "")]
+ [MemberData(nameof(TestDataLoader.GetTypesWithValidType), MemberType = typeof(TestDataLoader))]
+ [Trait("", "Valid type implementation tests")]
+ private void TestValidTypes(ValidTypeTestCase validType)
+ {
+ IEnumerable<VerificationResult> results = Verify(validType);
+ Assert.Empty(results);
+ }
+
+ [Theory(DisplayName = "")]
+ [MemberData(nameof(TestDataLoader.GetTypesWithInvalidType), MemberType = typeof(TestDataLoader))]
+ [Trait("", "Invalid type implementation tests")]
+ private void TestInvalidTypes(InvalidTypeTestCase invalidType)
+ {
+ IEnumerable<VerificationResult> results = null;
+
+ try
+ {
+ results = Verify(invalidType);
+ }
+ catch
+ {
+ //in some cases ILVerify throws exceptions when things look too wrong to continue
+ //currently these are not caught. In tests we just catch these and do the asserts.
+ //Once these exceptions are better handled and ILVerify instead of crashing aborts the verification
+ //gracefully we can remove this empty catch block.
+ }
+ finally
+ {
+ Assert.NotNull(results);
+ Assert.Equal(invalidType.ExpectedVerifierErrors.Count, results.Count());
+
+ foreach (VerifierError item in invalidType.ExpectedVerifierErrors)
+ {
+ IEnumerable<string> actual = results.Select(e => e.Code.ToString());
+ Assert.True(results.Where(r => r.Code == item).Count() > 0, $"Actual errors where: {string.Join(",", actual)}");
+ }
+ }
+ }
+
+ private static IEnumerable<VerificationResult> Verify(TestCase testCase)
+ {
+ EcmaModule module = TestDataLoader.GetModuleForTestAssembly(testCase.ModuleName);
+ var typeHandle = (TypeDefinitionHandle)MetadataTokens.EntityHandle(testCase.MetadataToken);
+ var type = (EcmaType)module.GetType(typeHandle);
+ var verifier = new Verifier((ILVerifyTypeSystemContext)type.Context, new VerifierOptions() { IncludeMetadataTokensInErrorMessages = true });
+ return verifier.Verify(module.PEReader, typeHandle);
+ }
+
+ public static int Main(string[] args)
+ {
+ return new ILTypeVerificationTester().RunTests();
+ }
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <OutputPath>$(BaseOutputPathWithConfig)ilverify\</OutputPath>
+ <CLRTestPriority>1</CLRTestPriority>
+ <!-- The test uses xunit directly and it fails to find the test assembly for some reason -->
+ <UnloadabilityIncompatible>true</UnloadabilityIncompatible>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="ILMethodTester.cs" />
+ <Compile Include="ILTypeVerificationTester.cs" />
+ <Compile Include="TestDataLoader.cs" />
+ <Compile Include="..\Common\XunitBase.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="xunit" Version="$(XUnitVersion)" />
+ <PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\src\tools\ILVerification\ILVerification.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="ILTests\*.ilproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <OutputItemType>Content</OutputItemType>
+ </ProjectReference>
+ </ItemGroup>
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+using System.Reflection.PortableExecutable;
+using System.Text;
+using ILVerify;
+using Internal.TypeSystem.Ecma;
+using Newtonsoft.Json;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace ILVerification.Tests
+{
+ /// <summary>
+ /// Parses the methods in the test assemblies.
+ /// It loads all assemblies from the test folder defined in <code>TestDataLoader.TestAssemblyPath</code>
+ /// This class feeds the xunit Theories
+ /// </summary>
+ class TestDataLoader
+ {
+ /// <summary>
+ /// The folder with the test binaries
+ /// </summary>
+ private const string TestAssemblyPath = @"Tests\";
+
+ private const string SpecialTestPrefix = "special.";
+
+ /// <summary>
+ /// Returns all class correctly implement based on following naming convention
+ /// [FriendlyName]_ValidType_Valid
+ /// </summary>
+ /// <returns></returns>
+ public static TheoryData<TestCase> GetTypesWithValidType()
+ {
+ var typeSelector = new Func<string[], TypeDefinitionHandle, TestCase>((mparams, typeDefinitionHandle) =>
+ {
+ if (mparams[1] == "ValidType")
+ {
+ return new ValidTypeTestCase { MetadataToken = MetadataTokens.GetToken(typeDefinitionHandle) };
+ }
+ return null;
+ });
+ return GetTestTypeFromDll(typeSelector);
+ }
+
+ /// <summary>
+ /// Returns all class doesn't correctly implement based on following naming convention
+ /// [FriendlyName]_InvalidType_[ExpectedVerifierError1]@[ExpectedVerifierError2]....[ExpectedVerifierErrorN]
+ /// </summary>
+ /// <returns></returns>
+ public static TheoryData<TestCase> GetTypesWithInvalidType()
+ {
+ var typeSelector = new Func<string[], TypeDefinitionHandle, TestCase>((mparams, typeDefinitionHandle) =>
+ {
+ if (mparams[1] == "InvalidType")
+ {
+ var verificationErros = new List<VerifierError>();
+ foreach (var expectedError in mparams[2].Split('@'))
+ {
+ verificationErros.Add((VerifierError)Enum.Parse(typeof(VerifierError), expectedError));
+ }
+ var newItem = new InvalidTypeTestCase { MetadataToken = MetadataTokens.GetToken(typeDefinitionHandle) };
+ newItem.ExpectedVerifierErrors = verificationErros;
+ return newItem;
+ }
+ return null;
+ });
+ return GetTestTypeFromDll(typeSelector);
+ }
+
+ private static TheoryData<TestCase> GetTestTypeFromDll(Func<string[], TypeDefinitionHandle, TestCase> typeSelector)
+ {
+ var retVal = new TheoryData<TestCase>();
+
+ foreach (var testDllName in GetAllTestDlls())
+ {
+ EcmaModule testModule = GetModuleForTestAssembly(testDllName);
+ MetadataReader metadataReader = testModule.PEReader.GetMetadataReader();
+ foreach (TypeDefinitionHandle typeHandle in metadataReader.TypeDefinitions)
+ {
+ var typeDef = metadataReader.GetTypeDefinition(typeHandle);
+ var typeName = metadataReader.GetString(typeDef.Name);
+ if (!string.IsNullOrEmpty(typeName) && typeName.Contains("_"))
+ {
+ var mparams = typeName.Split('_');
+ TestCase newItem = typeSelector(mparams, typeHandle);
+ if (newItem != null)
+ {
+ newItem.TestName = mparams[0];
+ newItem.TypeName = typeName;
+ newItem.ModuleName = testDllName;
+ retVal.Add(newItem);
+ }
+ }
+ }
+ }
+ return retVal;
+ }
+
+ /// <summary>
+ /// Returns all methods that contain valid IL code based on the following naming convention:
+ /// [FriendlyName]_Valid
+ /// The method must contain 1 '_'. The part before the '_' is a friendly name describing what the method does.
+ /// The word after the '_' has to be 'Valid' (Case sensitive)
+ /// E.g.: 'SimpleAdd_Valid'
+ /// </summary>
+ public static TheoryData<TestCase> GetMethodsWithValidIL()
+ {
+ var methodSelector = new Func<string[], MethodDefinitionHandle, TestCase>((mparams, methodHandle) =>
+ {
+ if (mparams.Length == 2 && mparams[1] == "Valid")
+ {
+ return new ValidILTestCase { MetadataToken = MetadataTokens.GetToken(methodHandle) };
+ }
+ return null;
+ });
+ return GetTestMethodsFromDll(methodSelector);
+ }
+
+ /// <summary>
+ /// Returns all methods that contain valid IL code based on the following naming convention:
+ /// [FriendlyName]_Invalid_[ExpectedVerifierError1].[ExpectedVerifierError2]....[ExpectedVerifierErrorN]
+ /// The method name must contain 2 '_' characters.
+ /// 1. part: a friendly name
+ /// 2. part: must be the word 'Invalid' (Case sensitive)
+ /// 3. part: the expected VerifierErrors as string separated by '.'.
+ /// E.g.: SimpleAdd_Invalid_ExpectedNumericType
+ /// </summary>
+ public static TheoryData<TestCase> GetMethodsWithInvalidIL()
+ {
+ var methodSelector = new Func<string[], MethodDefinitionHandle, TestCase>((mparams, methodHandle) =>
+ {
+ if (mparams.Length == 3 && mparams[1] == "Invalid")
+ {
+ var expectedErrors = mparams[2].Split('.');
+ var verificationErros = new List<VerifierError>();
+
+ foreach (var item in expectedErrors)
+ {
+ if (Enum.TryParse(item, out VerifierError expectedError))
+ {
+ verificationErros.Add(expectedError);
+ }
+ }
+
+ var newItem = new InvalidILTestCase { MetadataToken = MetadataTokens.GetToken(methodHandle) };
+
+ if (expectedErrors.Length > 0)
+ {
+ newItem.ExpectedVerifierErrors = verificationErros;
+ }
+
+ return newItem;
+ }
+ return null;
+ });
+ return GetTestMethodsFromDll(methodSelector);
+ }
+
+ private static TheoryData<TestCase> GetTestMethodsFromDll(Func<string[], MethodDefinitionHandle, TestCase> methodSelector)
+ {
+ var retVal = new TheoryData<TestCase>();
+
+ foreach (var testDllName in GetAllTestDlls())
+ {
+ var testModule = GetModuleForTestAssembly(testDllName);
+
+ foreach (var methodHandle in testModule.MetadataReader.MethodDefinitions)
+ {
+ var method = (EcmaMethod)testModule.GetMethod(methodHandle);
+ var methodName = method.Name;
+
+ if (!String.IsNullOrEmpty(methodName) && methodName.Contains("_"))
+ {
+ var mparams = methodName.Split('_');
+ var specialMethodHandle = HandleSpecialTests(mparams, method);
+ var newItem = methodSelector(mparams, specialMethodHandle);
+
+ if (newItem != null)
+ {
+ newItem.TestName = mparams[0];
+ newItem.MethodName = methodName;
+ newItem.ModuleName = testDllName;
+
+ retVal.Add(newItem);
+ }
+ }
+ }
+ }
+ return retVal;
+ }
+
+ private static MethodDefinitionHandle HandleSpecialTests(string[] methodParams, EcmaMethod method)
+ {
+ if (!methodParams[0].StartsWith(SpecialTestPrefix))
+ return method.Handle;
+
+ // Cut off special prefix
+ var specialParams = methodParams[0].Substring(SpecialTestPrefix.Length);
+
+ // Get friendly name / special name
+ int delimiter = specialParams.IndexOf('.');
+ if (delimiter < 0)
+ return method.Handle;
+
+ var friendlyName = specialParams.Substring(0, delimiter);
+ var specialName = specialParams.Substring(delimiter + 1);
+
+ // Substitute method parameters with friendly name
+ methodParams[0] = friendlyName;
+
+ var specialMethodHandle = (EcmaMethod)method.OwningType.GetMethod(specialName, method.Signature);
+ return specialMethodHandle == null ? method.Handle : specialMethodHandle.Handle;
+ }
+
+ private static IEnumerable<string> GetAllTestDlls()
+ {
+ foreach (var item in Directory.GetFiles(TestAssemblyPath))
+ {
+ if (item.ToLower().EndsWith(".dll"))
+ {
+ yield return Path.GetFileName(item);
+ }
+ }
+ }
+
+ public static EcmaModule GetModuleForTestAssembly(string assemblyName)
+ {
+ var simpleNameToPathMap = new Dictionary<string, string>();
+
+ foreach (var fileName in GetAllTestDlls())
+ {
+ simpleNameToPathMap.Add(Path.GetFileNameWithoutExtension(fileName), TestAssemblyPath + fileName);
+ }
+
+ Assembly coreAssembly = typeof(object).GetTypeInfo().Assembly;
+ simpleNameToPathMap.Add(coreAssembly.GetName().Name, coreAssembly.Location);
+
+ Assembly systemRuntime = Assembly.Load(new AssemblyName("System.Runtime"));
+ simpleNameToPathMap.Add(systemRuntime.GetName().Name, systemRuntime.Location);
+
+ var resolver = new TestResolver(simpleNameToPathMap);
+ var typeSystemContext = new ILVerifyTypeSystemContext(resolver);
+ typeSystemContext.SetSystemModule(typeSystemContext.GetModule(resolver.Resolve(coreAssembly.GetName().Name)));
+
+ return typeSystemContext.GetModule(resolver.Resolve(new AssemblyName(Path.GetFileNameWithoutExtension(assemblyName)).Name));
+ }
+
+ private sealed class TestResolver : ResolverBase
+ {
+ Dictionary<string, string> _simpleNameToPathMap;
+ public TestResolver(Dictionary<string, string> simpleNameToPathMap)
+ {
+ _simpleNameToPathMap = simpleNameToPathMap;
+ }
+
+ protected override PEReader ResolveCore(string simpleName)
+ {
+ if (_simpleNameToPathMap.TryGetValue(simpleName, out string path))
+ {
+ return new PEReader(File.OpenRead(path));
+ }
+
+ return null;
+ }
+ }
+ }
+
+ abstract class TestCase : IXunitSerializable
+ {
+ public string TestName { get; set; }
+ public string TypeName { get; set; }
+ public string MethodName { get; set; }
+ public int MetadataToken { get; set; }
+ public string ModuleName { get; set; }
+
+ public virtual void Deserialize(IXunitSerializationInfo info)
+ {
+ TestName = info.GetValue<string>(nameof(TestName));
+ TypeName = info.GetValue<string>(nameof(TypeName));
+ MethodName = info.GetValue<string>(nameof(MethodName));
+ MetadataToken = info.GetValue<int>(nameof(MetadataToken));
+ ModuleName = info.GetValue<string>(nameof(ModuleName));
+ }
+
+ public virtual void Serialize(IXunitSerializationInfo info)
+ {
+ info.AddValue(nameof(TestName), TestName);
+ info.AddValue(nameof(TypeName), TypeName);
+ info.AddValue(nameof(MethodName), MethodName);
+ info.AddValue(nameof(MetadataToken), MetadataToken);
+ info.AddValue(nameof(ModuleName), ModuleName);
+ }
+
+ public override string ToString()
+ {
+ return $"[{Path.GetFileNameWithoutExtension(ModuleName)}] {TestName}";
+ }
+ }
+
+ /// <summary>
+ /// Describes a test case with a method that contains valid IL
+ /// </summary>
+ class ValidILTestCase : TestCase { }
+
+ /// <summary>
+ /// Describes a test case with a method that contains invalid IL with the expected VerifierErrors
+ /// </summary>
+ class InvalidILTestCase : TestCase
+ {
+ public List<VerifierError> ExpectedVerifierErrors { get; set; }
+
+ public override void Serialize(IXunitSerializationInfo info)
+ {
+ base.Serialize(info);
+ var serializedExpectedErrors = JsonConvert.SerializeObject(ExpectedVerifierErrors);
+ info.AddValue(nameof(ExpectedVerifierErrors), serializedExpectedErrors);
+ }
+
+ public override void Deserialize(IXunitSerializationInfo info)
+ {
+ base.Deserialize(info);
+ var serializedExpectedErrors = info.GetValue<string>(nameof(ExpectedVerifierErrors));
+ ExpectedVerifierErrors = JsonConvert.DeserializeObject<List<VerifierError>>(serializedExpectedErrors);
+ }
+
+ public override string ToString()
+ {
+ return base.ToString() + GetErrorsString(ExpectedVerifierErrors);
+ }
+
+ private static string GetErrorsString(List<VerifierError> errors)
+ {
+ if (errors == null || errors.Count <= 0)
+ return String.Empty;
+
+ var errorsString = new StringBuilder(" (");
+
+ for (int i = 0; i < errors.Count - 1; ++i)
+ errorsString.Append(errors[i]).Append(", ");
+
+ errorsString.Append(errors[errors.Count - 1]);
+ errorsString.Append(")");
+
+ return errorsString.ToString();
+ }
+ }
+
+ class ValidTypeTestCase : TestCase { }
+
+ class InvalidTypeTestCase : TestCase
+ {
+ public List<VerifierError> ExpectedVerifierErrors { get; set; }
+
+ public override void Serialize(IXunitSerializationInfo info)
+ {
+ base.Serialize(info);
+ var serializedExpectedErrors = JsonConvert.SerializeObject(ExpectedVerifierErrors);
+ info.AddValue(nameof(ExpectedVerifierErrors), serializedExpectedErrors);
+ }
+
+ public override void Deserialize(IXunitSerializationInfo info)
+ {
+ base.Deserialize(info);
+ var serializedExpectedErrors = info.GetValue<string>(nameof(ExpectedVerifierErrors));
+ ExpectedVerifierErrors = JsonConvert.DeserializeObject<List<VerifierError>>(serializedExpectedErrors);
+ }
+
+ public override string ToString()
+ {
+ return base.ToString() + GetErrorsString(ExpectedVerifierErrors);
+ }
+
+ private static string GetErrorsString(List<VerifierError> errors)
+ {
+ if (errors == null || errors.Count <= 0)
+ return String.Empty;
+
+ var errorsString = new StringBuilder(" (");
+
+ for (int i = 0; i < errors.Count - 1; ++i)
+ errorsString.Append(errors[i]).Append(", ");
+
+ errorsString.Append(errors[errors.Count - 1]);
+ errorsString.Append(")");
+
+ return errorsString.ToString();
+ }
+ }
+}