https://github.com/alanzhao1 created 
https://github.com/llvm/llvm-project/pull/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

>From f4f5d88d287600c40746f16c008ed95d6838f9ff Mon Sep 17 00:00:00 2001
From: Alan Zhao <ayz...@google.com>
Date: Fri, 28 Mar 2025 12:53:15 -0700
Subject: [PATCH] [clang] Automatically add the `returns_twice` attribute to
 certain functions even if `-fno-builtin` is set

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
---
 clang/lib/CodeGen/CGCall.cpp              |  9 +++++++++
 clang/test/CodeGen/2003-08-20-vfork-bug.c |  5 ++++-
 clang/test/CodeGen/setjmp.c               | 15 +++++++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)

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(

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to