Author: Stephen Long Date: 2022-05-20T06:41:47-07:00 New Revision: ae80024fbe51339afabfa2ff43ae532356fa3c93
URL: https://github.com/llvm/llvm-project/commit/ae80024fbe51339afabfa2ff43ae532356fa3c93 DIFF: https://github.com/llvm/llvm-project/commit/ae80024fbe51339afabfa2ff43ae532356fa3c93.diff LOG: [clang] Honor __attribute__((no_builtin("foo"))) on functions 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. Reviewed By: hans Differential Revision: https://reviews.llvm.org/D124701 Added: clang/test/CodeGen/no-builtin-2.c Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/AttrDocs.td clang/lib/CodeGen/CGExpr.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 69b5dc1dd1fd..5d1b12504f78 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -318,6 +318,10 @@ Attribute Changes in Clang - The ``__declspec(naked)`` attribute can no longer be written on a member function in Microsoft compatibility mode, matching the behavior of cl.exe. +- Attribute ``no_builtin`` should now affect the generated code. It now disables + builtins (corresponding to the specific names listed in the attribute) in the + body of the function the attribute is on. + Windows Support --------------- diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index d635da6b84b8..aedf11a70753 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -6000,9 +6000,6 @@ attribute `clang_builtin_alias`. def NoBuiltinDocs : Documentation { let Category = DocCatFunction; let Content = [{ -.. Note:: This attribute is not yet fully implemented, it is validated but has - no effect on the generated code. - The ``__attribute__((no_builtin))`` is similar to the ``-fno-builtin`` flag except it is specific to the body of a function. The attribute may also be applied to a virtual function but has no effect on the behavior of overriding diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index fbe1586001b1..3d7f13aed0ab 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5034,7 +5034,16 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, GlobalDecl GD) { const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); if (auto builtinID = FD->getBuiltinID()) { + std::string NoBuiltinFD = ("no-builtin-" + FD->getName()).str(); + std::string NoBuiltins = "no-builtins"; std::string FDInlineName = (FD->getName() + ".inline").str(); + + bool IsPredefinedLibFunction = + CGF.getContext().BuiltinInfo.isPredefinedLibFunction(builtinID); + bool HasAttributeNoBuiltin = + CGF.CurFn->getAttributes().hasFnAttr(NoBuiltinFD) || + CGF.CurFn->getAttributes().hasFnAttr(NoBuiltins); + // When directing calling an inline builtin, call it through it's mangled // name to make it clear it's not the actual builtin. if (CGF.CurFn->getName() != FDInlineName && @@ -5054,8 +5063,11 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, GlobalDecl GD) { // 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"))) or + // __attribute__((no_builtin)) on the current function unless foo is + // not a predefined library function which means we must generate the + // builtin no matter what. + else if (!IsPredefinedLibFunction || !HasAttributeNoBuiltin) return CGCallee::forBuiltin(builtinID, FD); } diff --git a/clang/test/CodeGen/no-builtin-2.c b/clang/test/CodeGen/no-builtin-2.c new file mode 100644 index 000000000000..f236f29779e0 --- /dev/null +++ b/clang/test/CodeGen/no-builtin-2.c @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +typedef typeof(sizeof(0)) size_t; + +void bar(char *s); +void *memset(void *s, int c, size_t n); +void *memcpy(void *d, const void *s, size_t n); +void *memmove(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 +// CHECK: call void @llvm.memmove +void foo1(char *s, char *d, size_t n) { + bar(s); + memset(s, 0, n); + memcpy(d, s, n); + memmove(d, s, n); +} + +// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]] +// CHECK: call void @bar +// CHECK: {{.*}}call {{.*}} @memset +// CHECK: call void @llvm.memcpy +// CHECK: call void @llvm.memmove +void foo2(char *s, char *d, size_t n) __attribute__((no_builtin("memset"))) { + bar(s); + memset(s, 1, n); + memcpy(d, s, n); + memmove(d, s, n); +} + +// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]] +// CHECK: call void @bar +// CHECK: {{.*}}call {{.*}} @memset +// CHECK: {{.*}}call {{.*}} @memcpy +// CHECK: call void @llvm.memmove +void foo3(char *s, char *d, size_t n) __attribute__((no_builtin("memset", "memcpy"))) { + bar(s); + memset(s, 2, n); + memcpy(d, s, n); + memmove(d, s, n); +} + +// CHECK: define{{.*}} void @foo4({{.*}}) #[[NOBUILTINS:[0-9]+]] +// CHECK: call void @bar +// CHECK: {{.*}}call {{.*}} @memset +// CHECK: {{.*}}call {{.*}} @memcpy +// CHECK: {{.*}}call {{.*}} @memmove +void foo4(char *s, char *d, size_t n) __attribute__((no_builtin)) { + bar(s); + memset(s, 2, n); + memcpy(d, s, n); + memmove(s, d, n); +} + +// CHECK-NOT: attributes #[[NO_NOBUILTIN]] = {{{.*}}"no-builtin-memset"{{.*}}} +// CHECK-NOT: attributes #[[NO_NOBUILTIN]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}} +// CHECK-NOT: attributes #[[NO_NOBUILTIN]] = {{{.*}}"no-builtins"{{.*}}} +// CHECK: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memset"{{.*}}} +// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}} +// CHECK: attributes #[[NOBUILTINS]] = {{{.*}}"no-builtins"{{.*}}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits