Exclude code dealing with System.Numeric.Vector`1 from CPAOT compilation (#6527)
I have added a new field layout algorithm for Vector<T> and checks to abort method compilation when it tries to access this information.
This commit is contained in:
Родитель
93ee893418
Коммит
93cc8811fe
|
@ -27,7 +27,7 @@ namespace ILCompiler
|
|||
private ArrayOfTRuntimeInterfacesAlgorithm _arrayOfTRuntimeInterfacesAlgorithm;
|
||||
private MetadataVirtualMethodAlgorithm _virtualMethodAlgorithm = new MetadataVirtualMethodAlgorithm();
|
||||
|
||||
private SimdHelper _simdHelper;
|
||||
protected SimdHelper _simdHelper;
|
||||
|
||||
private TypeDesc[] _arrayOfTInterfaces;
|
||||
|
||||
|
|
|
@ -128,6 +128,10 @@ namespace ILCompiler
|
|||
// If compilation fails, don't emit code for this method. It will be Jitted at runtime
|
||||
Logger.Writer.WriteLine($"Warning: Method `{method}` was not compiled because: {ex.Message}");
|
||||
}
|
||||
catch (RequiresRuntimeJitException ex)
|
||||
{
|
||||
Logger.Writer.WriteLine($"Info: Method `{method}` was not compiled because `{ex.Message}` requires runtime JIT");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,12 +14,14 @@ namespace ILCompiler
|
|||
{
|
||||
private FieldLayoutAlgorithm _r2rFieldLayoutAlgorithm;
|
||||
private SystemObjectFieldLayoutAlgorithm _systemObjectFieldLayoutAlgorithm;
|
||||
private VectorFieldLayoutAlgorithm _vectorFieldLayoutAlgorithm;
|
||||
|
||||
public ReadyToRunCompilerContext(TargetDetails details, SharedGenericsMode genericsMode)
|
||||
: base(details, genericsMode)
|
||||
{
|
||||
_r2rFieldLayoutAlgorithm = new ReadyToRunMetadataFieldLayoutAlgorithm();
|
||||
_systemObjectFieldLayoutAlgorithm = new SystemObjectFieldLayoutAlgorithm(_r2rFieldLayoutAlgorithm);
|
||||
_vectorFieldLayoutAlgorithm = new VectorFieldLayoutAlgorithm(_r2rFieldLayoutAlgorithm);
|
||||
}
|
||||
|
||||
public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type)
|
||||
|
@ -30,10 +32,10 @@ namespace ILCompiler
|
|||
throw new NotImplementedException();
|
||||
else if (type.IsRuntimeDeterminedType)
|
||||
throw new NotImplementedException();
|
||||
/* TODO
|
||||
else if (_simdHelper.IsVectorOfT(type))
|
||||
throw new NotImplementedException();
|
||||
*/
|
||||
{
|
||||
return _vectorFieldLayoutAlgorithm;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(_r2rFieldLayoutAlgorithm != null);
|
||||
|
@ -70,5 +72,56 @@ namespace ILCompiler
|
|||
{
|
||||
return BaseTypeRuntimeInterfacesAlgorithm.Instance;
|
||||
}
|
||||
|
||||
private class VectorFieldLayoutAlgorithm : FieldLayoutAlgorithm
|
||||
{
|
||||
private FieldLayoutAlgorithm _fallbackAlgorithm;
|
||||
|
||||
public VectorFieldLayoutAlgorithm(FieldLayoutAlgorithm fallbackAlgorithm)
|
||||
{
|
||||
_fallbackAlgorithm = fallbackAlgorithm;
|
||||
}
|
||||
|
||||
public override bool ComputeContainsGCPointers(DefType type)
|
||||
{
|
||||
return _fallbackAlgorithm.ComputeContainsGCPointers(type);
|
||||
}
|
||||
|
||||
public override DefType ComputeHomogeneousFloatAggregateElementType(DefType type)
|
||||
{
|
||||
return _fallbackAlgorithm.ComputeHomogeneousFloatAggregateElementType(type);
|
||||
}
|
||||
|
||||
public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
|
||||
{
|
||||
List<FieldAndOffset> fieldsAndOffsets = new List<FieldAndOffset>();
|
||||
foreach (FieldDesc field in type.GetFields())
|
||||
{
|
||||
if (!field.IsStatic)
|
||||
{
|
||||
fieldsAndOffsets.Add(new FieldAndOffset(field, LayoutInt.Indeterminate));
|
||||
}
|
||||
}
|
||||
ComputedInstanceFieldLayout instanceLayout = new ComputedInstanceFieldLayout()
|
||||
{
|
||||
FieldSize = LayoutInt.Indeterminate,
|
||||
FieldAlignment = LayoutInt.Indeterminate,
|
||||
ByteCountUnaligned = LayoutInt.Indeterminate,
|
||||
ByteCountAlignment = LayoutInt.Indeterminate,
|
||||
Offsets = fieldsAndOffsets.ToArray(),
|
||||
};
|
||||
return instanceLayout;
|
||||
}
|
||||
|
||||
public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType type, StaticLayoutKind layoutKind)
|
||||
{
|
||||
return _fallbackAlgorithm.ComputeStaticFieldLayout(type, layoutKind);
|
||||
}
|
||||
|
||||
public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type)
|
||||
{
|
||||
return _fallbackAlgorithm.ComputeValueTypeShapeCharacteristics(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,14 @@ namespace Internal.JitInterface
|
|||
}
|
||||
}
|
||||
|
||||
public class RequiresRuntimeJitException : Exception
|
||||
{
|
||||
public RequiresRuntimeJitException(object reason)
|
||||
: base(reason.ToString())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
unsafe partial class CorInfoImpl
|
||||
{
|
||||
private const CORINFO_RUNTIME_ABI TargetABI = CORINFO_RUNTIME_ABI.CORINFO_CORECLR_ABI;
|
||||
|
|
|
@ -187,6 +187,13 @@ namespace Internal.JitInterface
|
|||
// Type system exceptions can be turned into code that throws the exception at runtime.
|
||||
_lastException.Throw();
|
||||
}
|
||||
#if READYTORUN
|
||||
else if (_lastException.SourceException is RequiresRuntimeJitException)
|
||||
{
|
||||
// Runtime JIT requirement is not a cause for failure, we just mustn't JIT a particular method
|
||||
_lastException.Throw();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
// This is just a bug somewhere.
|
||||
|
@ -1220,7 +1227,14 @@ namespace Internal.JitInterface
|
|||
private uint getClassSize(CORINFO_CLASS_STRUCT_* cls)
|
||||
{
|
||||
TypeDesc type = HandleToObject(cls);
|
||||
return (uint)type.GetElementSize().AsInt;
|
||||
LayoutInt classSize = type.GetElementSize();
|
||||
#if READYTORUN
|
||||
if (classSize.IsIndeterminate)
|
||||
{
|
||||
throw new RequiresRuntimeJitException(type);
|
||||
}
|
||||
#endif
|
||||
return (uint)classSize.AsInt;
|
||||
}
|
||||
|
||||
private uint getHeapClassSize(CORINFO_CLASS_STRUCT_* cls)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
|
||||
internal class ClassWithStatic
|
||||
|
@ -627,6 +628,27 @@ internal class Program
|
|||
return result;
|
||||
}
|
||||
|
||||
private static bool VectorTestOf<T>(T value1, T value2, T sum)
|
||||
where T : struct
|
||||
{
|
||||
Console.WriteLine("Constructing vector of {0}", value1);
|
||||
Vector<T> vector1 = new Vector<T>(value1);
|
||||
Console.WriteLine("Vector[0] = {0}", vector1[0]);
|
||||
Vector<T> vector2 = new Vector<T>(value2);
|
||||
Vector<T> vectorSum = vector1 + vector2;
|
||||
Console.WriteLine("Vector sum = {0}, {1} expected", vectorSum[0], sum);
|
||||
return vectorSum[0].Equals(sum);
|
||||
}
|
||||
|
||||
private static bool VectorTest()
|
||||
{
|
||||
bool success = true;
|
||||
success &= VectorTestOf<int>(10, 20, 30);
|
||||
success &= VectorTestOf<float>(15.0f, 30.0f, 45.0f);
|
||||
success &= VectorTestOf<double>(50.0, 100.0, 150.0);
|
||||
return success;
|
||||
}
|
||||
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
if (args.Length > 0)
|
||||
|
@ -671,6 +693,7 @@ internal class Program
|
|||
RunTest("ThisObjGenericLookupTest", ThisObjGenericLookupTest());
|
||||
RunTest("ClassParamGenericLookupTest", ClassParamGenericLookupTest());
|
||||
RunTest("MethodParamGenericLookupTest", MethodParamGenericLookupTest());
|
||||
RunTest("VectorTest", VectorTest());
|
||||
|
||||
Console.WriteLine($@"{_passedTests.Count} tests pass:");
|
||||
foreach (string testName in _passedTests)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
Program..cctor()
|
||||
Program.VectorTestOf(!!0,!!0,!!0)
|
||||
Program+DisposeStruct..cctor()
|
||||
Program+DisposeClass.Dispose()
|
||||
Program+DisposeClass..cctor()
|
||||
|
|
Загрузка…
Ссылка в новой задаче