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
2 changes: 2 additions & 0 deletions src/coreclr/tools/ILTrim.Tests/ILTrimExpectedFailures.txt
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ TypeForwarding.AttributesScopeUpdated
TypeForwarding.MultiForwardedTypesWithCopyUsed
TypeForwarding.MultiForwardedTypesWithLink
TypeForwarding.NestedTypeForwarder
TypeForwarding.RootedForwarderWithExportedTypesIsHandled
TypeForwarding.SecurityAttributeScope
TypeForwarding.TypeForwardedIsUpdatedForMissingType
TypeForwarding.TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml
Expand All @@ -537,6 +538,7 @@ TypeForwarding.UsedForwarderInCopyAssemblyKeptByUsedProperty
TypeForwarding.UsedForwarderInCopyAssemblyKeptByUsedTypeAsGenericArg
TypeForwarding.UsedForwarderInGenericIsDynamicallyAccessedWithAssemblyCopyUsed
TypeForwarding.UsedForwarderIsDynamicallyAccessedWithAssemblyCopyUsed
TypeForwarding.UsedForwarderIsRemovedWhenReferencedByRootedAssembly
TypeForwarding.UsedForwarderWithAssemblyCopy
TypeForwarding.UsedForwarderWithAssemblyCopyUsed
TypeForwarding.UsedForwarderWithAssemblyCopyUsedAndForwarderLibraryKept
Expand Down
13 changes: 10 additions & 3 deletions src/tools/illink/src/linker/Linker.Steps/MarkStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,8 @@ public virtual void MarkAssembly(AssemblyDefinition assembly, DependencyInfo rea
disableMarkingOfCopyAssembliesValue != "true")
{
MarkEntireAssembly(assembly, assemblyOrigin);
// For copy/save assemblies, also mark scopes of type references, since they won't be rewritten.
TypeReferenceMarker.MarkTypeReferences(assembly, MarkingHelpers);
}
return;
}
Expand Down Expand Up @@ -1519,8 +1521,14 @@ void MarkEntireAssembly(AssemblyDefinition assembly, MessageOrigin origin)
foreach (TypeDefinition type in module.Types)
MarkEntireType(type, new DependencyInfo(DependencyKind.TypeInAssembly, assembly), origin);

// Mark scopes of type references and exported types.
TypeReferenceMarker.MarkTypeReferences(assembly, MarkingHelpers);
MarkExportedTypes(assembly, origin);
}

void MarkExportedTypes(AssemblyDefinition assembly, MessageOrigin origin)
{
ModuleDefinition module = assembly.MainModule;
foreach (ExportedType exportedType in module.ExportedTypes)
MarkingHelpers.MarkExportedType(exportedType, module, new DependencyInfo(DependencyKind.ExportedType, assembly), origin);
}

sealed class TypeReferenceMarker : TypeReferenceWalker
Expand All @@ -1546,7 +1554,6 @@ protected override void ProcessTypeReference(TypeReference type)

protected override void ProcessExportedType(ExportedType exportedType)
{
markingHelpers.MarkExportedType(exportedType, assembly.MainModule, new DependencyInfo(DependencyKind.ExportedType, assembly), new MessageOrigin(assembly));
markingHelpers.MarkForwardedScope(CreateTypeReferenceForExportedTypeTarget(exportedType), new MessageOrigin(assembly));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// 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 Mono.Linker.Tests.Cases.Expectations.Assertions;
using Mono.Linker.Tests.Cases.Expectations.Metadata;
using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies;

namespace Mono.Linker.Tests.Cases.TypeForwarding
{
// Actions:
// link - This assembly (default), Forwarder.dll and Implementation.dll
// Rooting Forwarder.dll with -a (link action) while it is itself a type forwarder:
// MarkExportedTypes marks the exported type entries without TypeReferenceMarker running,
// and the implementation assembly is still preserved because the forwarded type is used.
[SetupLinkerArgument("-a", "Forwarder")]

[SetupCompileBefore("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })]

// After compiling the test case we then replace the reference impl with implementation + type forwarder
[SetupCompileAfter("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })]
[SetupCompileAfter("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })]

[KeptAssembly("Forwarder.dll")]
[KeptTypeInAssembly("Forwarder.dll", typeof(ImplementationLibrary))]
[RemovedAssemblyReference("test", "Forwarder")]
[KeptMemberInAssembly("Implementation.dll", typeof(ImplementationLibrary), "GetSomeValue()")]
class RootedForwarderWithExportedTypesIsHandled
{
static void Main()
{
new ImplementationLibrary().GetSomeValue();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// 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 Mono.Linker.Tests.Cases.Expectations.Assertions;
using Mono.Linker.Tests.Cases.Expectations.Metadata;
using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies;

namespace Mono.Linker.Tests.Cases.TypeForwarding
{
// Actions:
// link - This assembly (default), Forwarder.dll and Implementation.dll
// Rooting the test assembly with -a should not cause Forwarder.dll to be preserved,
// because type references are rewritten to point directly to Implementation.dll.
[SetupLinkerArgument("-a", "test")]

[SetupCompileBefore("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })]

// After compiling the test case we then replace the reference impl with implementation + type forwarder
[SetupCompileAfter("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })]
[SetupCompileAfter("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })]

[RemovedAssembly("Forwarder.dll")]
[RemovedAssemblyReference("test", "Forwarder")]
[KeptMemberInAssembly("Implementation.dll", typeof(ImplementationLibrary), "GetSomeValue()")]
[KeptMember(".ctor()")]
class UsedForwarderIsRemovedWhenReferencedByRootedAssembly
{
static void Main()
{
new ImplementationLibrary().GetSomeValue();
}
}
}
Loading