From 34cbd02e6dbefb408e693887f0fa571e5fcc1260 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Wed, 17 Jun 2026 16:05:37 +0200 Subject: [PATCH 1/2] JIT: don't narrow relocatable handle constants in optNarrowTree optNarrowTree could narrow a GT_CNS_INT handle to TYP_INT whenever its value happened to fit in 32 bits. For a relocatable handle (e.g. a function-address handle that is the operand of the fat-pointer check NE(AND(fptr, 2), 0)), this made ARM64 codegen materialize the address with a 32-bit adrp+add (0x11000000) while still recording a 64-bit PAGEOFFSET_12A relocation, tripping the (addInstr & 0xFFC00000) == 0x91000000 assert in the NativeAOT relocation writer. The bug was latent and only became observable on checked/debug NativeAOT once handle values stopped carrying a high tag bit (so they fit in int32). Guard the GT_CNS_INT narrowing on !ImmedValNeedsReloc so handle constants keep their pointer width. Fixes #129504 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/coreclr/jit/optimizer.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index a1ccf0717a9354..60d177569ca31e 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -3161,6 +3161,17 @@ bool Compiler::optNarrowTree(GenTree* tree, var_types srct, var_types dstt, Valu case GT_CNS_INT: + // Do not narrow relocatable handle constants. They are materialized as + // pointer-sized addresses (e.g. an ARM64 adrp+add pair carrying a page-offset + // relocation), so they must retain their full width even when the value happens + // to fit in the narrower type. Narrowing such a handle to TYP_INT would make the + // backend emit a 32-bit address materialization and attach a 64-bit page-offset + // relocation to it. + if (tree->AsIntCon()->ImmedValNeedsReloc(this)) + { + return false; + } + ssize_t ival; ival = tree->AsIntCon()->IconValue(); ssize_t imask; From 970c359dac17f7ebe68cb732782ddd999168022e Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Wed, 17 Jun 2026 16:07:12 +0200 Subject: [PATCH 2/2] Update optimizer.cpp --- src/coreclr/jit/optimizer.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 60d177569ca31e..cfc66d241c0cdc 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -3161,12 +3161,7 @@ bool Compiler::optNarrowTree(GenTree* tree, var_types srct, var_types dstt, Valu case GT_CNS_INT: - // Do not narrow relocatable handle constants. They are materialized as - // pointer-sized addresses (e.g. an ARM64 adrp+add pair carrying a page-offset - // relocation), so they must retain their full width even when the value happens - // to fit in the narrower type. Narrowing such a handle to TYP_INT would make the - // backend emit a 32-bit address materialization and attach a 64-bit page-offset - // relocation to it. + // Do not narrow relocatable handle constants. if (tree->AsIntCon()->ImmedValNeedsReloc(this)) { return false;