Skip to content

Invalid codegen for custom IL with ldtoken #97949

@MichalPetryka

Description

@MichalPetryka

Description

CoreCLR generates invalid codegen for custom IL that returns a ldtoken of a type and passes that to GetTypeFromHandle.
It happens to somewhat work today cause RuntimeTypeHandle has the Type as its first field today.

Generated code:

; Assembly listing for method DisasmoPlayground.LdtokenRepro:GetIntHandle():System.RuntimeTypeHandle (FullOpts)
; Emitting BLENDED_CODE for X64 with AVX512 - Windows
; FullOpts code
; optimized code
; rsp based frame
; partially interruptible
; No PGO data
; Final local variable assignments
;
;  V00 OutArgs      [V00    ] (  1,  1   )  struct (32) [rsp+0x00]  do-not-enreg[XS] addr-exposed "OutgoingArgSpace"
;
; Lcl frame size = 40

G_M32313_IG01:  ;; offset=0x0000
       4883EC28             sub      rsp, 40
						;; size=4 bbWeight=1 PerfScore 0.25
G_M32313_IG02:  ;; offset=0x0004
       48B9B0F14B57FD7F0000 mov      rcx, 0x7FFD574BF1B0      ; System.Int32
       E87D4F4E5F           call     CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE
       90                   nop      
						;; size=16 bbWeight=1 PerfScore 1.50
G_M32313_IG03:  ;; offset=0x0014
       4883C428             add      rsp, 40
       C3                   ret      
						;; size=5 bbWeight=1 PerfScore 1.25

; Total bytes of code 25, prolog size 4, PerfScore 3.00, instruction count 6, allocated bytes for code 25 (MethodHash=a5a181c6) for method DisasmoPlayground.LdtokenRepro:GetIntHandle():System.RuntimeTypeHandle (FullOpts)
; ============================================================

; Assembly listing for method DisasmoPlayground.LdtokenRepro:GetIntType():System.Type (FullOpts)
; Emitting BLENDED_CODE for X64 with AVX512 - Windows
; FullOpts code
; optimized code
; rsp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 2 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
;  V00 OutArgs      [V00    ] (  1,  1   )  struct (32) [rsp+0x00]  do-not-enreg[XS] addr-exposed "OutgoingArgSpace"
;* V01 tmp1         [V01    ] (  0,  0   )  struct ( 8) zero-ref    single-def "spilled call-like call argument" <System.RuntimeTypeHandle>
;* V02 tmp2         [V02    ] (  0,  0   )  struct ( 8) zero-ref    ld-addr-op "Inlining Arg" <System.RuntimeTypeHandle>
;  V03 tmp3         [V03,T00] (  2,  2   )     ref  ->  rax         "field V01.m_type (fldOffset=0x0)" P-INDEP
;* V04 tmp4         [V04    ] (  0,  0   )     ref  ->  zero-ref    single-def "field V02.m_type (fldOffset=0x0)" P-INDEP
;
; Lcl frame size = 40

G_M55709_IG01:  ;; offset=0x0000
       4883EC28             sub      rsp, 40
						;; size=4 bbWeight=1 PerfScore 0.25
G_M55709_IG02:  ;; offset=0x0004
       48B9B0F14B57FD7F0000 mov      rcx, 0x7FFD574BF1B0      ; System.Int32
       E83D4B4E5F           call     CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE
       90                   nop      
						;; size=16 bbWeight=1 PerfScore 1.50
G_M55709_IG03:  ;; offset=0x0014
       4883C428             add      rsp, 40
       C3                   ret      
						;; size=5 bbWeight=1 PerfScore 1.25

; Total bytes of code 25, prolog size 4, PerfScore 3.00, instruction count 6, allocated bytes for code 25 (MethodHash=71282662) for method DisasmoPlayground.LdtokenRepro:GetIntType():System.Type (FullOpts)
; ============================================================

cc @EgorBo

Reproduction Steps

Disasm the code here (requires Fody.InlineIL):

using InlineIL;
using System;

public static class LdtokenRepro
{
	public static RuntimeTypeHandle GetIntHandle()
	{
		IL.Emit.Ldtoken(typeof(int));
		return IL.Return<RuntimeTypeHandle>();
	}
	public static Type GetIntType() => Type.GetTypeFromHandle(GetIntHandle());
}

Expected behavior

GetIntType is optimized the same as typeof or at least calls CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE.

Actual behavior

GetIntType calls CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE and returns that as Type.

Regression?

Not sure.

Known Workarounds

Don't use such IL.

Configuration

.NET 8.0.1/main
Windows 10 x64

Other information

No response

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions