steplong updated this revision to Diff 429703.
steplong added a comment.
- Update documentation
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D124701/new/
https://reviews.llvm.org/D124701
Files:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/AttrDocs.td
clang/lib/CodeGen/CGExpr.cpp
clang/lib/Sema/SemaDeclAttr.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,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"{{.*}}}
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -1142,7 +1142,8 @@
if (!S.checkStringLiteralArgumentAttr(AL, I, BuiltinName, &LiteralLoc))
return;
- if (Builtin::Context::isBuiltinFunc(BuiltinName))
+ bool ParsedAttrIsWildCard = BuiltinName == kWildcard;
+ if (Builtin::Context::isBuiltinFunc(BuiltinName) || ParsedAttrIsWildCard)
AddBuiltinName(BuiltinName);
else
S.Diag(LiteralLoc, diag::warn_attribute_no_builtin_invalid_builtin_name)
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -5034,7 +5034,16 @@
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 @@
// 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);
}
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -6000,9 +6000,6 @@
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
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -307,6 +307,10 @@
- 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
---------------
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits