Skip to content

[CodeGen][ARM64EC] Copy first four arguments to FP registers in vararg exit thunks - #209581

Merged
cjacek merged 1 commit into
llvm:mainfrom
cjacek:vararg-float
Jul 16, 2026
Merged

[CodeGen][ARM64EC] Copy first four arguments to FP registers in vararg exit thunks#209581
cjacek merged 1 commit into
llvm:mainfrom
cjacek:vararg-float

Conversation

@cjacek

@cjacek cjacek commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

ARM64EC vararg functions receive all types of the first four arguments in x0-x3. Because x86_64 expects floating-point arguments in FP registers, always copy x0-x3 to d0-d3 in the exit thunks, matching MSVC's behavior.

…g exit thunks

ARM64EC vararg functions receive all types of the first four arguments in x0-x3.
Because x86_64 expects floating-point arguments in FP registers, always copy x0-x3 to d0-d3
in the exit thunks, matching MSVC's behavior.
@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-backend-aarch64

Author: Jacek Caban (cjacek)

Changes

ARM64EC vararg functions receive all types of the first four arguments in x0-x3. Because x86_64 expects floating-point arguments in FP registers, always copy x0-x3 to d0-d3 in the exit thunks, matching MSVC's behavior.


Full diff: https://github.com/llvm/llvm-project/pull/209581.diff

2 Files Affected:

  • (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+21)
  • (modified) llvm/test/CodeGen/AArch64/arm64ec-exit-thunks.ll (+12)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index d6f2633297e51..abb62492342f8 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -10556,6 +10556,27 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
         const TargetOptions &Options = DAG.getTarget().Options;
         if (Options.EmitCallSiteInfo)
           CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), i);
+        if (IsArm64ECVarArgExitThunk) {
+          Register FPReg;
+          switch (VA.getLocReg()) {
+          case AArch64::X0:
+            FPReg = AArch64::D0;
+            break;
+          case AArch64::X1:
+            FPReg = AArch64::D1;
+            break;
+          case AArch64::X2:
+            FPReg = AArch64::D2;
+            break;
+          case AArch64::X3:
+            FPReg = AArch64::D3;
+            break;
+          }
+          if (FPReg) {
+            RegsToPass.emplace_back(FPReg, Arg);
+            RegsUsed.insert(FPReg);
+          }
+        }
       }
     } else {
       assert(VA.isMemLoc());
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-exit-thunks.ll b/llvm/test/CodeGen/AArch64/arm64ec-exit-thunks.ll
index 03ce3ca919a56..78b59cfa196d8 100644
--- a/llvm/test/CodeGen/AArch64/arm64ec-exit-thunks.ll
+++ b/llvm/test/CodeGen/AArch64/arm64ec-exit-thunks.ll
@@ -313,7 +313,11 @@ declare void @has_varargs(...) nounwind;
 ; CHECK-NEXT:     mov     x2, x5
 ; CHECK-NEXT:     bl      "#memcpy"
 ; CHECK-NEXT:     sub     sp, sp, #32
+; CHECK-NEXT:     fmov    d0, x22
+; CHECK-NEXT:     fmov    d1, x21
 ; CHECK-NEXT:     mov     x9, x26
+; CHECK-NEXT:     fmov    d2, x20
+; CHECK-NEXT:     fmov    d3, x19
 ; CHECK-NEXT:     mov     x0, x22
 ; CHECK-NEXT:     mov     x1, x21
 ; CHECK-NEXT:     mov     x2, x20
@@ -391,7 +395,11 @@ declare [2 x i8] @has_varargs_small_struct(...) nounwind;
 ; CHECK-NEXT:     mov     x2, x5
 ; CHECK-NEXT:     bl      "#memcpy"
 ; CHECK-NEXT:     sub     sp, sp, #32
+; CHECK-NEXT:     fmov    d0, x22
+; CHECK-NEXT:     fmov    d1, x21
 ; CHECK-NEXT:     mov     x9, x26
+; CHECK-NEXT:     fmov    d2, x20
+; CHECK-NEXT:     fmov    d3, x19
 ; CHECK-NEXT:     mov     x0, x22
 ; CHECK-NEXT:     mov     x1, x21
 ; CHECK-NEXT:     mov     x2, x20
@@ -566,7 +574,11 @@ declare void @has_varargs_sret(ptr sret([100 x i8]), ...) nounwind;
 ; CHECK-NEXT:     mov     x2, x4
 ; CHECK-NEXT:     bl      "#memcpy"
 ; CHECK-NEXT:     sub     sp, sp, #32
+; CHECK-NEXT:     fmov    d0, x22
+; CHECK-NEXT:     fmov    d1, x21
 ; CHECK-NEXT:     mov     x9, x26
+; CHECK-NEXT:     fmov    d2, x20
+; CHECK-NEXT:     fmov    d3, x19
 ; CHECK-NEXT:     mov     x0, x22
 ; CHECK-NEXT:     mov     x1, x21
 ; CHECK-NEXT:     mov     x2, x20

@github-actions

Copy link
Copy Markdown

🐧 Linux x64 Test Results

  • 178942 tests passed
  • 3540 tests skipped
  • 1 test failed

Failed Tests

(click on a test name to see its output)

lldb-api

lldb-api.tools/lldb-dap/breakpoint/TestDAP_logpoints.py
Script:
--
/usr/bin/python3 /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib --env LLVM_INCLUDE_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include --env LLVM_TOOLS_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin --libcxx-include-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/include/c++/v1 --libcxx-include-target-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/include/x86_64-unknown-linux-gnu/c++/v1 --libcxx-library-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib/x86_64-unknown-linux-gnu --triple x86_64-unknown-linux-gnu --build-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build --lldb-module-cache-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build/module-cache-lldb/lldb-api --clang-module-cache-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build/module-cache-clang/lldb-api --executable /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/lldb --lldb-python-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/local/lib/python3.12/dist-packages --compiler /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/clang --dsymutil /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin --lldb-obj-root /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/lldb --lldb-libs-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib --cmake-build-type Release /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/tools/lldb-dap/breakpoint -p TestDAP_logpoints.py
--
Exit Code: 1

Command Output (stdout):
--
Skipping the following test categories: msvcstl, dsym, pdb, gmodules, debugserver, objc

--
Command Output (stderr):
--
PASS: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_logmessage_advanced (TestDAP_logpoints.TestDAP_logpoints.test_logmessage_advanced)
PASS: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_logmessage_basic (TestDAP_logpoints.TestDAP_logpoints.test_logmessage_basic)
FAIL: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_logmessage_format (TestDAP_logpoints.TestDAP_logpoints.test_logmessage_format)
Log Files:
 - /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build/tools/lldb-dap/breakpoint/TestDAP_logpoints/Failure_test_logmessage_format.log
 - /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build/tools/lldb-dap/breakpoint/TestDAP_logpoints/Failure_test_logmessage_format-dap.log
PASS: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_logmessage_format_failure (TestDAP_logpoints.TestDAP_logpoints.test_logmessage_format_failure)
======================================================================
FAIL: test_logmessage_format (TestDAP_logpoints.TestDAP_logpoints.test_logmessage_format)
   Tests breakpoint logmessage functionality with format.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py", line 204, in test_logmessage_format
    self.assertEqual(
AssertionError: "This is log message for -- part1\tpart2\[44 chars]11'." != 'This is log message for -- part1\tpart2\x08part3dpart4-1'
- This is log message for -- part1	part2part3dpart4<error: Ran expression as 'C++11'.
?                                 	                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---
+ This is log message for -- part1	part2part3dpart4-1
?                                 	                 ^

Config=x86_64-/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang
----------------------------------------------------------------------
Ran 4 tests in 5.439s

FAILED (failures=1)

--

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

@efriedma-quic efriedma-quic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The x64 ABI spec says "For floating-point values only, both the integer register and the floating-point register must contain the value", but I guess we can't tell if a value is a floating-point value at this point because we've already moved everything into integer registers.

I'm not sure anything actually uses the values from the FP registers in practice, but I guess matching MSVC is a good enough excuse.

LGTM

@cjacek
cjacek merged commit 9c6a9f5 into llvm:main Jul 16, 2026
10 of 11 checks passed
@cjacek
cjacek deleted the vararg-float branch July 16, 2026 08:55
@cjacek

cjacek commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Merged, thanks!

@mstorsjo

Copy link
Copy Markdown
Member

I presume this is relevant to backport to 23.x?

@cjacek

cjacek commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

/cherry-pick 9c6a9f5

EDIT: Trying to retrigger the backport.

@cjacek

cjacek commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

I presume this is relevant to backport to 23.x?

Yes, it probably makes sense to ship together with the rest of vararg thunks fixes.

@llvmbot

llvmbot commented Jul 17, 2026

Copy link
Copy Markdown
Member

/pull-request #210315

dyung pushed a commit to llvmbot/llvm-project that referenced this pull request Jul 22, 2026
…g exit thunks (llvm#209581)

ARM64EC vararg functions receive all types of the first four arguments
in x0-x3. Because x86_64 expects floating-point arguments in FP
registers, always copy x0-x3 to d0-d3 in the exit thunks, matching
MSVC's behavior.

(cherry picked from commit 9c6a9f5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

4 participants