[PATCH] D128649: [clang-cl] Accept a pragma alloc_text corner case accepted by MSVC

2022-06-27 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

MSVC's pragma alloc_text accepts a function that was redeclared in
a non extern-C context if the previous declaration was in an extern-C
context. i.e.

  extern "C" { static void f(); }
  static void f();


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128649

Files:
  clang/lib/Sema/SemaAttr.cpp
  clang/test/Sema/pragma-ms-alloc-text.cpp


Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- clang/test/Sema/pragma-ms-alloc-text.cpp
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -40,3 +40,10 @@
 #pragma alloc_text(c, foo6) // no-warning
 void foo6() {}
 }
+
+extern "C" {
+static void foo7();
+}
+static void foo7();
+#pragma alloc_text(c, foo7) // no-warning
+void foo7() {}
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -810,10 +810,23 @@
   return;
 }
 
-DeclContext *DC = ND->getDeclContext();
-if (getLangOpts().CPlusPlus && !DC->isExternCContext()) {
-  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
-  return;
+if (getLangOpts().CPlusPlus) {
+  bool IsInExternCContext = false;
+  Decl *D = ND;
+  while (D != nullptr) {
+if (auto *FD = dyn_cast(D)) {
+  if (FD->isInExternCContext()) {
+IsInExternCContext = true;
+break;
+  }
+}
+D = D->getPreviousDecl();
+  }
+
+  if (!IsInExternCContext) {
+Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+return;
+  }
 }
 
 FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc);


Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- clang/test/Sema/pragma-ms-alloc-text.cpp
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -40,3 +40,10 @@
 #pragma alloc_text(c, foo6) // no-warning
 void foo6() {}
 }
+
+extern "C" {
+static void foo7();
+}
+static void foo7();
+#pragma alloc_text(c, foo7) // no-warning
+void foo7() {}
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -810,10 +810,23 @@
   return;
 }
 
-DeclContext *DC = ND->getDeclContext();
-if (getLangOpts().CPlusPlus && !DC->isExternCContext()) {
-  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
-  return;
+if (getLangOpts().CPlusPlus) {
+  bool IsInExternCContext = false;
+  Decl *D = ND;
+  while (D != nullptr) {
+if (auto *FD = dyn_cast(D)) {
+  if (FD->isInExternCContext()) {
+IsInExternCContext = true;
+break;
+  }
+}
+D = D->getPreviousDecl();
+  }
+
+  if (!IsInExternCContext) {
+Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+return;
+  }
 }
 
 FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128649: [clang-cl] Accept a pragma alloc_text corner case accepted by MSVC

2022-06-27 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

This does make us accept, but MSVC doesn't:

  static void f();
  extern "C" {
static void f();
  }
  #pragma alloc_text(c, f);
  static void f() {}

MSVC and GCC fail with an error for conflicting declaration.
GCC: https://godbolt.org/z/Tavvx88E4
MSVC: https://godbolt.org/z/vj41TWdYh


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128649/new/

https://reviews.llvm.org/D128649

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


[PATCH] D128649: [clang-cl] Accept a pragma alloc_text corner case accepted by MSVC

2022-06-27 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 440268.
steplong added a comment.

- Use `getCanonicalDecl()`. This does make us reject (MSVC rejects it already 
because of conflicting declarations):

  static void f();
  extern "C" { static void f(); }
  static void f() {}



- Error if not function decl

I think we have to use `isInExternCContext()` to accept the following (MSVC 
accepts this):

  extern "C" { static void f(); }
  static void f() {}


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128649/new/

https://reviews.llvm.org/D128649

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaAttr.cpp
  clang/test/Sema/pragma-ms-alloc-text.cpp


Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- clang/test/Sema/pragma-ms-alloc-text.cpp
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -40,3 +40,20 @@
 #pragma alloc_text(c, foo6) // no-warning
 void foo6() {}
 }
+
+extern "C" {
+static void foo7();
+}
+static void foo7();
+#pragma alloc_text(c, foo7) // no-warning
+void foo7() {}
+
+static void foo8();
+extern "C" {
+static void foo8();
+}
+#pragma alloc_text(c, foo8) // expected-error {{'#pragma alloc_text' is 
applicable only to functions with C linkage}}
+void foo7() {}
+
+enum foo9 { A, B, C };
+#pragma alloc_text(c, foo9) // expected-error {{'#pragma alloc_text' is 
applicable only to functions}}
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -810,10 +810,18 @@
   return;
 }
 
-DeclContext *DC = ND->getDeclContext();
-if (getLangOpts().CPlusPlus && !DC->isExternCContext()) {
-  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
-  return;
+if (getLangOpts().CPlusPlus) {
+  Decl *D = cast(ND)->getCanonicalDecl();
+
+  if (auto *FD = dyn_cast(D)) {
+if (!FD->isInExternCContext()) {
+  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+  return;
+}
+  } else {
+Diag(Loc, diag::err_pragma_alloc_text_not_function);
+return;
+  }
 }
 
 FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc);
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -992,6 +992,8 @@
   "'#pragma %0' can only appear at file scope">;
 def err_pragma_alloc_text_c_linkage: Error<
   "'#pragma alloc_text' is applicable only to functions with C linkage">;
+def err_pragma_alloc_text_not_function: Error<
+  "'#pragma alloc_text' is applicable only to functions">;
 
 def warn_pragma_unused_undeclared_var : Warning<
   "undeclared variable %0 used as an argument for '#pragma unused'">,


Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- clang/test/Sema/pragma-ms-alloc-text.cpp
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -40,3 +40,20 @@
 #pragma alloc_text(c, foo6) // no-warning
 void foo6() {}
 }
+
+extern "C" {
+static void foo7();
+}
+static void foo7();
+#pragma alloc_text(c, foo7) // no-warning
+void foo7() {}
+
+static void foo8();
+extern "C" {
+static void foo8();
+}
+#pragma alloc_text(c, foo8) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+void foo7() {}
+
+enum foo9 { A, B, C };
+#pragma alloc_text(c, foo9) // expected-error {{'#pragma alloc_text' is applicable only to functions}}
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -810,10 +810,18 @@
   return;
 }
 
-DeclContext *DC = ND->getDeclContext();
-if (getLangOpts().CPlusPlus && !DC->isExternCContext()) {
-  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
-  return;
+if (getLangOpts().CPlusPlus) {
+  Decl *D = cast(ND)->getCanonicalDecl();
+
+  if (auto *FD = dyn_cast(D)) {
+if (!FD->isInExternCContext()) {
+  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+  return;
+}
+  } else {
+Diag(Loc, diag::err_pragma_alloc_text_not_function);
+return;
+  }
 }
 
 FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc);
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -992,6 +992,8 @@
   "'#pragma %0' can only appear at file scope">;
 def err_pragma_alloc_text_c_linkage: Error<
   "'#pragma alloc_text' is applicable only to functions with C linkage">;
+def err_pragma_alloc_text_not_function: Error<
+  "'#pragma alloc

[PATCH] D128649: [clang-cl] Handle some pragma alloc_text corner cases handled by MSVC

2022-06-27 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

> Isn't the question whether `f` is considered "extern C" in the end or not? I 
> thought `isExternC()` checks that? Are you saying it would return false for 
> `f` in your example?

Yup, `isExternC()` is returning false for that case because there's "static".

> I'm probably missing something. Is the "static" important in this example? 
> Since `f` has internal linkage, I don't see why a user would care if it's 
> "extern C" or not, and also not in which section it would go (in this case it 
> will not be emitted at all, because it's not used).

Hmm, good point. This is the disassembly I see for:

  extern "C" { static void f(); }
  static void f();
  #pragma alloc_text(s, f)
  static void f() {}
  
  void bar() {
f();
  }
  
  Disassembly of section .text$mn:
  ?bar@@YAXXZ:
 0:   fd 7b bf a9 stp x29, x30, [sp, #-16]!
 4:   fd 03 00 91 mov x29, sp
 8:   00 00 00 94 bl  #0 
 c:   fd 7b c1 a8 ldp x29, x30, [sp], #16
10:   c0 03 5f d6 ret
  Disassembly of section s:
  s:
 0:   c0 03 5f d6 ret


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128649/new/

https://reviews.llvm.org/D128649

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


[PATCH] D128649: [clang-cl] Handle some pragma alloc_text corner cases handled by MSVC

2022-06-27 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 440344.
steplong added a comment.

- Error for c also


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128649/new/

https://reviews.llvm.org/D128649

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaAttr.cpp
  clang/test/Sema/pragma-ms-alloc-text.c
  clang/test/Sema/pragma-ms-alloc-text.cpp


Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- clang/test/Sema/pragma-ms-alloc-text.cpp
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -40,3 +40,20 @@
 #pragma alloc_text(c, foo6) // no-warning
 void foo6() {}
 }
+
+extern "C" {
+static void foo7();
+}
+static void foo7();
+#pragma alloc_text(c, foo7) // no-warning
+void foo7() {}
+
+static void foo8();
+extern "C" {
+static void foo8();
+}
+#pragma alloc_text(c, foo8) // expected-error {{'#pragma alloc_text' is 
applicable only to functions with C linkage}}
+void foo8() {}
+
+enum foo9 { A, B, C };
+#pragma alloc_text(c, foo9) // expected-error {{'#pragma alloc_text' is 
applicable only to functions}}
Index: clang/test/Sema/pragma-ms-alloc-text.c
===
--- clang/test/Sema/pragma-ms-alloc-text.c
+++ clang/test/Sema/pragma-ms-alloc-text.c
@@ -1,9 +1,12 @@
 // RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
 
 void foo();
-#pragma alloc_text("hello", foo) // expected-no-diagnostics
+#pragma alloc_text("hello", foo) // no-error
 void foo() {}
 
 static void foo1();
-#pragma alloc_text("hello", foo1) // expected-no-diagnostics
+#pragma alloc_text("hello", foo1) // no-error
 void foo1() {}
+
+int foo2;
+#pragma alloc_text(c, foo2) // expected-error {{'#pragma alloc_text' is 
applicable only to functions}}
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -810,9 +810,20 @@
   return;
 }
 
-DeclContext *DC = ND->getDeclContext();
-if (getLangOpts().CPlusPlus && !DC->isExternCContext()) {
-  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+if (getLangOpts().CPlusPlus) {
+  Decl *D = cast(ND)->getCanonicalDecl();
+
+  if (auto *FD = dyn_cast(D)) {
+if (!FD->isInExternCContext()) {
+  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+  return;
+}
+  } else {
+Diag(Loc, diag::err_pragma_alloc_text_not_function);
+return;
+  }
+} else if (!isa(ND)) {
+  Diag(Loc, diag::err_pragma_alloc_text_not_function);
   return;
 }
 
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -992,6 +992,8 @@
   "'#pragma %0' can only appear at file scope">;
 def err_pragma_alloc_text_c_linkage: Error<
   "'#pragma alloc_text' is applicable only to functions with C linkage">;
+def err_pragma_alloc_text_not_function: Error<
+  "'#pragma alloc_text' is applicable only to functions">;
 
 def warn_pragma_unused_undeclared_var : Warning<
   "undeclared variable %0 used as an argument for '#pragma unused'">,


Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- clang/test/Sema/pragma-ms-alloc-text.cpp
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -40,3 +40,20 @@
 #pragma alloc_text(c, foo6) // no-warning
 void foo6() {}
 }
+
+extern "C" {
+static void foo7();
+}
+static void foo7();
+#pragma alloc_text(c, foo7) // no-warning
+void foo7() {}
+
+static void foo8();
+extern "C" {
+static void foo8();
+}
+#pragma alloc_text(c, foo8) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+void foo8() {}
+
+enum foo9 { A, B, C };
+#pragma alloc_text(c, foo9) // expected-error {{'#pragma alloc_text' is applicable only to functions}}
Index: clang/test/Sema/pragma-ms-alloc-text.c
===
--- clang/test/Sema/pragma-ms-alloc-text.c
+++ clang/test/Sema/pragma-ms-alloc-text.c
@@ -1,9 +1,12 @@
 // RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
 
 void foo();
-#pragma alloc_text("hello", foo) // expected-no-diagnostics
+#pragma alloc_text("hello", foo) // no-error
 void foo() {}
 
 static void foo1();
-#pragma alloc_text("hello", foo1) // expected-no-diagnostics
+#pragma alloc_text("hello", foo1) // no-error
 void foo1() {}
+
+int foo2;
+#pragma alloc_text(c, foo2) // expected-error {{'#pragma alloc_text' is applicable only to functions}}
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -810,9 +810,20 @@
   return;
 }
 
-DeclContext *DC = ND->getDeclContext();
-  

[PATCH] D128649: [clang-cl] Handle some pragma alloc_text corner cases handled by MSVC

2022-06-28 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 440618.
steplong added a comment.

- Rework logic for rejecting non-functions and non-extern C functions when C++


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128649/new/

https://reviews.llvm.org/D128649

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaAttr.cpp
  clang/test/Sema/pragma-ms-alloc-text.c
  clang/test/Sema/pragma-ms-alloc-text.cpp


Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- clang/test/Sema/pragma-ms-alloc-text.cpp
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -40,3 +40,20 @@
 #pragma alloc_text(c, foo6) // no-warning
 void foo6() {}
 }
+
+extern "C" {
+static void foo7();
+}
+static void foo7();
+#pragma alloc_text(c, foo7) // no-warning
+void foo7() {}
+
+static void foo8();
+extern "C" {
+static void foo8();
+}
+#pragma alloc_text(c, foo8) // expected-error {{'#pragma alloc_text' is 
applicable only to functions with C linkage}}
+void foo8() {}
+
+enum foo9 { A, B, C };
+#pragma alloc_text(c, foo9) // expected-error {{'#pragma alloc_text' is 
applicable only to functions}}
Index: clang/test/Sema/pragma-ms-alloc-text.c
===
--- clang/test/Sema/pragma-ms-alloc-text.c
+++ clang/test/Sema/pragma-ms-alloc-text.c
@@ -1,9 +1,12 @@
 // RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
 
 void foo();
-#pragma alloc_text("hello", foo) // expected-no-diagnostics
+#pragma alloc_text("hello", foo) // no-error
 void foo() {}
 
 static void foo1();
-#pragma alloc_text("hello", foo1) // expected-no-diagnostics
+#pragma alloc_text("hello", foo1) // no-error
 void foo1() {}
+
+int foo2;
+#pragma alloc_text(c, foo2) // expected-error {{'#pragma alloc_text' is 
applicable only to functions}}
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -810,8 +810,13 @@
   return;
 }
 
-DeclContext *DC = ND->getDeclContext();
-if (getLangOpts().CPlusPlus && !DC->isExternCContext()) {
+auto *FD = dyn_cast(ND->getCanonicalDecl());
+if (!FD) {
+  Diag(Loc, diag::err_pragma_alloc_text_not_function);
+  return;
+}
+
+if (getLangOpts().CPlusPlus && !FD->isInExternCContext()) {
   Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
   return;
 }
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -992,6 +992,8 @@
   "'#pragma %0' can only appear at file scope">;
 def err_pragma_alloc_text_c_linkage: Error<
   "'#pragma alloc_text' is applicable only to functions with C linkage">;
+def err_pragma_alloc_text_not_function: Error<
+  "'#pragma alloc_text' is applicable only to functions">;
 
 def warn_pragma_unused_undeclared_var : Warning<
   "undeclared variable %0 used as an argument for '#pragma unused'">,


Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- clang/test/Sema/pragma-ms-alloc-text.cpp
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -40,3 +40,20 @@
 #pragma alloc_text(c, foo6) // no-warning
 void foo6() {}
 }
+
+extern "C" {
+static void foo7();
+}
+static void foo7();
+#pragma alloc_text(c, foo7) // no-warning
+void foo7() {}
+
+static void foo8();
+extern "C" {
+static void foo8();
+}
+#pragma alloc_text(c, foo8) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+void foo8() {}
+
+enum foo9 { A, B, C };
+#pragma alloc_text(c, foo9) // expected-error {{'#pragma alloc_text' is applicable only to functions}}
Index: clang/test/Sema/pragma-ms-alloc-text.c
===
--- clang/test/Sema/pragma-ms-alloc-text.c
+++ clang/test/Sema/pragma-ms-alloc-text.c
@@ -1,9 +1,12 @@
 // RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
 
 void foo();
-#pragma alloc_text("hello", foo) // expected-no-diagnostics
+#pragma alloc_text("hello", foo) // no-error
 void foo() {}
 
 static void foo1();
-#pragma alloc_text("hello", foo1) // expected-no-diagnostics
+#pragma alloc_text("hello", foo1) // no-error
 void foo1() {}
+
+int foo2;
+#pragma alloc_text(c, foo2) // expected-error {{'#pragma alloc_text' is applicable only to functions}}
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -810,8 +810,13 @@
   return;
 }
 
-DeclContext *DC = ND->getDeclContext();
-if (getLangOpts().CPlusPlus && !DC->isExternCContext()) {
+auto *FD = dyn_cast(ND->getCanonicalDecl());
+if (!FD) {
+  Diag(Loc, diag::err_pragma_alloc_text_not

[PATCH] D128649: [clang-cl] Handle some pragma alloc_text corner cases handled by MSVC

2022-06-29 Thread Stephen Long via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGf382545b2ba8: [clang-cl] Handle some pragma alloc_text 
corner cases handled by MSVC (authored by steplong).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128649/new/

https://reviews.llvm.org/D128649

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaAttr.cpp
  clang/test/Sema/pragma-ms-alloc-text.c
  clang/test/Sema/pragma-ms-alloc-text.cpp


Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- clang/test/Sema/pragma-ms-alloc-text.cpp
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -40,3 +40,20 @@
 #pragma alloc_text(c, foo6) // no-warning
 void foo6() {}
 }
+
+extern "C" {
+static void foo7();
+}
+static void foo7();
+#pragma alloc_text(c, foo7) // no-warning
+void foo7() {}
+
+static void foo8();
+extern "C" {
+static void foo8();
+}
+#pragma alloc_text(c, foo8) // expected-error {{'#pragma alloc_text' is 
applicable only to functions with C linkage}}
+void foo8() {}
+
+enum foo9 { A, B, C };
+#pragma alloc_text(c, foo9) // expected-error {{'#pragma alloc_text' is 
applicable only to functions}}
Index: clang/test/Sema/pragma-ms-alloc-text.c
===
--- clang/test/Sema/pragma-ms-alloc-text.c
+++ clang/test/Sema/pragma-ms-alloc-text.c
@@ -1,9 +1,12 @@
 // RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
 
 void foo();
-#pragma alloc_text("hello", foo) // expected-no-diagnostics
+#pragma alloc_text("hello", foo) // no-error
 void foo() {}
 
 static void foo1();
-#pragma alloc_text("hello", foo1) // expected-no-diagnostics
+#pragma alloc_text("hello", foo1) // no-error
 void foo1() {}
+
+int foo2;
+#pragma alloc_text(c, foo2) // expected-error {{'#pragma alloc_text' is 
applicable only to functions}}
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -810,8 +810,13 @@
   return;
 }
 
-DeclContext *DC = ND->getDeclContext();
-if (getLangOpts().CPlusPlus && !DC->isExternCContext()) {
+auto *FD = dyn_cast(ND->getCanonicalDecl());
+if (!FD) {
+  Diag(Loc, diag::err_pragma_alloc_text_not_function);
+  return;
+}
+
+if (getLangOpts().CPlusPlus && !FD->isInExternCContext()) {
   Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
   return;
 }
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -992,6 +992,8 @@
   "'#pragma %0' can only appear at file scope">;
 def err_pragma_alloc_text_c_linkage: Error<
   "'#pragma alloc_text' is applicable only to functions with C linkage">;
+def err_pragma_alloc_text_not_function: Error<
+  "'#pragma alloc_text' is applicable only to functions">;
 
 def warn_pragma_unused_undeclared_var : Warning<
   "undeclared variable %0 used as an argument for '#pragma unused'">,


Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- clang/test/Sema/pragma-ms-alloc-text.cpp
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -40,3 +40,20 @@
 #pragma alloc_text(c, foo6) // no-warning
 void foo6() {}
 }
+
+extern "C" {
+static void foo7();
+}
+static void foo7();
+#pragma alloc_text(c, foo7) // no-warning
+void foo7() {}
+
+static void foo8();
+extern "C" {
+static void foo8();
+}
+#pragma alloc_text(c, foo8) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+void foo8() {}
+
+enum foo9 { A, B, C };
+#pragma alloc_text(c, foo9) // expected-error {{'#pragma alloc_text' is applicable only to functions}}
Index: clang/test/Sema/pragma-ms-alloc-text.c
===
--- clang/test/Sema/pragma-ms-alloc-text.c
+++ clang/test/Sema/pragma-ms-alloc-text.c
@@ -1,9 +1,12 @@
 // RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
 
 void foo();
-#pragma alloc_text("hello", foo) // expected-no-diagnostics
+#pragma alloc_text("hello", foo) // no-error
 void foo() {}
 
 static void foo1();
-#pragma alloc_text("hello", foo1) // expected-no-diagnostics
+#pragma alloc_text("hello", foo1) // no-error
 void foo1() {}
+
+int foo2;
+#pragma alloc_text(c, foo2) // expected-error {{'#pragma alloc_text' is applicable only to functions}}
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -810,8 +810,13 @@
   return;
 }
 
-DeclContext *DC = ND->getDeclContext();
-if (getLangOpts().CPlusPlus && !DC->isExternCContext()) {
+auto 

[PATCH] D127641: [clang-cl][MSVC] Enable /Zc:alignedNew for C++17 and /Zc:sizedDealloc by default

2022-08-01 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 449140.
steplong added a comment.
Herald added a subscriber: steakhal.

- Change unittest to match Num Args 1 or 2

I won't merge this. Just want to see if this passes the unittest


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127641/new/

https://reviews.llvm.org/D127641

Files:
  clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-zc.cpp
  clang/unittests/StaticAnalyzer/CallEventTest.cpp

Index: clang/unittests/StaticAnalyzer/CallEventTest.cpp
===
--- clang/unittests/StaticAnalyzer/CallEventTest.cpp
+++ clang/unittests/StaticAnalyzer/CallEventTest.cpp
@@ -81,7 +81,7 @@
 }
   )",
  Diags));
-  EXPECT_EQ(Diags, "test.CXXDeallocator: NumArgs: 1\n");
+  EXPECT_THAT(Diags, MatchesRegex("test.CXXDeallocator: NumArgs: (1|2)\n"));
 }
 
 } // namespace
Index: clang/test/Driver/cl-zc.cpp
===
--- clang/test/Driver/cl-zc.cpp
+++ clang/test/Driver/cl-zc.cpp
@@ -1,6 +1,19 @@
 // Note: %s must be preceded by --, otherwise it may be interpreted as a
 // command-line option, e.g. on Mac where %s is commonly under /Users.
 
+// RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=SIZED-DEALLOC %s
+// RUN: %clang_cl /c -### -fms-compatibility-version=18 -- %s 2>&1 | FileCheck -check-prefix=SIZED-DEALLOC-OFF %s
+// SIZED-DEALLOC: "-fsized-deallocation"
+// SIZED-DEALLOC-OFF-NOT: "-fsized-deallocation"
+
+// RUN: %clang_cl /c /std:c++11 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-BEFORE-CPP17 %s
+// RUN: %clang_cl /c /std:c++14 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-BEFORE-CPP17 %s
+// RUN: %clang_cl /c /std:c++17 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// RUN: %clang_cl /c /std:c++20 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// RUN: %clang_cl /c /std:c++latest -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// ALIGNED-NEW-BEFORE-CPP17-NOT: "-faligned-allocation"
+// ALIGNED-NEW-CPP17ONWARDS: "-faligned-allocation"
+
 // RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=TRIGRAPHS-DEFAULT %s
 // cc1 will disable trigraphs for -fms-compatibility as long as -ftrigraphs
 // isn't explicitly passed.
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -6470,6 +6470,7 @@
 }
 CmdArgs.push_back(LanguageStandard.data());
   }
+  bool IsCPP17Onwards = false;
   if (ImplyVCPPCXXVer) {
 StringRef LanguageStandard;
 if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
@@ -6493,6 +6494,9 @@
 }
 
 CmdArgs.push_back(LanguageStandard.data());
+
+IsCPP17Onwards =
+LanguageStandard != "-std=c++11" && LanguageStandard != "-std=c++14";
   }
 
   Args.addOptInFlag(CmdArgs, options::OPT_fborland_extensions,
@@ -6622,9 +6626,15 @@
 options::OPT_fno_relaxed_template_template_args);
 
   // -fsized-deallocation is off by default, as it is an ABI-breaking change for
-  // most platforms.
-  Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
-options::OPT_fno_sized_deallocation);
+  // most platforms. MSVC turns on /Zc:sizedDealloc by default, starting in
+  // MSVC 2015.
+  if (IsWindowsMSVC && IsMSVC2015Compatible &&
+  !Args.getLastArg(options::OPT_fsized_deallocation,
+   options::OPT_fno_sized_deallocation))
+CmdArgs.push_back("-fsized-deallocation");
+  else
+Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
+  options::OPT_fno_sized_deallocation);
 
   // -faligned-allocation is on by default in C++17 onwards and otherwise off
   // by default.
@@ -6635,6 +6645,8 @@
   CmdArgs.push_back("-fno-aligned-allocation");
 else
   CmdArgs.push_back("-faligned-allocation");
+  } else if (IsCPP17Onwards) {
+CmdArgs.push_back("-faligned-allocation");
   }
 
   // The default new alignment can be specified using a dedicated option or via
Index: clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp
@@ -1,5 +1,10 @@
 // RUN: %check_clang_tidy %s misc-new-delete-overloads %t
 
+// MSVC turns on sized deallocations by default, so we unsupport this test
+// for windows.
+
+// UNSUPPORTED: system-windows
+
 typedef decltype(sizeof(int)) size_t;
 
 struct S {
___
cfe-commits mailing list

[PATCH] D127641: [clang-cl][MSVC] Enable /Zc:alignedNew for C++17 and /Zc:sizedDealloc by default

2022-08-02 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 449303.
steplong added a comment.

- Add necessary includes to use EXPECT_THAT and MatchesRegex


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127641/new/

https://reviews.llvm.org/D127641

Files:
  clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-zc.cpp
  clang/unittests/StaticAnalyzer/CallEventTest.cpp

Index: clang/unittests/StaticAnalyzer/CallEventTest.cpp
===
--- clang/unittests/StaticAnalyzer/CallEventTest.cpp
+++ clang/unittests/StaticAnalyzer/CallEventTest.cpp
@@ -8,6 +8,7 @@
 
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "CheckerRegistration.h"
+#include "gmock/gmock.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
@@ -22,6 +23,8 @@
 #include "clang/Tooling/Tooling.h"
 #include "gtest/gtest.h"
 
+using testing::MatchesRegex;
+
 namespace clang {
 namespace ento {
 namespace {
@@ -81,7 +84,7 @@
 }
   )",
  Diags));
-  EXPECT_EQ(Diags, "test.CXXDeallocator: NumArgs: 1\n");
+  EXPECT_THAT(Diags, MatchesRegex("test.CXXDeallocator: NumArgs: (1|2)\n"));
 }
 
 } // namespace
Index: clang/test/Driver/cl-zc.cpp
===
--- clang/test/Driver/cl-zc.cpp
+++ clang/test/Driver/cl-zc.cpp
@@ -1,6 +1,19 @@
 // Note: %s must be preceded by --, otherwise it may be interpreted as a
 // command-line option, e.g. on Mac where %s is commonly under /Users.
 
+// RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=SIZED-DEALLOC %s
+// RUN: %clang_cl /c -### -fms-compatibility-version=18 -- %s 2>&1 | FileCheck -check-prefix=SIZED-DEALLOC-OFF %s
+// SIZED-DEALLOC: "-fsized-deallocation"
+// SIZED-DEALLOC-OFF-NOT: "-fsized-deallocation"
+
+// RUN: %clang_cl /c /std:c++11 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-BEFORE-CPP17 %s
+// RUN: %clang_cl /c /std:c++14 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-BEFORE-CPP17 %s
+// RUN: %clang_cl /c /std:c++17 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// RUN: %clang_cl /c /std:c++20 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// RUN: %clang_cl /c /std:c++latest -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// ALIGNED-NEW-BEFORE-CPP17-NOT: "-faligned-allocation"
+// ALIGNED-NEW-CPP17ONWARDS: "-faligned-allocation"
+
 // RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=TRIGRAPHS-DEFAULT %s
 // cc1 will disable trigraphs for -fms-compatibility as long as -ftrigraphs
 // isn't explicitly passed.
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -6470,6 +6470,7 @@
 }
 CmdArgs.push_back(LanguageStandard.data());
   }
+  bool IsCPP17Onwards = false;
   if (ImplyVCPPCXXVer) {
 StringRef LanguageStandard;
 if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
@@ -6493,6 +6494,9 @@
 }
 
 CmdArgs.push_back(LanguageStandard.data());
+
+IsCPP17Onwards =
+LanguageStandard != "-std=c++11" && LanguageStandard != "-std=c++14";
   }
 
   Args.addOptInFlag(CmdArgs, options::OPT_fborland_extensions,
@@ -6622,9 +6626,15 @@
 options::OPT_fno_relaxed_template_template_args);
 
   // -fsized-deallocation is off by default, as it is an ABI-breaking change for
-  // most platforms.
-  Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
-options::OPT_fno_sized_deallocation);
+  // most platforms. MSVC turns on /Zc:sizedDealloc by default, starting in
+  // MSVC 2015.
+  if (IsWindowsMSVC && IsMSVC2015Compatible &&
+  !Args.getLastArg(options::OPT_fsized_deallocation,
+   options::OPT_fno_sized_deallocation))
+CmdArgs.push_back("-fsized-deallocation");
+  else
+Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
+  options::OPT_fno_sized_deallocation);
 
   // -faligned-allocation is on by default in C++17 onwards and otherwise off
   // by default.
@@ -6635,6 +6645,8 @@
   CmdArgs.push_back("-fno-aligned-allocation");
 else
   CmdArgs.push_back("-faligned-allocation");
+  } else if (IsCPP17Onwards) {
+CmdArgs.push_back("-faligned-allocation");
   }
 
   // The default new alignment can be specified using a dedicated option or via
Index: clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/m

[PATCH] D124026: [Headers][MSVC] Define wchar_t in stddef.h like MSVC if not using the builtin type

2022-04-19 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
steplong added reviewers: rnk, efriedma.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

MSVC expects wchar_t to be defined in stddef.h if /Zc:wchar_t- is specified


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D124026

Files:
  clang/lib/Headers/stddef.h
  clang/test/Headers/ms-no-wchar.cpp


Index: clang/test/Headers/ms-no-wchar.cpp
===
--- /dev/null
+++ clang/test/Headers/ms-no-wchar.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-windows-msvc 
-fms-compatibility-version=17.00 -fno-wchar %s
+// MSVC defines wchar_t instead of using the builtin if /Zc:wchar_t- is passed
+
+#include 
+
+wchar_t c;
Index: clang/lib/Headers/stddef.h
===
--- clang/lib/Headers/stddef.h
+++ clang/lib/Headers/stddef.h
@@ -62,7 +62,7 @@
 #endif /* defined(__need_STDDEF_H_misc) */
 
 #if defined(__need_wchar_t)
-#ifndef __cplusplus
+#if !defined(__cplusplus) || (defined(_MSC_VER) && !_NATIVE_WCHAR_T_DEFINED)
 /* Always define wchar_t when modules are available. */
 #if !defined(_WCHAR_T) || __has_feature(modules)
 #if !__has_feature(modules)


Index: clang/test/Headers/ms-no-wchar.cpp
===
--- /dev/null
+++ clang/test/Headers/ms-no-wchar.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-windows-msvc -fms-compatibility-version=17.00 -fno-wchar %s
+// MSVC defines wchar_t instead of using the builtin if /Zc:wchar_t- is passed
+
+#include 
+
+wchar_t c;
Index: clang/lib/Headers/stddef.h
===
--- clang/lib/Headers/stddef.h
+++ clang/lib/Headers/stddef.h
@@ -62,7 +62,7 @@
 #endif /* defined(__need_STDDEF_H_misc) */
 
 #if defined(__need_wchar_t)
-#ifndef __cplusplus
+#if !defined(__cplusplus) || (defined(_MSC_VER) && !_NATIVE_WCHAR_T_DEFINED)
 /* Always define wchar_t when modules are available. */
 #if !defined(_WCHAR_T) || __has_feature(modules)
 #if !__has_feature(modules)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-04-29 Thread Stephen Long via Phabricator via cfe-commits
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 
+
+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(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 
+
+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
=

[PATCH] D124702: [MSVC] Add support for pragma function

2022-04-29 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
steplong added reviewers: rnk, rsmith, whunt, hans, thakis.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

MSVC pragma function tells the compiler to generate calls to functions in the 
pragma function list, instead of using the builtin. Needs 
https://reviews.llvm.org/D124701


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D124702

Files:
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function.c

Index: clang/test/CodeGen/pragma-ms-function.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function.c
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -o - %s | FileCheck %s
+
+#include 
+
+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);
+}
+
+#pragma function(strlen, memset)
+
+// 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)
+{
+bar(s);
+memset(s, 1, n);
+memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// 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)
+{
+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/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10190,10 +10190,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if we have to apply any
+  // attributes (i.e. optnone and no_builtin) due to a pragma.
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddRangeBasedNoBuiltin(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1044,6 +1044,11 @@
 OptimizeOffPragmaLocation = PragmaLoc;
 }
 
+void Sema::ActOnPragmaMSFunction(std::vector NoBuiltins) {
+  MSFunctionNoBuiltins.insert(MSFunctionNoBuiltins.end(),
+  NoBuiltins.begin(), NoBuiltins.end());
+}
+
 // QC-Specific. Begin.
 void Sema::ActOnPragmaObfuscate(SourceLocation Loc, PragmaMsStackAction Action,
 bool Val) {
@@ -1122,6 +1127,13 @@
 FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
 }
 
+void Sema::AddRangeBasedNoBuiltin(FunctionDecl *FD) {
+  if (!MSFunctionNoBuiltins.empty()) {
+FD->addAttr(NoBuiltinAttr::CreateImplicit(Context,
+MSFunctionNoBuiltins.data(), MSFunctionNoBuiltins.size()));
+  }
+}
+
 typedef std::vector > VisStack;
 enum : unsigned { NoVisibility = ~0U };
 
Index: clang/lib/Parse/ParsePragma.cpp
===
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -275,6 +275,15 @@
 Token &FirstToken) override;
 };
 
+struct PragmaMSFunctionHandler : public PragmaHandler {
+  PragmaMSFunctionHandler(Sema &S) : PragmaHandler("function"), Actions(S) {}
+  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+Token &FirstToken) override;
+
+private:
+  Sema &Actions;
+};
+
 struct PragmaMSOptimizeHandler : public PragmaHandler {
   PragmaMSOptimizeHandler() : PragmaHandler("optimize") {}
   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
@@ -477,6 +486,8 @@
 PP.AddPragmaHandler(MSRuntimeChecks.get());
 MSIntrinsic = std::make_unique();
 PP.AddPragmaHandler(MSIntrinsic.get());
+MSFunction = std::ma

[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-02 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

In D124701#3485317 , @hans wrote:

> If I understand correctly, D68028  made it 
> so that LLVM doesn't add any builtin calls (e.g. turning for-loops into 
> memcpy), but Clang could still turn calls into builtins. Maybe the patch 
> description could be expanded to explain this?

I'm not too sure, but I think D68028  just 
adds the attribute nobuiltin, but it gets ignored. It doesn't seem to affect 
the calls in the function. They're still being converted into builtins even 
with the attribute on the function.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124701/new/

https://reviews.llvm.org/D124701

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


[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-02 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 426400.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124701/new/

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
+
+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);
+
+// 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(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
+
+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);
+
+// 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(GD.getDecl());
 
   if (auto builtinID = FD->getBuiltinID()) {
+std::string AttributeNoBuiltin = "no-builtin-" + FD->getName

[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-02 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

In D124702#3485475 , @hans wrote:

> From the MS docs:
>
>> Once a function pragma is seen, it takes effect at the first function 
>> definition that contains a specified intrinsic function. The effect 
>> continues to the end of the source file, or to the appearance of an 
>> intrinsic pragma specifying the same intrinsic function. You can only use 
>> the function pragma outside of a function, at the global level.
>
> Should we try to handle the interaction between pragma intrinsic and pragma 
> function, i.e. that the former "undoes" the latter? And should we error/warn 
> if the pragma occurs not in namespace scope?

Oh I wasn't sure how to check if the function pragma was outside of a function. 
Yup, we can try to handle pragma intrinsic


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

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


[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-02 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 426433.
steplong edited the summary of this revision.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function-intrinsic.c

Index: clang/test/CodeGen/pragma-ms-function-intrinsic.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function-intrinsic.c
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -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);
+
+// 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);
+}
+
+#pragma function(strlen, memset)
+
+// 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)
+{
+bar(s);
+memset(s, 1, n);
+memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// 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)
+{
+bar(s);
+memset(s, 2, n);
+memcpy(d, s, n);
+}
+
+#pragma intrinsic(memset, strlen)
+
+// CHECK: define{{.*}} void @foo4({{.*}}) #[[NOBUILTIN_MEMCPY:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   {{.*}}call i8* @memcpy
+void foo4(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 3, n);
+memcpy(d, s, n);
+}
+
+#pragma intrinsic(memcpy)
+
+// CHECK: define{{.*}} void @foo5({{.*}}) #[[NO_NOBUILTIN]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   call void @llvm.memcpy
+void foo5(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 4, 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-NOT: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}}
+// CHECK-NOT: attributes #[[NOBUILTIN_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10190,10 +10190,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if we have to apply any
+  // attributes (i.e. optnone and no_builtin) due to a pragma.
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddRangeBasedNoBuiltin(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1044,6 +1044,19 @@
 OptimizeOffPragmaLocation = PragmaLoc;
 }
 
+void Sema::ActOnPragmaMSIntrinsic(const std::vector &Intrinsics) {
+  for (auto &Intrinsic : Intrinsics) {
+MSFunctionNoBuiltins.erase(std::remove(MSFunctionNoBuiltins.begin(),
+   MSFunctionNoBuiltins.end(),
+   Intrinsic));
+  }
+}
+
+void Sema::ActOnPragmaMSFunction(const std::vector &NoBuiltins) {
+  MSFunctionNoBuiltins.insert(MSFunctionNoBuiltins.end(),
+  NoBuiltins.begin(), NoBuiltins.end());
+}
+
 // QC-Specific. Begin.
 void Sema::ActOnPragmaObfuscate(SourceLocation Loc, PragmaMsStackAction Action,
 bool Val) {
@@ -1122,6 +1135,13 @@
 FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
 }
 
+void Sema::AddRangeBasedNoBuiltin(FunctionDecl *FD) {
+  if (!MSFunctionNoBuiltins.empty()) {
+FD->addAttr(NoBuiltinAttr::CreateImplicit(Context,
+MSFunctionNoB

[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-03 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 426700.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124701/new/

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
+
+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);
+
+// 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
@@ -5034,6 +5034,7 @@
   const FunctionDecl *FD = cast(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.
@@ -5054,8 +5055,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
+
+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);
+
+// 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
@@ -5034,6 +5034,7 @@
   const FunctionDecl *FD = cast(GD.getDecl());
 
   if (auto builtinID = FD->getBuiltinID()) {
+std::string AttributeNoBuiltin = "no-builtin-" + FD->getName().str

[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-03 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 426702.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function-intrinsic.c

Index: clang/test/CodeGen/pragma-ms-function-intrinsic.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function-intrinsic.c
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -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);
+
+// 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);
+}
+
+#pragma function(strlen, memset)
+
+// 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)
+{
+bar(s);
+memset(s, 1, n);
+memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// 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)
+{
+bar(s);
+memset(s, 2, n);
+memcpy(d, s, n);
+}
+
+#pragma intrinsic(memset, strlen)
+
+// CHECK: define{{.*}} void @foo4({{.*}}) #[[NOBUILTIN_MEMCPY:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   {{.*}}call i8* @memcpy
+void foo4(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 3, n);
+memcpy(d, s, n);
+}
+
+#pragma intrinsic(memcpy)
+
+// CHECK: define{{.*}} void @foo5({{.*}}) #[[NO_NOBUILTIN]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   call void @llvm.memcpy
+void foo5(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 4, 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-NOT: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}}
+// CHECK-NOT: attributes #[[NOBUILTIN_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if we have to apply any
+  // attributes (i.e. optnone and no_builtin) due to a pragma.
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddRangeBasedNoBuiltin(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1065,6 +1065,19 @@
 OptimizeOffPragmaLocation = PragmaLoc;
 }
 
+void Sema::ActOnPragmaMSIntrinsic(const std::vector &Intrinsics) {
+  for (auto &Intrinsic : Intrinsics) {
+MSFunctionNoBuiltins.erase(std::remove(MSFunctionNoBuiltins.begin(),
+   MSFunctionNoBuiltins.end(),
+   Intrinsic));
+  }
+}
+
+void Sema::ActOnPragmaMSFunction(const std::vector &NoBuiltins) {
+  MSFunctionNoBuiltins.insert(MSFunctionNoBuiltins.end(),
+  NoBuiltins.begin(), NoBuiltins.end());
+}
+
 void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
   // In the future, check other pragmas if they're implemented (e.g. pragma
   // optimize 0 will probably map to this functionality too).
@@ -1086,6 +1099,13 @@
 FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
 }
 
+void Sema::AddRangeBasedNoBuiltin(FunctionDecl *FD) {
+  if (!MSFunctionNoBuiltins.empty()) {
+FD->addAttr(NoBuiltinAttr::CreateImplicit(Context,
+MSFunctionNoBuil

[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-03 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 426795.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124701/new/

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
+
+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);
+
+// 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 {{.*}} @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 {{.*}} @memset
+// CHECK:   {{.*}}call {{.*}} @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
@@ -5034,6 +5034,7 @@
   const FunctionDecl *FD = cast(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.
@@ -5054,8 +5055,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
+
+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);
+
+// 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 {{.*}} @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 {{.*}} @memset
+// CHECK:   {{.*}}call {{.*}} @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
@@ -5034,6 +5034,7 @@
   const FunctionDecl *FD = cast(GD.getDecl());
 
   if (auto builtinID = FD->getBuiltinID()) {
+std::string AttributeNoBuiltin = "no-builtin-" +

[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-03 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 426802.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function-intrinsic.c

Index: clang/test/CodeGen/pragma-ms-function-intrinsic.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function-intrinsic.c
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -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);
+
+// 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);
+}
+
+#pragma function(strlen, memset)
+
+// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call {{.*}} @memset
+// CHECK:   call void @llvm.memcpy
+void foo2(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 1, n);
+memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call {{.*}} @memset
+// CHECK:   {{.*}}call {{.*}} @memcpy
+void foo3(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 2, n);
+memcpy(d, s, n);
+}
+
+#pragma intrinsic(memset, strlen)
+
+// CHECK: define{{.*}} void @foo4({{.*}}) #[[NOBUILTIN_MEMCPY:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   {{.*}}call {{.*}} @memcpy
+void foo4(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 3, n);
+memcpy(d, s, n);
+}
+
+#pragma intrinsic(memcpy)
+
+// CHECK: define{{.*}} void @foo5({{.*}}) #[[NO_NOBUILTIN]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   call void @llvm.memcpy
+void foo5(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 4, 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-NOT: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}}
+// CHECK-NOT: attributes #[[NOBUILTIN_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if we have to apply any
+  // attributes (i.e. optnone and no_builtin) due to a pragma.
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddRangeBasedNoBuiltin(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1065,6 +1065,20 @@
 OptimizeOffPragmaLocation = PragmaLoc;
 }
 
+void Sema::ActOnPragmaMSIntrinsic(const std::vector &Intrinsics) {
+  for (auto &Intrinsic : Intrinsics) {
+MSFunctionNoBuiltins.erase(std::remove(MSFunctionNoBuiltins.begin(),
+   MSFunctionNoBuiltins.end(),
+   Intrinsic),
+   MSFunctionNoBuiltins.end());
+  }
+}
+
+void Sema::ActOnPragmaMSFunction(const std::vector &NoBuiltins) {
+  MSFunctionNoBuiltins.insert(MSFunctionNoBuiltins.end(),
+  NoBuiltins.begin(), NoBuiltins.end());
+}
+
 void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
   // In the future, check other pragmas if they're implemented (e.g. pragma
   // optimize 0 will probably map to this functionality too).
@@ -1086,6 +1100,13 @@
 FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
 }
 
+void Sema::AddRangeBasedNoBuiltin(FunctionDecl *FD) {
+  if (!MSFunctionNoBuiltins.empty()) {
+FD->addAttr(NoBu

[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-04 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 426998.
steplong added a comment.

Removed unnecessary braces (mentioned in the LLVM coding standard)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp

Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if we have to apply any
+  // attributes (i.e. optnone and no_builtin) due to a pragma.
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddRangeBasedNoBuiltin(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1065,6 +1065,19 @@
 OptimizeOffPragmaLocation = PragmaLoc;
 }
 
+void Sema::ActOnPragmaMSIntrinsic(const std::vector &Intrinsics) {
+  for (auto &Intrinsic : Intrinsics)
+MSFunctionNoBuiltins.erase(std::remove(MSFunctionNoBuiltins.begin(),
+   MSFunctionNoBuiltins.end(),
+   Intrinsic),
+   MSFunctionNoBuiltins.end());
+}
+
+void Sema::ActOnPragmaMSFunction(const std::vector &NoBuiltins) {
+  MSFunctionNoBuiltins.insert(MSFunctionNoBuiltins.end(),
+  NoBuiltins.begin(), NoBuiltins.end());
+}
+
 void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
   // In the future, check other pragmas if they're implemented (e.g. pragma
   // optimize 0 will probably map to this functionality too).
@@ -1086,6 +1099,12 @@
 FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
 }
 
+void Sema::AddRangeBasedNoBuiltin(FunctionDecl *FD) {
+  if (!MSFunctionNoBuiltins.empty())
+FD->addAttr(NoBuiltinAttr::CreateImplicit(Context,
+MSFunctionNoBuiltins.data(), MSFunctionNoBuiltins.size()));
+}
+
 typedef std::vector > VisStack;
 enum : unsigned { NoVisibility = ~0U };
 
Index: clang/lib/Parse/ParsePragma.cpp
===
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -250,9 +250,21 @@
 };
 
 struct PragmaMSIntrinsicHandler : public PragmaHandler {
-  PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
+  PragmaMSIntrinsicHandler(Sema &S) : PragmaHandler("intrinsic"), Actions(S) {}
   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
 Token &FirstToken) override;
+
+private:
+  Sema &Actions;
+};
+
+struct PragmaMSFunctionHandler : public PragmaHandler {
+  PragmaMSFunctionHandler(Sema &S) : PragmaHandler("function"), Actions(S) {}
+  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+Token &FirstToken) override;
+
+private:
+  Sema &Actions;
 };
 
 struct PragmaMSOptimizeHandler : public PragmaHandler {
@@ -447,8 +459,10 @@
 PP.AddPragmaHandler(MSSection.get());
 MSRuntimeChecks = std::make_unique();
 PP.AddPragmaHandler(MSRuntimeChecks.get());
-MSIntrinsic = std::make_unique();
+MSIntrinsic = std::make_unique(Actions);
 PP.AddPragmaHandler(MSIntrinsic.get());
+MSFunction = std::make_unique(Actions);
+PP.AddPragmaHandler(MSFunction.get());
 MSOptimize = std::make_unique();
 PP.AddPragmaHandler(MSOptimize.get());
 MSFenvAccess = std::make_unique();
@@ -558,6 +572,8 @@
 MSRuntimeChecks.reset();
 PP.RemovePragmaHandler(MSIntrinsic.get());
 MSIntrinsic.reset();
+PP.RemovePragmaHandler(MSFunction.get());
+MSFunction.reset();
 PP.RemovePragmaHandler(MSOptimize.get());
 MSOptimize.reset();
 PP.RemovePragmaHandler(MSFenvAccess.get());
@@ -3523,11 +3539,14 @@
 
   bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
 
+  std::vector Intrinsics;
   while (Tok.is(tok::identifier)) {
 IdentifierInfo *II = Tok.getIdentifierInfo();
 if (!II->getBuiltinID())
   PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
   << II << SuggestIntrinH;
+else
+  Intrinsics.push_back(II->getName());
 
 PP.Lex(Tok);
 if (Tok.isNot(tok::comma))
@@ -3545,6 +3564,51 @@
   if (Tok.isNot(tok::eod))
 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
 << "intrinsic";
+
+  Actions.ActOnPragmaMSIntrinsic(Intrinsics);
+}
+
+void PragmaMSFunctionHandler::Ha

[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-04 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 427040.
steplong added a comment.

Changed std::vector to llvm::SmallVector


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp

Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if we have to apply any
+  // attributes (i.e. optnone and no_builtin) due to a pragma.
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddRangeBasedNoBuiltin(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1065,6 +1065,20 @@
 OptimizeOffPragmaLocation = PragmaLoc;
 }
 
+void Sema::ActOnPragmaMSIntrinsic(
+const SmallVectorImpl &Intrinsics) {
+  for (auto &Intrinsic : Intrinsics)
+MSFunctionNoBuiltins.erase(std::remove(MSFunctionNoBuiltins.begin(),
+   MSFunctionNoBuiltins.end(),
+   Intrinsic),
+   MSFunctionNoBuiltins.end());
+}
+
+void Sema::ActOnPragmaMSFunction(const SmallVectorImpl &NoBuiltins) {
+  MSFunctionNoBuiltins.insert(MSFunctionNoBuiltins.end(),
+  NoBuiltins.begin(), NoBuiltins.end());
+}
+
 void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
   // In the future, check other pragmas if they're implemented (e.g. pragma
   // optimize 0 will probably map to this functionality too).
@@ -1086,6 +1100,12 @@
 FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
 }
 
+void Sema::AddRangeBasedNoBuiltin(FunctionDecl *FD) {
+  if (!MSFunctionNoBuiltins.empty())
+FD->addAttr(NoBuiltinAttr::CreateImplicit(Context,
+MSFunctionNoBuiltins.data(), MSFunctionNoBuiltins.size()));
+}
+
 typedef std::vector > VisStack;
 enum : unsigned { NoVisibility = ~0U };
 
Index: clang/lib/Parse/ParsePragma.cpp
===
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -250,9 +250,21 @@
 };
 
 struct PragmaMSIntrinsicHandler : public PragmaHandler {
-  PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
+  PragmaMSIntrinsicHandler(Sema &S) : PragmaHandler("intrinsic"), Actions(S) {}
   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
 Token &FirstToken) override;
+
+private:
+  Sema &Actions;
+};
+
+struct PragmaMSFunctionHandler : public PragmaHandler {
+  PragmaMSFunctionHandler(Sema &S) : PragmaHandler("function"), Actions(S) {}
+  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+Token &FirstToken) override;
+
+private:
+  Sema &Actions;
 };
 
 struct PragmaMSOptimizeHandler : public PragmaHandler {
@@ -447,8 +459,10 @@
 PP.AddPragmaHandler(MSSection.get());
 MSRuntimeChecks = std::make_unique();
 PP.AddPragmaHandler(MSRuntimeChecks.get());
-MSIntrinsic = std::make_unique();
+MSIntrinsic = std::make_unique(Actions);
 PP.AddPragmaHandler(MSIntrinsic.get());
+MSFunction = std::make_unique(Actions);
+PP.AddPragmaHandler(MSFunction.get());
 MSOptimize = std::make_unique();
 PP.AddPragmaHandler(MSOptimize.get());
 MSFenvAccess = std::make_unique();
@@ -558,6 +572,8 @@
 MSRuntimeChecks.reset();
 PP.RemovePragmaHandler(MSIntrinsic.get());
 MSIntrinsic.reset();
+PP.RemovePragmaHandler(MSFunction.get());
+MSFunction.reset();
 PP.RemovePragmaHandler(MSOptimize.get());
 MSOptimize.reset();
 PP.RemovePragmaHandler(MSFenvAccess.get());
@@ -3523,11 +3539,14 @@
 
   bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
 
+  SmallVector Intrinsics;
   while (Tok.is(tok::identifier)) {
 IdentifierInfo *II = Tok.getIdentifierInfo();
 if (!II->getBuiltinID())
   PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
   << II << SuggestIntrinH;
+else
+  Intrinsics.emplace_back(II->getName());
 
 PP.Lex(Tok);
 if (Tok.isNot(tok::comma))
@@ -3545,6 +3564,51 @@
   if (Tok.isNot(tok::eod))
 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
 << "intrinsic";
+
+  Actions.ActOnPragmaMSIntrinsic(Intrinsics);
+}
+
+void PragmaMSFunctionHandler::HandlePragm

[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-04 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/lib/Parse/ParsePragma.cpp:3561
 << "intrinsic";
 return;
   }

hans wrote:
> since the above is just a warning, we should probably still call the ActOn.. 
> method?
Hmm, I'm not sure because all the msgs above are also warnings (diag::warn_)



Comment at: clang/lib/Sema/SemaAttr.cpp:1079
+  MSFunctionNoBuiltins.insert(MSFunctionNoBuiltins.end(),
+  NoBuiltins.begin(), NoBuiltins.end());
+}

hans wrote:
> Do we want to avoid duplicates in MSFunctionNoBuiltins? Or maybe it doesn't 
> matter?
Yea, I didn't think it really mattered. I originally wanted to use a set, but I 
needed the strings to be stored in contiguous memory for 
NoBuitinAttr::CreateImplicit() in Sema::AddRangeBasedNoBuiltin()


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

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


[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-04 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/lib/CodeGen/CGExpr.cpp:5219
+// function.
+else if (!CGF.CurFn->getAttributes().hasFnAttr(AttributeNoBuiltin))
   return CGCallee::forBuiltin(builtinID, FD);

hans wrote:
> What if CurFn has the "wildcard" no-builtins attribute?
Hmmm, good question. Currently, "*" generates a warning. I was able to get "*" 
to add the attribute no-builtins to the function, but if I try making it affect 
the calls in the function, I see a compiler crash when compiling compiler-rt. 
It looks like some builtins must be generated even if -fno-builtins is called 
such as __sync_lock_test_and_set_1. I'm not sure how to check for that.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124701/new/

https://reviews.llvm.org/D124701

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


[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-04 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 427127.
steplong added a comment.

Error if pragma function/intrinsic is used inside a function


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function-intrinsic.c

Index: clang/test/CodeGen/pragma-ms-function-intrinsic.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function-intrinsic.c
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -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);
+
+// 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);
+}
+
+#pragma function(strlen, memset)
+
+// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call {{.*}} @memset
+// CHECK:   call void @llvm.memcpy
+void foo2(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 1, n);
+memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call {{.*}} @memset
+// CHECK:   {{.*}}call {{.*}} @memcpy
+void foo3(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 2, n);
+memcpy(d, s, n);
+}
+
+#pragma intrinsic(memset, strlen)
+
+// CHECK: define{{.*}} void @foo4({{.*}}) #[[NOBUILTIN_MEMCPY:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   {{.*}}call {{.*}} @memcpy
+void foo4(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 3, n);
+memcpy(d, s, n);
+}
+
+#pragma intrinsic(memcpy)
+
+// CHECK: define{{.*}} void @foo5({{.*}}) #[[NO_NOBUILTIN]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   call void @llvm.memcpy
+void foo5(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 4, 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-NOT: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}}
+// CHECK-NOT: attributes #[[NOBUILTIN_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if we have to apply any
+  // attributes (i.e. optnone and no_builtin) due to a pragma.
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddRangeBasedNoBuiltin(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1065,6 +1065,31 @@
 OptimizeOffPragmaLocation = PragmaLoc;
 }
 
+void Sema::ActOnPragmaMSIntrinsic(
+SourceLocation Loc, const SmallVectorImpl &Intrinsics) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(Loc, diag::err_pragma_intrinsic_function_scope);
+return;
+  }
+
+  for (auto &Intrinsic : Intrinsics)
+MSFunctionNoBuiltins.erase(std::remove(MSFunctionNoBuiltins.begin(),
+   MSFunctionNoBuiltins.end(),
+   Intrinsic),
+   MSFunctionNoBuiltins.end());
+}
+
+void Sema::ActOnPragmaMSFunction(SourceLocation Loc,
+ const SmallVectorImpl &NoBuiltins) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(Loc, diag::err_pragma_intrinsic_function_scope);
+return;
+  }
+
+  MSFunctionNoBuiltins.insert(MSFun

[PATCH] D125011: [MSVC] Add support for pragma alloc_text

2022-05-05 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

`#pragma alloc_text` is a MSVC pragma that names the code section where 
functions should be placed. It only
applies to functions with C linkage.

https://docs.microsoft.com/en-us/cpp/preprocessor/alloc-text?view=msvc-170


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D125011

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp

Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10220,8 +10220,10 @@
 
   // If this is a function definition, check if we have to apply optnone due to
   // a pragma.
-  if(D.isFunctionDefinition())
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddSectionMSAllocText(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -741,6 +741,18 @@
   CurInitSegLoc = PragmaLocation;
 }
 
+void Sema::ActOnPragmaMSAllocText(SourceLocation PragmaLocation,
+  StringRef Section,
+  const SmallVector &Functions) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(PragmaLocation, diag::err_pragma_alloc_text_scope);
+return;
+  }
+
+  for (auto &Function : Functions)
+FunctionToSectionMap[Function] = Section;
+}
+
 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
  SourceLocation PragmaLoc) {
 
@@ -1072,6 +1084,17 @@
 AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
 }
 
+void Sema::AddSectionMSAllocText(FunctionDecl *FD) {
+  if (!FD->getIdentifier())
+return;
+
+  StringRef Name = FD->getName();
+  auto It = FunctionToSectionMap.find(Name);
+  if (It != FunctionToSectionMap.end())
+if (FD->isExternC() && !FD->hasAttr())
+  FD->addAttr(SectionAttr::CreateImplicit(Context, It->second));
+}
+
 void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
 SourceLocation Loc) {
   // Don't add a conflicting attribute. No diagnostic is needed.
Index: clang/lib/Parse/ParsePragma.cpp
===
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -445,6 +445,8 @@
 PP.AddPragmaHandler(MSCodeSeg.get());
 MSSection = std::make_unique("section");
 PP.AddPragmaHandler(MSSection.get());
+MSAllocText = std::make_unique("alloc_text");
+PP.AddPragmaHandler(MSAllocText.get());
 MSRuntimeChecks = std::make_unique();
 PP.AddPragmaHandler(MSRuntimeChecks.get());
 MSIntrinsic = std::make_unique();
@@ -554,6 +556,8 @@
 MSCodeSeg.reset();
 PP.RemovePragmaHandler(MSSection.get());
 MSSection.reset();
+PP.RemovePragmaHandler(MSAllocText.get());
+MSAllocText.reset();
 PP.RemovePragmaHandler(MSRuntimeChecks.get());
 MSRuntimeChecks.reset();
 PP.RemovePragmaHandler(MSIntrinsic.get());
@@ -912,7 +916,8 @@
 .Case("const_seg", &Parser::HandlePragmaMSSegment)
 .Case("code_seg", &Parser::HandlePragmaMSSegment)
 .Case("section", &Parser::HandlePragmaMSSection)
-.Case("init_seg", &Parser::HandlePragmaMSInitSeg);
+.Case("init_seg", &Parser::HandlePragmaMSInitSeg)
+.Case("alloc_text", &Parser::HandlePragmaMSAllocText);
 
   if (!(this->*Handler)(PragmaName, PragmaLocation)) {
 // Pragma handling failed, and has been diagnosed.  Slurp up the tokens
@@ -1149,6 +1154,72 @@
   return true;
 }
 
+bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
+ SourceLocation PragmaLocation) {
+  Token FirstTok = Tok;
+  if (Tok.isNot(tok::l_paren)) {
+PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
+<< PragmaName;
+return false;
+  }
+  PP.Lex(Tok);
+
+  if (Tok.isNot(tok::string_literal)) {
+PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
+<< PragmaName;
+return false;
+  }
+  ExprResult StringResult = ParseStringLiteralExpression();
+  if (StringResult.isInvalid())
+return false; // Already diagnosed.
+  StringLiteral *SegmentName = cast(StringResult.get());
+  if (SegmentName->getCharByteWidth() != 1) {
+PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
+<< PragmaName;
+return false;
+  }
+
+  if (Tok.isNot(tok::comma)) {
+PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << Pra

[PATCH] D125011: [MSVC] Add support for pragma alloc_text

2022-05-05 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 427329.
steplong added reviewers: rnk, aaron.ballman, hans.
steplong added a comment.

Update patch to error out if a function is not C linkage. Not sure how to check 
if a function has been declared


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125011/new/

https://reviews.llvm.org/D125011

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/msvc_pragma_alloc_text.cpp

Index: clang/test/CodeGen/msvc_pragma_alloc_text.cpp
===
--- /dev/null
+++ clang/test/CodeGen/msvc_pragma_alloc_text.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fms-extensions -S -emit-llvm -o - %s | FileCheck %s
+
+extern "C" void foo();
+extern "C" void foo1();
+extern "C" void foo2();
+extern "C" void foo3();
+
+#pragma alloc_text("abc", foo, foo1)
+#pragma alloc_text("def", foo2)
+#pragma alloc_text("def", foo3)
+
+// CHECK-LABEL: define{{.*}} void @foo() {{.*}} section "abc"
+extern "C" void foo() {}
+
+// CHECK-LABEL: define{{.*}} void @foo1() {{.*}} section "abc"
+extern "C" void foo1() {}
+
+// CHECK-LABEL: define{{.*}} void @foo2() {{.*}} section "def"
+extern "C" void foo2() {}
+
+// CHECK-LABEL: define{{.*}} void @foo3() {{.*}} section "def"
+extern "C" void foo3() {}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10220,8 +10220,10 @@
 
   // If this is a function definition, check if we have to apply optnone due to
   // a pragma.
-  if(D.isFunctionDefinition())
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddSectionMSAllocText(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -741,6 +741,24 @@
   CurInitSegLoc = PragmaLocation;
 }
 
+void Sema::ActOnPragmaMSAllocText(
+SourceLocation PragmaLocation,
+StringRef Section,
+const SmallVector> &Functions) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(PragmaLocation, diag::err_pragma_alloc_text_scope);
+return;
+  }
+
+  for (auto &Function : Functions) {
+StringRef Name;
+SourceLocation Loc;
+std::tie(Name, Loc) = Function;
+
+FunctionToSectionMap[Name] = std::make_tuple(Section, Loc);
+  }
+}
+
 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
  SourceLocation PragmaLoc) {
 
@@ -1072,6 +1090,27 @@
 AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
 }
 
+void Sema::AddSectionMSAllocText(FunctionDecl *FD) {
+  if (!FD->getIdentifier())
+return;
+
+  StringRef Name = FD->getName();
+  auto It = FunctionToSectionMap.find(Name);
+  if (It != FunctionToSectionMap.end()) {
+StringRef Section;
+SourceLocation Loc;
+std::tie(Section, Loc) = It->second;
+
+if (!FD->isExternC()) {
+  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+  return;
+}
+
+if (!FD->hasAttr())
+  FD->addAttr(SectionAttr::CreateImplicit(Context, Section));
+  }
+}
+
 void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
 SourceLocation Loc) {
   // Don't add a conflicting attribute. No diagnostic is needed.
Index: clang/lib/Parse/ParsePragma.cpp
===
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -445,6 +445,8 @@
 PP.AddPragmaHandler(MSCodeSeg.get());
 MSSection = std::make_unique("section");
 PP.AddPragmaHandler(MSSection.get());
+MSAllocText = std::make_unique("alloc_text");
+PP.AddPragmaHandler(MSAllocText.get());
 MSRuntimeChecks = std::make_unique();
 PP.AddPragmaHandler(MSRuntimeChecks.get());
 MSIntrinsic = std::make_unique();
@@ -554,6 +556,8 @@
 MSCodeSeg.reset();
 PP.RemovePragmaHandler(MSSection.get());
 MSSection.reset();
+PP.RemovePragmaHandler(MSAllocText.get());
+MSAllocText.reset();
 PP.RemovePragmaHandler(MSRuntimeChecks.get());
 MSRuntimeChecks.reset();
 PP.RemovePragmaHandler(MSIntrinsic.get());
@@ -912,7 +916,8 @@
 .Case("const_seg", &Parser::HandlePragmaMSSegment)
 .Case("code_seg", &Parser::HandlePragmaMSSegment)
 .Case("section", &Parser::HandlePragmaMSSection)
-.Case("init_seg", &Parser::HandlePragmaMSInitSeg);
+.Case("init_seg", &Parser::HandlePragmaMSInitSeg)
+.Case("alloc_text", &Parser::HandlePragmaMSAllocText);
 
   if (!(this->*Handler)(PragmaName, PragmaLocation)) {
 // Pragma han

[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-06 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

In D124702#3496534 , @hans wrote:

> It needs tests for the warnings about badly formed pragmas, and for pragmas 
> outside file/namespace scope.

Appreciate the comments. I have a couple of questions:

Is the tests for badly formed pragmas, 
clang/test/Preprocessor/pragma_microsoft.c?
It looks like MSVC only cares about it not being in a function like mentioned 
in the comments in D125011 . Do we try to 
mimic MSVC behavior because MSVC rejects `#pragma function(memset` whichout the 
right paren?
MSVC also rejects `#pragma function(foo)` if foo isn't extern C or declared. We 
probably to match that behavior even if it isn't documented?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

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


[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-06 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/lib/Sema/SemaAttr.cpp:1079
+  MSFunctionNoBuiltins.insert(MSFunctionNoBuiltins.end(),
+  NoBuiltins.begin(), NoBuiltins.end());
+}

hans wrote:
> steplong wrote:
> > hans wrote:
> > > Do we want to avoid duplicates in MSFunctionNoBuiltins? Or maybe it 
> > > doesn't matter?
> > Yea, I didn't think it really mattered. I originally wanted to use a set, 
> > but I needed the strings to be stored in contiguous memory for 
> > NoBuitinAttr::CreateImplicit() in Sema::AddRangeBasedNoBuiltin()
> A set would be nicer conceptually of course.
> 
> How about using an llvm::SmallSetVector. That will solve the problem of 
> duplicates, it will be deterministic, and you can use getArrayRef() to get 
> the values in contiguous memory, or maybe being() and end() will work too.
Hmm do you know where I can find an Allocator? getArrayRef().data() returns a 
pointer to a constant StringRef, but CreateImplicit takes a pointer to a 
StringRef.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

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


[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-06 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 427716.
steplong added a reviewer: aaron.ballman.
steplong added a comment.

Changed it to use SmallSetVector instead of SmallVector. Had to use an 
temporary SmallVector in AddRangeBasedNoBuiltin() because I'm not sure how to 
get a pointer to StringRef. getArrayRef().copy().data() needs an Allocator.

Also, I can't figure out why the test pragma-ms-function-intrinsic.c is failing 
from the pragma not being in file context. The pragmas are not inside a 
function.

Will add Sema and parsing tests in the next update to this patch.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function-intrinsic.c

Index: clang/test/CodeGen/pragma-ms-function-intrinsic.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function-intrinsic.c
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -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);
+
+// 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);
+}
+
+#pragma function(strlen, memset)
+
+// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call {{.*}} @memset
+// CHECK:   call void @llvm.memcpy
+void foo2(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 1, n);
+memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call {{.*}} @memset
+// CHECK:   {{.*}}call {{.*}} @memcpy
+void foo3(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 2, n);
+memcpy(d, s, n);
+}
+
+#pragma intrinsic(memset, strlen)
+
+// CHECK: define{{.*}} void @foo4({{.*}}) #[[NOBUILTIN_MEMCPY:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   {{.*}}call {{.*}} @memcpy
+void foo4(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 3, n);
+memcpy(d, s, n);
+}
+
+#pragma intrinsic(memcpy)
+
+// CHECK: define{{.*}} void @foo5({{.*}}) #[[NO_NOBUILTIN]]
+// CHECK:   call void @bar
+// CHECK:   call void @llvm.memset
+// CHECK:   call void @llvm.memcpy
+void foo5(char *s, char *d, size_t n)
+{
+bar(s);
+memset(s, 4, 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-NOT: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}}
+// CHECK-NOT: attributes #[[NOBUILTIN_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if we have to apply any
+  // attributes (i.e. optnone and no_builtin) due to a pragma.
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddRangeBasedNoBuiltin(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1065,6 +1065,27 @@
 OptimizeOffPragmaLocation = PragmaLoc;
 }
 
+void Sema::ActOnPragmaMSIntrinsic(
+SourceLocation Loc, const llvm::SmallSetVector &Intrinsics) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(Loc, diag::err_pragma_intrinsic_function_scope);
+return;
+  }
+
+  for (auto &Intrinsic : Intrinsics)
+MSFunctionNoBuiltins.remove(Intrinsic);
+}
+
+void Sema::ActOnPragmaMSFunction(
+SourceLocation Loc, const llvm::

[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-06 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 427741.
steplong added a comment.

Update patch to accept __attribute__((no_builtin("*")). It adds no-builtins to 
the function attributes, but it still doesn't affect the calls. The calls in 
the function still become builtin calls.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124701/new/

https://reviews.llvm.org/D124701

Files:
  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,45 @@
+// 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);
+
+// 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 {{.*}} @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 {{.*}} @memset
+// CHECK:   {{.*}}call {{.*}} @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/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,6 +5034,7 @@
   const FunctionDecl *FD = cast(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.
@@ -5054,8 +5055,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
+
+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);
+
+// 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 {{.*}} @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 {{.*}} @memset
+// CHECK:   {{.*}}call {

[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-09 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 428195.
steplong added a comment.

clang-formatted patch


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124701/new/

https://reviews.llvm.org/D124701

Files:
  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,42 @@
+// 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);
+
+// 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 {{.*}} @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 {{.*}} @memset
+// CHECK:   {{.*}}call {{.*}} @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/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,6 +5034,7 @@
   const FunctionDecl *FD = cast(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.
@@ -5054,8 +5055,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,42 @@
+// 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);
+
+// 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 {{.*}} @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 {{.*}} @memset
+// CHECK:   {{.*}}call {{.*}} @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-NO

[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-10 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/lib/Parse/ParsePragma.cpp:3578
+
+  if (Tok.isNot(tok::l_paren)) {
+PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)

aaron.ballman wrote:
> Can we use `ExpectAndConsume()` here instead?
I don't think we can use `ExpectAndConsume()` here because it's not a `Parser`



Comment at: clang/lib/Sema/SemaAttr.cpp:1070
+SourceLocation Loc, const llvm::SmallSetVector &Intrinsics) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(Loc, diag::err_pragma_intrinsic_function_scope);

aaron.ballman wrote:
> What is `CurContext` when this gets called for your .c test file? I would 
> have expected it to be the `TranslationUnitDecl` which should be a file 
> context (getting the redecl context shouldn't do anything in the cases I've 
> seen).
It looks like it's a `FunctionDecl`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

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


[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-10 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 428375.
steplong edited the summary of this revision.
steplong added a comment.

- Clang-formatted patch
- Split out the pragma intrinsic stuff
- Replaced SmallSetVector in pragma handler with SmallVector. MSNoBuiltins is 
still a SmallSetVector in Sema.
- Commented out if not file scope block in `ActOn..` method. Will investigate 
next
- Added pragma warnings test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function.c
  clang/test/Preprocessor/pragma_microsoft.c

Index: clang/test/Preprocessor/pragma_microsoft.c
===
--- clang/test/Preprocessor/pragma_microsoft.c
+++ clang/test/Preprocessor/pragma_microsoft.c
@@ -201,6 +201,31 @@
 #pragma clang diagnostic pop
 #pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
 
+// Test pragma function
+#pragma function(memset) // no-warning
+#pragma function(memcpy, strlen, strlen) // no-warning
+#pragma function()   // no-warning
+#pragma function(asdf)   // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+#pragma function(main)   // expected-warning {{'main' is not a recognized builtin; consider including }}
+#pragma function(// expected-warning {{missing ')' after}}
+#pragma function(int)// expected-warning {{missing ')' after}}
+#pragma function(strcmp) asdf// expected-warning {{extra tokens at end}}
+
+#define __INTRIN_H   // there should be no notes after defining __INTRIN_H
+#pragma function(asdf)   // expected-warning-re {{'asdf' is not a recognized builtin{{$
+#pragma function(memset) // no-warning
+#undef __INTRIN_H
+#pragma function(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+
+struct pragma_function_S {
+#pragma function(memset) // no-warning
+  int a;
+};
+
+void pragma_function_foo() {
+#pragma function(memset) // expected-error {{'#pragma function' can only appear outside a function, at the global level}}
+}
+
 #pragma optimize  // expected-warning{{missing '(' after '#pragma optimize'}}
 #pragma optimize( // expected-warning{{expected string literal in '#pragma optimize'}}
 #pragma optimize(a// expected-warning{{expected string literal in '#pragma optimize'}}
Index: clang/test/CodeGen/pragma-ms-function.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function.c
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -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);
+
+// 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);
+}
+
+#pragma function(strlen, memset)
+
+// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call {{.*}} @memset
+// CHECK:   call void @llvm.memcpy
+void foo2(char *s, char *d, size_t n) {
+  bar(s);
+  memset(s, 1, n);
+  memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]]
+// CHECK:   call void @bar
+// CHECK:   {{.*}}call {{.*}} @memset
+// CHECK:   {{.*}}call {{.*}} @memcpy
+void foo3(char *s, char *d, size_t n) {
+  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-NOT: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, chec

[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-10 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/lib/Sema/SemaAttr.cpp:1070
+SourceLocation Loc, const llvm::SmallSetVector &Intrinsics) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(Loc, diag::err_pragma_intrinsic_function_scope);

aaron.ballman wrote:
> steplong wrote:
> > aaron.ballman wrote:
> > > What is `CurContext` when this gets called for your .c test file? I would 
> > > have expected it to be the `TranslationUnitDecl` which should be a file 
> > > context (getting the redecl context shouldn't do anything in the cases 
> > > I've seen).
> > It looks like it's a `FunctionDecl`
> Wha? That seems rather surprising -- which function does it think the pragma 
> is scoped to?
> 
> You might consider putting breakpoints in `PushDeclContext()` and 
> `PopDeclContext()` to see what's going on (or search for other places where 
> we assign to `CurContext` and break on those).
This is what I see when I run it on pragma-ms-function.c:
```
PUSHING TranslationUnit
PUSHING Function foo1
FOUND PRAGMA FUNCTION
POPPING Function foo1
PUSHING TranslationUnit
PUSHING Function foo2
FOUND PRAGMA FUNCTION
POPPING Function foo2
PUSHING TranslationUnit
PUSHING Function foo3
POPPING Function foo3
PUSHING TranslationUnit
```
I'm logging the swap in `PopDeclContext()` with POPPING and PUSHING and the 
push in `PushDeclContext()` with just PUSHING.
I'm also logging FOUND PRAGMA in the pragma handler


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

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


[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-10 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/lib/Sema/SemaAttr.cpp:1070
+SourceLocation Loc, const llvm::SmallSetVector &Intrinsics) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(Loc, diag::err_pragma_intrinsic_function_scope);

aaron.ballman wrote:
> steplong wrote:
> > aaron.ballman wrote:
> > > steplong wrote:
> > > > aaron.ballman wrote:
> > > > > What is `CurContext` when this gets called for your .c test file? I 
> > > > > would have expected it to be the `TranslationUnitDecl` which should 
> > > > > be a file context (getting the redecl context shouldn't do anything 
> > > > > in the cases I've seen).
> > > > It looks like it's a `FunctionDecl`
> > > Wha? That seems rather surprising -- which function does it think the 
> > > pragma is scoped to?
> > > 
> > > You might consider putting breakpoints in `PushDeclContext()` and 
> > > `PopDeclContext()` to see what's going on (or search for other places 
> > > where we assign to `CurContext` and break on those).
> > This is what I see when I run it on pragma-ms-function.c:
> > ```
> > PUSHING TranslationUnit
> > PUSHING Function foo1
> > FOUND PRAGMA FUNCTION
> > POPPING Function foo1
> > PUSHING TranslationUnit
> > PUSHING Function foo2
> > FOUND PRAGMA FUNCTION
> > POPPING Function foo2
> > PUSHING TranslationUnit
> > PUSHING Function foo3
> > POPPING Function foo3
> > PUSHING TranslationUnit
> > ```
> > I'm logging the swap in `PopDeclContext()` with POPPING and PUSHING and the 
> > push in `PushDeclContext()` with just PUSHING.
> > I'm also logging FOUND PRAGMA in the pragma handler
> Huh. For fun, can you try changing the test to:
> ```
> void foo1(char *s, char *d, size_t n) {
>   bar(s);
>   memset(s, 0, n);
>   memcpy(d, s, n);
> }
> 
> int i; // Now there's a declaration here
> 
> #pragma function(strlen, memset)
> ```
> and see if you get different results? I'm wondering if what's happening is 
> that the `CurContext` is being updated after we've lexed the next token from 
> the preprocessor, which means we're still in the context of `foo1` until 
> after we've processed the pragma due to it being a preprocessing token. It 
> still wouldn't make much sense to me, because I think we should hit that on 
> the `}` for `foo1()`, but it's a shot in the dark.
It looks like you're right. The `int i` makes the pragma show up after the 
`TranslationUnit` is pushed.

```
PUSHING TranslationUnit
PUSHING Function foo1
POPPING Function foo1
PUSHING TranslationUnit
FOUND PRAGMA FUNCTION
PUSHING Function foo2
POPPING Function foo2
PUSHING TranslationUnit
FOUND PRAGMA FUNCTION
PUSHING Function foo3
POPPING Function foo3
PUSHING TranslationUnit
```

I really appreciate the review and you helping me debug this


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

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


[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-10 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 428456.
steplong added a comment.

- Changed pragma-ms-functions.c to only check that the no-builtin attributes 
are added to the functions
- Moved pragma handler to Parser
- Changed scope check to only file scope. MSVC accepts stuff like that we don't:

  struct S {
int a;
  #pragma function(memset)
  };


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function.c
  clang/test/Preprocessor/pragma_microsoft.c

Index: clang/test/Preprocessor/pragma_microsoft.c
===
--- clang/test/Preprocessor/pragma_microsoft.c
+++ clang/test/Preprocessor/pragma_microsoft.c
@@ -201,6 +201,26 @@
 #pragma clang diagnostic pop
 #pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
 
+// Test pragma function
+#pragma function(memset) // no-warning
+#pragma function(memcpy, strlen, strlen) // no-warning
+#pragma function()   // no-warning
+#pragma function(asdf)   // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+#pragma function(main)   // expected-warning {{'main' is not a recognized builtin; consider including }}
+#pragma function(// expected-warning {{missing ')' after}}
+#pragma function(int)// expected-warning {{missing ')' after}}
+#pragma function(strcmp) asdf// expected-warning {{extra tokens at end}}
+
+#define __INTRIN_H   // there should be no notes after defining __INTRIN_H
+#pragma function(asdf)   // expected-warning-re {{'asdf' is not a recognized builtin{{$
+#pragma function(memset) // no-warning
+#undef __INTRIN_H
+#pragma function(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+
+void pragma_function_foo() {
+#pragma function(memset) // expected-error {{'#pragma function' can only appear at file scope}}
+}
+
 #pragma optimize  // expected-warning{{missing '(' after '#pragma optimize'}}
 #pragma optimize( // expected-warning{{expected string literal in '#pragma optimize'}}
 #pragma optimize(a// expected-warning{{expected string literal in '#pragma optimize'}}
Index: clang/test/CodeGen/pragma-ms-function.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function.c
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -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);
+
+// CHECK: define{{.*}} void @foo1({{.*}}) #[[NO_NOBUILTIN:[0-9]+]]
+void foo1(char *s, char *d, size_t n) {
+  bar(s);
+  memset(s, 0, n);
+  memcpy(d, s, n);
+}
+
+#pragma function(strlen, memset)
+
+// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]]
+void foo2(char *s, char *d, size_t n) {
+  bar(s);
+  memset(s, 1, n);
+  memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]]
+void foo3(char *s, char *d, size_t n) {
+  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-NOT: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if we have to apply any
+  // attributes (i.e. optnone and no_builtin) due to a pragma.
+  if (D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddRangeBasedNoBuiltin(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ 

[PATCH] D125011: [MSVC] Add support for pragma alloc_text

2022-05-10 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 428536.
steplong added a comment.

- Added Sema tests
- Added checking of c linkage
- Changed some parsing logic in the parser handler e.g #pragma alloc_text(a, 
foo  without the right paren is only a warning


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125011/new/

https://reviews.llvm.org/D125011

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/msvc_pragma_alloc_text.cpp
  clang/test/Sema/pragma-ms-alloc-text.cpp

Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- /dev/null
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
+
+#pragma alloc_text()// expected-warning {{expected a string literal for the section name in '#pragma alloc_text'}}
+#pragma alloc_text(a// expected-warning {{expected ',' in '#pragma alloc_text'}}
+#pragma alloc_text(a, a // expected-warning {{missing ')' after '#pragma alloc_text'}} expected-error {{use of undeclared a}}
+#pragma alloc_text(L"a", a) // expected-warning {{expected a string literal for the section name}}
+
+void foo();
+#pragma alloc_text(a, foo) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+
+extern "C" void foo1();
+#pragma alloc_text(a, foo1)  // no-warning
+#pragma alloc_text(a, foo1) asdf // expected-warning {{extra tokens at end of '#pragma alloc_text'}}
+#pragma alloc_text(a, foo1   // expected-warning {{missing ')' after '#pragma alloc_text'}}
+
+namespace N {
+#pragma alloc_text(b, foo1) // no-warning
+}
+
+extern "C" {
+void foo2();
+#pragma alloc_text(a, foo2) // no-warning
+}
+
+void foo3() {
+#pragma alloc_text(a, foo1) // expected-error {{'#pragma alloc_text' can only appear at file scope}}
+}
+
+extern "C" void foo4();
+#pragma alloc_text(c, foo4) // no-warning
+void foo4() {}
+
+void foo5();// expected-note {{previous declaration is here}}
+#pragma alloc_text(c, foo5) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+extern "C" void foo5() {}   // expected-error {{declaration of 'foo5' has a different language linkage}}
Index: clang/test/CodeGen/msvc_pragma_alloc_text.cpp
===
--- /dev/null
+++ clang/test/CodeGen/msvc_pragma_alloc_text.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fms-extensions -S -emit-llvm -o - %s | FileCheck %s
+
+extern "C" {
+
+void foo();
+void foo1();
+void foo2();
+void foo3();
+
+#pragma alloc_text("abc", foo, foo1)
+#pragma alloc_text("def", foo2)
+#pragma alloc_text("def", foo3)
+
+// CHECK-LABEL: define{{.*}} void @foo() {{.*}} section "abc"
+void foo() {}
+
+// CHECK-LABEL: define{{.*}} void @foo1() {{.*}} section "abc"
+void foo1() {}
+
+// CHECK-LABEL: define{{.*}} void @foo2() {{.*}} section "def"
+void foo2() {}
+
+// CHECK-LABEL: define{{.*}} void @foo3() {{.*}} section "def"
+void foo3() {}
+
+}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10220,8 +10220,10 @@
 
   // If this is a function definition, check if we have to apply optnone due to
   // a pragma.
-  if(D.isFunctionDefinition())
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddSectionMSAllocText(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -741,6 +741,37 @@
   CurInitSegLoc = PragmaLocation;
 }
 
+void Sema::ActOnPragmaMSAllocText(
+SourceLocation PragmaLocation, StringRef Section,
+const SmallVector>
+&Functions) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(PragmaLocation, diag::err_pragma_expected_file_scope) << "alloc_text";
+return;
+  }
+
+  for (auto &Function : Functions) {
+IdentifierInfo *II;
+SourceLocation Loc;
+std::tie(II, Loc) = Function;
+
+DeclarationName DN(II);
+NamedDecl *ND = LookupSingleName(TUScope, DN, Loc, LookupOrdinaryName);
+if (!ND) {
+  Diag(Loc, diag::err_undeclared_use) << II->getName();
+  return;
+}
+
+DeclContext *DC = ND->getDeclContext();
+if (!DC->isExternCContext()) {
+  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+  return;
+}
+
+FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc);
+  }
+}
+
 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope 

[PATCH] D125011: [MSVC] Add support for pragma alloc_text

2022-05-11 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/test/Sema/pragma-ms-alloc-text.cpp:5
+#pragma alloc_text(a// expected-warning {{expected ',' in '#pragma 
alloc_text'}}
+#pragma alloc_text(a, a // expected-warning {{missing ')' after '#pragma 
alloc_text'}} expected-error {{use of undeclared a}}
+#pragma alloc_text(L"a", a) // expected-warning {{expected a string literal 
for the section name}}

aaron.ballman wrote:
> This shows we have the parsing logic wrong -- we shouldn't get the use of 
> undeclared identifier a because we shouldn't have gotten into Sema for this 
> one.
MSVC accepts it and only warns about the missing paren if the identifier is 
declared like on Line 14. That's why I decided to handle it that way. We can 
decide to reject it though


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125011/new/

https://reviews.llvm.org/D125011

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


[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-11 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 428657.
steplong added a comment.

- Renamed `AddRangeBasedNoBuiltin` to `AddImplicitMSFunctionNoBuiltinAttr`
- Renamed `err_pragma_intrinsic_function_scope` to 
`err_pragma_expected_file_scope`
- Added comment about MSVC accepting struct test
- Removed `->getRedeclContext()`. Seems to be ok (i.e. tests are still passing)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function.c
  clang/test/Preprocessor/pragma_microsoft.c

Index: clang/test/Preprocessor/pragma_microsoft.c
===
--- clang/test/Preprocessor/pragma_microsoft.c
+++ clang/test/Preprocessor/pragma_microsoft.c
@@ -201,6 +201,27 @@
 #pragma clang diagnostic pop
 #pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
 
+// Test pragma function
+#pragma function(memset) // no-warning
+#pragma function(memcpy, strlen, strlen) // no-warning
+#pragma function()   // no-warning
+#pragma function(asdf)   // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+#pragma function(main)   // expected-warning {{'main' is not a recognized builtin; consider including }}
+#pragma function(// expected-warning {{missing ')' after}}
+#pragma function(int)// expected-warning {{missing ')' after}}
+#pragma function(strcmp) asdf// expected-warning {{extra tokens at end}}
+
+#define __INTRIN_H   // there should be no notes after defining __INTRIN_H
+#pragma function(asdf)   // expected-warning-re {{'asdf' is not a recognized builtin{{$
+#pragma function(memset) // no-warning
+#undef __INTRIN_H
+#pragma function(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+
+// MSVC accepts this, but we decide to reject it based on the MS docs saying the pragma must appear at the global level
+void pragma_function_foo() {
+#pragma function(memset) // expected-error {{'#pragma function' can only appear at file scope}}
+}
+
 #pragma optimize  // expected-warning{{missing '(' after '#pragma optimize'}}
 #pragma optimize( // expected-warning{{expected string literal in '#pragma optimize'}}
 #pragma optimize(a// expected-warning{{expected string literal in '#pragma optimize'}}
Index: clang/test/CodeGen/pragma-ms-function.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function.c
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -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);
+
+// CHECK: define{{.*}} void @foo1({{.*}}) #[[NO_NOBUILTIN:[0-9]+]]
+void foo1(char *s, char *d, size_t n) {
+  bar(s);
+  memset(s, 0, n);
+  memcpy(d, s, n);
+}
+
+#pragma function(strlen, memset)
+
+// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]]
+void foo2(char *s, char *d, size_t n) {
+  bar(s);
+  memset(s, 1, n);
+  memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]]
+void foo3(char *s, char *d, size_t n) {
+  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-NOT: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if we have to apply any
+  // attributes (i.e. optnone and no_builtin) due to a pragma.
+  if (D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddImplicitMSFunctionNoBuiltinAttr(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/Se

[PATCH] D125011: [MSVC] Add support for pragma alloc_text

2022-05-11 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 428727.
steplong added a comment.

- Reject `#pragma alloc_text(a, a`
- On Line 1180, I didn't use `ExpectAndConsume()` there because I wanted to 
accept both identifiers and strings (i.e `pragma alloc_text(a, foo)` and 
`pragma alloc_text("a", foo)`
- It looks like we need `->getRedeclContext()`  to accept

  extern "C" {
  void foo();
  #pragma alloc_text(a, foo)
  }


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125011/new/

https://reviews.llvm.org/D125011

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/msvc_pragma_alloc_text.cpp
  clang/test/Sema/pragma-ms-alloc-text.cpp

Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- /dev/null
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
+
+#pragma alloc_text()// expected-warning {{expected a string literal for the section name in '#pragma alloc_text'}}
+#pragma alloc_text(a// expected-warning {{expected ',' in '#pragma alloc_text'}}
+#pragma alloc_text(a, a // expected-warning {{missing ')' after '#pragma alloc_text'}}
+#pragma alloc_text(a, a)// expected-error {{use of undeclared a}}
+#pragma alloc_text(L"a", a) // expected-warning {{expected a string literal for the section name}}
+
+void foo();
+#pragma alloc_text(a, foo) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+
+extern "C" void foo1();
+#pragma alloc_text(a, foo1)  // no-warning
+#pragma alloc_text(a, foo1) asdf // expected-warning {{extra tokens at end of '#pragma alloc_text'}}
+#pragma alloc_text(a, foo1   // expected-warning {{missing ')' after '#pragma alloc_text'}}
+
+namespace N {
+#pragma alloc_text(b, foo1) // no-warning
+}
+
+extern "C" {
+void foo2();
+#pragma alloc_text(a, foo2) // no-warning
+}
+
+void foo3() {
+#pragma alloc_text(a, foo1) // expected-error {{'#pragma alloc_text' can only appear at file scope}}
+}
+
+extern "C" void foo4();
+#pragma alloc_text(c, foo4) // no-warning
+void foo4() {}
+
+void foo5();// expected-note {{previous declaration is here}}
+#pragma alloc_text(c, foo5) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+extern "C" void foo5() {}   // expected-error {{declaration of 'foo5' has a different language linkage}}
Index: clang/test/CodeGen/msvc_pragma_alloc_text.cpp
===
--- /dev/null
+++ clang/test/CodeGen/msvc_pragma_alloc_text.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fms-extensions -S -emit-llvm -o - %s | FileCheck %s
+
+extern "C" {
+
+void foo();
+void foo1();
+void foo2();
+void foo3();
+
+#pragma alloc_text("abc", foo, foo1)
+#pragma alloc_text("def", foo2)
+#pragma alloc_text("def", foo3)
+
+// CHECK-LABEL: define{{.*}} void @foo() {{.*}} section "abc"
+void foo() {}
+
+// CHECK-LABEL: define{{.*}} void @foo1() {{.*}} section "abc"
+void foo1() {}
+
+// CHECK-LABEL: define{{.*}} void @foo2() {{.*}} section "def"
+void foo2() {}
+
+// CHECK-LABEL: define{{.*}} void @foo3() {{.*}} section "def"
+void foo3() {}
+
+}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10220,8 +10220,10 @@
 
   // If this is a function definition, check if we have to apply optnone due to
   // a pragma.
-  if(D.isFunctionDefinition())
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddSectionMSAllocText(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -741,6 +741,37 @@
   CurInitSegLoc = PragmaLocation;
 }
 
+void Sema::ActOnPragmaMSAllocText(
+SourceLocation PragmaLocation, StringRef Section,
+const SmallVector>
+&Functions) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(PragmaLocation, diag::err_pragma_expected_file_scope) << "alloc_text";
+return;
+  }
+
+  for (auto &Function : Functions) {
+IdentifierInfo *II;
+SourceLocation Loc;
+std::tie(II, Loc) = Function;
+
+DeclarationName DN(II);
+NamedDecl *ND = LookupSingleName(TUScope, DN, Loc, LookupOrdinaryName);
+if (!ND) {
+  Diag(Loc, diag::err_undeclared_use) << II->getName();
+  return;
+}
+
+DeclContext *DC = ND->getDeclContext();
+if (!DC->isExternCContext()) {
+  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+  return;
+}

[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-11 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/test/Preprocessor/pragma_microsoft.c:210
+#pragma function(main)   // expected-warning {{'main' is not a 
recognized builtin; consider including }}
+#pragma function(// expected-warning {{missing ')' 
after}}
+#pragma function(int)// expected-warning {{missing ')' 
after}}

Hmm does it make sense for this to be a warning and not an error?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

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


[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-12 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 428941.
steplong added a comment.

- Added test case for the `getRedeclContext()` case
- Brought back `getRedeclContext()`
- Clang-formatted
- Added description in docs


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function.c
  clang/test/Preprocessor/pragma_microsoft.c
  clang/test/Preprocessor/pragma_microsoft.cpp

Index: clang/test/Preprocessor/pragma_microsoft.cpp
===
--- clang/test/Preprocessor/pragma_microsoft.cpp
+++ clang/test/Preprocessor/pragma_microsoft.cpp
@@ -1,3 +1,7 @@
 // RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify -fms-extensions
 
 #pragma warning(push, 4_D) // expected-warning {{requires a level between 0 and 4}}
+
+extern "C" {
+#pragma function(memset) // no-warning
+}
Index: clang/test/Preprocessor/pragma_microsoft.c
===
--- clang/test/Preprocessor/pragma_microsoft.c
+++ clang/test/Preprocessor/pragma_microsoft.c
@@ -201,6 +201,27 @@
 #pragma clang diagnostic pop
 #pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
 
+// Test pragma function
+#pragma function(memset) // no-warning
+#pragma function(memcpy, strlen, strlen) // no-warning
+#pragma function()   // no-warning
+#pragma function(asdf)   // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+#pragma function(main)   // expected-warning {{'main' is not a recognized builtin; consider including }}
+#pragma function(// expected-warning {{missing ')' after}}
+#pragma function(int)// expected-warning {{missing ')' after}}
+#pragma function(strcmp) asdf// expected-warning {{extra tokens at end}}
+
+#define __INTRIN_H   // there should be no notes after defining __INTRIN_H
+#pragma function(asdf)   // expected-warning-re {{'asdf' is not a recognized builtin{{$
+#pragma function(memset) // no-warning
+#undef __INTRIN_H
+#pragma function(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+
+// MSVC accepts this, but we decide to reject it based on the MS docs saying the pragma must appear at the global level
+void pragma_function_foo() {
+#pragma function(memset) // expected-error {{'#pragma function' can only appear at file scope}}
+}
+
 #pragma optimize  // expected-warning{{missing '(' after '#pragma optimize'}}
 #pragma optimize( // expected-warning{{expected string literal in '#pragma optimize'}}
 #pragma optimize(a// expected-warning{{expected string literal in '#pragma optimize'}}
Index: clang/test/CodeGen/pragma-ms-function.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function.c
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -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);
+
+// CHECK: define{{.*}} void @foo1({{.*}}) #[[NO_NOBUILTIN:[0-9]+]]
+void foo1(char *s, char *d, size_t n) {
+  bar(s);
+  memset(s, 0, n);
+  memcpy(d, s, n);
+}
+
+#pragma function(strlen, memset)
+
+// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]]
+void foo2(char *s, char *d, size_t n) {
+  bar(s);
+  memset(s, 1, n);
+  memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]]
+void foo3(char *s, char *d, size_t n) {
+  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-NOT: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If thi

[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-12 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 428970.
steplong edited the summary of this revision.
steplong added a comment.

- Added `isPredefinedLibFunction()` check
- Added testcase for __attribute__((no_builtin("*")))


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124701/new/

https://reviews.llvm.org/D124701

Files:
  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(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

[PATCH] D124026: [Headers][MSVC] Define wchar_t in stddef.h like MSVC if not using the builtin type

2022-05-12 Thread Stephen Long via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG7f9837cfa636: [Headers][MSVC] Define wchar_t in stddef.h 
like MSVC if not using the builtin… (authored by steplong).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124026/new/

https://reviews.llvm.org/D124026

Files:
  clang/lib/Headers/stddef.h
  clang/test/Headers/ms-no-wchar.cpp


Index: clang/test/Headers/ms-no-wchar.cpp
===
--- /dev/null
+++ clang/test/Headers/ms-no-wchar.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-windows-msvc 
-fms-compatibility-version=17.00 -fno-wchar %s
+// MSVC defines wchar_t instead of using the builtin if /Zc:wchar_t- is passed
+
+#include 
+
+wchar_t c;
Index: clang/lib/Headers/stddef.h
===
--- clang/lib/Headers/stddef.h
+++ clang/lib/Headers/stddef.h
@@ -62,7 +62,7 @@
 #endif /* defined(__need_STDDEF_H_misc) */
 
 #if defined(__need_wchar_t)
-#ifndef __cplusplus
+#if !defined(__cplusplus) || (defined(_MSC_VER) && !_NATIVE_WCHAR_T_DEFINED)
 /* Always define wchar_t when modules are available. */
 #if !defined(_WCHAR_T) || __has_feature(modules)
 #if !__has_feature(modules)


Index: clang/test/Headers/ms-no-wchar.cpp
===
--- /dev/null
+++ clang/test/Headers/ms-no-wchar.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-windows-msvc -fms-compatibility-version=17.00 -fno-wchar %s
+// MSVC defines wchar_t instead of using the builtin if /Zc:wchar_t- is passed
+
+#include 
+
+wchar_t c;
Index: clang/lib/Headers/stddef.h
===
--- clang/lib/Headers/stddef.h
+++ clang/lib/Headers/stddef.h
@@ -62,7 +62,7 @@
 #endif /* defined(__need_STDDEF_H_misc) */
 
 #if defined(__need_wchar_t)
-#ifndef __cplusplus
+#if !defined(__cplusplus) || (defined(_MSC_VER) && !_NATIVE_WCHAR_T_DEFINED)
 /* Always define wchar_t when modules are available. */
 #if !defined(_WCHAR_T) || __has_feature(modules)
 #if !__has_feature(modules)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-12 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 428981.
steplong added a comment.

- Updated line in docs


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function.c
  clang/test/Preprocessor/pragma_microsoft.c
  clang/test/Preprocessor/pragma_microsoft.cpp

Index: clang/test/Preprocessor/pragma_microsoft.cpp
===
--- clang/test/Preprocessor/pragma_microsoft.cpp
+++ clang/test/Preprocessor/pragma_microsoft.cpp
@@ -1,3 +1,7 @@
 // RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify -fms-extensions
 
 #pragma warning(push, 4_D) // expected-warning {{requires a level between 0 and 4}}
+
+extern "C" {
+#pragma function(memset) // no-warning
+}
Index: clang/test/Preprocessor/pragma_microsoft.c
===
--- clang/test/Preprocessor/pragma_microsoft.c
+++ clang/test/Preprocessor/pragma_microsoft.c
@@ -201,6 +201,27 @@
 #pragma clang diagnostic pop
 #pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
 
+// Test pragma function
+#pragma function(memset) // no-warning
+#pragma function(memcpy, strlen, strlen) // no-warning
+#pragma function()   // no-warning
+#pragma function(asdf)   // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+#pragma function(main)   // expected-warning {{'main' is not a recognized builtin; consider including }}
+#pragma function(// expected-warning {{missing ')' after}}
+#pragma function(int)// expected-warning {{missing ')' after}}
+#pragma function(strcmp) asdf// expected-warning {{extra tokens at end}}
+
+#define __INTRIN_H   // there should be no notes after defining __INTRIN_H
+#pragma function(asdf)   // expected-warning-re {{'asdf' is not a recognized builtin{{$
+#pragma function(memset) // no-warning
+#undef __INTRIN_H
+#pragma function(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+
+// MSVC accepts this, but we decide to reject it based on the MS docs saying the pragma must appear at the global level
+void pragma_function_foo() {
+#pragma function(memset) // expected-error {{'#pragma function' can only appear at file scope}}
+}
+
 #pragma optimize  // expected-warning{{missing '(' after '#pragma optimize'}}
 #pragma optimize( // expected-warning{{expected string literal in '#pragma optimize'}}
 #pragma optimize(a// expected-warning{{expected string literal in '#pragma optimize'}}
Index: clang/test/CodeGen/pragma-ms-function.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function.c
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -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);
+
+// CHECK: define{{.*}} void @foo1({{.*}}) #[[NO_NOBUILTIN:[0-9]+]]
+void foo1(char *s, char *d, size_t n) {
+  bar(s);
+  memset(s, 0, n);
+  memcpy(d, s, n);
+}
+
+#pragma function(strlen, memset)
+
+// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]]
+void foo2(char *s, char *d, size_t n) {
+  bar(s);
+  memset(s, 1, n);
+  memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]]
+void foo3(char *s, char *d, size_t n) {
+  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-NOT: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if we have to apply any
+  // attributes (i.e. optnone and no_builtin) due to

[PATCH] D125011: [MSVC] Add support for pragma alloc_text

2022-05-12 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 429000.
steplong added a comment.

- Added description in release notes
- Fixed up some comments in Sema.h

Will merge once build passes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125011/new/

https://reviews.llvm.org/D125011

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/msvc_pragma_alloc_text.cpp
  clang/test/Sema/pragma-ms-alloc-text.cpp

Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- /dev/null
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
+
+#pragma alloc_text()// expected-warning {{expected a string literal for the section name in '#pragma alloc_text'}}
+#pragma alloc_text(a// expected-warning {{expected ',' in '#pragma alloc_text'}}
+#pragma alloc_text(a, a // expected-warning {{missing ')' after '#pragma alloc_text'}}
+#pragma alloc_text(a, a)// expected-error {{use of undeclared a}}
+#pragma alloc_text(L"a", a) // expected-warning {{expected a string literal for the section name}}
+
+void foo();
+#pragma alloc_text(a, foo) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+
+extern "C" void foo1();
+#pragma alloc_text(a, foo1)  // no-warning
+#pragma alloc_text(a, foo1) asdf // expected-warning {{extra tokens at end of '#pragma alloc_text'}}
+#pragma alloc_text(a, foo1   // expected-warning {{missing ')' after '#pragma alloc_text'}}
+
+namespace N {
+#pragma alloc_text(b, foo1) // no-warning
+}
+
+extern "C" {
+void foo2();
+#pragma alloc_text(a, foo2) // no-warning
+}
+
+void foo3() {
+#pragma alloc_text(a, foo1) // expected-error {{'#pragma alloc_text' can only appear at file scope}}
+}
+
+extern "C" void foo4();
+#pragma alloc_text(c, foo4) // no-warning
+void foo4() {}
+
+void foo5();// expected-note {{previous declaration is here}}
+#pragma alloc_text(c, foo5) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+extern "C" void foo5() {}   // expected-error {{declaration of 'foo5' has a different language linkage}}
Index: clang/test/CodeGen/msvc_pragma_alloc_text.cpp
===
--- /dev/null
+++ clang/test/CodeGen/msvc_pragma_alloc_text.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fms-extensions -S -emit-llvm -o - %s | FileCheck %s
+
+extern "C" {
+
+void foo();
+void foo1();
+void foo2();
+void foo3();
+
+#pragma alloc_text("abc", foo, foo1)
+#pragma alloc_text("def", foo2)
+#pragma alloc_text("def", foo3)
+
+// CHECK-LABEL: define{{.*}} void @foo() {{.*}} section "abc"
+void foo() {}
+
+// CHECK-LABEL: define{{.*}} void @foo1() {{.*}} section "abc"
+void foo1() {}
+
+// CHECK-LABEL: define{{.*}} void @foo2() {{.*}} section "def"
+void foo2() {}
+
+// CHECK-LABEL: define{{.*}} void @foo3() {{.*}} section "def"
+void foo3() {}
+
+}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10220,8 +10220,10 @@
 
   // If this is a function definition, check if we have to apply optnone due to
   // a pragma.
-  if(D.isFunctionDefinition())
+  if(D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
+AddSectionMSAllocText(NewFD);
+  }
 
   // If this is the first declaration of an extern C variable, update
   // the map of such variables.
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -741,6 +741,37 @@
   CurInitSegLoc = PragmaLocation;
 }
 
+void Sema::ActOnPragmaMSAllocText(
+SourceLocation PragmaLocation, StringRef Section,
+const SmallVector>
+&Functions) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(PragmaLocation, diag::err_pragma_expected_file_scope) << "alloc_text";
+return;
+  }
+
+  for (auto &Function : Functions) {
+IdentifierInfo *II;
+SourceLocation Loc;
+std::tie(II, Loc) = Function;
+
+DeclarationName DN(II);
+NamedDecl *ND = LookupSingleName(TUScope, DN, Loc, LookupOrdinaryName);
+if (!ND) {
+  Diag(Loc, diag::err_undeclared_use) << II->getName();
+  return;
+}
+
+DeclContext *DC = ND->getDeclContext();
+if (!DC->isExternCContext()) {
+  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+  return;
+}
+
+FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc);
+  }
+}
+
 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
  SourceLocation Pragma

[PATCH] D124702: [MSVC] Add support for pragma function

2022-05-13 Thread Stephen Long via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3946de0456fc: [MSVC] Add support for pragma function 
(authored by steplong).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124702/new/

https://reviews.llvm.org/D124702

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-ms-function.c
  clang/test/Preprocessor/pragma_microsoft.c
  clang/test/Preprocessor/pragma_microsoft.cpp

Index: clang/test/Preprocessor/pragma_microsoft.cpp
===
--- clang/test/Preprocessor/pragma_microsoft.cpp
+++ clang/test/Preprocessor/pragma_microsoft.cpp
@@ -1,3 +1,7 @@
 // RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify -fms-extensions
 
 #pragma warning(push, 4_D) // expected-warning {{requires a level between 0 and 4}}
+
+extern "C" {
+#pragma function(memset) // no-warning
+}
Index: clang/test/Preprocessor/pragma_microsoft.c
===
--- clang/test/Preprocessor/pragma_microsoft.c
+++ clang/test/Preprocessor/pragma_microsoft.c
@@ -201,6 +201,27 @@
 #pragma clang diagnostic pop
 #pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
 
+// Test pragma function
+#pragma function(memset) // no-warning
+#pragma function(memcpy, strlen, strlen) // no-warning
+#pragma function()   // no-warning
+#pragma function(asdf)   // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+#pragma function(main)   // expected-warning {{'main' is not a recognized builtin; consider including }}
+#pragma function(// expected-warning {{missing ')' after}}
+#pragma function(int)// expected-warning {{missing ')' after}}
+#pragma function(strcmp) asdf// expected-warning {{extra tokens at end}}
+
+#define __INTRIN_H   // there should be no notes after defining __INTRIN_H
+#pragma function(asdf)   // expected-warning-re {{'asdf' is not a recognized builtin{{$
+#pragma function(memset) // no-warning
+#undef __INTRIN_H
+#pragma function(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including }}
+
+// MSVC accepts this, but we decide to reject it based on the MS docs saying the pragma must appear at the global level
+void pragma_function_foo() {
+#pragma function(memset) // expected-error {{'#pragma function' can only appear at file scope}}
+}
+
 #pragma optimize  // expected-warning{{missing '(' after '#pragma optimize'}}
 #pragma optimize( // expected-warning{{expected string literal in '#pragma optimize'}}
 #pragma optimize(a// expected-warning{{expected string literal in '#pragma optimize'}}
Index: clang/test/CodeGen/pragma-ms-function.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-ms-function.c
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -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);
+
+// CHECK: define{{.*}} void @foo1({{.*}}) #[[NO_NOBUILTIN:[0-9]+]]
+void foo1(char *s, char *d, size_t n) {
+  bar(s);
+  memset(s, 0, n);
+  memcpy(d, s, n);
+}
+
+#pragma function(strlen, memset)
+
+// CHECK: define{{.*}} void @foo2({{.*}}) #[[NOBUILTIN_MEMSET:[0-9]+]]
+void foo2(char *s, char *d, size_t n) {
+  bar(s);
+  memset(s, 1, n);
+  memcpy(d, s, n);
+}
+
+#pragma function(memcpy)
+
+// CHECK: define{{.*}} void @foo3({{.*}}) #[[NOBUILTIN_MEMSET_MEMCPY:[0-9]+]]
+void foo3(char *s, char *d, size_t n) {
+  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-NOT: attributes #[[NOBUILTIN_MEMSET]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #[[NOBUILTIN_MEMSET_MEMCPY]] = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10218,10 +10218,12 @@
   // marking the function.
   AddCFAuditedAttribute(NewFD);
 
-  // If this is a function definition, check if we have to apply optnone due to
-  // a pragma.
-  if(D.isFunctionDefinition())
+  // If this is a function definition, check if w

[PATCH] D125011: [MSVC] Add support for pragma alloc_text

2022-05-13 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 429261.
steplong added a comment.

- Rebased patch


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125011/new/

https://reviews.llvm.org/D125011

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/msvc_pragma_alloc_text.cpp
  clang/test/Sema/pragma-ms-alloc-text.cpp

Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- /dev/null
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
+
+#pragma alloc_text()// expected-warning {{expected a string literal for the section name in '#pragma alloc_text'}}
+#pragma alloc_text(a// expected-warning {{expected ',' in '#pragma alloc_text'}}
+#pragma alloc_text(a, a // expected-warning {{missing ')' after '#pragma alloc_text'}}
+#pragma alloc_text(a, a)// expected-error {{use of undeclared a}}
+#pragma alloc_text(L"a", a) // expected-warning {{expected a string literal for the section name}}
+
+void foo();
+#pragma alloc_text(a, foo) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+
+extern "C" void foo1();
+#pragma alloc_text(a, foo1)  // no-warning
+#pragma alloc_text(a, foo1) asdf // expected-warning {{extra tokens at end of '#pragma alloc_text'}}
+#pragma alloc_text(a, foo1   // expected-warning {{missing ')' after '#pragma alloc_text'}}
+
+namespace N {
+#pragma alloc_text(b, foo1) // no-warning
+}
+
+extern "C" {
+void foo2();
+#pragma alloc_text(a, foo2) // no-warning
+}
+
+void foo3() {
+#pragma alloc_text(a, foo1) // expected-error {{'#pragma alloc_text' can only appear at file scope}}
+}
+
+extern "C" void foo4();
+#pragma alloc_text(c, foo4) // no-warning
+void foo4() {}
+
+void foo5();// expected-note {{previous declaration is here}}
+#pragma alloc_text(c, foo5) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+extern "C" void foo5() {}   // expected-error {{declaration of 'foo5' has a different language linkage}}
Index: clang/test/CodeGen/msvc_pragma_alloc_text.cpp
===
--- /dev/null
+++ clang/test/CodeGen/msvc_pragma_alloc_text.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fms-extensions -S -emit-llvm -o - %s | FileCheck %s
+
+extern "C" {
+
+void foo();
+void foo1();
+void foo2();
+void foo3();
+
+#pragma alloc_text("abc", foo, foo1)
+#pragma alloc_text("def", foo2)
+#pragma alloc_text("def", foo3)
+
+// CHECK-LABEL: define{{.*}} void @foo() {{.*}} section "abc"
+void foo() {}
+
+// CHECK-LABEL: define{{.*}} void @foo1() {{.*}} section "abc"
+void foo1() {}
+
+// CHECK-LABEL: define{{.*}} void @foo2() {{.*}} section "def"
+void foo2() {}
+
+// CHECK-LABEL: define{{.*}} void @foo3() {{.*}} section "def"
+void foo3() {}
+
+}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10223,6 +10223,7 @@
   if (D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
 AddImplicitMSFunctionNoBuiltinAttr(NewFD);
+AddSectionMSAllocText(NewFD);
   }
 
   // If this is the first declaration of an extern C variable, update
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -741,6 +741,37 @@
   CurInitSegLoc = PragmaLocation;
 }
 
+void Sema::ActOnPragmaMSAllocText(
+SourceLocation PragmaLocation, StringRef Section,
+const SmallVector>
+&Functions) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(PragmaLocation, diag::err_pragma_expected_file_scope) << "alloc_text";
+return;
+  }
+
+  for (auto &Function : Functions) {
+IdentifierInfo *II;
+SourceLocation Loc;
+std::tie(II, Loc) = Function;
+
+DeclarationName DN(II);
+NamedDecl *ND = LookupSingleName(TUScope, DN, Loc, LookupOrdinaryName);
+if (!ND) {
+  Diag(Loc, diag::err_undeclared_use) << II->getName();
+  return;
+}
+
+DeclContext *DC = ND->getDeclContext();
+if (!DC->isExternCContext()) {
+  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+  return;
+}
+
+FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc);
+  }
+}
+
 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
  SourceLocation PragmaLoc) {
 
@@ -1082,6 +1113,22 @@
 AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
 }
 
+void Sema::AddSectionMSAllocText(FunctionDecl *FD) {
+  if (!FD->getIdentifier())
+return;

[PATCH] D125011: [MSVC] Add support for pragma alloc_text

2022-05-13 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 429320.
steplong added a comment.

- Clang-formatted. It didn't like the empty line before the bracket in 
clang/test/CodeGen/msvc_pragma_alloc_text.cpp


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125011/new/

https://reviews.llvm.org/D125011

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/msvc_pragma_alloc_text.cpp
  clang/test/Sema/pragma-ms-alloc-text.cpp

Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- /dev/null
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
+
+#pragma alloc_text()// expected-warning {{expected a string literal for the section name in '#pragma alloc_text'}}
+#pragma alloc_text(a// expected-warning {{expected ',' in '#pragma alloc_text'}}
+#pragma alloc_text(a, a // expected-warning {{missing ')' after '#pragma alloc_text'}}
+#pragma alloc_text(a, a)// expected-error {{use of undeclared a}}
+#pragma alloc_text(L"a", a) // expected-warning {{expected a string literal for the section name}}
+
+void foo();
+#pragma alloc_text(a, foo) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+
+extern "C" void foo1();
+#pragma alloc_text(a, foo1)  // no-warning
+#pragma alloc_text(a, foo1) asdf // expected-warning {{extra tokens at end of '#pragma alloc_text'}}
+#pragma alloc_text(a, foo1   // expected-warning {{missing ')' after '#pragma alloc_text'}}
+
+namespace N {
+#pragma alloc_text(b, foo1) // no-warning
+}
+
+extern "C" {
+void foo2();
+#pragma alloc_text(a, foo2) // no-warning
+}
+
+void foo3() {
+#pragma alloc_text(a, foo1) // expected-error {{'#pragma alloc_text' can only appear at file scope}}
+}
+
+extern "C" void foo4();
+#pragma alloc_text(c, foo4) // no-warning
+void foo4() {}
+
+void foo5();// expected-note {{previous declaration is here}}
+#pragma alloc_text(c, foo5) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+extern "C" void foo5() {}   // expected-error {{declaration of 'foo5' has a different language linkage}}
Index: clang/test/CodeGen/msvc_pragma_alloc_text.cpp
===
--- /dev/null
+++ clang/test/CodeGen/msvc_pragma_alloc_text.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -fms-extensions -S -emit-llvm -o - %s | FileCheck %s
+
+extern "C" {
+
+void foo();
+void foo1();
+void foo2();
+void foo3();
+
+#pragma alloc_text("abc", foo, foo1)
+#pragma alloc_text("def", foo2)
+#pragma alloc_text("def", foo3)
+
+// CHECK-LABEL: define{{.*}} void @foo() {{.*}} section "abc"
+void foo() {}
+
+// CHECK-LABEL: define{{.*}} void @foo1() {{.*}} section "abc"
+void foo1() {}
+
+// CHECK-LABEL: define{{.*}} void @foo2() {{.*}} section "def"
+void foo2() {}
+
+// CHECK-LABEL: define{{.*}} void @foo3() {{.*}} section "def"
+void foo3() {}
+}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10223,6 +10223,7 @@
   if (D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
 AddImplicitMSFunctionNoBuiltinAttr(NewFD);
+AddSectionMSAllocText(NewFD);
   }
 
   // If this is the first declaration of an extern C variable, update
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -741,6 +741,37 @@
   CurInitSegLoc = PragmaLocation;
 }
 
+void Sema::ActOnPragmaMSAllocText(
+SourceLocation PragmaLocation, StringRef Section,
+const SmallVector>
+&Functions) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(PragmaLocation, diag::err_pragma_expected_file_scope) << "alloc_text";
+return;
+  }
+
+  for (auto &Function : Functions) {
+IdentifierInfo *II;
+SourceLocation Loc;
+std::tie(II, Loc) = Function;
+
+DeclarationName DN(II);
+NamedDecl *ND = LookupSingleName(TUScope, DN, Loc, LookupOrdinaryName);
+if (!ND) {
+  Diag(Loc, diag::err_undeclared_use) << II->getName();
+  return;
+}
+
+DeclContext *DC = ND->getDeclContext();
+if (!DC->isExternCContext()) {
+  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+  return;
+}
+
+FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc);
+  }
+}
+
 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
  SourceLocation PragmaLoc) {
 
@@ -1082,6 +1113,22 @@
 AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);

[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-16 Thread Stephen Long via Phabricator via cfe-commits
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(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/AttrDo

[PATCH] D125011: [MSVC] Add support for pragma alloc_text

2022-05-16 Thread Stephen Long via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb147717bb36c: [MSVC] Add support for pragma alloc_text 
(authored by steplong).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125011/new/

https://reviews.llvm.org/D125011

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/msvc_pragma_alloc_text.cpp
  clang/test/Sema/pragma-ms-alloc-text.cpp

Index: clang/test/Sema/pragma-ms-alloc-text.cpp
===
--- /dev/null
+++ clang/test/Sema/pragma-ms-alloc-text.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
+
+#pragma alloc_text()// expected-warning {{expected a string literal for the section name in '#pragma alloc_text'}}
+#pragma alloc_text(a// expected-warning {{expected ',' in '#pragma alloc_text'}}
+#pragma alloc_text(a, a // expected-warning {{missing ')' after '#pragma alloc_text'}}
+#pragma alloc_text(a, a)// expected-error {{use of undeclared a}}
+#pragma alloc_text(L"a", a) // expected-warning {{expected a string literal for the section name}}
+
+void foo();
+#pragma alloc_text(a, foo) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+
+extern "C" void foo1();
+#pragma alloc_text(a, foo1)  // no-warning
+#pragma alloc_text(a, foo1) asdf // expected-warning {{extra tokens at end of '#pragma alloc_text'}}
+#pragma alloc_text(a, foo1   // expected-warning {{missing ')' after '#pragma alloc_text'}}
+
+namespace N {
+#pragma alloc_text(b, foo1) // no-warning
+}
+
+extern "C" {
+void foo2();
+#pragma alloc_text(a, foo2) // no-warning
+}
+
+void foo3() {
+#pragma alloc_text(a, foo1) // expected-error {{'#pragma alloc_text' can only appear at file scope}}
+}
+
+extern "C" void foo4();
+#pragma alloc_text(c, foo4) // no-warning
+void foo4() {}
+
+void foo5();// expected-note {{previous declaration is here}}
+#pragma alloc_text(c, foo5) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}}
+extern "C" void foo5() {}   // expected-error {{declaration of 'foo5' has a different language linkage}}
Index: clang/test/CodeGen/msvc_pragma_alloc_text.cpp
===
--- /dev/null
+++ clang/test/CodeGen/msvc_pragma_alloc_text.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -fms-extensions -S -emit-llvm -o - %s | FileCheck %s
+
+extern "C" {
+
+void foo();
+void foo1();
+void foo2();
+void foo3();
+
+#pragma alloc_text("abc", foo, foo1)
+#pragma alloc_text("def", foo2)
+#pragma alloc_text("def", foo3)
+
+// CHECK-LABEL: define{{.*}} void @foo() {{.*}} section "abc"
+void foo() {}
+
+// CHECK-LABEL: define{{.*}} void @foo1() {{.*}} section "abc"
+void foo1() {}
+
+// CHECK-LABEL: define{{.*}} void @foo2() {{.*}} section "def"
+void foo2() {}
+
+// CHECK-LABEL: define{{.*}} void @foo3() {{.*}} section "def"
+void foo3() {}
+}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10219,6 +10219,7 @@
   if (D.isFunctionDefinition()) {
 AddRangeBasedOptnone(NewFD);
 AddImplicitMSFunctionNoBuiltinAttr(NewFD);
+AddSectionMSAllocText(NewFD);
   }
 
   // If this is the first declaration of an extern C variable, update
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -741,6 +741,37 @@
   CurInitSegLoc = PragmaLocation;
 }
 
+void Sema::ActOnPragmaMSAllocText(
+SourceLocation PragmaLocation, StringRef Section,
+const SmallVector>
+&Functions) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(PragmaLocation, diag::err_pragma_expected_file_scope) << "alloc_text";
+return;
+  }
+
+  for (auto &Function : Functions) {
+IdentifierInfo *II;
+SourceLocation Loc;
+std::tie(II, Loc) = Function;
+
+DeclarationName DN(II);
+NamedDecl *ND = LookupSingleName(TUScope, DN, Loc, LookupOrdinaryName);
+if (!ND) {
+  Diag(Loc, diag::err_undeclared_use) << II->getName();
+  return;
+}
+
+DeclContext *DC = ND->getDeclContext();
+if (!DC->isExternCContext()) {
+  Diag(Loc, diag::err_pragma_alloc_text_c_linkage);
+  return;
+}
+
+FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc);
+  }
+}
+
 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
  SourceLocation PragmaLoc) {
 
@@ -1082,6 +1113,22 @@
 AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
 }
 
+void Sema::Add

[PATCH] D125719: [Attribute] Add attribute NeverOptimizeNone

2022-05-16 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Add NeverOptimizeNone to facilitate removing OptimizeNone. This allows
us to remove OptimizeNone even if -O0 is passed on the cmdline


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D125719

Files:
  clang/include/clang/Basic/Attr.td
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Sema/SemaDeclAttr.cpp


Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -8519,6 +8519,9 @@
   case ParsedAttr::AT_OptimizeNone:
 handleOptimizeNoneAttr(S, D, AL);
 break;
+  case ParsedAttr::AT_NeverOptimizeNone:
+handleSimpleAttribute(S, D, AL);
+break;
   case ParsedAttr::AT_EnumExtensibility:
 handleEnumExtensibilityAttr(S, D, AL);
 break;
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -1928,7 +1928,8 @@
   ShouldAddOptNone &= !D->hasAttr();
 
   // Add optnone, but do so only if the function isn't always_inline.
-  if ((ShouldAddOptNone || D->hasAttr()) &&
+  if (!D->hasAttr() &&
+  (ShouldAddOptNone || D->hasAttr()) &&
   !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
 B.addAttribute(llvm::Attribute::OptimizeNone);
 
Index: clang/include/clang/Basic/Attr.td
===
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -2255,6 +2255,13 @@
   let Documentation = [OptnoneDocs];
 }
 
+def NeverOptimizeNone : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let Subjects = SubjectList<[Function]>;
+  let Documentation = [Undocumented];
+}
+
 def Overloadable : Attr {
   let Spellings = [Clang<"overloadable">];
   let Subjects = SubjectList<[Function], ErrorDiag>;


Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -8519,6 +8519,9 @@
   case ParsedAttr::AT_OptimizeNone:
 handleOptimizeNoneAttr(S, D, AL);
 break;
+  case ParsedAttr::AT_NeverOptimizeNone:
+handleSimpleAttribute(S, D, AL);
+break;
   case ParsedAttr::AT_EnumExtensibility:
 handleEnumExtensibilityAttr(S, D, AL);
 break;
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -1928,7 +1928,8 @@
   ShouldAddOptNone &= !D->hasAttr();
 
   // Add optnone, but do so only if the function isn't always_inline.
-  if ((ShouldAddOptNone || D->hasAttr()) &&
+  if (!D->hasAttr() &&
+  (ShouldAddOptNone || D->hasAttr()) &&
   !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
 B.addAttribute(llvm::Attribute::OptimizeNone);
 
Index: clang/include/clang/Basic/Attr.td
===
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -2255,6 +2255,13 @@
   let Documentation = [OptnoneDocs];
 }
 
+def NeverOptimizeNone : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let Subjects = SubjectList<[Function]>;
+  let Documentation = [Undocumented];
+}
+
 def Overloadable : Attr {
   let Spellings = [Clang<"overloadable">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D125720: [Attribute] Add clang frame_pointer attribute

2022-05-16 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Add the ability to put __attribute__((frame_pointer(arg))) on functions.
arg is only allowed to be none, non_leaf, or all. Depends on D125719 
.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D125720

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Sema/SemaDeclAttr.cpp

Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -6763,6 +6763,24 @@
 checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr);
 }
 
+static void handleFramePointer(Sema &S, Decl *D, const ParsedAttr &AL) {
+  if (!AL.isArgIdent(0)) {
+S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+<< AL << 1 << AANT_ArgumentIdentifier;
+return;
+  }
+
+  FramePointerAttr::Kind Kind;
+  IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
+  if (!FramePointerAttr::ConvertStrToKind(II->getName(), Kind)) {
+S.Diag(AL.getLoc(), diag::warn_frame_pointer_type_not_supported) << AL
+ << II;
+return;
+  }
+
+  D->addAttr(::new (S.Context) FramePointerAttr(S.Context, AL, Kind));
+}
+
 //===--===//
 // Microsoft specific attribute handlers.
 //===--===//
@@ -9031,6 +9049,10 @@
   case ParsedAttr::AT_UsingIfExists:
 handleSimpleAttribute(S, D, AL);
 break;
+
+  case ParsedAttr::AT_FramePointer:
+handleFramePointer(S, D, AL);
+break;
   }
 }
 
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -1650,6 +1650,24 @@
  /*AttrOnCallSite=*/false, IsThunk);
   F->setAttributes(PAL);
   F->setCallingConv(static_cast(CallingConv));
+  if (!GD.getDecl())
+return;
+
+  if (GD.getDecl()->hasAttr()) {
+F->removeFnAttr("frame-pointer");
+FramePointerAttr *Attr = GD.getDecl()->getAttr();
+switch (Attr->getKind()) {
+case FramePointerAttr::None:
+  F->addFnAttr("frame-pointer", "none");
+  break;
+case FramePointerAttr::NonLeaf:
+  F->addFnAttr("frame-pointer", "non-leaf");
+  break;
+case FramePointerAttr::All:
+  F->addFnAttr("frame-pointer", "all");
+  break;
+}
+  }
 }
 
 static void removeImageAccessQualifier(std::string& TyName) {
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11633,4 +11633,8 @@
   "a randomized struct can only be initialized with a designated initializer">;
 def err_cast_from_randomized_struct : Error<
   "casting from randomized structure pointer type %0 to %1">;
+
+def warn_frame_pointer_type_not_supported : Warning<
+  "%0 frame_pointer argument not supported: %1">,
+  InGroup;
 } // end of sema component.
Index: clang/include/clang/Basic/Attr.td
===
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -1441,6 +1441,16 @@
   let Documentation = [Undocumented];
 }
 
+def FramePointer : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let Subjects = SubjectList<[Function]>;
+  let Args = [EnumArgument<"Kind", "Kind",
+["none", "non_leaf", "all"],
+["None", "NonLeaf", "All"]>];
+  let Documentation = [Undocumented];
+}
+
 def FlagEnum : InheritableAttr {
   let Spellings = [Clang<"flag_enum">];
   let Subjects = SubjectList<[Enum]>;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D125722: [Attribute] Add clang optsize attribute

2022-05-16 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Add the ability to put `__attribute__((optsize))` on functions. Depends on 
D125720 .


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D125722

Files:
  clang/include/clang/Basic/Attr.td
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Sema/SemaDeclAttr.cpp


Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -6763,6 +6763,19 @@
 checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr);
 }
 
+static void handleOptimizeSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  if (!AL.isArgIdent(0)) {
+S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+<< AL << 1 << AANT_ArgumentIdentifier;
+return;
+  }
+
+  OptimizeSizeAttr::Kind Kind;
+  IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
+  OptimizeSizeAttr::ConvertStrToKind(II->getName(), Kind);
+  D->addAttr(::new (S.Context) OptimizeSizeAttr(S.Context, AL, Kind));
+}
+
 static void handleFramePointer(Sema &S, Decl *D, const ParsedAttr &AL) {
   if (!AL.isArgIdent(0)) {
 S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
@@ -8534,6 +8547,9 @@
   case ParsedAttr::AT_MinSize:
 handleMinSizeAttr(S, D, AL);
 break;
+  case ParsedAttr::AT_OptimizeSize:
+handleOptimizeSizeAttr(S, D, AL);
+break;
   case ParsedAttr::AT_OptimizeNone:
 handleOptimizeNoneAttr(S, D, AL);
 break;
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -1653,6 +1653,19 @@
   if (!GD.getDecl())
 return;
 
+  bool HasOptnone = GD.getDecl()->hasAttr();
+  bool HasOptsizeOn = false;
+  bool HasOptsizeOff = false;
+  if (GD.getDecl()->hasAttr()) {
+OptimizeSizeAttr *Attr = GD.getDecl()->getAttr();
+HasOptsizeOn = Attr->getKind() == OptimizeSizeAttr::On;
+HasOptsizeOff = Attr->getKind() == OptimizeSizeAttr::Off;
+  }
+  if (HasOptsizeOn && !HasOptnone)
+F->addFnAttr(llvm::Attribute::OptimizeForSize);
+  if (HasOptsizeOff)
+F->removeFnAttr(llvm::Attribute::OptimizeForSize);
+
   if (GD.getDecl()->hasAttr()) {
 F->removeFnAttr("frame-pointer");
 FramePointerAttr *Attr = GD.getDecl()->getAttr();
Index: clang/include/clang/Basic/Attr.td
===
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -1451,6 +1451,16 @@
   let Documentation = [Undocumented];
 }
 
+def OptimizeSize: InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let Subjects = SubjectList<[Function]>;
+  let Args = [EnumArgument<"Kind", "Kind",
+["off", "on"],
+["Off", "On"]>];
+  let Documentation = [Undocumented];
+}
+
 def FlagEnum : InheritableAttr {
   let Spellings = [Clang<"flag_enum">];
   let Subjects = SubjectList<[Enum]>;


Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -6763,6 +6763,19 @@
 checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr);
 }
 
+static void handleOptimizeSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  if (!AL.isArgIdent(0)) {
+S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+<< AL << 1 << AANT_ArgumentIdentifier;
+return;
+  }
+
+  OptimizeSizeAttr::Kind Kind;
+  IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
+  OptimizeSizeAttr::ConvertStrToKind(II->getName(), Kind);
+  D->addAttr(::new (S.Context) OptimizeSizeAttr(S.Context, AL, Kind));
+}
+
 static void handleFramePointer(Sema &S, Decl *D, const ParsedAttr &AL) {
   if (!AL.isArgIdent(0)) {
 S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
@@ -8534,6 +8547,9 @@
   case ParsedAttr::AT_MinSize:
 handleMinSizeAttr(S, D, AL);
 break;
+  case ParsedAttr::AT_OptimizeSize:
+handleOptimizeSizeAttr(S, D, AL);
+break;
   case ParsedAttr::AT_OptimizeNone:
 handleOptimizeNoneAttr(S, D, AL);
 break;
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -1653,6 +1653,19 @@
   if (!GD.getDecl())
 return;
 
+  bool HasOptnone = GD.getDecl()->hasAttr();
+  bool HasOptsizeOn = false;
+  bool HasOptsizeOff = false;
+  if (GD.getDecl()->hasAttr()) {
+OptimizeSizeAttr *Attr = GD.getDecl()->getAttr();
+HasOptsizeOn = Attr->getKind() == OptimizeSizeAttr::On;
+HasOptsizeOff = Attr->getKind() == OptimizeSizeAttr::O

[PATCH] D125723: [MSVC] Add support for MSVC pragma optimize

2022-05-16 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

MSVC's pragma optimize turns optimizations on or off based on the list
passed. Depends on D125722 .

>From MSVC's docs:
+---+-+

| Parameter | Type of optimization |
|

+---+-+

| g | Enable global optimizations. Deprecated |
|

+---+-+

| s or t | Specify short or fast sequences of machine code |
|

+---+-+

| y | Generate frame pointers on the program stack |
|

+---+-+

https://docs.microsoft.com/en-us/cpp/preprocessor/optimize?view=msvc-170


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D125723

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-msvc-optimize.c
  clang/test/Preprocessor/pragma_microsoft.c

Index: clang/test/Preprocessor/pragma_microsoft.c
===
--- clang/test/Preprocessor/pragma_microsoft.c
+++ clang/test/Preprocessor/pragma_microsoft.c
@@ -228,7 +228,12 @@
 #pragma optimize("g"  // expected-warning{{expected ',' in '#pragma optimize'}}
 #pragma optimize("g", // expected-warning{{missing argument to '#pragma optimize'; expected 'on' or 'off'}}
 #pragma optimize("g",xyz  // expected-warning{{unexpected argument 'xyz' to '#pragma optimize'; expected 'on' or 'off'}}
-#pragma optimize("g",on)  // expected-warning{{#pragma optimize' is not supported}}
+#pragma optimize("g",on)  // no-warning
+#pragma optimize("g", on) asdf // expected-warning{{extra tokens at end of '#pragma optimize'}}
+
+void pragma_optimize_foo() {
+#pragma optimize("g", on) // expected-error {{'#pragma optimize' can only appear at file scope}}
+}
 
 #pragma execution_character_set // expected-warning {{expected '('}}
 #pragma execution_character_set(// expected-warning {{expected 'push' or 'pop'}}
Index: clang/test/CodeGen/pragma-msvc-optimize.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-msvc-optimize.c
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -O2 -emit-llvm -fms-extensions -o - %s | FileCheck %s -check-prefix CHECK-O2
+// RUN: %clang_cc1 -O0 -emit-llvm -fms-extensions -o - %s | FileCheck %s -check-prefix CHECK-O0
+// RUN: %clang_cc1 -Os -emit-llvm -fms-extensions -o - %s | FileCheck %s -check-prefix CHECK-Os
+
+#pragma optimize("s", on)
+
+// CHECK-O2: define{{.*}} void @f0(){{.*}} #[[OPTSIZE:[0-9]+]]
+void f0() {}
+
+#pragma optimize("y", on)
+
+// CHECK-O2: define{{.*}} void @f1(){{.*}} #[[OPTSIZE_FRAMEPTR_NONLEAF:[0-9]+]]
+void f1() {}
+
+#pragma optimize("t", on)
+
+// CHECK-O2: define{{.*}} void @f2(){{.*}} #[[OPTSIZE_FRAMEPTR_NONLEAF]]
+// CHECK-O0: define{{.*}} void @f2(){{.*}} #[[NO_OPTNONE:[0-9]+]]
+void f2() {}
+
+#pragma optimize("s", off)
+
+// CHECK-O2: define{{.*}} void @f3(){{.*}} #[[FRAMEPTR_NONLEAF:[0-9]+]]
+// CHECK-Os: define{{.*}} void @f3(){{.*}} #[[FRAMEPTR_NONLEAF:[0-9]+]]
+void f3() {}
+
+#pragma optimize("y", off)
+
+// CHECK-O2: define{{.*}} void @f4(){{.*}} #[[FRAMEPTR_NONE:[0-9]+]]
+void f4() {}
+
+#pragma optimize("t", off)
+
+// CHECK-O2: define{{.*}} void @f5(){{.*}} #[[OPTNONE_FRAMEPTR_NONE:[0-9]+]]
+void f5() {}
+
+// CHECK-O2: attributes #[[OPTSIZE]] = {{{.*}}optsize{{.*}}}
+// CHECK-O2-NOT: attributes #[[OPTSIZE]] = {{{.*}}optsize{{.*}}"frame-pointer"="non-leaf"{{.*}}}
+// CHECK-O2: attributes #[[OPTSIZE_FRAMEPTR_NONLEAF]] = {{{.*}}optsize{{.*}}"frame-pointer"="non-leaf"{{.*}}}
+// CHECK-O2: attributes #[[FRAMEPTR_NONLEAF]] = {{{.*}}"frame-pointer"="non-leaf"{{.*}}}
+// CHECK-O2-NOT: attributes #[[FRAMEPTR_NONLEAF]] = {{{.*}}optsize{{.*}}"frame-pointer"="non-leaf"{{.*}}}
+// CHECK-O2: attributes #[[FRAMEPTR_NONE]] = {{{.*}}"frame-pointer"="none"{{.*}}}
+// CHECK-O2: attributes #[[OPTNONE_FRAMEPTR_NONE]] = {{{.*}}optnone{{.*}}"frame-pointer"="none"{{.*}}}
+
+// CHECK-O0-NOT: attributes #[[NO_OPTNONE]] = {{{.*}}optnone{{.*}}}
+
+// CHECK-Os: attributes #[[FRAMEPTR_NONLEAF]] = {{{.*}}"frame-pointer"="non-leaf"{{.*}}}
+// CHECK-Os-NOT: attributes #[[FRAMEPTR_NONLEAF]] = {{{.*}}optsize{{.*}}"frame-pointer"="non-leaf"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10220,6 +10220,7 @@
 AddRangeBasedOptnone(NewFD);
 AddImplicitMSFunctionNoBuiltinAttr(NewFD);
 AddSectionMSAllocText(NewFD);

[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-17 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/test/CodeGen/no-builtin-2.c:51
+// CHECK:   {{.*}}call {{.*}} @memmove
+void foo4(char *s, char *d, size_t n) __attribute__((no_builtin("*"))) {
+  bar(s);

hans wrote:
> In AttrDocs.td it says the wildcard case is spelled 
> "__attribute__((no_builtin))".
Ah whoops, missed that. I don't think I need the changes in SemaDeclAttr.cpp 
then. Thanks for catching this!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124701/new/

https://reviews.llvm.org/D124701

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


[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-17 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 430060.
steplong added a comment.

- Removed `__attribute__((no_builtin("*")))` from test
- Remove the logic that accepted `__attribute__((no_builtin("*")))`


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/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/CodeGen/CGExpr.cpp
===
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -5034,7 +5034,16 @@
   const FunctionDecl *FD = cast(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 virtu

[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-18 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 430365.
steplong added a comment.

- Fixed comment about __attribute__((no_builtin))


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/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/CodeGen/CGExpr.cpp
===
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -5034,7 +5034,16 @@
   const FunctionDecl *FD = cast(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/doc

[PATCH] D126023: [MSVC, ARM64] Add __writex18 intrinsics

2022-05-19 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
Herald added a subscriber: kristof.beyls.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

https://docs.microsoft.com/en-us/cpp/intrinsics/arm64-intrinsics?view=msvc-170

  void __writex18byte(unsigned long, unsigned char)
  void __writex18word(unsigned long, unsigned short)
  void __writex18dword(unsigned long, unsigned long)
  void __writex18qword(unsigned long, unsigned __int64)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D126023

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -176,5 +176,69 @@
 // CHECK-MSVC: %[[RETVAL:.*]] = load i64, i64 addrspace(256)* %[[PTR]], align 8
 // CHECK-MSVC: ret i64 %[[RETVAL]]
 
+void check__writex18byte(unsigned long offset, unsigned char data) {
+  __writex18byte(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i8, align 1
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i8 %data, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i8, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i8 %[[DATA]], i8 addrspace(256)* %[[PTR]], align 1
+
+void check__writex18word(unsigned long offset, unsigned short data) {
+  __writex18word(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i16, align 2
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i16 %data, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i16 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i16, i16 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i16, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i16 %[[DATA]], i16 addrspace(256)* %[[PTR]], align 1
+
+void check__writex18dword(unsigned long offset, unsigned long data) {
+  __writex18dword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %data, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i32 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i32, i32 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i32, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %[[DATA]], i32 addrspace(256)* %[[PTR]], align 1
+
+void check__writex18qword(unsigned long offset, unsigned __int64 data) {
+  __writex18qword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i64, align 8
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i64 %data, i64* %[[DATA_ADDR]], align 8
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i64 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i64, i64 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i64, i64* %[[DATA_ADDR]], align 8
+// CHECK-MSVC: store i64 %[[DATA]], i64 addrspace(256)* %[[PTR]], align 1
+
 // CHECK-MSVC: ![[MD2]] = !{!"x18"}
 // CHECK-MSVC: ![[MD3]] = !{!"sp"}
Index: clang/lib/Headers/intrin.h
===
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -567,

[PATCH] D126023: [MSVC, ARM64] Add __writex18 intrinsics

2022-05-19 Thread Stephen Long via Phabricator via cfe-commits
steplong added reviewers: hans, rnk, efriedma, thakis, mstorsjo.
steplong added a comment.

The generated assembly is a little different from MSVC's:

  MSVC  
LLVM
  __writex18byte:
strbw1, [x18, x0] 
strbw1, [x18, w0, uxtw]
  __writex18word:
strhw1, [x18, x0] 
strhw1, [x18, w0, uxtw #1]
  __writex18dword:
str w1, [x18, x0]  
str w1, [x18, w0, uxtw #2]
  __writex18qword:
str x1, [x18, x0]  
str x1, [x18, w0, uxtw #3]


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126023/new/

https://reviews.llvm.org/D126023

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


[PATCH] D126024: [MSVC, ARM64] Add __readx18 intrinsics

2022-05-19 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
Herald added a subscriber: kristof.beyls.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

https://docs.microsoft.com/en-us/cpp/intrinsics/arm64-intrinsics?view=msvc-170

  unsigned char __readx18byte(unsigned long)
  unsigned short __readx18word(unsigned long)
  unsigned long __readx18dword(unsigned long)
  unsigned __int64 __readx18qword(unsigned long)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D126024

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -119,5 +119,62 @@
 
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+
+unsigned char check__readx18byte(unsigned long offset) {
+  return __readx18byte(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[RETVAL:.*]] = load i8, i8 addrspace(256)* %[[PTR]], align 1
+// CHECK-MSVC: ret i8 %[[RETVAL]]
+
+unsigned short check__readx18word(unsigned long offset) {
+  return __readx18word(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i16 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i16, i16 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[RETVAL:.*]] = load i16, i16 addrspace(256)* %[[PTR]], align 2
+// CHECK-MSVC: ret i16 %[[RETVAL]]
+
+unsigned long check__readx18dword(unsigned long offset) {
+  return __readx18dword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i32 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i32, i32 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[RETVAL:.*]] = load i32, i32 addrspace(256)* %[[PTR]], align 4
+// CHECK-MSVC: ret i32 %[[RETVAL]]
+
+unsigned __int64 check__readx18qword(unsigned long offset) {
+  return __readx18qword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i64 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i64, i64 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[RETVAL:.*]] = load i64, i64 addrspace(256)* %[[PTR]], align 8
+// CHECK-MSVC: ret i64 %[[RETVAL]]
+
 // CHECK-MSVC: ![[MD2]] = !{!"x18"}
 // CHECK-MSVC: ![[MD3]] = !{!"sp"}
Index: clang/lib/Headers/intrin.h
===
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -562,6 +562,11 @@
 unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b);
 
 void __break(int);
+
+unsigned char __readx18byte(unsigned long offset);
+unsigned short __readx18word(unsigned long offset);
+unsigned long __readx18dword(unsigned long offset);
+unsigned __int64 __readx18qword(unsigned long offset);
 #endif
 
 /**\
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -9952,6 +9952,30 @@
 return H

[PATCH] D126024: [MSVC, ARM64] Add __readx18 intrinsics

2022-05-19 Thread Stephen Long via Phabricator via cfe-commits
steplong added reviewers: hans, mstorsjo, rnk, efriedma, thakis.
steplong added a comment.

Like D126023 , the generated assembly for 
MSVC is slightly different:

  MSVC  
LLVM
  __readx18byte:
ldrbw0, [x18, x0] 
ldrbw0, [x18, w0, uxtw] 
  __readx18word:
ldrhw0, [x18, x0] 
ldrhw0, [x18, w0, uxtw #1]
  __readx18dword:
ldr w0, [x18, x0] 
ldr w0, [x18, w0, uxtw #2]
  __readx18qword:
ldr x0, [x18, x0]  
ldr x0, [x18, w0, uxtw #3]


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126024/new/

https://reviews.llvm.org/D126024

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


[PATCH] D126023: [MSVC, ARM64] Add __writex18 intrinsics

2022-05-19 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 430831.
steplong added a comment.

- Rebased it on top of main instead of D126024 



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126023/new/

https://reviews.llvm.org/D126023

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -119,5 +119,70 @@
 
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+
+void check__writex18byte(unsigned long offset, unsigned char data) {
+  __writex18byte(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i8, align 1
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i8 %data, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i8, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i8 %[[DATA]], i8 addrspace(256)* %[[PTR]], align 1
+
+void check__writex18word(unsigned long offset, unsigned short data) {
+  __writex18word(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i16, align 2
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i16 %data, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i16 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i16, i16 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i16, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i16 %[[DATA]], i16 addrspace(256)* %[[PTR]], align 1
+
+void check__writex18dword(unsigned long offset, unsigned long data) {
+  __writex18dword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %data, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i32 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i32, i32 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i32, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %[[DATA]], i32 addrspace(256)* %[[PTR]], align 1
+
+void check__writex18qword(unsigned long offset, unsigned __int64 data) {
+  __writex18qword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i64, align 8
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i64 %data, i64* %[[DATA_ADDR]], align 8
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i64 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i64, i64 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i64, i64* %[[DATA_ADDR]], align 8
+// CHECK-MSVC: store i64 %[[DATA]], i64 addrspace(256)* %[[PTR]], align 1
+
 // CHECK-MSVC: ![[MD2]] = !{!"x18"}
 // CHECK-MSVC: ![[MD3]] = !{!"sp"}
Index: clang/lib/Headers/intrin.h
===
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -562,6 +562,11 @@
 unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b);
 
 void __break(int);
+
+void __writex18byte(unsigned long offset, unsigned char data);
+void __writex18word(unsigned long offset, unsigned short data);
+void __writex18dword(uns

[PATCH] D124701: [clang] Honor __attribute__((no_builtin("foo"))) on functions

2022-05-20 Thread Stephen Long via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGae80024fbe51: [clang] Honor 
__attribute__((no_builtin("foo"))) on functions (authored by 
steplong).

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/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/CodeGen/CGExpr.cpp
===
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -5034,7 +5034,16 @@
   const FunctionDecl *FD = cast(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 fun

[PATCH] D126023: [MSVC, ARM64] Add __writex18 intrinsics

2022-05-20 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 430979.
steplong added a comment.

The assembly for LLVM now looks like:

  __writex18byte:
  strbw1, [x18, w0, uxtw]
  ret
  
  __writex18word:
  strhw1, [x18, w0, uxtw]
  ret
  
  __writex18dword:
  str w1, [x18, w0, uxtw]
  ret
  
  __writex18qword:
  str x1, [x18, w0, uxtw]
  ret


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126023/new/

https://reviews.llvm.org/D126023

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -119,5 +119,73 @@
 
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+
+void check__writex18byte(unsigned long offset, unsigned char data) {
+  __writex18byte(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i8, align 1
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i8 %data, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i8, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i8 %[[DATA]], i8 addrspace(256)* %[[PTR]], align 1
+
+void check__writex18word(unsigned long offset, unsigned short data) {
+  __writex18word(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i16, align 2
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i16 %data, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8 addrspace(256)* %[[PTR]] to i16 addrspace(256)*
+// CHECK-MSVC: %[[DATA:.*]] = load i16, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i16 %[[DATA]], i16 addrspace(256)* %[[BITCAST_PTR]], align 1
+
+void check__writex18dword(unsigned long offset, unsigned long data) {
+  __writex18dword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %data, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8 addrspace(256)* %[[PTR]] to i32 addrspace(256)*
+// CHECK-MSVC: %[[DATA:.*]] = load i32, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %[[DATA]], i32 addrspace(256)* %[[BITCAST_PTR]], align 1
+
+void check__writex18qword(unsigned long offset, unsigned __int64 data) {
+  __writex18qword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i64, align 8
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i64 %data, i64* %[[DATA_ADDR]], align 8
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8 addrspace(256)* %[[PTR]] to i

[PATCH] D126024: [MSVC, ARM64] Add __readx18 intrinsics

2022-05-20 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 430994.
steplong added a comment.

The assembly for LLVM is now:

  __readx18byte:
 ldrbw0, [x18, w0, uxtw]
  __readx18word:
 ldrhw0, [x18, w0, uxtw]
  __readx18dword:
 ldr w0, [x18, w0, uxtw]
  __readx18qword:
 ldr x0, [x18, w0, uxtw]


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126024/new/

https://reviews.llvm.org/D126024

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -119,5 +119,65 @@
 
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+
+unsigned char check__readx18byte(unsigned long offset) {
+  return __readx18byte(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[RETVAL:.*]] = load i8, i8 addrspace(256)* %[[PTR]], align 1
+// CHECK-MSVC: ret i8 %[[RETVAL]]
+
+unsigned short check__readx18word(unsigned long offset) {
+  return __readx18word(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8 addrspace(256)* %[[PTR]] to i16 addrspace(256)*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i16, i16 addrspace(256)* %[[BITCAST_PTR]], align 2
+// CHECK-MSVC: ret i16 %[[RETVAL]]
+
+unsigned long check__readx18dword(unsigned long offset) {
+  return __readx18dword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8 addrspace(256)* %[[PTR]] to i32 addrspace(256)*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i32, i32 addrspace(256)* %[[BITCAST_PTR]], align 4
+// CHECK-MSVC: ret i32 %[[RETVAL]]
+
+unsigned __int64 check__readx18qword(unsigned long offset) {
+  return __readx18qword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8 addrspace(256)*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8 addrspace(256)* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8 addrspace(256)* %[[PTR]] to i64 addrspace(256)*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i64, i64 addrspace(256)* %[[BITCAST_PTR]], align 8
+// CHECK-MSVC: ret i64 %[[RETVAL]]
+
 // CHECK-MSVC: ![[MD2]] = !{!"x18"}
 // CHECK-MSVC: ![[MD3]] = !{!"sp"}
Index: clang/lib/Headers/intrin.h
===
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -562,6 +562,11 @@
 unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b);
 
 void __break(int);
+
+unsigned char __readx18byte(unsigned long offset);
+unsigned short __readx18word(unsigned long offset);
+unsigned long __readx18dword(unsigned long offset);
+unsigned __int64 __readx18qword(unsigned long offset);
 #endif
 
 /**\
Inde

[PATCH] D126023: [MSVC, ARM64] Add __writex18 intrinsics

2022-05-20 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

In D126023#3528077 , @rnk wrote:

> I was unable to find any documentation for the meaning of AArch64 
> addrspace(256), and I wasn't able to figure it out after studying the code in 
> llvm/lib/Target/AArch64 for ten minutes or so. The change seems fine, but 
> please add some documentation as a follow-up. X86 has some of its address 
> spaces documented here, not that this is the best place:
> https://llvm.org/docs/CodeGenerator.html#x86-address-spaces-supported

Hmm yea I don't think addrspace(256) is correct. I was using D31248 
 as a reference and addrspace(256) makes sense 
for that patch.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126023/new/

https://reviews.llvm.org/D126023

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


[PATCH] D126024: [MSVC, ARM64] Add __readx18 intrinsics

2022-05-20 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 431011.
steplong added a comment.

- Change addrspace(256) to the default addrspace 0


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126024/new/

https://reviews.llvm.org/D126024

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -119,5 +119,65 @@
 
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+
+unsigned char check__readx18byte(unsigned long offset) {
+  return __readx18byte(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[RETVAL:.*]] = load i8, i8* %[[PTR]], align 1
+// CHECK-MSVC: ret i8 %[[RETVAL]]
+
+unsigned short check__readx18word(unsigned long offset) {
+  return __readx18word(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i16*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i16, i16* %[[BITCAST_PTR]], align 2
+// CHECK-MSVC: ret i16 %[[RETVAL]]
+
+unsigned long check__readx18dword(unsigned long offset) {
+  return __readx18dword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i32*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i32, i32* %[[BITCAST_PTR]], align 4
+// CHECK-MSVC: ret i32 %[[RETVAL]]
+
+unsigned __int64 check__readx18qword(unsigned long offset) {
+  return __readx18qword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i64*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i64, i64* %[[BITCAST_PTR]], align 8
+// CHECK-MSVC: ret i64 %[[RETVAL]]
+
 // CHECK-MSVC: ![[MD2]] = !{!"x18"}
 // CHECK-MSVC: ![[MD3]] = !{!"sp"}
Index: clang/lib/Headers/intrin.h
===
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -562,6 +562,11 @@
 unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b);
 
 void __break(int);
+
+unsigned char __readx18byte(unsigned long offset);
+unsigned short __readx18word(unsigned long offset);
+unsigned long __readx18dword(unsigned long offset);
+unsigned __int64 __readx18qword(unsigned long offset);
 #endif
 
 /**\
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -9952,6 +9952,31 @@
 return HigherBits;
   }
 
+  if (BuiltinID == AArch64::BI__readx18byte ||
+  BuiltinID == AArch64::BI__readx18word ||
+  BuiltinID == AArch64::BI__readx18dword ||
+  BuiltinID == AArch64::BI__readx18qword) {
+llvm::Type *IntTy = ConvertType(E->getTy

[PATCH] D126023: [MSVC, ARM64] Add __writex18 intrinsics

2022-05-20 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 431013.
steplong added a comment.

- Changed addrspace(256) to the default addrspace 0


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126023/new/

https://reviews.llvm.org/D126023

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -119,5 +119,73 @@
 
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+
+void check__writex18byte(unsigned long offset, unsigned char data) {
+  __writex18byte(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i8, align 1
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i8 %data, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i8, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i8 %[[DATA]], i8* %[[PTR]], align 1
+
+void check__writex18word(unsigned long offset, unsigned short data) {
+  __writex18word(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i16, align 2
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i16 %data, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i16*
+// CHECK-MSVC: %[[DATA:.*]] = load i16, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i16 %[[DATA]], i16* %[[BITCAST_PTR]], align 1
+
+void check__writex18dword(unsigned long offset, unsigned long data) {
+  __writex18dword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %data, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i32*
+// CHECK-MSVC: %[[DATA:.*]] = load i32, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %[[DATA]], i32* %[[BITCAST_PTR]], align 1
+
+void check__writex18qword(unsigned long offset, unsigned __int64 data) {
+  __writex18qword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i64, align 8
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i64 %data, i64* %[[DATA_ADDR]], align 8
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i64*
+// CHECK-MSVC: %[[DATA:.*]] = load i64, i64* %[[DATA_ADDR]], align 8
+// CHECK-MSVC: store i64 %[[DATA]], i64* %[[BITCAST_PTR]], align 1
+
 // CHECK-MSVC: ![[MD2]] = !{!"x18"}
 // CHECK-MSVC: ![[MD3]] = !{!"sp"}
Index: clang/lib/Headers/intrin.h
===
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -562,6 +562,11 @@
 unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b);
 
 void __break(int);
+
+void __writex18byte(unsigned long offset, unsigned char data);
+void __writex18word(unsigned long offset, unsigned short data);
+void __writex18dwor

[PATCH] D126023: [MSVC, ARM64] Add __writex18 intrinsics

2022-05-20 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 431019.
steplong added a comment.

- Switch to `CharUnits::One()` instead of `getContext().getTypeInChars()`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126023/new/

https://reviews.llvm.org/D126023

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -119,5 +119,73 @@
 
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+
+void check__writex18byte(unsigned long offset, unsigned char data) {
+  __writex18byte(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i8, align 1
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i8 %data, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i8, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i8 %[[DATA]], i8* %[[PTR]], align 1
+
+void check__writex18word(unsigned long offset, unsigned short data) {
+  __writex18word(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i16, align 2
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i16 %data, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i16*
+// CHECK-MSVC: %[[DATA:.*]] = load i16, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i16 %[[DATA]], i16* %[[BITCAST_PTR]], align 1
+
+void check__writex18dword(unsigned long offset, unsigned long data) {
+  __writex18dword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %data, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i32*
+// CHECK-MSVC: %[[DATA:.*]] = load i32, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %[[DATA]], i32* %[[BITCAST_PTR]], align 1
+
+void check__writex18qword(unsigned long offset, unsigned __int64 data) {
+  __writex18qword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i64, align 8
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i64 %data, i64* %[[DATA_ADDR]], align 8
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i64*
+// CHECK-MSVC: %[[DATA:.*]] = load i64, i64* %[[DATA_ADDR]], align 8
+// CHECK-MSVC: store i64 %[[DATA]], i64* %[[BITCAST_PTR]], align 1
+
 // CHECK-MSVC: ![[MD2]] = !{!"x18"}
 // CHECK-MSVC: ![[MD3]] = !{!"sp"}
Index: clang/lib/Headers/intrin.h
===
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -562,6 +562,11 @@
 unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b);
 
 void __break(int);
+
+void __writex18byte(unsigned long offset, unsigned char data);
+void __writex18word(unsigned long offset, unsigned short data)

[PATCH] D126024: [MSVC, ARM64] Add __readx18 intrinsics

2022-05-20 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 431021.
steplong added a comment.

- Use `CharUnits::One()` instead of `getTypeAlignInChars()`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126024/new/

https://reviews.llvm.org/D126024

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -119,5 +119,65 @@
 
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+
+unsigned char check__readx18byte(unsigned long offset) {
+  return __readx18byte(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[RETVAL:.*]] = load i8, i8* %[[PTR]], align 1
+// CHECK-MSVC: ret i8 %[[RETVAL]]
+
+unsigned short check__readx18word(unsigned long offset) {
+  return __readx18word(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i16*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i16, i16* %[[BITCAST_PTR]], align 1
+// CHECK-MSVC: ret i16 %[[RETVAL]]
+
+unsigned long check__readx18dword(unsigned long offset) {
+  return __readx18dword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i32*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i32, i32* %[[BITCAST_PTR]], align 1
+// CHECK-MSVC: ret i32 %[[RETVAL]]
+
+unsigned __int64 check__readx18qword(unsigned long offset) {
+  return __readx18qword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i64*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i64, i64* %[[BITCAST_PTR]], align 1
+// CHECK-MSVC: ret i64 %[[RETVAL]]
+
 // CHECK-MSVC: ![[MD2]] = !{!"x18"}
 // CHECK-MSVC: ![[MD3]] = !{!"sp"}
Index: clang/lib/Headers/intrin.h
===
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -562,6 +562,11 @@
 unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b);
 
 void __break(int);
+
+unsigned char __readx18byte(unsigned long offset);
+unsigned short __readx18word(unsigned long offset);
+unsigned long __readx18dword(unsigned long offset);
+unsigned __int64 __readx18qword(unsigned long offset);
 #endif
 
 /**\
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -9952,6 +9952,30 @@
 return HigherBits;
   }
 
+  if (BuiltinID == AArch64::BI__readx18byte ||
+  BuiltinID == AArch64::BI__readx18word ||
+  BuiltinID == AArch64::BI__readx18dword ||
+  BuiltinID == AArch64::BI__readx18qword) {
+llvm::Type *IntTy = ConvertType

[PATCH] D126023: [MSVC, ARM64] Add __writex18 intrinsics

2022-05-23 Thread Stephen Long via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3e0be5610ff0: [MSVC, ARM64] Add __writex18 intrinsics 
(authored by steplong).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126023/new/

https://reviews.llvm.org/D126023

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -119,5 +119,73 @@
 
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
 // CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+
+void check__writex18byte(unsigned long offset, unsigned char data) {
+  __writex18byte(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i8, align 1
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i8 %data, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[DATA:.*]] = load i8, i8* %[[DATA_ADDR]], align 1
+// CHECK-MSVC: store i8 %[[DATA]], i8* %[[PTR]], align 1
+
+void check__writex18word(unsigned long offset, unsigned short data) {
+  __writex18word(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i16, align 2
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i16 %data, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i16*
+// CHECK-MSVC: %[[DATA:.*]] = load i16, i16* %[[DATA_ADDR]], align 2
+// CHECK-MSVC: store i16 %[[DATA]], i16* %[[BITCAST_PTR]], align 1
+
+void check__writex18dword(unsigned long offset, unsigned long data) {
+  __writex18dword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %data, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i32*
+// CHECK-MSVC: %[[DATA:.*]] = load i32, i32* %[[DATA_ADDR]], align 4
+// CHECK-MSVC: store i32 %[[DATA]], i32* %[[BITCAST_PTR]], align 1
+
+void check__writex18qword(unsigned long offset, unsigned __int64 data) {
+  __writex18qword(offset, data);
+}
+
+// CHECK-MSVC: %[[DATA_ADDR:.*]] = alloca i64, align 8
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i64 %data, i64* %[[DATA_ADDR]], align 8
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i64*
+// CHECK-MSVC: %[[DATA:.*]] = load i64, i64* %[[DATA_ADDR]], align 8
+// CHECK-MSVC: store i64 %[[DATA]], i64* %[[BITCAST_PTR]], align 1
+
 // CHECK-MSVC: ![[MD2]] = !{!"x18"}
 // CHECK-MSVC: ![[MD3]] = !{!"sp"}
Index: clang/lib/Headers/intrin.h
===
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -562,6 +562,11 @@
 unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b);
 
 void __break(int);
+
+void __writex18byte(unsigned long offset, unsigned char data);
+void __writex18word(unsigned long offse

[PATCH] D126024: [MSVC, ARM64] Add __readx18 intrinsics

2022-05-23 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 431392.
steplong added a comment.

- Rebased patch on top of main


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126024/new/

https://reviews.llvm.org/D126024

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -187,5 +187,64 @@
 // CHECK-MSVC: %[[DATA:.*]] = load i64, i64* %[[DATA_ADDR]], align 8
 // CHECK-MSVC: store i64 %[[DATA]], i64* %[[BITCAST_PTR]], align 1
 
+unsigned char check__readx18byte(unsigned long offset) {
+  return __readx18byte(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[RETVAL:.*]] = load i8, i8* %[[PTR]], align 1
+// CHECK-MSVC: ret i8 %[[RETVAL]]
+
+unsigned short check__readx18word(unsigned long offset) {
+  return __readx18word(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i16*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i16, i16* %[[BITCAST_PTR]], align 1
+// CHECK-MSVC: ret i16 %[[RETVAL]]
+
+unsigned long check__readx18dword(unsigned long offset) {
+  return __readx18dword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i32*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i32, i32* %[[BITCAST_PTR]], align 1
+// CHECK-MSVC: ret i32 %[[RETVAL]]
+
+unsigned __int64 check__readx18qword(unsigned long offset) {
+  return __readx18qword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i64*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i64, i64* %[[BITCAST_PTR]], align 1
+// CHECK-MSVC: ret i64 %[[RETVAL]]
+
 // CHECK-MSVC: ![[MD2]] = !{!"x18"}
 // CHECK-MSVC: ![[MD3]] = !{!"sp"}
Index: clang/lib/Headers/intrin.h
===
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -567,6 +567,11 @@
 void __writex18word(unsigned long offset, unsigned short data);
 void __writex18dword(unsigned long offset, unsigned long data);
 void __writex18qword(unsigned long offset, unsigned __int64 data);
+
+unsigned char __readx18byte(unsigned long offset);
+unsigned short __readx18word(unsigned long offset);
+unsigned long __readx18dword(unsigned long offset);
+unsigned __int64 __readx18qword(unsigned long offset);
 #endif
 
 /**\
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -9977,6 +9977,30 @@
 return Store;
   }
 
+  if (BuiltinID == AArch64::BI__readx18byte ||
+  BuiltinID == AArch64::BI__readx18word ||
+  BuiltinID == AArch64::BI__readx18dword ||
+  BuiltinID == 

[PATCH] D126024: [MSVC, ARM64] Add __readx18 intrinsics

2022-05-23 Thread Stephen Long via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG4f1e64b54f59: [MSVC, ARM64] Add __readx18 intrinsics 
(authored by steplong).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126024/new/

https://reviews.llvm.org/D126024

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/intrin.h
  clang/test/CodeGen/arm64-microsoft-intrinsics.c

Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c
===
--- clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -187,5 +187,64 @@
 // CHECK-MSVC: %[[DATA:.*]] = load i64, i64* %[[DATA_ADDR]], align 8
 // CHECK-MSVC: store i64 %[[DATA]], i64* %[[BITCAST_PTR]], align 1
 
+unsigned char check__readx18byte(unsigned long offset) {
+  return __readx18byte(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[RETVAL:.*]] = load i8, i8* %[[PTR]], align 1
+// CHECK-MSVC: ret i8 %[[RETVAL]]
+
+unsigned short check__readx18word(unsigned long offset) {
+  return __readx18word(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i16*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i16, i16* %[[BITCAST_PTR]], align 1
+// CHECK-MSVC: ret i16 %[[RETVAL]]
+
+unsigned long check__readx18dword(unsigned long offset) {
+  return __readx18dword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i32*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i32, i32* %[[BITCAST_PTR]], align 1
+// CHECK-MSVC: ret i32 %[[RETVAL]]
+
+unsigned __int64 check__readx18qword(unsigned long offset) {
+  return __readx18qword(offset);
+}
+
+// CHECK-MSVC: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSVC: store i32 %offset, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSVC: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to i8*
+// CHECK-MSVC: %[[OFFSET:.*]] = load i32, i32* %[[OFFSET_ADDR]], align 4
+// CHECK-MSVC: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSVC: %[[PTR:.*]] = getelementptr i8, i8* %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSVC: %[[BITCAST_PTR:.*]] = bitcast i8* %[[PTR]] to i64*
+// CHECK-MSVC: %[[RETVAL:.*]] = load i64, i64* %[[BITCAST_PTR]], align 1
+// CHECK-MSVC: ret i64 %[[RETVAL]]
+
 // CHECK-MSVC: ![[MD2]] = !{!"x18"}
 // CHECK-MSVC: ![[MD3]] = !{!"sp"}
Index: clang/lib/Headers/intrin.h
===
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -567,6 +567,11 @@
 void __writex18word(unsigned long offset, unsigned short data);
 void __writex18dword(unsigned long offset, unsigned long data);
 void __writex18qword(unsigned long offset, unsigned __int64 data);
+
+unsigned char __readx18byte(unsigned long offset);
+unsigned short __readx18word(unsigned long offset);
+unsigned long __readx18dword(unsigned long offset);
+unsigned __int64 __readx18qword(unsigned long offset);
 #endif
 
 /**\
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -9977,6 +9977,30 @@
 return Store;
   }
 
+  if (BuiltinID == AArch64::BI__readx18byte ||
+  BuiltinID == AArch64::BI__readx18word ||
+   

[PATCH] D93428: [AArch64] Add bti note property when compiling asm files with -mbranch-protection=bti

2020-12-16 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
Herald added subscribers: danielkiss, kristof.beyls.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Generate the .note.gnu.property section with GNU_PROPERTY_AARCH64_FEATURE_1_BTI
when compiling assembly files with -mbranch-protection=bti.

See https://reviews.llvm.org/D81930 for generating the section when compiling
C/C++ files with -mbranch-protection=bti.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D93428

Files:
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Driver/ToolChains/Clang.h
  clang/test/Driver/arm64-markbti.S


Index: clang/test/Driver/arm64-markbti.S
===
--- clang/test/Driver/arm64-markbti.S
+++ clang/test/Driver/arm64-markbti.S
@@ -1,10 +1,12 @@
 // REQUIRES: aarch64-registered-target
 
-// When -mmark-bti-property is passed the generated file object gets BTI 
marking.
+// When -mmark-bti-property or -mbranch-protection=bti is passed the generated 
file object gets BTI marking.
 // RUN: %clang -target arm64-linux-none -mmark-bti-property -c -o - %s | 
llvm-readobj -n - | FileCheck -check-prefix=CHECK  -check-prefix=CHECK_GEN %s
 // RUN: %clang -target arm64-linux-none -DNOTE_PRESENT -c %s -o - | 
llvm-readobj -n - | FileCheck -check-prefix=CHECK  -check-prefix=CHECK_PRESET %s
 // RUN: %clang -target arm64-linux-none -mmark-bti-property -DNOTE_PRESENT -c 
%s -o - | llvm-readobj -n - | FileCheck -check-prefix=CHECK  
-check-prefix=CHECK_PRESET %s
 // RUN: %clang -target arm64-linux-none -mmark-bti-property -DNOTE_PRESENT -c 
%s -o - 2>&1 |  FileCheck -check-prefix=CHECK_WARNING %s
+// RUN: %clang -target arm64-linux-none -mbranch-protection=bti -c -o - %s | 
llvm-readobj -n - | FileCheck -check-prefix=CHECK  -check-prefix=CHECK_GEN %s
+// RUN: %clang -target arm64-linux-none -mbranch-protection=bti -DNOTE_PRESENT 
-c %s -o - 2>&1 |  FileCheck -check-prefix=CHECK_WARNING %s
 //
 // CHECK_WARNING: The .note.gnu.property is not emitted because it is already 
present.
 // CHECK: Name: .note.gnu.property
Index: clang/lib/Driver/ToolChains/Clang.h
===
--- clang/lib/Driver/ToolChains/Clang.h
+++ clang/lib/Driver/ToolChains/Clang.h
@@ -128,6 +128,8 @@
 llvm::opt::ArgStringList &CmdArgs) const;
   void AddRISCVTargetArgs(const llvm::opt::ArgList &Args,
   llvm::opt::ArgStringList &CmdArgs) const;
+  void AddAArch64TargetArgs(const llvm::opt::ArgList &Args,
+llvm::opt::ArgStringList &CmdArgs) const;
   bool hasGoodDiagnostics() const override { return true; }
   bool hasIntegratedAssembler() const override { return false; }
   bool hasIntegratedCPP() const override { return false; }
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -7015,6 +7015,29 @@
   CmdArgs.push_back(ABIName.data());
 }
 
+void ClangAs::AddAArch64TargetArgs(const ArgList &Args,
+   ArgStringList &CmdArgs) const {
+  bool BranchTargetEnforce = false;
+  const auto &D = getToolChain().getDriver();
+
+  if (Arg *A = Args.getLastArg(options::OPT_mbranch_protection_EQ)) {
+StringRef Err;
+llvm::AArch64::ParsedBranchProtection PBP;
+
+if (!llvm::AArch64::parseBranchProtection(A->getValue(), PBP, Err)) {
+  D.Diag(diag::err_invalid_branch_protection)
+  << Err << A->getAsString(Args);
+} else {
+  BranchTargetEnforce = PBP.BranchTargetEnforcement;
+}
+  }
+
+  if (Args.hasArg(options::OPT_mmark_bti_property) || BranchTargetEnforce) {
+CmdArgs.push_back("-mllvm");
+CmdArgs.push_back("-aarch64-mark-bti-property");
+  }
+}
+
 void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList 
&Inputs,
const ArgList &Args,
@@ -7193,10 +7216,7 @@
   case llvm::Triple::aarch64:
   case llvm::Triple::aarch64_32:
   case llvm::Triple::aarch64_be:
-if (Args.hasArg(options::OPT_mmark_bti_property)) {
-  CmdArgs.push_back("-mllvm");
-  CmdArgs.push_back("-aarch64-mark-bti-property");
-}
+AddAArch64TargetArgs(Args, CmdArgs);
 break;
 
   case llvm::Triple::riscv32:


Index: clang/test/Driver/arm64-markbti.S
===
--- clang/test/Driver/arm64-markbti.S
+++ clang/test/Driver/arm64-markbti.S
@@ -1,10 +1,12 @@
 // REQUIRES: aarch64-registered-target
 
-// When -mmark-bti-property is passed the generated file object gets BTI marking.
+// When -mmark-bti-property or -mbranch-protection=bti is passed the generated file object gets BTI marking.
 // RUN: %clang -target arm64-linux-none -mmark-bti-property -c -o - %s | llvm-readobj 

[PATCH] D93428: [AArch64] Add bti note property when compiling asm files with -mbranch-protection=bti

2020-12-17 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

In D93428#2460032 , @danielkiss wrote:

> The `.note.gnu.property` is already generated when C/C++ files are compiled 
> with `-mbranch-protection=bti`.  
> `-mmark-bti-property` is only for assembly file where the 
> `.note.gnu.property` should be added manually otherwise.
>
> Do you have any reproducer where C/C++ behaves unexpectedly?

I think Ana misunderstood the reason for this patch. We haven't seen any 
compilation of C/C++ behaving unexpectedly. -mbranch-protection=bti generates 
the .nute.gnu.property for C/C++ files from our experiments, but doesn't work 
for assembly files. Is there a reason why assembly files have a different flag 
(i.e. -mmark-bti-property) to create the .note.gnu.property with the BTI entry?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D93428/new/

https://reviews.llvm.org/D93428

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


[PATCH] D127641: [clang-cl][MSVC] Enable /Zc:alignedNew for C++17 and /Zc:sizedDealloc by default

2022-08-11 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 452062.
steplong added a comment.

- Change (1|2) to [12]. Test is failing because () isn't supported


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127641/new/

https://reviews.llvm.org/D127641

Files:
  clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-zc.cpp
  clang/unittests/StaticAnalyzer/CallEventTest.cpp

Index: clang/unittests/StaticAnalyzer/CallEventTest.cpp
===
--- clang/unittests/StaticAnalyzer/CallEventTest.cpp
+++ clang/unittests/StaticAnalyzer/CallEventTest.cpp
@@ -8,6 +8,7 @@
 
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "CheckerRegistration.h"
+#include "gmock/gmock.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
@@ -22,6 +23,8 @@
 #include "clang/Tooling/Tooling.h"
 #include "gtest/gtest.h"
 
+using testing::MatchesRegex;
+
 namespace clang {
 namespace ento {
 namespace {
@@ -81,7 +84,7 @@
 }
   )",
  Diags));
-  EXPECT_EQ(Diags, "test.CXXDeallocator: NumArgs: 1\n");
+  EXPECT_THAT(Diags, MatchesRegex("test.CXXDeallocator: NumArgs: [12]\n"));
 }
 
 } // namespace
Index: clang/test/Driver/cl-zc.cpp
===
--- clang/test/Driver/cl-zc.cpp
+++ clang/test/Driver/cl-zc.cpp
@@ -1,6 +1,19 @@
 // Note: %s must be preceded by --, otherwise it may be interpreted as a
 // command-line option, e.g. on Mac where %s is commonly under /Users.
 
+// RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=SIZED-DEALLOC %s
+// RUN: %clang_cl /c -### -fms-compatibility-version=18 -- %s 2>&1 | FileCheck -check-prefix=SIZED-DEALLOC-OFF %s
+// SIZED-DEALLOC: "-fsized-deallocation"
+// SIZED-DEALLOC-OFF-NOT: "-fsized-deallocation"
+
+// RUN: %clang_cl /c /std:c++11 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-BEFORE-CPP17 %s
+// RUN: %clang_cl /c /std:c++14 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-BEFORE-CPP17 %s
+// RUN: %clang_cl /c /std:c++17 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// RUN: %clang_cl /c /std:c++20 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// RUN: %clang_cl /c /std:c++latest -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// ALIGNED-NEW-BEFORE-CPP17-NOT: "-faligned-allocation"
+// ALIGNED-NEW-CPP17ONWARDS: "-faligned-allocation"
+
 // RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=TRIGRAPHS-DEFAULT %s
 // cc1 will disable trigraphs for -fms-compatibility as long as -ftrigraphs
 // isn't explicitly passed.
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -6470,6 +6470,7 @@
 }
 CmdArgs.push_back(LanguageStandard.data());
   }
+  bool IsCPP17Onwards = false;
   if (ImplyVCPPCXXVer) {
 StringRef LanguageStandard;
 if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
@@ -6493,6 +6494,9 @@
 }
 
 CmdArgs.push_back(LanguageStandard.data());
+
+IsCPP17Onwards =
+LanguageStandard != "-std=c++11" && LanguageStandard != "-std=c++14";
   }
 
   Args.addOptInFlag(CmdArgs, options::OPT_fborland_extensions,
@@ -6622,9 +6626,15 @@
 options::OPT_fno_relaxed_template_template_args);
 
   // -fsized-deallocation is off by default, as it is an ABI-breaking change for
-  // most platforms.
-  Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
-options::OPT_fno_sized_deallocation);
+  // most platforms. MSVC turns on /Zc:sizedDealloc by default, starting in
+  // MSVC 2015.
+  if (IsWindowsMSVC && IsMSVC2015Compatible &&
+  !Args.getLastArg(options::OPT_fsized_deallocation,
+   options::OPT_fno_sized_deallocation))
+CmdArgs.push_back("-fsized-deallocation");
+  else
+Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
+  options::OPT_fno_sized_deallocation);
 
   // -faligned-allocation is on by default in C++17 onwards and otherwise off
   // by default.
@@ -6635,6 +6645,8 @@
   CmdArgs.push_back("-fno-aligned-allocation");
 else
   CmdArgs.push_back("-faligned-allocation");
+  } else if (IsCPP17Onwards) {
+CmdArgs.push_back("-faligned-allocation");
   }
 
   // The default new alignment can be specified using a dedicated option or via
Index: clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp
+++ clang-tools-extra/test/clang-tidy/check

[PATCH] D127641: [clang-cl][MSVC] Enable /Zc:alignedNew for C++17 and /Zc:sizedDealloc by default

2022-08-15 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 452655.
steplong added a comment.

- Update unit test to see if this regex works


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127641/new/

https://reviews.llvm.org/D127641

Files:
  clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-zc.cpp
  clang/unittests/StaticAnalyzer/CallEventTest.cpp

Index: clang/unittests/StaticAnalyzer/CallEventTest.cpp
===
--- clang/unittests/StaticAnalyzer/CallEventTest.cpp
+++ clang/unittests/StaticAnalyzer/CallEventTest.cpp
@@ -8,6 +8,7 @@
 
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "CheckerRegistration.h"
+#include "gmock/gmock.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
@@ -22,6 +23,8 @@
 #include "clang/Tooling/Tooling.h"
 #include "gtest/gtest.h"
 
+using testing::MatchesRegex;
+
 namespace clang {
 namespace ento {
 namespace {
@@ -81,7 +84,12 @@
 }
   )",
  Diags));
-  EXPECT_EQ(Diags, "test.CXXDeallocator: NumArgs: 1\n");
+// Sized deallocation is enabled on Windows, so we expect two arguments.
+#if defined(GTEST_USES_POSIX_RE)
+  EXPECT_THAT(Diags, MatchesRegex("test.CXXDeallocator: NumArgs: (1|2)\n"));
+#elif defined(GTEST_USES_SIMPLE_RE)
+  EXPECT_THAT(Diags, MatchesRegex("test.CXXDeallocator: NumArgs: 1?\n?2?\n?"));
+#endif
 }
 
 } // namespace
Index: clang/test/Driver/cl-zc.cpp
===
--- clang/test/Driver/cl-zc.cpp
+++ clang/test/Driver/cl-zc.cpp
@@ -1,6 +1,19 @@
 // Note: %s must be preceded by --, otherwise it may be interpreted as a
 // command-line option, e.g. on Mac where %s is commonly under /Users.
 
+// RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=SIZED-DEALLOC %s
+// RUN: %clang_cl /c -### -fms-compatibility-version=18 -- %s 2>&1 | FileCheck -check-prefix=SIZED-DEALLOC-OFF %s
+// SIZED-DEALLOC: "-fsized-deallocation"
+// SIZED-DEALLOC-OFF-NOT: "-fsized-deallocation"
+
+// RUN: %clang_cl /c /std:c++11 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-BEFORE-CPP17 %s
+// RUN: %clang_cl /c /std:c++14 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-BEFORE-CPP17 %s
+// RUN: %clang_cl /c /std:c++17 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// RUN: %clang_cl /c /std:c++20 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// RUN: %clang_cl /c /std:c++latest -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// ALIGNED-NEW-BEFORE-CPP17-NOT: "-faligned-allocation"
+// ALIGNED-NEW-CPP17ONWARDS: "-faligned-allocation"
+
 // RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=TRIGRAPHS-DEFAULT %s
 // cc1 will disable trigraphs for -fms-compatibility as long as -ftrigraphs
 // isn't explicitly passed.
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -6470,6 +6470,7 @@
 }
 CmdArgs.push_back(LanguageStandard.data());
   }
+  bool IsCPP17Onwards = false;
   if (ImplyVCPPCXXVer) {
 StringRef LanguageStandard;
 if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
@@ -6493,6 +6494,9 @@
 }
 
 CmdArgs.push_back(LanguageStandard.data());
+
+IsCPP17Onwards =
+LanguageStandard != "-std=c++11" && LanguageStandard != "-std=c++14";
   }
 
   Args.addOptInFlag(CmdArgs, options::OPT_fborland_extensions,
@@ -6622,9 +6626,15 @@
 options::OPT_fno_relaxed_template_template_args);
 
   // -fsized-deallocation is off by default, as it is an ABI-breaking change for
-  // most platforms.
-  Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
-options::OPT_fno_sized_deallocation);
+  // most platforms. MSVC turns on /Zc:sizedDealloc by default, starting in
+  // MSVC 2015.
+  if (IsWindowsMSVC && IsMSVC2015Compatible &&
+  !Args.getLastArg(options::OPT_fsized_deallocation,
+   options::OPT_fno_sized_deallocation))
+CmdArgs.push_back("-fsized-deallocation");
+  else
+Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
+  options::OPT_fno_sized_deallocation);
 
   // -faligned-allocation is on by default in C++17 onwards and otherwise off
   // by default.
@@ -6635,6 +6645,8 @@
   CmdArgs.push_back("-fno-aligned-allocation");
 else
   CmdArgs.push_back("-faligned-allocation");
+  } else if (IsCPP17Onwards) {
+CmdArgs.push_back("-faligned-allocation");
   }
 
   // The default new alignment can be specified using a dedicated option or via
Index: clang-tools-extra/test/clang-tidy/checkers/mis

[PATCH] D127641: [clang-cl][MSVC] Enable /Zc:alignedNew for C++17 and /Zc:sizedDealloc by default

2022-08-15 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/lib/Driver/ToolChains/Clang.cpp:6649
+  } else if (IsCPP17Onwards) {
+CmdArgs.push_back("-faligned-allocation");
   }

thakis wrote:
> Do we want to do this in the driver? From what I understand, we already do 
> this (MSVC or not) at the Driver->Frontend boundary. See Options.td:
> 
> ```
> defm aligned_allocation : BoolFOption<"aligned-allocation",
>   LangOpts<"AlignedAllocation">, Default,
>   PosFlag,
>   NegFlag, BothFlags<[CC1Option]>>;
> ```
> 
> It defaults to on when c++17 is set, and makes its way to 
> `LangOpts.AlignedAllocation`.
> 
> Does this change here have any effect? From looking at the code, this should 
> be the current behavior already (?)
Hmmm, my test regarding checking for `-faligned-allocation` fails if I remove 
the code here.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127641/new/

https://reviews.llvm.org/D127641

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


[PATCH] D127641: [clang-cl][MSVC] Enable /Zc:alignedNew for C++17 and /Zc:sizedDealloc by default

2022-08-15 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 452757.
steplong added a comment.

- Clang-format test

The regex isn't optimal since it will still accept strings that aren't "Num 
Args: 1\n" or "Num Args: 2\n" such as "Num Args: \n2\n"


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127641/new/

https://reviews.llvm.org/D127641

Files:
  clang-tools-extra/test/clang-tidy/checkers/misc/new-delete-overloads.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-zc.cpp
  clang/unittests/StaticAnalyzer/CallEventTest.cpp

Index: clang/unittests/StaticAnalyzer/CallEventTest.cpp
===
--- clang/unittests/StaticAnalyzer/CallEventTest.cpp
+++ clang/unittests/StaticAnalyzer/CallEventTest.cpp
@@ -20,8 +20,11 @@
 #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
 #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
 #include "clang/Tooling/Tooling.h"
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
+using testing::MatchesRegex;
+
 namespace clang {
 namespace ento {
 namespace {
@@ -81,7 +84,12 @@
 }
   )",
  Diags));
-  EXPECT_EQ(Diags, "test.CXXDeallocator: NumArgs: 1\n");
+// Sized deallocation is enabled on Windows, so we expect two arguments.
+#if defined(GTEST_USES_POSIX_RE)
+  EXPECT_THAT(Diags, MatchesRegex("test.CXXDeallocator: NumArgs: (1|2)\n"));
+#elif defined(GTEST_USES_SIMPLE_RE)
+  EXPECT_THAT(Diags, MatchesRegex("test.CXXDeallocator: NumArgs: 1?\n?2?\n?"));
+#endif
 }
 
 } // namespace
Index: clang/test/Driver/cl-zc.cpp
===
--- clang/test/Driver/cl-zc.cpp
+++ clang/test/Driver/cl-zc.cpp
@@ -1,6 +1,19 @@
 // Note: %s must be preceded by --, otherwise it may be interpreted as a
 // command-line option, e.g. on Mac where %s is commonly under /Users.
 
+// RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=SIZED-DEALLOC %s
+// RUN: %clang_cl /c -### -fms-compatibility-version=18 -- %s 2>&1 | FileCheck -check-prefix=SIZED-DEALLOC-OFF %s
+// SIZED-DEALLOC: "-fsized-deallocation"
+// SIZED-DEALLOC-OFF-NOT: "-fsized-deallocation"
+
+// RUN: %clang_cl /c /std:c++11 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-BEFORE-CPP17 %s
+// RUN: %clang_cl /c /std:c++14 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-BEFORE-CPP17 %s
+// RUN: %clang_cl /c /std:c++17 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// RUN: %clang_cl /c /std:c++20 -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// RUN: %clang_cl /c /std:c++latest -### -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-CPP17ONWARDS %s
+// ALIGNED-NEW-BEFORE-CPP17-NOT: "-faligned-allocation"
+// ALIGNED-NEW-CPP17ONWARDS: "-faligned-allocation"
+
 // RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=TRIGRAPHS-DEFAULT %s
 // cc1 will disable trigraphs for -fms-compatibility as long as -ftrigraphs
 // isn't explicitly passed.
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -6523,6 +6523,7 @@
 }
 CmdArgs.push_back(LanguageStandard.data());
   }
+  bool IsCPP17Onwards = false;
   if (ImplyVCPPCXXVer) {
 StringRef LanguageStandard;
 if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
@@ -6546,6 +6547,9 @@
 }
 
 CmdArgs.push_back(LanguageStandard.data());
+
+IsCPP17Onwards =
+LanguageStandard != "-std=c++11" && LanguageStandard != "-std=c++14";
   }
 
   Args.addOptInFlag(CmdArgs, options::OPT_fborland_extensions,
@@ -6675,9 +6679,15 @@
 options::OPT_fno_relaxed_template_template_args);
 
   // -fsized-deallocation is off by default, as it is an ABI-breaking change for
-  // most platforms.
-  Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
-options::OPT_fno_sized_deallocation);
+  // most platforms. MSVC turns on /Zc:sizedDealloc by default, starting in
+  // MSVC 2015.
+  if (IsWindowsMSVC && IsMSVC2015Compatible &&
+  !Args.getLastArg(options::OPT_fsized_deallocation,
+   options::OPT_fno_sized_deallocation))
+CmdArgs.push_back("-fsized-deallocation");
+  else
+Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
+  options::OPT_fno_sized_deallocation);
 
   // -faligned-allocation is on by default in C++17 onwards and otherwise off
   // by default.
@@ -6688,6 +6698,8 @@
   CmdArgs.push_back("-fno-aligned-allocation");
 else
   CmdArgs.push_back("-faligned-allocation");
+  } else if (IsCPP17Onwards) {
+CmdArgs.push_back("-faligned-allocation");
   }
 
   // The default new alignment can be specified using a dedicated option or via
Index: clang-tools-extra/test/clang-tidy/checkers/misc/new-delete-overloads.cpp

[PATCH] D127641: [clang-cl][MSVC] Enable /Zc:alignedNew for C++17 and /Zc:sizedDealloc by default

2022-08-18 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

@thakis @hans What do you both think of the latest version? I would like to get 
this merged


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127641/new/

https://reviews.llvm.org/D127641

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


[PATCH] D126984: [clang] Add initial support for gcc's optimize function attribute

2022-06-10 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

In D126984#3571573 , @aeubanks wrote:

> IIRC in the past there was a strong preference to not have the pass manager 
> support this sort of thing
> if you want to support this, there should be an RFC for how the optimization 
> part of this will work as it may require invasive changes to the LLVM pass 
> manager
>
> (if this is purely a clang frontend thing then ignore me)

Hmm, this does affect codegen, so I'm not sure if it's purely a clang frontend 
thing. Maybe someone else can confirm. The motivation behind this was to add 
support for MSVC's `pragma optimize` in D125723 
. 
https://docs.microsoft.com/en-us/cpp/preprocessor/optimize?view=msvc-170


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126984/new/

https://reviews.llvm.org/D126984

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


[PATCH] D126984: [clang] Add initial support for gcc's optimize function attribute

2022-06-10 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

In D126984#3574077 , @aeubanks wrote:

> In D126984#3574046 , @aaron.ballman 
> wrote:
>
>> In D126984#3571573 , @aeubanks 
>> wrote:
>>
>>> IIRC in the past there was a strong preference to not have the pass manager 
>>> support this sort of thing
>>> if you want to support this, there should be an RFC for how the 
>>> optimization part of this will work as it may require invasive changes to 
>>> the LLVM pass manager
>>>
>>> (if this is purely a clang frontend thing then ignore me)
>>
>> Hmm, does the pass manager have to support anything here? The only Clang 
>> codegen changes are for emitting IR attributes that we already emitted based 
>> on command line flags/other attributes, so I had the impression this would 
>> not be invasive for the backend at all.
>
> if we're allowing individual functions to specify that they want the `-O1` 
> pipeline when everything else in the module should be compiled with `-O2`, 
> that's a huge change in the pass manager. but perhaps I'm misunderstanding 
> the point of this patch

That makes sense. The MSVC pragma allows 4 options, "stgy":

| Parameter | On
  | Off 
   |
| - | 
---
 |  
  |
| g | Deprecated
  | Deprecated  
   |
| s | Add MinSize   
  | Remove MinSize (I think this would 
be difficult to do if -Os is passed on the cmdline) |
| t | Add -O2 (We can't support -O2 with this attribute so ignore)  
  | Add Optnone 
   |
| y | Add frame-pointers (We can't support -f arguments with the 
attribute in this patch so we are ignoring this) | No frame-pointers (Same 
thing as on)   |
|

For our use case, I think we only really see `#pragma optimize("", off)` and 
`#pragma optimize("", on)`, so I'm not opposed to abandoning this patch and 
just supporting the common use case for now. I think `#pragma optimize("", on)` 
would just mean do nothing and apply whatever is on the command line and 
`#pragma optimize("", off)` would mean add optnone to the functions below it


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126984/new/

https://reviews.llvm.org/D126984

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


[PATCH] D127519: [clang-cl] Accept /FA[c][s][u], but ignore the arguments

2022-06-10 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
Herald added a project: All.
steplong requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

Previously, /FAsc would emit a warning. Now, it will just do what /FA does.

https://docs.microsoft.com/en-us/cpp/build/reference/fa-fa-listing-file?view=msvc-170


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D127519

Files:
  clang/lib/Driver/Driver.cpp


Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -4872,7 +4872,8 @@
 return TC.useIntegratedAs() && !SaveTemps &&
!C.getArgs().hasArg(options::OPT_via_file_asm) &&
!C.getArgs().hasArg(options::OPT__SLASH_FA) &&
-   !C.getArgs().hasArg(options::OPT__SLASH_Fa);
+   !C.getArgs().hasArg(options::OPT__SLASH_Fa) &&
+   !C.getArgs().hasArg(options::OPT__SLASH_FA_joined);
   }
 
   /// Return true if a preprocessor action can be collapsed.
@@ -5552,7 +5553,8 @@
   // Is this the assembly listing for /FA?
   if (JA.getType() == types::TY_PP_Asm &&
   (C.getArgs().hasArg(options::OPT__SLASH_FA) ||
-   C.getArgs().hasArg(options::OPT__SLASH_Fa))) {
+   C.getArgs().hasArg(options::OPT__SLASH_Fa) ||
+   C.getArgs().hasArg(options::OPT__SLASH_FA_joined))) {
 // Use /Fa and the input filename to determine the asm file name.
 StringRef BaseName = llvm::sys::path::filename(BaseInput);
 StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa);


Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -4872,7 +4872,8 @@
 return TC.useIntegratedAs() && !SaveTemps &&
!C.getArgs().hasArg(options::OPT_via_file_asm) &&
!C.getArgs().hasArg(options::OPT__SLASH_FA) &&
-   !C.getArgs().hasArg(options::OPT__SLASH_Fa);
+   !C.getArgs().hasArg(options::OPT__SLASH_Fa) &&
+   !C.getArgs().hasArg(options::OPT__SLASH_FA_joined);
   }
 
   /// Return true if a preprocessor action can be collapsed.
@@ -5552,7 +5553,8 @@
   // Is this the assembly listing for /FA?
   if (JA.getType() == types::TY_PP_Asm &&
   (C.getArgs().hasArg(options::OPT__SLASH_FA) ||
-   C.getArgs().hasArg(options::OPT__SLASH_Fa))) {
+   C.getArgs().hasArg(options::OPT__SLASH_Fa) ||
+   C.getArgs().hasArg(options::OPT__SLASH_FA_joined))) {
 // Use /Fa and the input filename to determine the asm file name.
 StringRef BaseName = llvm::sys::path::filename(BaseInput);
 StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D127519: [clang-cl] Accept /FA[c][s][u], but ignore the arguments

2022-06-10 Thread Stephen Long via Phabricator via cfe-commits
steplong added reviewers: rnk, hans.
steplong added a comment.

I'm not sure which test file to modify and how to test this. I do see it 
generating the `.asm` file now when I pass `/FAsc`, not the `.codd` file though 
since we are ignoring the `c` argument.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127519/new/

https://reviews.llvm.org/D127519

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


[PATCH] D126984: [clang] Add initial support for gcc's optimize function attribute

2022-06-10 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/test/CodeGen/attr-optimize.c:4
+
+__attribute__((optimize("O0"))) void f1(void) {}
+// O2: @f1{{.*}}[[ATTR_OPTNONE:#[0-9]+]]

xbolva00 wrote:
> No support for 
> ```
> __attribute__ ((__optimize__ (0)))
> ```
> 
> ? GCC supports it
Nope, I only added support for one argument and only strings. I think gcc 
supports expressions, multiple args, -f args, and -O args. I wasn't sure how to 
implement it in Attr.td without making heavy changes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126984/new/

https://reviews.llvm.org/D126984

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


[PATCH] D127452: [clang-cl][MSVC] Map /external:Wn n=1-4 to -Wsystem-headers

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

Hmm do you know how I can restart the pre-merge checks? It looks like the x64 
debian openmp tests failed. I don't think this patch is related, but I want to 
make sure


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127452/new/

https://reviews.llvm.org/D127452

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


[PATCH] D127641: [clang-cl][MSVC] Add default /Zc conformance arguments

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong created this revision.
Herald added a project: All.
steplong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This patch doesn't turn on all the "on by default" /Zc arguments, but
this should be a good enough starting point.

https://docs.microsoft.com/en-us/cpp/build/reference/zc-conformance?view=msvc-170


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D127641

Files:
  clang/include/clang/Driver/Options.td
  clang/test/Driver/cl-zc.cpp
  clang/tools/driver/driver.cpp


Index: clang/tools/driver/driver.cpp
===
--- clang/tools/driver/driver.cpp
+++ clang/tools/driver/driver.cpp
@@ -234,6 +234,25 @@
   }
 }
 
+static void insertDefaultClangCLZcConformanceArgs(
+SmallVectorImpl &ArgVector) {
+  // Put the /Zc arguments at the start of argument list so that arguments
+  // specified on
+  // the command line could override them. Avoid putting them at index 0, as an
+  // option
+  // like '-cc1' must remain the first.
+  int InsertionPoint = 0;
+  if (ArgVector.size() > 0)
+++InsertionPoint;
+
+  const char *arr[] = {
+  "/Zc:auto", "/Zc:forScope",   "/Zc:implicitNoexcept",
+  "/Zc:sizedDealloc", "/Zc:threadSafeInit", "/Zc:wchar_t"};
+
+  ArgVector.insert(ArgVector.begin() + InsertionPoint, std::begin(arr),
+   std::end(arr));
+}
+
 static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver,
SmallVectorImpl &Opts) {
   llvm::cl::TokenizeWindowsCommandLine(EnvValue, Saver, Opts);
@@ -473,6 +492,9 @@
 
   insertTargetAndModeArgs(TargetAndMode, Args, SavedStrings);
 
+  if (ClangCLMode)
+insertDefaultClangCLZcConformanceArgs(Args);
+
   SetBackdoorDriverOutputsFromEnvVars(TheDriver);
 
   if (!UseNewCC1Process) {
Index: clang/test/Driver/cl-zc.cpp
===
--- clang/test/Driver/cl-zc.cpp
+++ clang/test/Driver/cl-zc.cpp
@@ -1,6 +1,9 @@
 // Note: %s must be preceded by --, otherwise it may be interpreted as a
 // command-line option, e.g. on Mac where %s is commonly under /Users.
 
+// RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=DEFAULT %s
+// DEFAULT: "-fsized-deallocation"
+
 // RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck 
-check-prefix=TRIGRAPHS-DEFAULT %s
 // cc1 will disable trigraphs for -fms-compatibility as long as -ftrigraphs
 // isn't explicitly passed.
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -6701,6 +6701,7 @@
 def _SLASH_Wv_ : CLIgnoredJoined<"Wv">;
 def _SLASH_Zc___cplusplus : CLIgnoredFlag<"Zc:__cplusplus">;
 def _SLASH_Zc_auto : CLIgnoredFlag<"Zc:auto">;
+def _SLASH_Zc_implicitNoexcept : CLIgnoredFlag<"Zc:implicitNoexcept">;
 def _SLASH_Zc_forScope : CLIgnoredFlag<"Zc:forScope">;
 def _SLASH_Zc_inline : CLIgnoredFlag<"Zc:inline">;
 def _SLASH_Zc_rvalueCast : CLIgnoredFlag<"Zc:rvalueCast">;


Index: clang/tools/driver/driver.cpp
===
--- clang/tools/driver/driver.cpp
+++ clang/tools/driver/driver.cpp
@@ -234,6 +234,25 @@
   }
 }
 
+static void insertDefaultClangCLZcConformanceArgs(
+SmallVectorImpl &ArgVector) {
+  // Put the /Zc arguments at the start of argument list so that arguments
+  // specified on
+  // the command line could override them. Avoid putting them at index 0, as an
+  // option
+  // like '-cc1' must remain the first.
+  int InsertionPoint = 0;
+  if (ArgVector.size() > 0)
+++InsertionPoint;
+
+  const char *arr[] = {
+  "/Zc:auto", "/Zc:forScope",   "/Zc:implicitNoexcept",
+  "/Zc:sizedDealloc", "/Zc:threadSafeInit", "/Zc:wchar_t"};
+
+  ArgVector.insert(ArgVector.begin() + InsertionPoint, std::begin(arr),
+   std::end(arr));
+}
+
 static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver,
SmallVectorImpl &Opts) {
   llvm::cl::TokenizeWindowsCommandLine(EnvValue, Saver, Opts);
@@ -473,6 +492,9 @@
 
   insertTargetAndModeArgs(TargetAndMode, Args, SavedStrings);
 
+  if (ClangCLMode)
+insertDefaultClangCLZcConformanceArgs(Args);
+
   SetBackdoorDriverOutputsFromEnvVars(TheDriver);
 
   if (!UseNewCC1Process) {
Index: clang/test/Driver/cl-zc.cpp
===
--- clang/test/Driver/cl-zc.cpp
+++ clang/test/Driver/cl-zc.cpp
@@ -1,6 +1,9 @@
 // Note: %s must be preceded by --, otherwise it may be interpreted as a
 // command-line option, e.g. on Mac where %s is commonly under /Users.
 
+// RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=DEFAULT %s
+// DEFAULT: "-fsized-deallocation"
+
 // RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=TRIGRAPHS-DEFAULT %s
 // cc1 will di

[PATCH] D127641: [clang-cl][MSVC] Add default /Zc conformance arguments

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong added reviewers: rnk, hans, thakis.
steplong added a comment.

I'm not sure how to check for `/std:` at this stage to turn on arguments like 
`/Zc:alignedNew`




Comment at: clang/test/Driver/cl-zc.cpp:98
 // thread safe statics are off for versions < 19.
 // RUN: %clang_cl /c -### -fms-compatibility-version=18 -- %s 2>&1 | FileCheck 
-check-prefix=NoThreadSafeStatics %s
 // RUN: %clang_cl /Zc:threadSafeInit /Zc:threadSafeInit- /c -### -- %s 2>&1 | 
FileCheck -check-prefix=NoThreadSafeStatics %s

This line will fail, but I can't find any documentation on thread safe statics 
being off for versions < 19. 
https://docs.microsoft.com/en-us/cpp/build/reference/zc-threadsafeinit-thread-safe-local-static-initialization?view=msvc-170
 says Visual Studio 2015 implements this by default.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127641/new/

https://reviews.llvm.org/D127641

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


[PATCH] D127452: [clang-cl][MSVC] Map /external:Wn n=1-4 to -Wsystem-headers

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 436394.
steplong added a comment.

- Rebase patch


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127452/new/

https://reviews.llvm.org/D127452

Files:
  clang/include/clang/Driver/Options.td
  clang/test/Driver/cl-options.c


Index: clang/test/Driver/cl-options.c
===
--- clang/test/Driver/cl-options.c
+++ clang/test/Driver/cl-options.c
@@ -752,4 +752,12 @@
 // RUN: %clang_cl /JMC /Z7 /c -### -- %s 2>&1 | FileCheck %s --check-prefix JMC
 // JMC: -fjmc
 
+// RUN: %clang_cl /external:W0 /c -### -- %s 2>&1 | FileCheck 
-check-prefix=EXTERNAL_W0 %s
+// RUN: %clang_cl /external:W1 /c -### -- %s 2>&1 | FileCheck 
-check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W2 /c -### -- %s 2>&1 | FileCheck 
-check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W3 /c -### -- %s 2>&1 | FileCheck 
-check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W4 /c -### -- %s 2>&1 | FileCheck 
-check-prefix=EXTERNAL_Wn %s
+// EXTERNAL_W0: "-Wno-system-headers"
+// EXTERNAL_Wn: "-Wsystem-headers"
+
 void f(void) { }
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -775,6 +775,8 @@
   MetaVarName<"">;
 def Wall : Flag<["-"], "Wall">, Group, Flags<[CC1Option, HelpHidden]>;
 def WCL4 : Flag<["-"], "WCL4">, Group, Flags<[CC1Option, HelpHidden]>;
+def Wsystem_headers : Flag<["-"], "Wsystem-headers">, Group, 
Flags<[CC1Option, HelpHidden]>;
+def Wno_system_headers : Flag<["-"], "Wno-system-headers">, Group, 
Flags<[CC1Option, HelpHidden]>;
 def Wdeprecated : Flag<["-"], "Wdeprecated">, Group, 
Flags<[CC1Option]>,
   HelpText<"Enable warnings for deprecated constructs and define 
__DEPRECATED">;
 def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group, 
Flags<[CC1Option]>;
@@ -6468,6 +6470,11 @@
   Alias, AliasArgs<["invalid-source-encoding"]>;
 def _SLASH_validate_charset_ : CLFlag<"validate-charset-">,
   Alias, AliasArgs<["no-invalid-source-encoding"]>;
+def _SLASH_external_W0 : CLFlag<"external:W0">, HelpText<"Ignore warnings from 
system headers (default)">, Alias;
+def _SLASH_external_W1 : CLFlag<"external:W1">, HelpText<"Enable 
-Wsystem-headers">, Alias;
+def _SLASH_external_W2 : CLFlag<"external:W2">, HelpText<"Enable 
-Wsystem-headers">, Alias;
+def _SLASH_external_W3 : CLFlag<"external:W3">, HelpText<"Enable 
-Wsystem-headers">, Alias;
+def _SLASH_external_W4 : CLFlag<"external:W4">, HelpText<"Enable 
-Wsystem-headers">, Alias;
 def _SLASH_W0 : CLFlag<"W0">, HelpText<"Disable all warnings">, Alias;
 def _SLASH_W1 : CLFlag<"W1">, HelpText<"Enable -Wall">, Alias;
 def _SLASH_W2 : CLFlag<"W2">, HelpText<"Enable -Wall">, Alias;


Index: clang/test/Driver/cl-options.c
===
--- clang/test/Driver/cl-options.c
+++ clang/test/Driver/cl-options.c
@@ -752,4 +752,12 @@
 // RUN: %clang_cl /JMC /Z7 /c -### -- %s 2>&1 | FileCheck %s --check-prefix JMC
 // JMC: -fjmc
 
+// RUN: %clang_cl /external:W0 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_W0 %s
+// RUN: %clang_cl /external:W1 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W2 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W3 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W4 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s
+// EXTERNAL_W0: "-Wno-system-headers"
+// EXTERNAL_Wn: "-Wsystem-headers"
+
 void f(void) { }
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -775,6 +775,8 @@
   MetaVarName<"">;
 def Wall : Flag<["-"], "Wall">, Group, Flags<[CC1Option, HelpHidden]>;
 def WCL4 : Flag<["-"], "WCL4">, Group, Flags<[CC1Option, HelpHidden]>;
+def Wsystem_headers : Flag<["-"], "Wsystem-headers">, Group, Flags<[CC1Option, HelpHidden]>;
+def Wno_system_headers : Flag<["-"], "Wno-system-headers">, Group, Flags<[CC1Option, HelpHidden]>;
 def Wdeprecated : Flag<["-"], "Wdeprecated">, Group, Flags<[CC1Option]>,
   HelpText<"Enable warnings for deprecated constructs and define __DEPRECATED">;
 def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group, Flags<[CC1Option]>;
@@ -6468,6 +6470,11 @@
   Alias, AliasArgs<["invalid-source-encoding"]>;
 def _SLASH_validate_charset_ : CLFlag<"validate-charset-">,
   Alias, AliasArgs<["no-invalid-source-encoding"]>;
+def _SLASH_external_W0 : CLFlag<"external:W0">, HelpText<"Ignore warnings from system headers (default)">, Alias;
+def _SLASH_external_W1 : CLFlag<"external:W1">, HelpText<"Enable -Wsystem-headers">, Alias;
+def _SLASH_external_W2 : CLFlag<"external:W2">, HelpText<"Enable -Wsystem-hea

[PATCH] D127519: [clang-cl] Accept /FA[c][s][u], but ignore the arguments

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 436436.
steplong added a comment.

- Removed SLASH_FA_joined and made SLASH_FA a CLJoined
- Add some /FAcsu tests. Just copies of /FA tests, but passing /FAcsu


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127519/new/

https://reviews.llvm.org/D127519

Files:
  clang/include/clang/Driver/Options.td
  clang/test/Driver/cl-options.c
  clang/test/Driver/cl-outputs.c


Index: clang/test/Driver/cl-outputs.c
===
--- clang/test/Driver/cl-outputs.c
+++ clang/test/Driver/cl-outputs.c
@@ -238,6 +238,28 @@
 // FaMULTIPLESOURCEOK: "-o" "cl-outputs.asm"
 // FaMULTIPLESOURCEOK: "-o" "cl-outputs.asm"
 
+// Copy of the same tests above, but with /FAcsu
+// RUN: %clang_cl /FAcsu -### -- %s 2>&1 | FileCheck -check-prefix=FA_CSU %s
+// FA_CSU: "-o" "cl-outputs.asm"
+// RUN: %clang_cl /FAcsu /Fa -### -- %s 2>&1 | FileCheck 
-check-prefix=FA_CSU_FaEMPTY %s
+// FA_CSU_FaEMPTY: "-o" "cl-outputs.asm"
+// RUN: %clang_cl /FAcsu /Fafoo -### -- %s 2>&1 | FileCheck 
-check-prefix=FA_CSU_FaNAME %s
+// RUN: %clang_cl /Fafoo -### -- %s 2>&1 | FileCheck 
-check-prefix=FA_CSU_FaNAME %s
+// FA_CSU_FaNAME:  "-o" "foo.asm"
+// RUN: %clang_cl /FAcsu /Faa.ext /Fab.ext -### -- %s 2>&1 | FileCheck 
-check-prefix=FA_CSU_FaNAMEEXT %s
+// FA_CSU_FaNAMEEXT:  "-o" "b.ext"
+// RUN: %clang_cl /FAcsu /Fafoo.dir/ -### -- %s 2>&1 | FileCheck 
-check-prefix=FA_CSU_FaDIR %s
+// FA_CSU_FaDIR:  "-o" "foo.dir{{[/\\]+}}cl-outputs.asm"
+// RUN: %clang_cl /FAcsu /Fafoo.dir/a -### -- %s 2>&1 | FileCheck 
-check-prefix=FA_CSU_FaDIRNAME %s
+// FA_CSU_FaDIRNAME:  "-o" "foo.dir{{[/\\]+}}a.asm"
+// RUN: %clang_cl /FAcsu /Fafoo.dir/a.ext -### -- %s 2>&1 | FileCheck 
-check-prefix=FA_CSU_FaDIRNAMEEXT %s
+// FA_CSU_FaDIRNAMEEXT:  "-o" "foo.dir{{[/\\]+}}a.ext"
+// RUN: %clang_cl /Faa.asm -### -- %s %s 2>&1 | FileCheck 
-check-prefix=FA_CSU_FaMULTIPLESOURCE %s
+// FA_CSU_FaMULTIPLESOURCE: error: cannot specify '/Faa.asm' when compiling 
multiple source files
+// RUN: %clang_cl /Fa -### -- %s %s 2>&1 | FileCheck 
-check-prefix=FA_CSU_FaMULTIPLESOURCEOK %s
+// FA_CSU_FaMULTIPLESOURCEOK: "-o" "cl-outputs.asm"
+// FA_CSU_FaMULTIPLESOURCEOK: "-o" "cl-outputs.asm"
+
 // RUN: %clang_cl /P -### -- %s 2>&1 | FileCheck -check-prefix=P %s
 // P: "-E"
 // P: "-o" "cl-outputs.i"
Index: clang/test/Driver/cl-options.c
===
--- clang/test/Driver/cl-options.c
+++ clang/test/Driver/cl-options.c
@@ -65,20 +65,29 @@
 
 // RUN: %clang_cl -### /FA -fprofile-instr-generate -- %s 2>&1 | FileCheck 
-check-prefix=CHECK-PROFILE-INSTR-GENERATE %s
 // RUN: %clang_cl -### /FA -fprofile-instr-generate=/tmp/somefile.profraw -- 
%s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE-FILE %s
+// RUN: %clang_cl -### /FAcsu -fprofile-instr-generate -- %s 2>&1 | FileCheck 
-check-prefix=CHECK-PROFILE-INSTR-GENERATE %s
+// RUN: %clang_cl -### /FAcsu -fprofile-instr-generate=/tmp/somefile.profraw 
-- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE-FILE %s
 // CHECK-PROFILE-INSTR-GENERATE: "-fprofile-instrument=clang" 
"--dependent-lib=clang_rt.profile{{[^"]*}}.lib"
 // CHECK-PROFILE-INSTR-GENERATE-FILE: 
"-fprofile-instrument-path=/tmp/somefile.profraw"
 
 // RUN: %clang_cl -### /FA -fprofile-generate -- %s 2>&1 | FileCheck 
-check-prefix=CHECK-PROFILE-GENERATE %s
+// RUN: %clang_cl -### /FAcsu -fprofile-generate -- %s 2>&1 | FileCheck 
-check-prefix=CHECK-PROFILE-GENERATE %s
 // CHECK-PROFILE-GENERATE: "-fprofile-instrument=llvm" 
"--dependent-lib=clang_rt.profile{{[^"]*}}.lib"
 
 // RUN: %clang_cl -### /FA -fprofile-instr-generate -fprofile-instr-use -- %s 
2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-GEN-USE %s
 // RUN: %clang_cl -### /FA -fprofile-instr-generate -fprofile-instr-use=file 
-- %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-GEN-USE %s
+// RUN: %clang_cl -### /FAcsu -fprofile-instr-generate -fprofile-instr-use -- 
%s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-GEN-USE %s
+// RUN: %clang_cl -### /FAcsu -fprofile-instr-generate 
-fprofile-instr-use=file -- %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-MIX-GEN-USE %s
 // CHECK-NO-MIX-GEN-USE: '{{[a-z=-]*}}' not allowed with '{{[a-z=-]*}}'
 
 // RUN: %clang_cl -### /FA -fprofile-instr-use -- %s 2>&1 | FileCheck 
-check-prefix=CHECK-PROFILE-USE %s
 // RUN: %clang_cl -### /FA -fprofile-use -- %s 2>&1 | FileCheck 
-check-prefix=CHECK-PROFILE-USE %s
 // RUN: %clang_cl -### /FA -fprofile-instr-use=/tmp/somefile.prof -- %s 2>&1 | 
FileCheck -check-prefix=CHECK-PROFILE-USE-FILE %s
 // RUN: %clang_cl -### /FA -fprofile-use=/tmp/somefile.prof -- %s 2>&1 | 
FileCheck -check-prefix=CHECK-PROFILE-USE-FILE %s
+// RUN: %clang_cl -### /FAcsu -fprofile-instr-use -- %s 2>&1 | FileCheck 
-check-prefix=CHECK-PROFILE-USE %s
+// RUN: %clang_cl -### /FAcsu -fprofile-use -- %s 2>&1 | FileCheck 
-check-prefix=CHECK-PROFILE-USE %s
+// RUN: %clan

[PATCH] D126984: [clang] Add initial support for gcc's optimize function attribute

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 436443.
steplong added a comment.

- Add llvm::Attribute::MinSize when OptimizeAttr::Oz
- Add test for checking minsize


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126984/new/

https://reviews.llvm.org/D126984

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/attr-optimize.c
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/Sema/attr-optimize.c

Index: clang/test/Sema/attr-optimize.c
===
--- /dev/null
+++ clang/test/Sema/attr-optimize.c
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+
+__attribute__((optimize(a))) // expected-error {{use of undeclared identifier 'a'}}
+void
+f1() {}
+
+int b = 1;
+__attribute__((optimize(b))) // expected-error {{'optimize' attribute requires a string}}
+void
+f2() {}
+
+__attribute__((optimize("O0", "O1"))) // expected-error {{'optimize' attribute takes one argument}}
+void
+f3() {}
+
+__attribute__((optimize("Og"))) // expected-no-error
+void
+f4() {}
+
+__attribute__((optimize("O-1"))) // expected-warning {{invalid optimization level 'O-1' specified; the argument to '-O' should be a non-negative integer, '-Os', '-Oz', '-Og', or '-Ofast'; attribute ignored}}
+void
+f5() {}
+
+__attribute__((optimize("O+1"))) // expected-warning {{invalid optimization level 'O+1' specified; the argument to '-O' should be a non-negative integer, '-Os', '-Oz', '-Og', or '-Ofast'; attribute ignored}}
+void
+f6() {}
+
+__attribute__((optimize("O0"))) // expected-no-error
+void
+f7() {}
+
+__attribute__((optimize("Os"))) // expected-no-error
+void
+f8() {}
+
+__attribute__((optimize("O44"))) // expected-no-error
+void
+f9() {}
+
+__attribute__((optimize("Oz"))) // expected-no-error
+void
+f10() {}
+
+__attribute__((optimize("Ofast"))) // expected-no-error
+void
+f11() {}
+
+__attribute__((optimize("O"))) // expected-no-error
+void
+f12() {}
+
+__attribute__((optimize("O0"))) // expected-error {{expected identifier or '('}}
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -142,6 +142,7 @@
 // CHECK-NEXT: ObjCSubclassingRestricted (SubjectMatchRule_objc_interface)
 // CHECK-NEXT: OpenCLIntelReqdSubGroupSize (SubjectMatchRule_function)
 // CHECK-NEXT: OpenCLNoSVM (SubjectMatchRule_variable)
+// CHECK-NEXT: Optimize (SubjectMatchRule_function)
 // CHECK-NEXT: OptimizeNone (SubjectMatchRule_function, SubjectMatchRule_objc_method)
 // CHECK-NEXT: Overloadable (SubjectMatchRule_function)
 // CHECK-NEXT: Owner (SubjectMatchRule_record_not_is_union)
Index: clang/test/CodeGen/attr-optimize.c
===
--- /dev/null
+++ clang/test/CodeGen/attr-optimize.c
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -O2 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=O2
+// RUN: %clang_cc1 -O0 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=O0
+
+__attribute__((optimize("O0"))) void f1(void) {}
+// O2: @f1{{.*}}[[ATTR_OPTNONE:#[0-9]+]]
+// O0: @f1{{.*}}[[ATTR_OPTNONE:#[0-9]+]]
+
+__attribute__((optimize("Os"))) void f2(void) {}
+// O2: @f2{{.*}}[[ATTR_OPTSIZE:#[0-9]+]]
+// O0: @f2{{.*}}[[ATTR_OPTNONE]]
+
+__attribute__((optimize("Og"))) void f3(void) {}
+// O2: @f3{{.*}}[[ATTR_OPTSIZE]]
+// O0: @f3{{.*}}[[ATTR_OPTNONE]]
+
+__attribute__((optimize("Oz"))) void f4(void) {}
+// O2: @f4{{.*}}[[ATTR_MINSIZE:#[0-9]+]]
+// O0: @f4{{.*}}[[ATTR_OPTNONE]]
+
+__attribute__((optimize("Ofast"))) void f5(void) {}
+// O2: @f5{{.*}}[[ATTR_OPTSIZE]]
+// O0: @f5{{.*}}[[ATTR_OPTNONE]]
+
+// O2: attributes [[ATTR_OPTNONE]] = { {{.*}}optnone{{.*}} }
+// O2: attributes [[ATTR_OPTSIZE]] = { {{.*}}optsize{{.*}} }
+// O2: attributes [[ATTR_MINSIZE]] = { {{.*}}minsize{{.*}}optsize{{.*}} }
+
+// Check that O0 overrides the attribute
+// O0: attributes [[ATTR_OPTNONE]] = { {{.*}}optnone{{.*}} }
Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -4833,6 +4833,46 @@
 D->addAttr(Optnone);
 }
 
+static void handleOptimizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  StringRef Arg;
+  if (!S.checkStringLiteralArgumentAttr(AL, 0, Arg))
+return;
+
+  StringRef Level;
+  // Check if argument is prefixed with "-O" or "O"
+  if (Arg.str().rfind("-O", 0) == 0)
+Level = Arg.substr(2);
+  else if (Arg.str().rfind("O", 0) == 0)
+Level = Arg.substr(1);
+  else
+S.Diag

[PATCH] D125723: [MSVC] Add support for MSVC pragma optimize

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong updated this revision to Diff 436476.
steplong added a comment.

- Parse the string in the pragma
- Some of the tests should fail. I'll fix them up once D126984 
 looks good


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125723/new/

https://reviews.llvm.org/D125723

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGen/pragma-msvc-optimize.c
  clang/test/Preprocessor/pragma_microsoft.c

Index: clang/test/Preprocessor/pragma_microsoft.c
===
--- clang/test/Preprocessor/pragma_microsoft.c
+++ clang/test/Preprocessor/pragma_microsoft.c
@@ -228,7 +228,12 @@
 #pragma optimize("g"  // expected-warning{{expected ',' in '#pragma optimize'}}
 #pragma optimize("g", // expected-warning{{missing argument to '#pragma optimize'; expected 'on' or 'off'}}
 #pragma optimize("g",xyz  // expected-warning{{unexpected argument 'xyz' to '#pragma optimize'; expected 'on' or 'off'}}
-#pragma optimize("g",on)  // expected-warning{{#pragma optimize' is not supported}}
+#pragma optimize("g",on)  // no-warning
+#pragma optimize("g", on) asdf // expected-warning{{extra tokens at end of '#pragma optimize'}}
+
+void pragma_optimize_foo() {
+#pragma optimize("g", on) // expected-error {{'#pragma optimize' can only appear at file scope}}
+}
 
 #pragma execution_character_set // expected-warning {{expected '('}}
 #pragma execution_character_set(// expected-warning {{expected 'push' or 'pop'}}
Index: clang/test/CodeGen/pragma-msvc-optimize.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-msvc-optimize.c
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -O2 -emit-llvm -fms-extensions -o - %s | FileCheck %s -check-prefix CHECK-O2
+// RUN: %clang_cc1 -O0 -emit-llvm -fms-extensions -o - %s | FileCheck %s -check-prefix CHECK-O0
+// RUN: %clang_cc1 -Os -emit-llvm -fms-extensions -o - %s | FileCheck %s -check-prefix CHECK-Os
+
+#pragma optimize("s", on)
+
+// CHECK-O2: define{{.*}} void @f0(){{.*}} #[[OPTSIZE:[0-9]+]]
+void f0() {}
+
+#pragma optimize("y", on)
+
+// CHECK-O2: define{{.*}} void @f1(){{.*}} #[[OPTSIZE_FRAMEPTR_NONLEAF:[0-9]+]]
+void f1() {}
+
+#pragma optimize("t", on)
+
+// CHECK-O2: define{{.*}} void @f2(){{.*}} #[[OPTSIZE_FRAMEPTR_NONLEAF]]
+// CHECK-O0: define{{.*}} void @f2(){{.*}} #[[NO_OPTNONE:[0-9]+]]
+void f2() {}
+
+#pragma optimize("s", off)
+
+// CHECK-O2: define{{.*}} void @f3(){{.*}} #[[FRAMEPTR_NONLEAF:[0-9]+]]
+// CHECK-Os: define{{.*}} void @f3(){{.*}} #[[FRAMEPTR_NONLEAF:[0-9]+]]
+void f3() {}
+
+#pragma optimize("y", off)
+
+// CHECK-O2: define{{.*}} void @f4(){{.*}} #[[FRAMEPTR_NONE:[0-9]+]]
+void f4() {}
+
+#pragma optimize("t", off)
+
+// CHECK-O2: define{{.*}} void @f5(){{.*}} #[[OPTNONE_FRAMEPTR_NONE:[0-9]+]]
+void f5() {}
+
+// CHECK-O2: attributes #[[OPTSIZE]] = {{{.*}}optsize{{.*}}}
+// CHECK-O2-NOT: attributes #[[OPTSIZE]] = {{{.*}}optsize{{.*}}"frame-pointer"="non-leaf"{{.*}}}
+// CHECK-O2: attributes #[[OPTSIZE_FRAMEPTR_NONLEAF]] = {{{.*}}optsize{{.*}}"frame-pointer"="non-leaf"{{.*}}}
+// CHECK-O2: attributes #[[FRAMEPTR_NONLEAF]] = {{{.*}}"frame-pointer"="non-leaf"{{.*}}}
+// CHECK-O2-NOT: attributes #[[FRAMEPTR_NONLEAF]] = {{{.*}}optsize{{.*}}"frame-pointer"="non-leaf"{{.*}}}
+// CHECK-O2: attributes #[[FRAMEPTR_NONE]] = {{{.*}}"frame-pointer"="none"{{.*}}}
+// CHECK-O2: attributes #[[OPTNONE_FRAMEPTR_NONE]] = {{{.*}}optnone{{.*}}"frame-pointer"="none"{{.*}}}
+
+// CHECK-O0-NOT: attributes #[[NO_OPTNONE]] = {{{.*}}optnone{{.*}}}
+
+// CHECK-Os: attributes #[[FRAMEPTR_NONLEAF]] = {{{.*}}"frame-pointer"="non-leaf"{{.*}}}
+// CHECK-Os-NOT: attributes #[[FRAMEPTR_NONLEAF]] = {{{.*}}optsize{{.*}}"frame-pointer"="non-leaf"{{.*}}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -10192,6 +10192,7 @@
 AddRangeBasedOptnone(NewFD);
 AddImplicitMSFunctionNoBuiltinAttr(NewFD);
 AddSectionMSAllocText(NewFD);
+ModifyFnAttributesMSPragmaOptimize(NewFD);
   }
 
   // If this is the first declaration of an extern C variable, update
Index: clang/lib/Sema/SemaAttr.cpp
===
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1096,6 +1096,17 @@
 OptimizeOffPragmaLocation = PragmaLoc;
 }
 
+void Sema::ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn,
+ std::string ValidOptimizationList) {
+  if (!CurContext->getRedeclContext()->isFileContext()) {
+Diag(Loc, diag::err_pragma_expected_fil

[PATCH] D125723: [MSVC] Add support for MSVC pragma optimize

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong added inline comments.



Comment at: clang/include/clang/Sema/Sema.h:768
+  /// (i.e. `ModifyFnAttributeMSPragmaOptimze()` does nothing)
+  bool MSPragmaOptimizeIsOn = true;
+

This might be confusing. `ModifyFnAttributeMSPragmaOptimize()` adds optnone to 
functions if `MSPragmaOptimizeIsOn` is false and `MSPragmaOptimizeValidParams` 
is empty.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125723/new/

https://reviews.llvm.org/D125723

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


[PATCH] D126984: [clang] Add initial support for gcc's optimize function attribute

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong added a comment.

>> and even for the MSVC pragma `#pragma optimize("t", on)`, what are we 
>> supporting if the user compiles their code with `-O0`? because right now we 
>> won't optimize anything with `-O0`
>
> @steplong -- what are your thoughts on this?

Hmm, I think I'm ok with ignoring the pragma when "-O0". In the case of "t", at 
the moment, we are just going to honor whatever is passed on the commandline. I 
think with what the patch looks like now, we'll be supporting the pragma 
optimize like:

| Parameter | On   | Off
|
| - |  |
|
| g | Deprecated   | Deprecated 
|
| s | Add OptimizeAttr::Os | Add Optnone (Not sure if this makes sense) 
|
| t | Do nothing   | Add Optnone
|
| y | Do nothing   | Do nothing 
|


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126984/new/

https://reviews.llvm.org/D126984

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


[PATCH] D127452: [clang-cl][MSVC] Map /external:Wn n=1-4 to -Wsystem-headers

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGee6ad7af45a0: [clang-cl][MSVC] Map /external:Wn n=1-4 to 
-Wsystem-headers (authored by steplong).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127452/new/

https://reviews.llvm.org/D127452

Files:
  clang/include/clang/Driver/Options.td
  clang/test/Driver/cl-options.c


Index: clang/test/Driver/cl-options.c
===
--- clang/test/Driver/cl-options.c
+++ clang/test/Driver/cl-options.c
@@ -752,4 +752,12 @@
 // RUN: %clang_cl /JMC /Z7 /c -### -- %s 2>&1 | FileCheck %s --check-prefix JMC
 // JMC: -fjmc
 
+// RUN: %clang_cl /external:W0 /c -### -- %s 2>&1 | FileCheck 
-check-prefix=EXTERNAL_W0 %s
+// RUN: %clang_cl /external:W1 /c -### -- %s 2>&1 | FileCheck 
-check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W2 /c -### -- %s 2>&1 | FileCheck 
-check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W3 /c -### -- %s 2>&1 | FileCheck 
-check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W4 /c -### -- %s 2>&1 | FileCheck 
-check-prefix=EXTERNAL_Wn %s
+// EXTERNAL_W0: "-Wno-system-headers"
+// EXTERNAL_Wn: "-Wsystem-headers"
+
 void f(void) { }
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -775,6 +775,8 @@
   MetaVarName<"">;
 def Wall : Flag<["-"], "Wall">, Group, Flags<[CC1Option, HelpHidden]>;
 def WCL4 : Flag<["-"], "WCL4">, Group, Flags<[CC1Option, HelpHidden]>;
+def Wsystem_headers : Flag<["-"], "Wsystem-headers">, Group, 
Flags<[CC1Option, HelpHidden]>;
+def Wno_system_headers : Flag<["-"], "Wno-system-headers">, Group, 
Flags<[CC1Option, HelpHidden]>;
 def Wdeprecated : Flag<["-"], "Wdeprecated">, Group, 
Flags<[CC1Option]>,
   HelpText<"Enable warnings for deprecated constructs and define 
__DEPRECATED">;
 def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group, 
Flags<[CC1Option]>;
@@ -6475,6 +6477,11 @@
   Alias, AliasArgs<["invalid-source-encoding"]>;
 def _SLASH_validate_charset_ : CLFlag<"validate-charset-">,
   Alias, AliasArgs<["no-invalid-source-encoding"]>;
+def _SLASH_external_W0 : CLFlag<"external:W0">, HelpText<"Ignore warnings from 
system headers (default)">, Alias;
+def _SLASH_external_W1 : CLFlag<"external:W1">, HelpText<"Enable 
-Wsystem-headers">, Alias;
+def _SLASH_external_W2 : CLFlag<"external:W2">, HelpText<"Enable 
-Wsystem-headers">, Alias;
+def _SLASH_external_W3 : CLFlag<"external:W3">, HelpText<"Enable 
-Wsystem-headers">, Alias;
+def _SLASH_external_W4 : CLFlag<"external:W4">, HelpText<"Enable 
-Wsystem-headers">, Alias;
 def _SLASH_W0 : CLFlag<"W0">, HelpText<"Disable all warnings">, Alias;
 def _SLASH_W1 : CLFlag<"W1">, HelpText<"Enable -Wall">, Alias;
 def _SLASH_W2 : CLFlag<"W2">, HelpText<"Enable -Wall">, Alias;


Index: clang/test/Driver/cl-options.c
===
--- clang/test/Driver/cl-options.c
+++ clang/test/Driver/cl-options.c
@@ -752,4 +752,12 @@
 // RUN: %clang_cl /JMC /Z7 /c -### -- %s 2>&1 | FileCheck %s --check-prefix JMC
 // JMC: -fjmc
 
+// RUN: %clang_cl /external:W0 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_W0 %s
+// RUN: %clang_cl /external:W1 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W2 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W3 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s
+// RUN: %clang_cl /external:W4 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s
+// EXTERNAL_W0: "-Wno-system-headers"
+// EXTERNAL_Wn: "-Wsystem-headers"
+
 void f(void) { }
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -775,6 +775,8 @@
   MetaVarName<"">;
 def Wall : Flag<["-"], "Wall">, Group, Flags<[CC1Option, HelpHidden]>;
 def WCL4 : Flag<["-"], "WCL4">, Group, Flags<[CC1Option, HelpHidden]>;
+def Wsystem_headers : Flag<["-"], "Wsystem-headers">, Group, Flags<[CC1Option, HelpHidden]>;
+def Wno_system_headers : Flag<["-"], "Wno-system-headers">, Group, Flags<[CC1Option, HelpHidden]>;
 def Wdeprecated : Flag<["-"], "Wdeprecated">, Group, Flags<[CC1Option]>,
   HelpText<"Enable warnings for deprecated constructs and define __DEPRECATED">;
 def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group, Flags<[CC1Option]>;
@@ -6475,6 +6477,11 @@
   Alias, AliasArgs<["invalid-source-encoding"]>;
 def _SLASH_validate_charset_ : CLFlag<"validate-charset-">,
   Alias, AliasArgs<["no-invalid-source-encoding"]>;
+def _SLASH_external_W0 : CLFlag<"external:W0">, HelpText<"Ignore warnings from system headers (default)">, Alias;
+def _SLASH_e

[PATCH] D125722: [Attribute] Add clang optsize attribute

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong abandoned this revision.
steplong added a comment.

Abandoning in favor of D126984 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125722/new/

https://reviews.llvm.org/D125722

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


[PATCH] D125720: [Attribute] Add clang frame_pointer attribute

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong abandoned this revision.
steplong added a comment.

Abandoning in favor of D126984 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125720/new/

https://reviews.llvm.org/D125720

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


[PATCH] D125719: [Attribute] Add attribute NeverOptimizeNone

2022-06-13 Thread Stephen Long via Phabricator via cfe-commits
steplong abandoned this revision.
steplong added a comment.

Abandoning in favor of D126984 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125719/new/

https://reviews.llvm.org/D125719

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


  1   2   >