|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Linq;
using ILLink.Shared.DataFlow;
using MultiValue = ILLink.Shared.DataFlow.ValueSet<ILLink.Shared.DataFlow.SingleValue>;
// This is needed due to NativeAOT which doesn't enable nullable globally yet
#nullable enable
namespace ILLink.Shared.TrimAnalysis
{
internal sealed partial record ArrayValue : SingleValue
{
private static ValueSetLattice<SingleValue> MultiValueLattice => default;
public readonly SingleValue Size;
public partial bool TryGetValueByIndex(int index, out MultiValue value);
public static MultiValue SanitizeArrayElementValue(MultiValue input)
{
// We need to be careful about self-referencing arrays. It's easy to have an array which has one of the elements as itself:
// var arr = new object[1];
// arr[0] = arr;
//
// We can't deep copy this, as it's an infinite recursion. And we can't easily guard against it with checks to self-referencing
// arrays - as this could be two or more levels deep.
//
// We need to deep copy arrays because we don't have a good way to track references (we treat everything as a value type)
// and thus we could get bad results if the array is involved in multiple branches for example.
// That said, it only matters for us to track arrays to be able to get integers or Type values (and we really only need relatively simple cases)
//
// So we will simply treat array value as an element value as "too complex to analyze" and give up by storing Unknown instead
bool needSanitization = false;
foreach (var v in input.AsEnumerable())
{
if (v is ArrayValue)
needSanitization = true;
}
if (!needSanitization)
return input;
return new(input.AsEnumerable().Select(v => v is ArrayValue ? UnknownValue.Instance : v));
}
}
}
|