From 989d5f623f3b3fa90591b18ad29c7a879c640a52 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Thu, 29 May 2025 22:50:04 +0200 Subject: [PATCH] Fix interpreter double and 64 bit constant processing There is a bug in extracting 64 bit and double constants on both the interpreter compiler and execution sides. The problem was that the lower 32 bits were extracted as signed 32 bit int and then casted to signed 64 bit int and or-ed to the other 32 bits shifted up. The problem is that when the lower 32 bits were signed, the sign got extended to the upper 32 bits and the combined result was incorrect. This fixes 24 codegen bringup tests with the interpreter that were previously failing with "Assert.Equal() Failure: Values differ". --- src/coreclr/interpreter/intops.h | 2 +- src/coreclr/vm/interpexec.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/interpreter/intops.h b/src/coreclr/interpreter/intops.h index 334242321d96d5..6886400ac35fe0 100644 --- a/src/coreclr/interpreter/intops.h +++ b/src/coreclr/interpreter/intops.h @@ -98,7 +98,7 @@ inline int32_t getI4LittleEndian(const uint8_t* ptr) inline int64_t getI8LittleEndian(const uint8_t* ptr) { - return (int64_t)getI4LittleEndian(ptr) | ((int64_t)getI4LittleEndian(ptr + 4)) << 32; + return (int64_t)getU4LittleEndian(ptr) | ((int64_t)getI4LittleEndian(ptr + 4)) << 32; } inline float getR4LittleEndian(const uint8_t* ptr) diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index 15d91a4cf5398c..e03a8870676c10 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -143,7 +143,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr ip += 2; break; case INTOP_LDC_I8: - LOCAL_VAR(ip[1], int64_t) = (int64_t)ip[2] + ((int64_t)ip[3] << 32); + LOCAL_VAR(ip[1], int64_t) = (int64_t)(uint32_t)ip[2] + ((int64_t)ip[3] << 32); ip += 4; break; case INTOP_LDC_R4: @@ -151,7 +151,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr ip += 3; break; case INTOP_LDC_R8: - LOCAL_VAR(ip[1], int64_t) = (int64_t)ip[2] + ((int64_t)ip[3] << 32); + LOCAL_VAR(ip[1], int64_t) = (int64_t)(uint32_t)ip[2] + ((int64_t)ip[3] << 32); ip += 4; break; case INTOP_LDPTR: