Skip to content
This repository was archived by the owner on Sep 25, 2026. It is now read-only.
This repository was archived by the owner on Sep 25, 2026. It is now read-only.

UnreachableBlocksOptimizer hits NotSupportedException when compiling crossgen2 in runtime build #2872

Closed

Description

@agocke

Stack trace:

Fatal error in IL Linker
Unhandled exception. System.NotImplementedException: switch
at Mono.Linker.Steps.UnreachableBlocksOptimizer.BodyReducer.IsConstantBranch(OpCode opCode, Int32 operand)
at Mono.Linker.Steps.UnreachableBlocksOptimizer.BodyReducer.RemoveConditions()
at Mono.Linker.Steps.UnreachableBlocksOptimizer.BodyReducer.RewriteBody()
at Mono.Linker.Steps.UnreachableBlocksOptimizer.ProcessMethod(MethodDefinition method)
at Mono.Linker.Steps.MarkStep.ProcessMethod(MethodDefinition method, DependencyInfo& reason, MessageOrigin& origin)
at Mono.Linker.Steps.MarkStep.ProcessQueue()
at Mono.Linker.Steps.MarkStep.ProcessPrimaryQueue()
at Mono.Linker.Steps.MarkStep.Process()
at Mono.Linker.Steps.MarkStep.Process(LinkContext context)
at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step)
at Mono.Linker.Pipeline.Process(LinkContext context)
at Mono.Linker.Driver.Run(ILogger customLogger)
at Mono.Linker.Driver.Main(String[] args)

It looks like the problematic method might be ComputeDefaultOptions which looks like

 public static void ComputeDefaultOptions(out TargetOS os, out TargetArchitecture arch)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                os = TargetOS.Windows;
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                os = TargetOS.Linux;
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                os = TargetOS.OSX;
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD))
                os = TargetOS.FreeBSD;
            else
                throw new NotImplementedException();

            switch (RuntimeInformation.ProcessArchitecture)
            {
                case Architecture.X86:
                    arch = TargetArchitecture.X86;
                    break;
                case Architecture.X64:
                    arch = TargetArchitecture.X64;
                    break;
                case Architecture.Arm:
                    arch = TargetArchitecture.ARM;
                    break;
                case Architecture.Arm64:
                    arch = TargetArchitecture.ARM64;
                    break;
                default:
                    throw new NotImplementedException();
            }

        }

Activity

  1. agocke commented on Jun 30, 2022

    @agocke
    MemberAuthor

    To replicate, commit is agocke/runtime@e564c27, then ./build.sh clr+libs+packs.product, on Mac (which is where trimming happens by default, this could be enabled on other platforms with some modifications to the crossgen2 project file)

  2. agocke commented on Jul 1, 2022

    @agocke
    MemberAuthor

    @marek-safar Any ideas here?

  3. added this to the .NET 7.0 milestone on Jul 1, 2022
  4. sbomer commented on Jul 8, 2022

    @sbomer
    Member

    This is being hit in dotnet/runtime#71378

  5. vitek-karas commented on Jul 11, 2022

    @vitek-karas
    Member

    Added a test which reproes this in #2887

    Note about the repro:
    There's a bug in linker where if the first thing method does is a switch the const. prop code will not recognize it as optimizable branch instruction. So the test adds a dummy call before it. We might as well fix it:

    if (i > 3 && GetConstantValue (FoldedInstructions[i - 3], out operand) && operand is int opint2 && IsPairedStlocLdloc (FoldedInstructions[i - 2], FoldedInstructions[i - 1])) {

    Should be i >= 3.

  6. vitek-karas commented on Jul 11, 2022

    @vitek-karas
    Member

    The bug is essentially the fact that the const. prop doesn't have code to optimize switch instructions. It recognizes them as branch instructions, so it tries to optimize them, but when it actually works on it, it doesn't know what to do.

    Note that this is only hittable in Release built input, in Debug builds Roslyn produces a pattern around switch which linker doesn't recognize currently.

  7. vitek-karas commented on Jul 11, 2022

    @vitek-karas
    Member

    Workaround would be to simply skip over switch instruction - don't support optimizing them for now.

    Actually optimizing switch instructions is obviously doable, but requires much more work. Some of the patterns which hit this would benefit from such support though (the one above doesn't really, but there are others hit in runtime repo).

  8. vitek-karas commented on Jul 12, 2022

    @vitek-karas
    Member

    #2889 has a "fix" - basically intentionally disable any support for switch instruction block removal to avoid the exception.

  9. vitek-karas commented on Jul 12, 2022

    @vitek-karas
    Member

    #2889 should fix this issue - that is should make the linker NOT crash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions