steplong created this revision.
steplong added reviewers: gchatelet, aaron.ballman, courbet, rsmith.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Support for `__attribute__((no_builtin("foo")))` was added in 
https://reviews.llvm.org/D68028,
but builtins were still being used even when the attribute was placed on a 
function


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D124701

Files:
  clang/lib/CodeGen/CGExpr.cpp
  clang/test/CodeGen/no-builtin-2.c


Index: clang/test/CodeGen/no-builtin-2.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/no-builtin-2.c
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+#include <stddef.h>
+
+void bar(char *s);
+void *memset(void *s, int c, size_t n);
+void *memcpy(void *d, const void *s, size_t n);
+
+// CHECK: define{{.*}} void @foo1({{.*}}) #[[NO_NOBUILTIN:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   call void @llvm.memcpy
+void foo1(char *s, char *d, size_t n)
+{
+    bar(s);
+    memset(s, 0, n);
+    memcpy(d, s, n);
+}
+
+// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call i8* @memset
+// CHECK:   call void @llvm.memcpy
+void foo2(char *s, char *d, size_t n) __attribute__((no_builtin("memset")))
+{
+    bar(s);
+    memset(s, 1, n);
+    memcpy(d, s, n);
+}
+
+// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call i8* @memset
+// CHECK:   {{.*}}call i8* @memcpy
+void foo3(char *s, char *d, size_t n) __attribute__((no_builtin("memset", 
"memcpy")))
+{
+    bar(s);
+    memset(s, 2, n);
+    memcpy(d, s, n);
+}
+
+// CHECK-NOT: attributes #[[NO_NOBUILTIN]] = {{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK-NOT: attributes #[[NO_NOBUILTIN]] = 
{{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK:     attributes #[[NOBUILTIN_MEMSET]] = 
{{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK:     attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = 
{{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -5193,6 +5193,7 @@
   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
 
   if (auto builtinID = FD->getBuiltinID()) {
+    std::string AttributeNoBuiltin = "no-builtin-" + FD->getName().str();
     std::string FDInlineName = (FD->getName() + ".inline").str();
     // When directing calling an inline builtin, call it through it's mangled
     // name to make it clear it's not the actual builtin.
@@ -5213,8 +5214,9 @@
 
     // Replaceable builtins provide their own implementation of a builtin. If 
we
     // are in an inline builtin implementation, avoid trivial infinite
-    // recursion.
-    else
+    // recursion. Honor __attribute__((no_builtin("foo"))) on the current
+    // function.
+    else if (!CGF.CurFn->getAttributes().hasFnAttr(AttributeNoBuiltin))
       return CGCallee::forBuiltin(builtinID, FD);
   }
 


Index: clang/test/CodeGen/no-builtin-2.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/no-builtin-2.c
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+#include <stddef.h>
+
+void bar(char *s);
+void *memset(void *s, int c, size_t n);
+void *memcpy(void *d, const void *s, size_t n);
+
+// CHECK: define{{.*}} void @foo1({{.*}}) #[[NO_NOBUILTIN:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   call void @llvm.memcpy
+void foo1(char *s, char *d, size_t n)
+{
+    bar(s);
+    memset(s, 0, n);
+    memcpy(d, s, n);
+}
+
+// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call i8* @memset
+// CHECK:   call void @llvm.memcpy
+void foo2(char *s, char *d, size_t n) __attribute__((no_builtin("memset")))
+{
+    bar(s);
+    memset(s, 1, n);
+    memcpy(d, s, n);
+}
+
+// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call i8* @memset
+// CHECK:   {{.*}}call i8* @memcpy
+void foo3(char *s, char *d, size_t n) __attribute__((no_builtin("memset", "memcpy")))
+{
+    bar(s);
+    memset(s, 2, n);
+    memcpy(d, s, n);
+}
+
+// CHECK-NOT: attributes #[[NO_NOBUILTIN]] = {{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK-NOT: attributes #[[NO_NOBUILTIN]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK:     attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK:     attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -5193,6 +5193,7 @@
   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
 
   if (auto builtinID = FD->getBuiltinID()) {
+    std::string AttributeNoBuiltin = "no-builtin-" + FD->getName().str();
     std::string FDInlineName = (FD->getName() + ".inline").str();
     // When directing calling an inline builtin, call it through it's mangled
     // name to make it clear it's not the actual builtin.
@@ -5213,8 +5214,9 @@
 
     // Replaceable builtins provide their own implementation of a builtin. If we
     // are in an inline builtin implementation, avoid trivial infinite
-    // recursion.
-    else
+    // recursion. Honor __attribute__((no_builtin("foo"))) on the current
+    // function.
+    else if (!CGF.CurFn->getAttributes().hasFnAttr(AttributeNoBuiltin))
       return CGCallee::forBuiltin(builtinID, FD);
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to