[llvm] [RISCV] Guard the alternative static chain register use on ILP32E/LP64E (PR #142715)

Jesse Huang via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 10 23:12:29 PDT 2025


https://github.com/jaidTw updated https://github.com/llvm/llvm-project/pull/142715

>From 20866709d984cc17a9aa8fd9438c923c1c201aa7 Mon Sep 17 00:00:00 2001
From: Jesse Huang <jesse.huang at sifive.com>
Date: Tue, 3 Jun 2025 21:55:37 -0700
Subject: [PATCH 1/6] [RISCV] Guard the alternative static chain register use
 on RV32E

---
 llvm/lib/Target/RISCV/RISCVCallingConv.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
index e0d1fb2facc87..3b609adcf8c09 100644
--- a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
@@ -338,6 +338,10 @@ bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT,
   bool HasCFBranch =
       Subtarget.hasStdExtZicfilp() &&
       MF.getFunction().getParent()->getModuleFlag("cf-protection-branch");
+  if (HasCFBranch && (Subtarget.isRV32() && Subtarget.hasStdExtE()))
+    reportFatalUsageError(
+        "Alternative static chain register is not supported on RV32E");
+
   // Normal: t2, Branch control flow protection: t3
   const auto StaticChainReg = HasCFBranch ? RISCV::X28 : RISCV::X7;
 

>From 8e410def9ae4daeb5175fc3f8ca1338edc281495 Mon Sep 17 00:00:00 2001
From: Jesse Huang <jesse.huang at sifive.com>
Date: Wed, 4 Jun 2025 00:57:46 -0700
Subject: [PATCH 2/6] Addressed comments

---
 llvm/lib/Target/RISCV/RISCVCallingConv.cpp | 27 ++++++++++++----------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
index 3b609adcf8c09..d1c31601f2871 100644
--- a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
@@ -333,19 +333,22 @@ bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT,
   unsigned XLen = Subtarget.getXLen();
   MVT XLenVT = Subtarget.getXLenVT();
 
-  // Static chain parameter must not be passed in normal argument registers,
-  // so we assign t2/t3 for it as done in GCC's __builtin_call_with_static_chain
-  bool HasCFBranch =
-      Subtarget.hasStdExtZicfilp() &&
-      MF.getFunction().getParent()->getModuleFlag("cf-protection-branch");
-  if (HasCFBranch && (Subtarget.isRV32() && Subtarget.hasStdExtE()))
-    reportFatalUsageError(
-        "Alternative static chain register is not supported on RV32E");
-
-  // Normal: t2, Branch control flow protection: t3
-  const auto StaticChainReg = HasCFBranch ? RISCV::X28 : RISCV::X7;
-
   if (ArgFlags.isNest()) {
+    // Static chain parameter must not be passed in normal argument registers,
+    // so we assign t2/t3 for it as done in GCC's
+    // __builtin_call_with_static_chain
+    bool HasCFBranch =
+        Subtarget.hasStdExtZicfilp() &&
+        MF.getFunction().getParent()->getModuleFlag("cf-protection-branch");
+
+    // Normal: t2, Branch control flow protection: t3
+    const auto StaticChainReg = HasCFBranch ? RISCV::X28 : RISCV::X7;
+
+    RISCVABI::ABI ABI = Subtarget.getTargetABI();
+    if (HasCFBranch &&
+        (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E))
+      reportFatalUsageError(
+          "Alternative static chain register t3 is not usable with EABI.");
     if (MCRegister Reg = State.AllocateReg(StaticChainReg)) {
       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
       return false;

>From 01b79860204db3127e8ce0fc3fb234dfab9cff4f Mon Sep 17 00:00:00 2001
From: Jesse Huang <jessehuang2222 at gmail.com>
Date: Wed, 4 Jun 2025 16:37:28 +0800
Subject: [PATCH 3/6] Update llvm/lib/Target/RISCV/RISCVCallingConv.cpp

Co-authored-by: Kito Cheng <kito.cheng at gmail.com>
---
 llvm/lib/Target/RISCV/RISCVCallingConv.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
index d1c31601f2871..f974daf997b8b 100644
--- a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
@@ -348,7 +348,7 @@ bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT,
     if (HasCFBranch &&
         (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E))
       reportFatalUsageError(
-          "Alternative static chain register t3 is not usable with EABI.");
+          "Alternative static chain register t3 is not usable with ILP32E or LP64E ABI.");
     if (MCRegister Reg = State.AllocateReg(StaticChainReg)) {
       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
       return false;

>From ac506b113f12bd7608776f885809257f67b5651f Mon Sep 17 00:00:00 2001
From: Jesse Huang <jesse.huang at sifive.com>
Date: Wed, 4 Jun 2025 01:46:03 -0700
Subject: [PATCH 4/6] clang-format

---
 llvm/lib/Target/RISCV/RISCVCallingConv.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
index f974daf997b8b..40099b90b232d 100644
--- a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
@@ -347,8 +347,8 @@ bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT,
     RISCVABI::ABI ABI = Subtarget.getTargetABI();
     if (HasCFBranch &&
         (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E))
-      reportFatalUsageError(
-          "Alternative static chain register t3 is not usable with ILP32E or LP64E ABI.");
+      reportFatalUsageError("Alternative static chain register t3 is not "
+                            "usable with ILP32E or LP64E ABI.");
     if (MCRegister Reg = State.AllocateReg(StaticChainReg)) {
       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
       return false;

>From db6d7b1949f0522a238d0f5b09b14deda3863487 Mon Sep 17 00:00:00 2001
From: Jesse Huang <jessehuang2222 at gmail.com>
Date: Wed, 11 Jun 2025 13:20:32 +0800
Subject: [PATCH 5/6] Update llvm/lib/Target/RISCV/RISCVCallingConv.cpp

Co-authored-by: Sam Elliott <sam at lenary.co.uk>
---
 llvm/lib/Target/RISCV/RISCVCallingConv.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
index 40099b90b232d..a5b6363193556 100644
--- a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
@@ -347,7 +347,7 @@ bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT,
     RISCVABI::ABI ABI = Subtarget.getTargetABI();
     if (HasCFBranch &&
         (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E))
-      reportFatalUsageError("Alternative static chain register t3 is not "
+      reportFatalUsageError("Nested functions with control flow protection are not "
                             "usable with ILP32E or LP64E ABI.");
     if (MCRegister Reg = State.AllocateReg(StaticChainReg)) {
       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));

>From d1a7d522427673f4e5acfc6aff46ea1106b89b4b Mon Sep 17 00:00:00 2001
From: Jesse Huang <jesse.huang at sifive.com>
Date: Tue, 10 Jun 2025 23:12:12 -0700
Subject: [PATCH 6/6] Add test

---
 llvm/test/CodeGen/RISCV/nest-register.ll | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/nest-register.ll b/llvm/test/CodeGen/RISCV/nest-register.ll
index 9f8e4e1a2d8d3..6e892e05c4297 100644
--- a/llvm/test/CodeGen/RISCV/nest-register.ll
+++ b/llvm/test/CodeGen/RISCV/nest-register.ll
@@ -5,6 +5,8 @@
 ; RUN:   | FileCheck -check-prefix=RV64I %s
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfilp -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64I-ZICFILP %s
+; RUN: not llc -mtriple=riscv64 -target-abi=lp64e -mattr=+experimental-zicfilp \
+; RUN:   -verify-machineinstrs < %s 2>&1 | FileCheck -check-prefix=LP64E-ZICFILP %s
 
 ; Tests that the 'nest' parameter attribute causes the relevant parameter to be
 ; passed in the right register.
@@ -63,6 +65,7 @@ define ptr @nest_caller(ptr %arg) nounwind {
   ret ptr %result
 }
 
+; LP64E-ZICFILP: LLVM ERROR: Nested functions with control flow protection are not usable with ILP32E or LP64E ABI.
 !llvm.module.flags = !{!0}
 
 !0 = !{i32 8, !"cf-protection-branch", i32 1}



More information about the llvm-commits mailing list