Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?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>
2 changes: 2 additions & 0 deletions src/coreclr/src/.nuget/coreclr-packages.proj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

<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>
Expand Down
10 changes: 10 additions & 0 deletions src/coreclr/src/.nuget/descriptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,15 @@
"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": [ ]
}
]
6 changes: 6 additions & 0 deletions src/coreclr/src/.nuget/dotnet-ilverify/DotnetToolSettings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<DotNetCliTool Version="1">
<Commands>
<Command Name="ilverify" EntryPoint="ILVerify.dll" Runner="dotnet" />
</Commands>
</DotNetCliTool>
36 changes: 36 additions & 0 deletions src/coreclr/src/.nuget/dotnet-ilverify/dotnet-ilverify.pkgproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// 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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// 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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// 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;
}
}
}
Loading