[clang] [clang] Automatically add the `returns_twice` attribute to certain functions even if `-fno-builtin` is set (PR #133511)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 28 13:09:07 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Alan Zhao (alanzhao1)
<details>
<summary>Changes</summary>
Certain functions require the `returns_twice` attribute in order to produce correct codegen. However, `-fno-builtin` removes all knowledge of functions that require this attribute, so this PR modifies Clang to add the `returns_twice` attribute even if `-fno-builtin` is set. This behavior is also consistent with what GCC does.
It's not (easily) possible to get the builtin information from `Builtins.td` because `-fno-builtin` causes Clang to never initialize any builtins, so functions never get tokenized as functions/builtins that require `returns_twice`. Therefore, the most straightforward solution is to explicitly hard code the function names that require `returns_twice`.
Fixes #<!-- -->122840
---
Full diff: https://github.com/llvm/llvm-project/pull/133511.diff
3 Files Affected:
- (modified) clang/lib/CodeGen/CGCall.cpp (+9)
- (modified) clang/test/CodeGen/2003-08-20-vfork-bug.c (+4-1)
- (modified) clang/test/CodeGen/setjmp.c (+15)
``````````diff
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 7aa77e55dbfcc..76119617f22e6 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2607,6 +2607,15 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
if (shouldDisableTailCalls())
FuncAttrs.addAttribute("disable-tail-calls", "true");
+ // These functions require the returns_twice attribute for correct codegen,
+ // but the attribute may not be added if -fno-builtin is specified. We
+ // explicitly add that attribute here.
+ static const llvm::StringSet<> ReturnsTwiceFn{
+ "_setjmpex", "setjmp", "_setjmp", "vfork",
+ "sigsetjmp", "__sigsetjmp", "savectx", "getcontext"};
+ if (ReturnsTwiceFn.contains(Name))
+ FuncAttrs.addAttribute(llvm::Attribute::ReturnsTwice);
+
// CPU/feature overrides. addDefaultFunctionDefinitionAttributes
// handles these separately to set them based on the global defaults.
GetCPUAndFeaturesAttributes(CalleeInfo.getCalleeDecl(), FuncAttrs);
diff --git a/clang/test/CodeGen/2003-08-20-vfork-bug.c b/clang/test/CodeGen/2003-08-20-vfork-bug.c
index 4966ab20904d4..438604f321da3 100644
--- a/clang/test/CodeGen/2003-08-20-vfork-bug.c
+++ b/clang/test/CodeGen/2003-08-20-vfork-bug.c
@@ -1,5 +1,8 @@
-// RUN: %clang_cc1 -emit-llvm %s -o /dev/null
+// RUN: %clang_cc1 -x c %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -x c %s -triple x86_64-linux-gnu -emit-llvm -fno-builtin -o - | FileCheck %s
+// CHECK: ; Function Attrs: returns_twice
+// CHECK-NEXT: declare {{.*}} @vfork(
extern int vfork(void);
void test() {
vfork();
diff --git a/clang/test/CodeGen/setjmp.c b/clang/test/CodeGen/setjmp.c
index 77dde35e69cae..00341e459941a 100644
--- a/clang/test/CodeGen/setjmp.c
+++ b/clang/test/CodeGen/setjmp.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -x c %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -x c %s -triple x86_64-linux-gnu -emit-llvm -fno-builtin -o - | FileCheck %s
// RUN: %clang_cc1 -x c++ %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s
#ifdef __cplusplus
@@ -6,13 +7,17 @@ extern "C" {
#endif
struct __jmp_buf_tag { int n; };
+struct __ucontext_t_tag { int n; };
int setjmp(struct __jmp_buf_tag*);
int sigsetjmp(struct __jmp_buf_tag*, int);
int _setjmp(struct __jmp_buf_tag*);
int __sigsetjmp(struct __jmp_buf_tag*, int);
+int _setjmpex(struct __jmp_buf_tag* env);
+int getcontext(struct __ucontext_t_tag*);
typedef struct __jmp_buf_tag jmp_buf[1];
typedef struct __jmp_buf_tag sigjmp_buf[1];
+typedef struct __ucontext_t_tag ucontext_t[1];
#ifdef __cplusplus
}
@@ -20,6 +25,7 @@ typedef struct __jmp_buf_tag sigjmp_buf[1];
void f(void) {
jmp_buf jb;
+ ucontext_t ut;
// CHECK: call {{.*}}@setjmp(
setjmp(jb);
// CHECK: call {{.*}}@sigsetjmp(
@@ -28,6 +34,10 @@ void f(void) {
_setjmp(jb);
// CHECK: call {{.*}}@__sigsetjmp(
__sigsetjmp(jb, 0);
+ // CHECK: call {{.*}}@_setjmpex(
+ _setjmpex(jb);
+ // CHECK: call {{.*}}@getcontext(
+ getcontext(ut);
}
// CHECK: ; Function Attrs: returns_twice
@@ -42,3 +52,8 @@ void f(void) {
// CHECK: ; Function Attrs: returns_twice
// CHECK-NEXT: declare {{.*}} @__sigsetjmp(
+// CHECK: ; Function Attrs: returns_twice
+// CHECK-NEXT: declare {{.*}} @_setjmpex(
+
+// CHECK: ; Function Attrs: returns_twice
+// CHECK-NEXT: declare {{.*}} @getcontext(
``````````
</details>
https://github.com/llvm/llvm-project/pull/133511
More information about the cfe-commits
mailing list