Parse custom attribute value blobs for dependencies and rewrite type name strings in ILTrim#127596
Parse custom attribute value blobs for dependencies and rewrite type name strings in ILTrim#127596
Conversation
…ame strings Implement custom attribute blob parsing in CustomAttributeNode: 1. GetStaticDependencies now decodes the custom attribute value blob and reports dependencies for typeof() arguments, enum types, property setters, and fields referenced in the blob. 2. WriteInternal now re-encodes the blob with type name strings resolved to their definitions, handling cases where trimming drops type forwarders (e.g. re-encoding "System.Object, System.Runtime" to "System.Object, System.Private.CoreLib"). Remove 24 tests from ILTrimExpectedFailures.txt that now pass. Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/f4173cc7-fd45-4a62-9a1c-1a31c06cc85b Co-authored-by: MichalStrehovsky <13110571+MichalStrehovsky@users.noreply.github.com>
… remove unused parameter - Catch TypeSystemException and BadImageFormatException instead of base Exception - Add DependencyNode type alias to reduce verbose fully-qualified type names - Remove unused isFixedArg parameter from WriteArgumentValue - Hoist constructor resolution out of named argument loop - Fix duplicate CustomAttributeTypeNameFormatter allocations Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/f4173cc7-fd45-4a62-9a1c-1a31c06cc85b Co-authored-by: MichalStrehovsky <13110571+MichalStrehovsky@users.noreply.github.com>
|
Tagging subscribers to this area: @agocke, @dotnet/illink |
| CustomAttributeValue<TypeDesc> decodedValue, | ||
| CustomAttributeTypeNameFormatter formatter) | ||
| { | ||
| var blobBuilder = new BlobBuilder(); |
There was a problem hiding this comment.
@copilot change the custom attribute encoding logic in this file to use BlobEncoder.CustomAttributeNamedArgumentsEncoder APIs. Use the BlobBuilder that is provided by writeContext.GetSharedBlobBuilder. Follow the existing patterns that the other callers of writeContext.GetSharedBlobBuilder use (the rewriter just returns void, writes to the provided BlobBuilder, do not materialize array).
There was a problem hiding this comment.
Done in da3465b. Refactored to use BlobEncoder.CustomAttributeSignature with FixedArgumentsEncoder / CustomAttributeNamedArgumentsEncoder, NamedArgumentTypeEncoder, CustomAttributeElementTypeEncoder, LiteralEncoder, ScalarEncoder, etc. Uses writeContext.GetSharedBlobBuilder() following the established pattern — the rewriter is now void and writes directly to the shared BlobBuilder, no array materialization.
… BlobBuilder Use BlobEncoder.CustomAttributeSignature with FixedArgumentsEncoder and CustomAttributeNamedArgumentsEncoder instead of manual byte writing. Use writeContext.GetSharedBlobBuilder() following established patterns. Removed byte[] materialization - writes directly to shared BlobBuilder. Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/d078b767-9d76-41e5-9168-8f6651786108 Co-authored-by: MichalStrehovsky <13110571+MichalStrehovsky@users.noreply.github.com>
| bool needsRewrite = false; | ||
| CheckArgumentsForRewrite(decodedValue, ref needsRewrite); | ||
|
|
||
| if (!needsRewrite) | ||
| { | ||
| blobBuilder.WriteBytes(_module.MetadataReader.GetBlobBytes(customAttribute.Value)); | ||
| return; | ||
| } |
There was a problem hiding this comment.
@copilot this optimization is premature, we should rewrite always, this will just make the rewriting logic run rarely and hide bugs
There was a problem hiding this comment.
Removed the CheckArgumentsForRewrite/CheckArgumentValueForRewrite optimization in 20a8fef. The blob is now always re-encoded through the EncodeCustomAttributeBlob path.
…bute blobs Remove CheckArgumentsForRewrite/CheckArgumentValueForRewrite that skipped rewriting when no typeof() references were found. Always rewrite to exercise the encoding logic and surface bugs. Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/46e2e54d-5313-4538-8274-c5cfe241e547 Co-authored-by: MichalStrehovsky <13110571+MichalStrehovsky@users.noreply.github.com>
| if (argType.IsObject) | ||
| { | ||
| type.Object(); | ||
| return; |
There was a problem hiding this comment.
@copilot The methods in this file have many return statements. Use cascading if/else if/else instead.
There was a problem hiding this comment.
Replaced early returns with cascading if/else if/else in EncodeNamedArgumentType, WriteLiteralValue, and WriteScalarValue in 229cd7f2.
| if (type.IsEnum) | ||
| { | ||
| encoder.Enum(formatter.FormatName(type, true)); | ||
| return; | ||
| } | ||
|
|
||
| if (IsSystemType(type)) | ||
| { | ||
| encoder.SystemType(); | ||
| return; | ||
| } | ||
|
|
||
| switch (type.UnderlyingType.Category) |
There was a problem hiding this comment.
@copilot Make the switch over type.Category and handle IsEnum and System.Type in the default case.
There was a problem hiding this comment.
Switched to type.Category and moved IsEnum/IsSystemType/IsString handling into the default case in 229cd7f2.
…pe.Category - Replace early returns with cascading if/else if/else in EncodeNamedArgumentType, WriteLiteralValue, and WriteScalarValue. - Switch on type.Category instead of type.UnderlyingType.Category in EncodeElementType, handling IsEnum and System.Type in the default case. Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/683a21bb-4e07-4219-81e8-b0a320967bd3 Co-authored-by: MichalStrehovsky <13110571+MichalStrehovsky@users.noreply.github.com>
Description
CustomAttributeNodehad two TODOs: it wasn't parsing the custom attribute value blob for dependencies, and it wasn't rewriting type name strings that could become stale after trimming removes type forwarders.Dependency analysis (
GetStaticDependencies)Decodes the custom attribute blob via
CustomAttributeTypeProviderand reports dependencies for:typeof()argumentsFollows the same pattern as
CustomAttributeBasedDependencyAlgorithmin ILCompiler.Blob rewriting (
WriteInternal)Always re-encodes the blob using
BlobEncoder.CustomAttributeSignaturewithFixedArgumentsEncoderandCustomAttributeNamedArgumentsEncoderAPIs to resolve type name strings to their definitions. UseswriteContext.GetSharedBlobBuilder()following the established pattern of other callers — the rewriter writes directly to the providedBlobBuilderwithout materializing an intermediate array. The blob is unconditionally re-encoded (no early-out optimization) to ensure the encoding logic is always exercised and bugs are not hidden.This handles the case where trimming drops type forwarders — e.g.
typeof(object)stored asSystem.Object, System.Runtimegets re-encoded asSystem.Object, System.Private.CoreLibviaCustomAttributeTypeNameFormatter.Code style
if/else if/elseinstead of earlyreturnstatements.EncodeElementTypeswitches ontype.Categoryand handlesIsEnumandSystem.Typein thedefaultcase, rather than checking them before the switch.Test results
24 previously-expected-failing tests now pass and have been removed from
ILTrimExpectedFailures.txt(382 passed, 0 failed).