Skip to content

Commit c5b3fe2

Browse files
authored
[clang] Automatically add the returns_twice attribute to certain functions even if -fno-builtin is set (#133511)
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
1 parent 94b04b4 commit c5b3fe2

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

clang/lib/CodeGen/CGCall.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2607,6 +2607,15 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
26072607
if (shouldDisableTailCalls())
26082608
FuncAttrs.addAttribute("disable-tail-calls", "true");
26092609

2610+
// These functions require the returns_twice attribute for correct codegen,
2611+
// but the attribute may not be added if -fno-builtin is specified. We
2612+
// explicitly add that attribute here.
2613+
static const llvm::StringSet<> ReturnsTwiceFn{
2614+
"_setjmpex", "setjmp", "_setjmp", "vfork",
2615+
"sigsetjmp", "__sigsetjmp", "savectx", "getcontext"};
2616+
if (ReturnsTwiceFn.contains(Name))
2617+
FuncAttrs.addAttribute(llvm::Attribute::ReturnsTwice);
2618+
26102619
// CPU/feature overrides. addDefaultFunctionDefinitionAttributes
26112620
// handles these separately to set them based on the global defaults.
26122621
GetCPUAndFeaturesAttributes(CalleeInfo.getCalleeDecl(), FuncAttrs);

clang/test/CodeGen/2003-08-20-vfork-bug.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
// RUN: %clang_cc1 -emit-llvm %s -o /dev/null
1+
// RUN: %clang_cc1 -x c %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s
2+
// RUN: %clang_cc1 -x c %s -triple x86_64-linux-gnu -emit-llvm -fno-builtin -o - | FileCheck %s
23

4+
// CHECK: ; Function Attrs: returns_twice
5+
// CHECK-NEXT: declare {{.*}} @vfork(
36
extern int vfork(void);
47
void test() {
58
vfork();

clang/test/CodeGen/setjmp.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
11
// RUN: %clang_cc1 -x c %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s
2+
// RUN: %clang_cc1 -x c %s -triple x86_64-linux-gnu -emit-llvm -fno-builtin -o - | FileCheck %s
23
// RUN: %clang_cc1 -x c++ %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s
34

45
#ifdef __cplusplus
56
extern "C" {
67
#endif
78

89
struct __jmp_buf_tag { int n; };
10+
struct __ucontext_t_tag { int n; };
911
int setjmp(struct __jmp_buf_tag*);
1012
int sigsetjmp(struct __jmp_buf_tag*, int);
1113
int _setjmp(struct __jmp_buf_tag*);
1214
int __sigsetjmp(struct __jmp_buf_tag*, int);
15+
int _setjmpex(struct __jmp_buf_tag* env);
16+
int getcontext(struct __ucontext_t_tag*);
1317

1418
typedef struct __jmp_buf_tag jmp_buf[1];
1519
typedef struct __jmp_buf_tag sigjmp_buf[1];
20+
typedef struct __ucontext_t_tag ucontext_t[1];
1621

1722
#ifdef __cplusplus
1823
}
1924
#endif
2025

2126
void f(void) {
2227
jmp_buf jb;
28+
ucontext_t ut;
2329
// CHECK: call {{.*}}@setjmp(
2430
setjmp(jb);
2531
// CHECK: call {{.*}}@sigsetjmp(
@@ -28,6 +34,10 @@ void f(void) {
2834
_setjmp(jb);
2935
// CHECK: call {{.*}}@__sigsetjmp(
3036
__sigsetjmp(jb, 0);
37+
// CHECK: call {{.*}}@_setjmpex(
38+
_setjmpex(jb);
39+
// CHECK: call {{.*}}@getcontext(
40+
getcontext(ut);
3141
}
3242

3343
// CHECK: ; Function Attrs: returns_twice
@@ -42,3 +52,8 @@ void f(void) {
4252
// CHECK: ; Function Attrs: returns_twice
4353
// CHECK-NEXT: declare {{.*}} @__sigsetjmp(
4454

55+
// CHECK: ; Function Attrs: returns_twice
56+
// CHECK-NEXT: declare {{.*}} @_setjmpex(
57+
58+
// CHECK: ; Function Attrs: returns_twice
59+
// CHECK-NEXT: declare {{.*}} @getcontext(

0 commit comments

Comments
 (0)