[PATCH] D138846: MC/DC in LLVM Source-Based Code Coverage: LLVM back-end and compiler-rt

2023-09-20 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

I'm still working on a repro, but after this patch we're seeing "truncated 
profile data" errors in chromium


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D138846

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


[PATCH] D157762: Implement [[msvc::no_unique_address]]

2023-09-07 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

turned this into a github PR  
https://github.com/llvm/llvm-project/pull/65675/commits/923a43cd6386f6e57023fd8928eed0dc0ab04d57


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157762

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


[PATCH] D157762: Implement [[msvc::no_unique_address]]

2023-09-06 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 556091.
akhuang added a comment.

add note to the docs about no ABI compatibility


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157762

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/AST/Decl.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/Layout/ms-no-unique-address.cpp

Index: clang/test/Layout/ms-no-unique-address.cpp
===
--- /dev/null
+++ clang/test/Layout/ms-no-unique-address.cpp
@@ -0,0 +1,338 @@
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-windows-msvc -fms-compatibility -fdump-record-layouts %s | FileCheck %s
+
+namespace Empty {
+  struct A {};
+  struct A2 {};
+  struct A3 { [[msvc::no_unique_address]] A a; };
+  struct alignas(8) A4 {};
+
+  struct B {
+[[msvc::no_unique_address]] A a;
+char b;
+  };
+  static_assert(sizeof(B) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::B
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   char b
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct C {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] A2 a2;
+char c;
+  };
+  static_assert(sizeof(C) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::C
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   struct Empty::A2 a2 (empty)
+  // CHECK-NEXT: 0 |   char c
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct D {
+[[msvc::no_unique_address]] A3 a;
+int i;
+  };
+  static_assert(sizeof(D) == 8);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::D
+  // CHECK-NEXT: 0 |   struct Empty::A3 a (empty)
+  // CHECK-NEXT: 0 | struct Empty::A a (empty)
+  // CHECK-NEXT: 4 |   int i
+  // CHECK-NEXT:   | [sizeof=8, align=4,
+  // CHECK-NEXT:   |  nvsize=8, nvalign=4]
+
+  struct E {
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char e;
+  };
+  static_assert(sizeof(E) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::E
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char e
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct F {
+~F();
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char f;
+  };
+  static_assert(sizeof(F) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::F
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char f
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct G { [[msvc::no_unique_address]] A a; ~G(); };
+  static_assert(sizeof(G) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::G
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct H {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] A b;
+~H();
+  };
+  static_assert(sizeof(H) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::H
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A b (empty)
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct I {
+[[msvc::no_unique_address]] A4 a;
+[[msvc::no_unique_address]] A4 b;
+  };
+  static_assert(sizeof(I) == 16);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::I
+  // CHECK-NEXT: 0 |   struct Empty::A4 a (empty)
+  // CHECK-NEXT: 8 |   struct Empty::A4 b (empty)
+  // CHECK-NEXT:   | [sizeof=16, align=8,
+  // CHECK-NEXT:   |  nvsize=16, nvalign=8]
+
+  struct J {
+[[msvc::no_unique_address]] A4 a;
+A4 b;
+  };
+  static_assert(sizeof(J) == 16);
+
+  // MSVC puts a and b at the same offset.
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::J
+  // CHECK-NEXT: 0 |   struct Empty::A4 a (empty)
+  // CHECK-NEXT: 8 |   struct Empty::A4 b (empty)
+  // CHECK-NEXT:   | [sizeof=16, align=8,
+  // CHECK-NEXT:   |  nvsize=16, nvalign=8]
+
+  struct K {
+[[msvc::no_unique_address]] A4 a;
+[[msvc::no_unique_address]] char c;
+[[msvc::no_unique_address]] A4 b;
+  

[PATCH] D157762: [WIP] Implement [[msvc::no_unique_address]]

2023-09-06 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 556090.
akhuang added a comment.

more code updates and added some test cases


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157762

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/AST/Decl.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/Layout/ms-no-unique-address.cpp

Index: clang/test/Layout/ms-no-unique-address.cpp
===
--- /dev/null
+++ clang/test/Layout/ms-no-unique-address.cpp
@@ -0,0 +1,338 @@
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-windows-msvc -fms-compatibility -fdump-record-layouts %s | FileCheck %s
+
+namespace Empty {
+  struct A {};
+  struct A2 {};
+  struct A3 { [[msvc::no_unique_address]] A a; };
+  struct alignas(8) A4 {};
+
+  struct B {
+[[msvc::no_unique_address]] A a;
+char b;
+  };
+  static_assert(sizeof(B) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::B
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   char b
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct C {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] A2 a2;
+char c;
+  };
+  static_assert(sizeof(C) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::C
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   struct Empty::A2 a2 (empty)
+  // CHECK-NEXT: 0 |   char c
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct D {
+[[msvc::no_unique_address]] A3 a;
+int i;
+  };
+  static_assert(sizeof(D) == 8);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::D
+  // CHECK-NEXT: 0 |   struct Empty::A3 a (empty)
+  // CHECK-NEXT: 0 | struct Empty::A a (empty)
+  // CHECK-NEXT: 4 |   int i
+  // CHECK-NEXT:   | [sizeof=8, align=4,
+  // CHECK-NEXT:   |  nvsize=8, nvalign=4]
+
+  struct E {
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char e;
+  };
+  static_assert(sizeof(E) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::E
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char e
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct F {
+~F();
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char f;
+  };
+  static_assert(sizeof(F) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::F
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char f
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct G { [[msvc::no_unique_address]] A a; ~G(); };
+  static_assert(sizeof(G) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::G
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct H {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] A b;
+~H();
+  };
+  static_assert(sizeof(H) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::H
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A b (empty)
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct I {
+[[msvc::no_unique_address]] A4 a;
+[[msvc::no_unique_address]] A4 b;
+  };
+  static_assert(sizeof(I) == 16);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::I
+  // CHECK-NEXT: 0 |   struct Empty::A4 a (empty)
+  // CHECK-NEXT: 8 |   struct Empty::A4 b (empty)
+  // CHECK-NEXT:   | [sizeof=16, align=8,
+  // CHECK-NEXT:   |  nvsize=16, nvalign=8]
+
+  struct J {
+[[msvc::no_unique_address]] A4 a;
+A4 b;
+  };
+  static_assert(sizeof(J) == 16);
+
+  // MSVC puts a and b at the same offset.
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::J
+  // CHECK-NEXT: 0 |   struct Empty::A4 a (empty)
+  // CHECK-NEXT: 8 |   struct Empty::A4 b (empty)
+  // CHECK-NEXT:   | [sizeof=16, align=8,
+  // CHECK-NEXT:   |  nvsize=16, nvalign=8]
+
+  struct K {
+[[msvc::no_unique_address]] A4 a;
+[[msvc::no_unique_address]] char c;
+[[msvc::no_unique_address]] A4 b;
+  };
+ 

[PATCH] D158857: [clang][aarch64] Add support for the MS qualifiers __ptr32, __ptr64, __sptr, __uptr for aarch64

2023-08-28 Thread Amy Huang via Phabricator via cfe-commits
akhuang accepted this revision.
akhuang added a comment.
This revision is now accepted and ready to land.

I think this looks good to me. I remember I also had to make this change to 
accept old datalayout strings https://reviews.llvm.org/D67631.


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

https://reviews.llvm.org/D158857

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


[PATCH] D157762: [WIP] Implement [[msvc::no_unique_address]]

2023-08-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 551662.
akhuang added a comment.

address small fixes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157762

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/AST/Decl.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/Layout/ms-no-unique-address.cpp

Index: clang/test/Layout/ms-no-unique-address.cpp
===
--- /dev/null
+++ clang/test/Layout/ms-no-unique-address.cpp
@@ -0,0 +1,310 @@
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-pc-win32 -fdump-record-layouts %s | FileCheck %s
+
+namespace Empty {
+  struct A {};
+  struct A2 {};
+  struct A3 { [[msvc::no_unique_address]] A a; };
+  struct alignas(8) A4 {};
+
+  struct B {
+[[msvc::no_unique_address]] A a;
+char b;
+  };
+  static_assert(sizeof(B) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::B
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   char b
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct C {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] A2 a2;
+char c;
+  };
+  static_assert(sizeof(C) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::C
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   struct Empty::A2 a2 (empty)
+  // CHECK-NEXT: 0 |   char c
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct D {
+[[msvc::no_unique_address]] A3 a;
+int i;
+  };
+  static_assert(sizeof(D) == 8);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::D
+  // CHECK-NEXT: 0 |   struct Empty::A3 a (empty)
+  // CHECK-NEXT: 0 | struct Empty::A a (empty)
+  // CHECK-NEXT: 4 |   int i 
+  // CHECK-NEXT:   | [sizeof=8, align=4,
+  // CHECK-NEXT:   |  nvsize=8, nvalign=4]
+
+  struct E {
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char e;
+  };
+  static_assert(sizeof(E) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::E
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char e
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct F {
+~F();
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char f;
+  };
+  static_assert(sizeof(F) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::F
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char f
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct G { [[msvc::no_unique_address]] A a; ~G(); };
+  static_assert(sizeof(G) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::G
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct H {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] A b;
+~H();
+  };
+  static_assert(sizeof(H) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::H
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A b (empty)
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct I {
+[[msvc::no_unique_address]] A4 a;
+[[msvc::no_unique_address]] A4 b;
+  };
+  static_assert(sizeof(I) == 16);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::I
+  // CHECK-NEXT: 0 |   struct Empty::A4 a (empty)
+  // CHECK-NEXT: 8 |   struct Empty::A4 b (empty)
+  // CHECK-NEXT:   | [sizeof=16, align=8,
+  // CHECK-NEXT:   |  nvsize=16, nvalign=8]
+
+  // FIXME: MSVC puts both fields at offset 0.
+  struct J {
+[[msvc::no_unique_address]] A4 a;
+A4 b;
+  };
+  static_assert(sizeof(J) == 16);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::J
+  // CHECK-NEXT: 0 |   struct Empty::A4 a (empty)
+  // CHECK-NEXT: 8 |   struct Empty::A4 b (empty)
+  // CHECK-NEXT:   | [sizeof=16, align=8,
+  // CHECK-NEXT:   |  nvsize=16, nvalign=8]
+
+  // FIXME: MSVC puts b at offset 1 instead of 8, and the struct size is 8.
+  struct K {
+[[msvc::no_unique_address]] A4 a;
+[[msvc::no_unique_address]] char c;
+

[PATCH] D157762: [WIP] Implement [[msvc::no_unique_address]]

2023-08-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang marked 2 inline comments as done.
akhuang added a comment.

I'm still trying to figure out the MSVC layouts. I used the EmptySubobjects 
class for a lot of the logic, which is not always the same as what MSVC does. 
(some examples of differences in https://godbolt.org/z/6cP554ddb)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157762

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


[PATCH] D157762: [WIP] Implement [[msvc::no_unique_address]]

2023-08-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang marked an inline comment as done.
akhuang added inline comments.



Comment at: clang/lib/AST/Decl.cpp:4523-4524
 bool FieldDecl::isPotentiallyOverlapping() const {
-  return hasAttr() && getType()->getAsCXXRecordDecl();
+  return (hasAttr() ||
+  hasAttr()) &&
+ getType()->getAsCXXRecordDecl();

aaron.ballman wrote:
> akhuang wrote:
> > aaron.ballman wrote:
> > > dblaikie wrote:
> > > > Having to check both of these in several places seems problematic - can 
> > > > we wrap that up somewhere? (or, maybe ideally, is there a way for 
> > > > `msvc::no_unique_address` to map to the actual NoUniqueAddressAttr as a 
> > > > different spelling of the same thing?)
> > > This was why I was hoping we could merge the two in Attr.td, but I'm not 
> > > certain that will be easy.
> > What does merging the two in Attr.td mean? Could we just put the two 
> > spellings in one attribute, or would that make it impossible for clang-cl 
> > to ignore the [[no_unique_address]] spelling
> We can have multiple syntactic spellings for the same semantic attribute 
> (e.g., `__attribute__((foo))` and `__attribute__((bar))` can both map to a 
> single `FooBarAttr` AST node), and we have "accessors" on the AST node that 
> let you tell which spelling was used: 
> https://github.com/llvm/llvm-project/blob/90ecadde62f30275c35fdf7928e3477a41691d21/clang/include/clang/Basic/Attr.td#L4095
> 
> The suggestion Erich and I are thinking of is:
> 
> 1) Add the additional spelling to `NoUniqueAddress`.
> 2) Add accessors to differentiate the spellings.
> 3) Remove the `TargetSpecificAttr` from `NoUniqueAddress`, manually implement 
> those checks in an attribute handler in SemaDeclAttr.cpp.
> 
> Then, anywhere you care about the attribute in general, you can look for 
> `isa`, and anywhere you care about which spelling, you can 
> use `cast(A)->isMSVC()` (or whatever you name the accessors).
Thanks! This patch should implement this, and so far, I don't think there are 
any places outside of SemaDeclAttr where we have to differentiate the two.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157762

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


[PATCH] D157762: [WIP] Implement [[msvc::no_unique_address]]

2023-08-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 551576.
akhuang added a comment.

combine attributes into the same attribute and add accessors


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157762

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/AST/Decl.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/Layout/ms-no-unique-address.cpp

Index: clang/test/Layout/ms-no-unique-address.cpp
===
--- /dev/null
+++ clang/test/Layout/ms-no-unique-address.cpp
@@ -0,0 +1,310 @@
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-pc-win32 -fdump-record-layouts %s | FileCheck %s
+
+namespace Empty {
+  struct A {};
+  struct A2 {};
+  struct A3 { [[msvc::no_unique_address]] A a; };
+  struct alignas(8) A4 {};
+
+  struct B {
+[[msvc::no_unique_address]] A a;
+char b;
+  };
+  static_assert(sizeof(B) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::B
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   char b
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct C {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] A2 a2;
+char c;
+  };
+  static_assert(sizeof(C) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::C
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   struct Empty::A2 a2 (empty)
+  // CHECK-NEXT: 0 |   char c
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct D {
+[[msvc::no_unique_address]] A3 a;
+int i;
+  };
+  static_assert(sizeof(D) == 8);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::D
+  // CHECK-NEXT: 0 |   struct Empty::A3 a (empty)
+  // CHECK-NEXT: 0 | struct Empty::A a (empty)
+  // CHECK-NEXT: 4 |   int i 
+  // CHECK-NEXT:   | [sizeof=8, align=4,
+  // CHECK-NEXT:   |  nvsize=8, nvalign=4]
+
+  struct E {
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char e;
+  };
+  static_assert(sizeof(E) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::E
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char e
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct F {
+~F();
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char f;
+  };
+  static_assert(sizeof(F) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::F
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char f
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct G { [[msvc::no_unique_address]] A a; ~G(); };
+  static_assert(sizeof(G) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::G
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct H {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] A b;
+~H();
+  };
+  static_assert(sizeof(H) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::H
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A b (empty)
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct I {
+[[msvc::no_unique_address]] A4 a;
+[[msvc::no_unique_address]] A4 b;
+  };
+  static_assert(sizeof(I) == 16);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::I
+  // CHECK-NEXT: 0 |   struct Empty::A4 a (empty)
+  // CHECK-NEXT: 8 |   struct Empty::A4 b (empty)
+  // CHECK-NEXT:   | [sizeof=16, align=8,
+  // CHECK-NEXT:   |  nvsize=16, nvalign=8]
+
+  // FIXME: MSVC puts both fields at offset 0.
+  struct J {
+[[msvc::no_unique_address]] A4 a;
+A4 b;
+  };
+  static_assert(sizeof(J) == 16);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::J
+  // CHECK-NEXT: 0 |   struct Empty::A4 a (empty)
+  // CHECK-NEXT: 8 |   struct Empty::A4 b (empty)
+  // CHECK-NEXT:   | [sizeof=16, align=8,
+  // CHECK-NEXT:   |  nvsize=16, nvalign=8]
+
+  // FIXME: MSVC puts b at offset 1 instead of 8, and the struct size is 8.
+  struct K {
+[[msvc::no_unique_address]] A4 a;
+

[PATCH] D157762: [WIP] Implement [[msvc::no_unique_address]]

2023-08-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang marked an inline comment as done.
akhuang added inline comments.



Comment at: clang/include/clang/Basic/AttrDocs.td:1410
+  For Windows targets, ``[[no_unique_address]]`` is ignored, but there is a
+  similar attribute spelled ``[[msvc::no_unique_address]]``.
   }];

aaron.ballman wrote:
> "similar" makes me wonder "so how is it different?" which the docs don't 
> answer. I think this could be stated as:
> ```
> For Windows targets, ``[[no_unique_address]]`` is ignored; use 
> ``[[msvc::no_unique_address]]`` instead.
> ```
> WDYT?
yep, that sounds good


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157762

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


[PATCH] D157762: [WIP] Implement [[msvc::no_unique_address]]

2023-08-17 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 551242.
akhuang marked an inline comment as done.
akhuang added a comment.
Herald added a reviewer: shafik.

Add function to check for no_unique_address attributes
Some changes to layout code


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157762

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/AST/Decl.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/CodeGen/ABIInfoImpl.cpp
  clang/lib/CodeGen/CGExprAgg.cpp
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
  clang/lib/CodeGen/Targets/SystemZ.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/test/Layout/ms-no-unique-address.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -8754,7 +8754,7 @@
   CXXRecordDecl *ToD = Import(FromD, Lang_CXX20);
   EXPECT_TRUE(ToD->isEmpty());
   for (auto *FD : ToD->fields())
-EXPECT_EQ(true, FD->hasAttr());
+EXPECT_EQ(true, FD->hasNoUniqueAddress());
 }
 
 TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingTypedefToRecord) {
Index: clang/test/Layout/ms-no-unique-address.cpp
===
--- /dev/null
+++ clang/test/Layout/ms-no-unique-address.cpp
@@ -0,0 +1,310 @@
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-pc-win32 -fdump-record-layouts %s | FileCheck %s
+
+namespace Empty {
+  struct A {};
+  struct A2 {};
+  struct A3 { [[msvc::no_unique_address]] A a; };
+  struct alignas(8) A4 {};
+
+  struct B {
+[[msvc::no_unique_address]] A a;
+char b;
+  };
+  static_assert(sizeof(B) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::B
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   char b
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct C {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] A2 a2;
+char c;
+  };
+  static_assert(sizeof(C) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::C
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   struct Empty::A2 a2 (empty)
+  // CHECK-NEXT: 0 |   char c
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct D {
+[[msvc::no_unique_address]] A3 a;
+char c;
+  };
+  static_assert(sizeof(D) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::D
+  // CHECK-NEXT: 0 |   struct Empty::A3 a (empty)
+  // CHECK-NEXT: 0 | struct Empty::A a (empty)
+  // CHECK-NEXT: 1 |   char c 
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct E {
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char e;
+  };
+  static_assert(sizeof(E) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::E
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char e
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct F {
+~F();
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char f;
+  };
+  static_assert(sizeof(F) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::F
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char f
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct G { [[msvc::no_unique_address]] A a; ~G(); };
+  static_assert(sizeof(G) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::G
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct H {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] A b;
+~H();
+  };
+  static_assert(sizeof(H) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::H
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A b (empty)
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct I {
+[[msvc::no_unique_address]] A4 a;
+[[msvc::no_unique_address]] A4 b;
+  };
+  static_assert(sizeof(I) == 16);
+
+  // CHECK:*** Dumping AST Record Layout
+  // 

[PATCH] D157762: [WIP] Implement [[msvc::no_unique_address]]

2023-08-17 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/AST/Decl.cpp:4523-4524
 bool FieldDecl::isPotentiallyOverlapping() const {
-  return hasAttr() && getType()->getAsCXXRecordDecl();
+  return (hasAttr() ||
+  hasAttr()) &&
+ getType()->getAsCXXRecordDecl();

aaron.ballman wrote:
> dblaikie wrote:
> > Having to check both of these in several places seems problematic - can we 
> > wrap that up somewhere? (or, maybe ideally, is there a way for 
> > `msvc::no_unique_address` to map to the actual NoUniqueAddressAttr as a 
> > different spelling of the same thing?)
> This was why I was hoping we could merge the two in Attr.td, but I'm not 
> certain that will be easy.
What does merging the two in Attr.td mean? Could we just put the two spellings 
in one attribute, or would that make it impossible for clang-cl to ignore the 
[[no_unique_address]] spelling


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157762

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


[PATCH] D157762: [WIP] Implement [[msvc::no_unique_address]]

2023-08-11 Thread Amy Huang via Phabricator via cfe-commits
akhuang created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a project: All.
akhuang requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This attribute should match the behavior of MSVC's [[msvc::no_unique_address]] 
attribute.

Bug: https://github.com/llvm/llvm-project/issues/49358


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D157762

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/AST/Decl.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/CodeGen/ABIInfoImpl.cpp
  clang/lib/CodeGen/CGExprAgg.cpp
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/test/Layout/ms-no-unique-address.cpp

Index: clang/test/Layout/ms-no-unique-address.cpp
===
--- /dev/null
+++ clang/test/Layout/ms-no-unique-address.cpp
@@ -0,0 +1,254 @@
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-pc-win32 -fdump-record-layouts %s | FileCheck %s
+
+namespace Empty {
+  struct A {};
+  struct B { [[msvc::no_unique_address]] A a; char b; };
+  static_assert(sizeof(B) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::B
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   char b
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct C {};
+  struct D {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] C c;
+char d;
+  };
+  static_assert(sizeof(D) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::D
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 0 |   struct Empty::C c (empty)
+  // CHECK-NEXT: 0 |   char d
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct E {
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char e;
+  };
+  static_assert(sizeof(E) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::E
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char e
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct F {
+~F();
+[[msvc::no_unique_address]] A a1;
+[[msvc::no_unique_address]] A a2;
+char f;
+  };
+  static_assert(sizeof(F) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::F
+  // CHECK-NEXT: 0 |   struct Empty::A a1 (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a2 (empty)
+  // CHECK-NEXT: 0 |   char f
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct G { [[msvc::no_unique_address]] A a; ~G(); };
+  static_assert(sizeof(G) == 1);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::G
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT:   | [sizeof=1, align=1,
+  // CHECK-NEXT:   |  nvsize=1, nvalign=1]
+
+  struct H {
+[[msvc::no_unique_address]] A a;
+[[msvc::no_unique_address]] A b;
+~H();
+  };
+  static_assert(sizeof(H) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::H
+  // CHECK-NEXT: 0 |   struct Empty::A a (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A b (empty)
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct OversizedEmpty : A {
+~OversizedEmpty();
+[[msvc::no_unique_address]] A a;
+  };
+  static_assert(sizeof(OversizedEmpty) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::OversizedEmpty
+  // CHECK-NEXT: 0 |   struct Empty::A (base) (empty)
+  // CHECK-NEXT: 1 |   struct Empty::A a (empty)
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct HasOversizedEmpty {
+[[msvc::no_unique_address]] OversizedEmpty m;
+  };
+  static_assert(sizeof(HasOversizedEmpty) == 2);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | struct Empty::HasOversizedEmpty
+  // CHECK-NEXT: 0 |   struct Empty::OversizedEmpty m (empty)
+  // CHECK-NEXT: 0 | struct Empty::A (base) (empty)
+  // CHECK-NEXT: 1 | struct Empty::A a (empty)
+  // CHECK-NEXT:   | [sizeof=2, align=1,
+  // CHECK-NEXT:   |  nvsize=2, nvalign=1]
+
+  struct EmptyWithNonzeroDSize {
+[[msvc::no_unique_address]] A a;
+int x;
+[[msvc::no_unique_address]] A b;
+int y;
+[[msvc::no_unique_address]] A c;
+  };
+  static_assert(sizeof(EmptyWithNonzeroDSize) == 8);
+
+  // CHECK:*** Dumping AST Record Layout
+  // CHECK:  0 | 

[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-26 Thread Amy Huang 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 rG27dab4d305ac: Reland Try to implement lambdas with 
inalloca parameters by forwarding without… (authored by akhuang).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/Targets/X86.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,63 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
+
+// Make sure we don't try to copy an uncopyable type.
+struct B {
+  B();
+  B(B &);
+  void operator=(B);
+  long long x;
+} b;
+
+void f() {
+  [](B) {}(b);
+}
 
Index: clang/lib/CodeGen/Targets/X86.cpp
===
--- clang/lib/CodeGen/Targets/X86.cpp
+++ clang/lib/CodeGen/Targets/X86.cpp
@@ -140,7 +140,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -737,8 +738,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -753,6 +754,12 @@
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
 if (RAA == CGCXXABI::RAA_Indirect) {
   return getIndirectResult(Ty, false, State);
+} else if (isDelegateCall) {
+  // Avoid having different alignments on delegate call args by always
+  // setting the alignment to 4, which is what we do for inallocas.
+  ABIArgInfo Res = getIndirectResult(Ty, false, 

[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-25 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 544101.
akhuang added a comment.

add TODO


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/Targets/X86.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,63 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
+
+// Make sure we don't try to copy an uncopyable type.
+struct B {
+  B();
+  B(B &);
+  void operator=(B);
+  long long x;
+} b;
+
+void f() {
+  [](B) {}(b);
+}
 
Index: clang/lib/CodeGen/Targets/X86.cpp
===
--- clang/lib/CodeGen/Targets/X86.cpp
+++ clang/lib/CodeGen/Targets/X86.cpp
@@ -140,7 +140,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -737,8 +738,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -753,6 +754,12 @@
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
 if (RAA == CGCXXABI::RAA_Indirect) {
   return getIndirectResult(Ty, false, State);
+} else if (isDelegateCall) {
+  // Avoid having different alignments on delegate call args by always
+  // setting the alignment to 4, which is what we do for inallocas.
+  ABIArgInfo Res = getIndirectResult(Ty, false, State);
+  Res.setIndirectAlign(CharUnits::fromQuantity(4));
+  return Res;
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix 

[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-25 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 544090.
akhuang added a comment.

go back to previous __impl naming method


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/Targets/X86.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,63 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
+
+// Make sure we don't try to copy an uncopyable type.
+struct B {
+  B();
+  B(B &);
+  void operator=(B);
+  long long x;
+} b;
+
+void f() {
+  [](B) {}(b);
+}
 
Index: clang/lib/CodeGen/Targets/X86.cpp
===
--- clang/lib/CodeGen/Targets/X86.cpp
+++ clang/lib/CodeGen/Targets/X86.cpp
@@ -140,7 +140,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -737,8 +738,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -753,6 +754,12 @@
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
 if (RAA == CGCXXABI::RAA_Indirect) {
   return getIndirectResult(Ty, false, State);
+} else if (isDelegateCall) {
+  // Avoid having different alignments on delegate call args by always
+  // setting the alignment to 4, which is what we do for inallocas.
+  ABIArgInfo Res = getIndirectResult(Ty, false, State);
+  Res.setIndirectAlign(CharUnits::fromQuantity(4));
+  return Res;
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field 

[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-25 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CGClass.cpp:3095
+  StringRef CallOpName = CallOpFn->getName();
+  std::string ImplName = ("__impl" + CallOpName).str();
+

rnk wrote:
> akhuang wrote:
> > The old code tried to find the "" part of the function name and 
> > replace the front with "?__impl@", so that the function name was consistent 
> > with the mangling scheme.  But apparently there are some cases where when 
> > the function name is too long, it uses a hash instead (?), so the attempt 
> > to find the  was failing. 
> > 
> > I couldn't find a good way to name this function through the actual 
> > mangling code -- is it fine to just add "__impl" to the front and have it 
> > not be mangled correctly? 
> Let me suggest one more thing to try here to convince the mangler to do our 
> work for us. You can create a CXXMethodDecl AST node here in CodeGen, and ask 
> the mangler to mangle it for you. If you search CodeGen, you can find other 
> examples of this, notably, for making implicit `this` variable declarations:
> ```
> $ git grep Decl::Create'(' ../clang/lib/CodeGen/
> ../clang/lib/CodeGen/CGBuiltin.cpp:  Args.push_back(ImplicitParamDecl::Create(
> ../clang/lib/CodeGen/CGBuiltin.cpp:
> Args.push_back(ImplicitParamDecl::Create(
> ../clang/lib/CodeGen/CGCXXABI.cpp:  auto *ThisDecl = 
> ImplicitParamDecl::Create(
> ```
> 
> Call `CXXMethodDecl::Create`, and copy in all of the attribute from the call 
> operator, but replace the DeclarationNameInfo with an IdentifierInfo of 
> `__impl`.
> 
> If that's not working out, let's land this as is and follow up on fixing the 
> mangling.
I think `CXXMethodDecl::Create` doesn't work because it needs a non-const 
CXXRecordDecl to construct? 

I added some functions to MicrosoftMangler so that we can pass in a custom 
DeclarationName, does that seem ok? 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

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


[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-25 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 544086.
akhuang added a comment.

Add some functions to MicrosoftMangle so we can pass in a custom function name.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

Files:
  clang/include/clang/AST/Mangle.h
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/AST/MicrosoftMangle.cpp
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/Targets/X86.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,63 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
+
+// Make sure we don't try to copy an uncopyable type.
+struct B {
+  B();
+  B(B &);
+  void operator=(B);
+  long long x;
+} b;
+
+void f() {
+  [](B) {}(b);
+}
 
Index: clang/lib/CodeGen/Targets/X86.cpp
===
--- clang/lib/CodeGen/Targets/X86.cpp
+++ clang/lib/CodeGen/Targets/X86.cpp
@@ -140,7 +140,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -737,8 +738,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -753,6 +754,12 @@
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
 if (RAA == CGCXXABI::RAA_Indirect) {
   return getIndirectResult(Ty, false, State);
+} else if (isDelegateCall) {
+  // Avoid having different alignments on delegate call args by always
+  // setting the alignment to 4, which is what we do for inallocas.
+  ABIArgInfo Res = getIndirectResult(Ty, false, State);
+  

[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-21 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 543038.
akhuang added a comment.

another fix to function naming code (do the same thing as before except when 
the mangled name is a hash)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/Targets/X86.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,63 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
+
+// Make sure we don't try to copy an uncopyable type.
+struct B {
+  B();
+  B(B &);
+  void operator=(B);
+  long long x;
+} b;
+
+void f() {
+  [](B) {}(b);
+}
 
Index: clang/lib/CodeGen/Targets/X86.cpp
===
--- clang/lib/CodeGen/Targets/X86.cpp
+++ clang/lib/CodeGen/Targets/X86.cpp
@@ -140,7 +140,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -737,8 +738,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -753,6 +754,12 @@
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
 if (RAA == CGCXXABI::RAA_Indirect) {
   return getIndirectResult(Ty, false, State);
+} else if (isDelegateCall) {
+  // Avoid having different alignments on delegate call args by always
+  // setting the alignment to 4, which is what we do for inallocas.
+  ABIArgInfo Res = getIndirectResult(Ty, false, State);
+  Res.setIndirectAlign(CharUnits::fromQuantity(4));
+  return Res;
 } 

[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-20 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CGClass.cpp:3095
+  StringRef CallOpName = CallOpFn->getName();
+  std::string ImplName = ("__impl" + CallOpName).str();
+

The old code tried to find the "" part of the function name and 
replace the front with "?__impl@", so that the function name was consistent 
with the mangling scheme.  But apparently there are some cases where when the 
function name is too long, it uses a hash instead (?), so the attempt to find 
the  was failing. 

I couldn't find a good way to name this function through the actual mangling 
code -- is it fine to just add "__impl" to the front and have it not be mangled 
correctly? 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

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


[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-20 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 542721.
akhuang added a comment.

Change impl function naming scheme


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/Targets/X86.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,63 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"__impl??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"__impl??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"__impl??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
+
+// Make sure we don't try to copy an uncopyable type.
+struct B {
+  B();
+  B(B &);
+  void operator=(B);
+  long long x;
+} b;
+
+void f() {
+  [](B) {}(b);
+}
 
Index: clang/lib/CodeGen/Targets/X86.cpp
===
--- clang/lib/CodeGen/Targets/X86.cpp
+++ clang/lib/CodeGen/Targets/X86.cpp
@@ -140,7 +140,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -737,8 +738,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -753,6 +754,12 @@
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
 if (RAA == CGCXXABI::RAA_Indirect) {
   return getIndirectResult(Ty, false, State);
+} else if (isDelegateCall) {
+  // Avoid having different alignments on delegate call args by always
+  // setting the alignment to 4, which is what we do for inallocas.
+  ABIArgInfo Res = getIndirectResult(Ty, false, State);
+  Res.setIndirectAlign(CharUnits::fromQuantity(4));
+  return Res;
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field 

[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-12 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 539795.
akhuang added a comment.

minor fixes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/Targets/X86.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,63 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
+
+// Make sure we don't try to copy an uncopyable type.
+struct B {
+  B();
+  B(B &);
+  void operator=(B);
+  long long x;
+} b;
+
+void f() {
+  [](B) {}(b);
+}
 
Index: clang/lib/CodeGen/Targets/X86.cpp
===
--- clang/lib/CodeGen/Targets/X86.cpp
+++ clang/lib/CodeGen/Targets/X86.cpp
@@ -140,7 +140,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -737,8 +738,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -753,6 +754,12 @@
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
 if (RAA == CGCXXABI::RAA_Indirect) {
   return getIndirectResult(Ty, false, State);
+} else if (isDelegateCall) {
+  // Avoid having different alignments on delegate call args by always
+  // setting the alignment to 4, which is what we do for inallocas.
+  ABIArgInfo Res = getIndirectResult(Ty, false, State);
+  Res.setIndirectAlign(CharUnits::fromQuantity(4));
+  return Res;
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll 

[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-12 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CGCall.cpp:5104
+if (CallInfo.isDelegateCall()) {
+  NeedCopy = false;
+} else if (Addr.getAlignment() < Align &&

rnk wrote:
> Please add a comment about this. We need to avoid copying uncopyable objects 
> passed in misaligned inalloca argument packs.
> 
> Another approach we could take here is to check 
> `CXXRecordDecl::isTriviallyCopyable`, and avoid doing the copy for such 
> argument types. That would be non-conforming anyway, and results in an assert 
> in `CallArg::copyInto`. For trivially copyable types, doing the copy may 
> actually be good, since it's more conforming.
Sorry, didn't mean to include this in the patch. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

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


[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-12 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 539784.
akhuang added a comment.

Fix alignment problem


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/Targets/X86.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,63 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call
+
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
+
+// Make sure we don't try to copy an uncopyable type.
+struct B {
+  B();
+  B(B &);
+  void operator=(B);
+  long long x;
+} b;
+
+void f() {
+  [](B) {}(b);
+}
 
Index: clang/lib/CodeGen/Targets/X86.cpp
===
--- clang/lib/CodeGen/Targets/X86.cpp
+++ clang/lib/CodeGen/Targets/X86.cpp
@@ -140,7 +140,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -738,8 +739,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -754,6 +755,12 @@
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
 if (RAA == CGCXXABI::RAA_Indirect) {
   return getIndirectResult(Ty, false, State);
+} else if (isDelegateCall) {
+  // Avoid having different alignments on delegate call args by always
+  // setting the alignment to 4, which is what we do for inallocas.
+  ABIArgInfo Res = getIndirectResult(Ty, false, State);
+  Res.setIndirectAlign(CharUnits::fromQuantity(4));
+  return Res;
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't 

[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-07-12 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CodeGenFunction.cpp:1319
+  // Check if the invoker is being emitted (could be in any calling conv).
+  for (CallingConv CC : {CC_C, CC_X86StdCall, CC_X86FastCall, CC_X86ThisCall, 
CC_X86VectorCall})
+if (MD->getParent()->getLambdaStaticInvoker(CC)->isUsed())

> I'm not confident that isUsed() works the way you want it to in this context. 
> In particular, if the code in question runs before we've translated the whole 
> translation unit, the isUsed() bit could change. If you want that's more 
> obviously safe, you could just check if there are any captures. (I'm assuming 
> the point of this is just to reduce the number of lambdas that go through 
> this codepath?)

Oh, checking for captures would be the same as checking for 
`getLambdaStaticInvoker()`, right? I think I'll just keep with the same check 
from the original patch, then.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

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


[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-06-28 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CGCall.cpp:5103
 
-if (Addr.getAlignment() < Align &&
+if (CallInfo.isDelegateCall()) {
+  NeedCopy = false;

rnk wrote:
> akhuang wrote:
> > I think the problem is that it tries to do a copy here because the 
> > alignment of the forwarding function arg is larger than the alignment of 
> > the object that's being passed. I'm not sure how alignments are computed or 
> > if there are any other requirements for alignment. Is it ok to just ignore 
> > the new alignment? Do we need to change the code that computes the argument 
> > alignment?
> > 
> > (crbug.com/1457256#comment2 has an example repro)
> Yes, in general, structs with doubles and i64 members are passed misaligned 
> on i686. This is true for all functions, not just lambdas. We should power 
> down whatever alignment logic is causing the copy.
huh, ok, good to know. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

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


[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-06-28 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

In D154007#4457561 , @efriedma wrote:

> I'm not confident that isUsed() works the way you want it to in this context. 
>  In particular, if the code in question runs before we've translated the 
> whole translation unit, the isUsed() bit could change.  If you want that's 
> more obviously safe, you could just check if there are any captures.  (I'm 
> assuming the point of this is just to reduce the number of lambdas that go 
> through this codepath?)

Oh, thanks. Yeah, the point is we don't have to go down this path if we never 
have to emit the invoker.

In D154007#4457592 , @rnk wrote:

> Can you please add a test case for the issue that caused the revert? I wanted 
> to dig into that to try to understand why the extra copy was being emitted. I 
> think you mentioned it has something to do with increasing the alignment.

oops, I added comments when I put up the patch but never submitted them.. 
there's a repro in crbug.com/1457256 but I'll also add a test case




Comment at: clang/lib/CodeGen/CGCall.cpp:5103
 
-if (Addr.getAlignment() < Align &&
+if (CallInfo.isDelegateCall()) {
+  NeedCopy = false;

I think the problem is that it tries to do a copy here because the alignment of 
the forwarding function arg is larger than the alignment of the object that's 
being passed. I'm not sure how alignments are computed or if there are any 
other requirements for alignment. Is it ok to just ignore the new alignment? Do 
we need to change the code that computes the argument alignment?

(crbug.com/1457256#comment2 has an example repro)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154007

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


[PATCH] D154007: Reland "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas."

2023-06-28 Thread Amy Huang via Phabricator via cfe-commits
akhuang created this revision.
Herald added a project: All.
akhuang requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This reverts commit 8ed7aa59f489715d39d32e72a787b8e75cfda151 
.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154007

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/Targets/X86.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/Targets/X86.cpp
===
--- clang/lib/CodeGen/Targets/X86.cpp
+++ clang/lib/CodeGen/Targets/X86.cpp
@@ -140,7 +140,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -738,8 +739,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -752,7 +753,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -941,7 +942,8 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info =
+

[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-20 Thread Amy Huang 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 rG015049338d7e: Try to implement lambdas with inalloca 
parameters by forwarding without use of… (authored by akhuang).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/Targets/X86.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/Targets/X86.cpp
===
--- clang/lib/CodeGen/Targets/X86.cpp
+++ clang/lib/CodeGen/Targets/X86.cpp
@@ -140,7 +140,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -738,8 +739,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -752,7 +753,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -941,7 +942,8 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info =
+

[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-20 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 533079.
akhuang added a comment.

rebase and clang format


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/Targets/X86.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/Targets/X86.cpp
===
--- clang/lib/CodeGen/Targets/X86.cpp
+++ clang/lib/CodeGen/Targets/X86.cpp
@@ -140,7 +140,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -738,8 +739,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -752,7 +753,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -941,7 +942,8 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info =
+classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
 UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
   }
 
Index: 

[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-16 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CodeGenFunction.cpp:1470
+->getLambdaStaticInvoker()) &&
+ !Fn->getName().contains("__impl")) {
+// If emitting a lambda with static invoker on X86 Windows, change

efriedma wrote:
> I'm not sure `__impl` is unique enough that user code will never use it.  (I 
> mean, it's reserved, but we don't actually forbid using it.)
> 
> Can we use the isDelegateCall() bit?
yep, that makes more sense. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

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


[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-16 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 532291.
akhuang added a comment.

Use isDelegateCall to check whether function is actual call op fn or not


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1197,7 +1197,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,8 +1825,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1838,7 +1839,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -2027,7 +2028,8 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info =
+classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
 UsedInAlloca |= (Args[I].info.getKind() == 

[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-14 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 531571.
akhuang added a comment.

update test case


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1197,7 +1197,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,8 +1825,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1838,7 +1839,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -2027,7 +2028,8 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info =
+classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
 UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
   }
 
Index: 

[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-14 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CodeGenFunction.cpp:1472
+// the call operator body.
+EmitLambdaStaticInvokeBody(cast(FD));
   } else if (FD->isDefaulted() && isa(FD) &&

efriedma wrote:
> akhuang wrote:
> > efriedma wrote:
> > > Does this pass the correct value of "this"?  EmitLambdaStaticInvokeBody 
> > > creates a new alloca to represent "this", but it's already an argument to 
> > > the function.
> > > 
> > > Granted, it only matters in really obscure cases, but still.
> > That's true, the "this" won't be passed correctly.
> > 
> > Actually, would it be fine to just emit the original call op body? (so that 
> > the same function body is emitted twice -- once in the call op and once in 
> > __impl). 
> Not completely sure what you're asking... but as I've mentioned, we can't 
> EmitFunctionBody() the body of a function more than once.
Oh, nevermind then. I think this version passes "this" from the call op. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

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


[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-14 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 531569.
akhuang added a comment.

Emit call op which forwards %this argument


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1197,7 +1197,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,8 +1825,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1838,7 +1839,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -2027,7 +2028,8 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info =
+classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
 UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
   }
 

[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-14 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 531435.
akhuang added a comment.

Call GenerateCode to emit __impl function body


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1197,7 +1197,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,8 +1825,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1838,7 +1839,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -2027,7 +2028,8 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info =
+classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
 UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
   

[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-14 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CGClass.cpp:3097
+  FD->getLocation(), FD->getLocation());
+CGF.EmitFunctionBody(FD->getBody());
+CGF.FinishFunction();

efriedma wrote:
> Is there any way we can use GenerateCode as the entrypoint here, instead of 
> calling EmitFunctionBody directly?  Without this patch, EmitFunctionBody has 
> exactly one caller, so this makes the control flow and special cases more 
> complicated to reason about.  For example, there's some special coroutine 
> handling in GenerateCode.
Changed to using GenerateCode -- had to add another case to the path in 
GenerateCode to make sure we emit different things for the call op body inside 
__impl and the call op body inside the call op function.



Comment at: clang/lib/CodeGen/CodeGenFunction.cpp:1472
+// the call operator body.
+EmitLambdaStaticInvokeBody(cast(FD));
   } else if (FD->isDefaulted() && isa(FD) &&

efriedma wrote:
> Does this pass the correct value of "this"?  EmitLambdaStaticInvokeBody 
> creates a new alloca to represent "this", but it's already an argument to the 
> function.
> 
> Granted, it only matters in really obscure cases, but still.
That's true, the "this" won't be passed correctly.

Actually, would it be fine to just emit the original call op body? (so that the 
same function body is emitted twice -- once in the call op and once in __impl). 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

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


[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-08 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 529780.
akhuang added a comment.

Fix ordering in the test case


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[V]])
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1197,7 +1197,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,8 +1825,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1838,7 +1839,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -2015,7 +2016,8 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info =
+classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
 UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
   }
 
Index: 

[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-08 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 529755.
akhuang added a comment.

more cleanup


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[V]])
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1197,7 +1197,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,8 +1825,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1838,7 +1839,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -2015,7 +2016,8 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info =
+classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
 UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
   }
 
Index: 

[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-08 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

In D137872#4357268 , @efriedma wrote:

> In D137872#4348314 , @akhuang wrote:
>
>> In D137872#4327615 , @efriedma 
>> wrote:
>>
>>> I'm having a bit of trouble following how exactly the thunk creation is 
>>> working here... do we generate different code depending on whether the call 
>>> operator and/or the static invoker are referenced?
>>
>> So I think it used to be that the static invoker calls the call operator 
>> which contains the body of the lambda? And now both the static invoker and 
>> the call operator are delegating to this new __impl function. In 
>> EmitLambdaStaticInvokeBody it first calls EmitLambdaInAllocaCallOpFn to make 
>> the new call operator (which is populated using 
>> EmitLambdaDelegatingInvokeBody). And then inside 
>> EmitLambdaDelegatingInvokeBody it generates the new impl function and calls 
>> it in the body. Not sure if that answers the question, I agree the code is a 
>> bit roundabout.
>>
>>> Why is the function in EmitLambdaInAllocaCallOpFn not getting defined using 
>>> the normal CodeGenModule machinery?
>>
>> Do you mean why it's not using CodeGenModule machinery to generate the new 
>> call op body or why we're changing the original call op body?
>
> I mean why it's not using the CodeGenModule machinery.  I understand there 
> are three function bodies involved.  But I would expect that when you "emit" 
> the lambda call operator, it emits the entry point for the call and for the 
> call impl, and when you emit the static invoker, it just emits a call to the 
> call impl.
>
> Or... hmm.  Is this actually erasing the existing definition of the call 
> operator, if it was already emitted?  That probably doesn't actually work in 
> general; once a function is emitted, you can't re-emit it.  Emitting a 
> function emits other related stuff like static variables; you can't 
> EmitFunctionBody() more than once.  Either you need to decide when it's first 
> emitted, or you need to rewrite the signature of the definition and splice 
> the existing body in.

good point, I realized I can just put the call operator emission where the call 
op is normally emitted, which removes the thing where I was trying to create a 
new call op while the static invoker body is being emitted.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

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


[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-08 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 529750.
akhuang added a comment.

remove print statements


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[V]])
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1197,7 +1197,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,8 +1825,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1838,7 +1839,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -2015,7 +2016,8 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info =
+classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
 UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
   }
 
Index: 

[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-06-08 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 529747.
akhuang added a comment.

- move call operator emission into the path in `GenerateCode`
- formatting


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[V]])
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1197,7 +1197,8 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ,
+  bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,8 +1825,8 @@
   }
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1838,7 +1839,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -2015,7 +2016,8 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info =
+classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
 UsedInAlloca |= (Args[I].info.getKind() 

[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-05-16 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

In D137872#4327615 , @efriedma wrote:

> I'm having a bit of trouble following how exactly the thunk creation is 
> working here... do we generate different code depending on whether the call 
> operator and/or the static invoker are referenced?

So I think it used to be that the static invoker calls the call operator which 
contains the body of the lambda? And now both the static invoker and the call 
operator are delegating to this new __impl function. In 
EmitLambdaStaticInvokeBody it first calls EmitLambdaInAllocaCallOpFn to make 
the new call operator (which is populated using 
EmitLambdaDelegatingInvokeBody). And then inside EmitLambdaDelegatingInvokeBody 
it generates the new impl function and calls it in the body. Not sure if that 
answers the question, I agree the code is a bit roundabout.

> Why is the function in EmitLambdaInAllocaCallOpFn not getting defined using 
> the normal CodeGenModule machinery?

Do you mean why it's not using CodeGenModule machinery to generate the new call 
op body or why we're changing the original call op body?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

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


[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2023-05-02 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

whoops, I've left this here for a while.. @efriedma, are you able to review it?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

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


[PATCH] D144931: DebugInfo: Disable ctor homing for types with only deleted (non copy/move) ctors

2023-02-27 Thread Amy Huang via Phabricator via cfe-commits
akhuang accepted this revision.
akhuang added a comment.
This revision is now accepted and ready to land.

Thanks for adding this!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144931

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


[PATCH] D137872: Implement lambdas with inalloca parameters by forwarding to function without inalloca calling convention.

2022-12-07 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

ping @efriedma, do you mind looking at this again? thanks!




Comment at: clang/include/clang/CodeGen/CGFunctionInfo.h:571
+  /// Whether this function should avoid inalloca arguments.
+  unsigned DontInAlloca: 1;
+

rnk wrote:
> This is an amusing name, but we should try to find something better. :)
> 
> Can we build on this flag to support re-writing a varargs prototype to 
> receive a va_list? If so, we should plan for that, and name this to cover 
> both use cases. Elsewhere in clang we use the terminology "delegate call" see 
> [EmitDelegateCallArg](https://github.com/llvm/llvm-project/blob/2e999b7dd1934a44d38c3a753460f1e5a217e9a5/clang/lib/CodeGen/CGVTables.cpp#L341).
>  Could this be something like `ForDelegation` or `ForDelegateCall` or 
> `IsDelegateCall` or `IsDelegateTarget` or something like that? Or Thunk? I 
> think I like `ForDelegateCall`, but I'm not sure.
> 
> ---
> 
> Does anyone know what a "chain call" is? It wasn't clear to me immediately.
> 
> 
Yeah, that naming makes sense. 

chain call: https://reviews.llvm.org/D6332? 



Comment at: clang/lib/CodeGen/CGClass.cpp:3097
+
+  std::string ImplName = (CallOpFn->getName() + ".impl").str();
+  llvm::Function *Fn = CallOpFn->getParent()->getFunction(ImplName);

rnk wrote:
> We should use a name which demangles correctly, as we do for `__invoke`. This 
> is a good first draft, though.
Fixed to replace different part of the mangled name with `__impl`. Don't know 
if it would be better to use the actual mangling functions, but the string 
replace here seems simple enough.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

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


[PATCH] D137872: Try to implement lambdas with inalloca parameters by forwarding without use of inallocas.

2022-11-28 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 478324.
akhuang marked 3 inline comments as done.
akhuang added a comment.

Address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[V]])
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1187,7 +1187,7 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState , bool isDelegateCall) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,7 +1824,8 @@
 }
 
 ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+   CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1837,7 +1838,7 @@
   const RecordType *RT = Ty->getAs();
   if (RT) {
 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-if (RAA == CGCXXABI::RAA_Indirect) {
+if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
   // The field index doesn't matter, we'll fix it up later.
@@ -2014,7 +2015,7 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info = classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
 UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
   }
 
Index: clang/lib/CodeGen/CodeGenTypes.h

[PATCH] D137872: Try to implement lambdas with inalloca parameters by forwarding without use of inallocas.

2022-11-22 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 477289.
akhuang marked 4 inline comments as done.
akhuang added a comment.

add to test case, modify name mangling, change fn info opts enum type


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,11 +1,50 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
-
-class A {
+struct A {
+  A();
   A(const A &);
+  int x;
 };
-typedef void (*fptr_t)(A);
-fptr_t fn1() { return [](A) {}; }
+void decayToFp(int (*f)(A));
+void test() {
+  auto ld = [](A a) {
+static int calls = 0;
+++calls;
+return a.x + calls;
+  };
+  decayToFp(ld);
+  ld(A{});
+}
+
+// CHECK: define internal noundef i32
+// CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z"
+// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]])
+// CHECK: ret i32 %call 
+
+// CHECK: define internal x86_thiscallcc noundef i32 
+// CHECK-SAME: @"??R@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]])
+// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0
+// CHECK: %call = call x86_thiscallcc noundef i32 
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[V]])
 
+// CHECK: define internal x86_thiscallcc noundef i32
+// CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]])
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %inc = add nsw i32 %{{.*}}, 1
+// CHECK: store i32 %inc, ptr @"?calls@?1???R
+// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R
+// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}}
+// CHECK: ret i32 %add
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1187,7 +1187,7 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState , bool NoInAlloca) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,7 +1824,8 @@
 }
 
 ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+   CCState ,
+   bool isDelegateCall) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1840,6 +1841,9 @@
 if (RAA == CGCXXABI::RAA_Indirect) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
+  // Don't use inallocas if this is a delegate call.
+  if (isDelegateCall)
+return getIndirectResult(Ty, false, State);
   // The field index doesn't matter, we'll fix it up later.
   return ABIArgInfo::getInAlloca(/*FieldIndex=*/0);
 }
@@ -2014,7 +2018,7 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info = classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
 UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
   }
 
Index: 

[PATCH] D137872: Try to implement lambdas with inalloca parameters by forwarding without use of inallocas.

2022-11-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

In D137872#3925723 , @efriedma wrote:

> I'm not quite sure I understand what's happening here.  Does this actually 
> avoid generating two copies of the function body if both the call operator 
> and the conversion are used?

That was intended but missing; patch is now updated to make both the invoker 
and the call operator call the new function.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

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


[PATCH] D137872: Try to implement lambdas with inalloca parameters by forwarding without use of inallocas.

2022-11-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 476634.
akhuang added a comment.

cleanup


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,23 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+
+// CHECK: define internal void @"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z"
+// CHECK-SAME:  (ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %1 = getelementptr inbounds <{ %class.A, [3 x i8] }>, ptr %0, i32 0, i32 0
+// CHECK: call x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0...@z.impl"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %1)
+// CHECK: ret void
+
+// CHECK: define internal x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0@Z"
+// CHECK-SAME:  (ptr noundef %this, ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: call x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0...@z.impl"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %1)
+
+// CHECK: define internal x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0...@z.impl"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %0)
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: ret void
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1187,7 +1187,7 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState , bool NoInAlloca) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,7 +1824,8 @@
 }
 
 ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+   CCState ,
+   bool NoInAlloca) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1840,6 +1841,8 @@
 if (RAA == CGCXXABI::RAA_Indirect) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
+  if (NoInAlloca)
+return getIndirectResult(Ty, false, State);
   // The field index doesn't matter, we'll fix it up later.
   return ABIArgInfo::getInAlloca(/*FieldIndex=*/0);
 }
@@ -2014,7 +2017,7 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info = classifyArgumentType(Args[I].type, State, FI.isAvoidingInAlloca());
 UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
   }
 
Index: clang/lib/CodeGen/CodeGenTypes.h
===
--- clang/lib/CodeGen/CodeGenTypes.h
+++ clang/lib/CodeGen/CodeGenTypes.h
@@ -260,8 +260,7 @@
   ///
   /// \param argTypes - must all actually be canonical as params
   const CGFunctionInfo (CanQualType returnType,
-bool instanceMethod,
-bool chainCall,
+FnInfoOptions opts,
 ArrayRef argTypes,
 FunctionType::ExtInfo info,
 ArrayRef paramInfos,
Index: clang/lib/CodeGen/CodeGenFunction.h
===
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2219,10 +2219,16 @@
   void 

[PATCH] D137872: Try to implement lambdas with inalloca parameters by forwarding without use of inallocas.

2022-11-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 476633.
akhuang added a comment.

Clean up existing code and add code to make the call operator also call the new 
function.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137872

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/lib/AST/DeclCXX.cpp
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGCall.h
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenABITypes.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenTypes.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,23 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+
+// CHECK: define internal void @"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z"
+// CHECK-SAME:  (ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: %unused.capture = alloca %class.anon, align 1
+// CHECK: %1 = getelementptr inbounds <{ %class.A, [3 x i8] }>, ptr %0, i32 0, i32 0
+// CHECK: call x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0...@z.impl"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %1)
+// CHECK: ret void
+
+// CHECK: define internal x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0@Z"
+// CHECK-SAME:  (ptr noundef %this, ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: call x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0...@z.impl"
+// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %1)
+
+// CHECK: define internal x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0...@z.impl"
+// CHECK-SAME: (ptr noundef %this, ptr noundef %0)
+// CHECK: %this.addr = alloca ptr, align 4
+// CHECK: store ptr %this, ptr %this.addr, align 4
+// CHECK: %this1 = load ptr, ptr %this.addr, align 4
+// CHECK: ret void
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1187,7 +1187,7 @@
 
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy, CCState ) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy, CCState ) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, CCState , bool NoInAlloca) const;
 
   /// Updates the number of available free registers, returns
   /// true if any registers were allocated.
@@ -1824,7 +1824,8 @@
 }
 
 ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
-   CCState ) const {
+   CCState ,
+   bool NoInAlloca) const {
   // FIXME: Set alignment on indirect arguments.
   bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
   bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -1840,6 +1841,8 @@
 if (RAA == CGCXXABI::RAA_Indirect) {
   return getIndirectResult(Ty, false, State);
 } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
+  if (NoInAlloca)
+return getIndirectResult(Ty, false, State);
   // The field index doesn't matter, we'll fix it up later.
   return ABIArgInfo::getInAlloca(/*FieldIndex=*/0);
 }
@@ -2014,7 +2017,7 @@
 if (State.IsPreassigned.test(I))
   continue;
 
-Args[I].info = classifyArgumentType(Args[I].type, State);
+Args[I].info = classifyArgumentType(Args[I].type, State, FI.isAvoidingInAlloca());
 UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
   }
 
Index: clang/lib/CodeGen/CodeGenTypes.h
===
--- clang/lib/CodeGen/CodeGenTypes.h
+++ clang/lib/CodeGen/CodeGenTypes.h
@@ -260,8 +260,7 @@
   ///
   /// \param argTypes - must all actually be canonical as params
   const CGFunctionInfo (CanQualType returnType,
-bool instanceMethod,
-bool chainCall,
+FnInfoOptions opts,
 ArrayRef argTypes,
 FunctionType::ExtInfo info,
 ArrayRef paramInfos,
Index: clang/lib/CodeGen/CodeGenFunction.h

[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-14 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

In D136998#3926368 , @efriedma wrote:

> In D136998#3926321 , @rnk wrote:
>
>> In D136998#3906874 , @efriedma 
>> wrote:
>>
>>> Should we try to use this codepath for variadic lambdas as well?
>>
>> Yes!
>>
>>> Do we want to try to unify our cloning code?  
>>> CodeGenFunction::GenerateVarArgsThunk has code doing something similar.  
>>> (It's at least worth comparing to see if you're doing something 
>>> significantly different...)
>>
>> Good idea
>>
>> In D136998#3906881 , @efriedma 
>> wrote:
>>
>>> Might also be worth considering if we can avoid cloning here.  It should be 
>>> possible to emit the lambda body into a separate function with a calling 
>>> convention of your choice, and make both the call operator and the static 
>>> invoker call it.
>>
>> This would be nice. I wasn't able to provide guidance on how to do that, and 
>> I think Amy was struggling to synthesize a new method (`__invoke`, `__impl`) 
>> at the AST layer.
>
> I think you wouldn't actually synthesize it at all in the AST.
>
> Basically, the follow code changes:
>
> 1. Change the mangling of the function that contains the actual lambda body.
> 2. Make that function use an alternate calling convention that doesn't 
> involve inalloca etc.
> 3. Synthesize thunks to represent the actual call operator and static invoker.
>
> This is similar to the way virtual overriding works: there's an actual 
> function, but there are also alternate entry points that end up in the 
> vtables.

Thanks, that makes sense. I'm not very familiar with thunks but I'll look into 
it. Would we make a thunk that contains the call to the new lambda body 
function, and then the invoker and call op functions return that thunk?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

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


[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-14 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 475269.
akhuang added a comment.

Fix calling convention of cloned function.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

Files:
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGVTables.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,7 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+// CHECK: define internal void @"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z"
+// CHECK-SAME: (ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: %1 = getelementptr inbounds <{ %class.A, [3 x i8] }>, ptr %0, i32 0, i32 0
+// CHECK: ret void
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3554,6 +3554,18 @@
 EmitGlobalFunctionDefinition(GD, GV);
 }
 
+static bool isInAllocaArg(CGCXXABI , QualType T) {
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
+}
+
+static bool hasInAllocaArg(const TargetInfo , CGCXXABI , const CXXMethodDecl *MD) {
+  return TI.getCXXABI().isMicrosoft() && 
+llvm::any_of(MD->parameters(), [&](ParmVarDecl *P) {
+return isInAllocaArg(CGABI, P->getType());
+  });
+}
+
 void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
   const auto *D = cast(GD.getDecl());
 
@@ -3580,6 +3592,14 @@
   // This is necessary for the generation of certain thunks.
   if (isa(Method) || isa(Method))
 ABI->emitCXXStructor(GD);
+  // Special path for emitting lambda static invokers with inalloca parameters.
+  else if (Method->isLambdaStaticInvoker() && 
+   hasInAllocaArg(getTarget(), getCXXABI(), Method)) {
+// Emit the call operator definition before emitting a static invoker.
+const CXXMethodDecl *CallOp = Method->getParent()->getLambdaCallOperator();
+EmitGlobalFunctionDefinition(GlobalDecl(CallOp), nullptr);
+CodeGenFunction(*this).EmitClonedLambdaStaticInvoke(Method);
+  }
   else if (FD->isMultiVersion())
 EmitMultiVersionFunctionDefinition(GD, GV);
   else
Index: clang/lib/CodeGen/CodeGenFunction.h
===
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2223,6 +2223,8 @@
   void EmitLambdaBlockInvokeBody();
   void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
   void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
+  void EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD);
+
   void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) {
 EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
   }
@@ -2255,6 +2257,8 @@
  GlobalDecl GD, const ThunkInfo ,
  bool IsUnprototyped);
 
+  void CreateClonedFunction(llvm::Function *Fn, llvm::Function *BaseFn,
+llvm::ValueToValueMapTy );
   llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn,
const CGFunctionInfo ,
GlobalDecl GD, const ThunkInfo );
Index: clang/lib/CodeGen/CGVTables.cpp
===
--- clang/lib/CodeGen/CGVTables.cpp
+++ clang/lib/CodeGen/CGVTables.cpp
@@ -139,6 +139,21 @@
   }
 }
 
+void CodeGenFunction::CreateClonedFunction(
+llvm::Function *Fn, llvm::Function *BaseFn, llvm::ValueToValueMapTy ) {
+  // We are cloning a function while some Metadata nodes are still unresolved.
+  // Ensure that the value mapper does not encounter any of them.
+  resolveTopLevelMetadata(BaseFn, VMap);
+  llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
+  Fn->replaceAllUsesWith(NewFn);
+  NewFn->takeName(Fn);
+  Fn->eraseFromParent();
+  Fn = NewFn;
+
+  // "Initialize" CGF (minimally).
+  CurFn = Fn;
+}
+
 // This function does roughly the same thing as GenerateThunk, but in a
 // very different way, so that va_start and va_end work correctly.
 // FIXME: This function assumes "this" is the first non-sret LLVM argument of
@@ -181,17 +196,7 @@
   // Clone to thunk.
   llvm::ValueToValueMapTy 

[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-11 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

In D136998#3906881 , @efriedma wrote:

> Might also be worth considering if we can avoid cloning here.  It should be 
> possible to emit the lambda body into a separate function with a calling 
> convention of your choice, and make both the call operator and the static 
> invoker call it.

Thanks for reviewing! I started a patch to emit a new function with a different 
calling convention here https://reviews.llvm.org/D137872. It probably has some 
issues - I'm not sure if the argument arranging for the call actually works 
generally, and it has a bunch of copied code from `EmitCall` and 
`EmitLambdaForwardingCall`. But, it doesn't involve changing code in 
`EmitGlobalDefinition`, which seems better.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

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


[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-11 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 474889.
akhuang marked an inline comment as done.
akhuang added a comment.

Move cloning code into a function.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

Files:
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGVTables.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,7 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+// CHECK: define internal x86_thiscallcc void @"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z"
+// CHECK-SAME: (ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: %1 = getelementptr inbounds <{ %class.A, [3 x i8] }>, ptr %0, i32 0, i32 0
+// CHECK: ret void
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3554,6 +3554,18 @@
 EmitGlobalFunctionDefinition(GD, GV);
 }
 
+static bool isInAllocaArg(CGCXXABI , QualType T) {
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
+}
+
+static bool hasInAllocaArg(const TargetInfo , CGCXXABI , const CXXMethodDecl *MD) {
+  return TI.getCXXABI().isMicrosoft() && 
+llvm::any_of(MD->parameters(), [&](ParmVarDecl *P) {
+return isInAllocaArg(CGABI, P->getType());
+  });
+}
+
 void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
   const auto *D = cast(GD.getDecl());
 
@@ -3580,6 +3592,14 @@
   // This is necessary for the generation of certain thunks.
   if (isa(Method) || isa(Method))
 ABI->emitCXXStructor(GD);
+  // Special path for emitting lambda static invokers with inalloca parameters.
+  else if (Method->isLambdaStaticInvoker() && 
+   hasInAllocaArg(getTarget(), getCXXABI(), Method)) {
+// Emit the call operator definition before emitting a static invoker.
+const CXXMethodDecl *CallOp = Method->getParent()->getLambdaCallOperator();
+EmitGlobalFunctionDefinition(GlobalDecl(CallOp), nullptr);
+CodeGenFunction(*this).EmitClonedLambdaStaticInvoke(Method);
+  }
   else if (FD->isMultiVersion())
 EmitMultiVersionFunctionDefinition(GD, GV);
   else
Index: clang/lib/CodeGen/CodeGenFunction.h
===
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2223,6 +2223,8 @@
   void EmitLambdaBlockInvokeBody();
   void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
   void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
+  void EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD);
+
   void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) {
 EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
   }
@@ -2255,6 +2257,8 @@
  GlobalDecl GD, const ThunkInfo ,
  bool IsUnprototyped);
 
+  void CreateClonedFunction(llvm::Function *Fn, llvm::Function *BaseFn,
+llvm::ValueToValueMapTy );
   llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn,
const CGFunctionInfo ,
GlobalDecl GD, const ThunkInfo );
Index: clang/lib/CodeGen/CGVTables.cpp
===
--- clang/lib/CodeGen/CGVTables.cpp
+++ clang/lib/CodeGen/CGVTables.cpp
@@ -139,6 +139,21 @@
   }
 }
 
+void CodeGenFunction::CreateClonedFunction(
+llvm::Function *Fn, llvm::Function *BaseFn, llvm::ValueToValueMapTy ) {
+  // We are cloning a function while some Metadata nodes are still unresolved.
+  // Ensure that the value mapper does not encounter any of them.
+  resolveTopLevelMetadata(BaseFn, VMap);
+  llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
+  Fn->replaceAllUsesWith(NewFn);
+  NewFn->takeName(Fn);
+  Fn->eraseFromParent();
+  Fn = NewFn;
+
+  // "Initialize" CGF (minimally).
+  CurFn = Fn;
+}
+
 // This function does roughly the same thing as GenerateThunk, but in a
 // very different way, so that va_start and va_end work correctly.
 // FIXME: This function assumes "this" is the first non-sret LLVM argument of
@@ -181,17 +196,7 @@
 

[PATCH] D137872: Try to implement lambdas with inalloca parameters by forwarding without use of inallocas.

2022-11-11 Thread Amy Huang via Phabricator via cfe-commits
akhuang created this revision.
Herald added a project: All.
akhuang requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D137872

Files:
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CodeGenFunction.h

Index: clang/lib/CodeGen/CodeGenFunction.h
===
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2223,6 +2223,10 @@
   void EmitLambdaBlockInvokeBody();
   void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
   void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
+  void EmitInAllocaForwardingCallToLambda(const CXXMethodDecl *MD, 
+  const CXXMethodDecl *CallOp, 
+  ArrayRef ArgList,
+  CallArgList );
   void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) {
 EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
   }
Index: clang/lib/CodeGen/CGClass.cpp
===
--- clang/lib/CodeGen/CGClass.cpp
+++ clang/lib/CodeGen/CGClass.cpp
@@ -3003,21 +3003,41 @@
   EmitForwardingCallToLambda(CallOp, CallArgs);
 }
 
+static bool isInAllocaArg(CGCXXABI , QualType T) {
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
+}
+
+static bool hasInAllocaArg(const TargetInfo , CGCXXABI , const CXXMethodDecl *MD) {
+  return TI.getCXXABI().isMicrosoft() &&
+llvm::any_of(MD->parameters(), [&](ParmVarDecl *P) {
+  return isInAllocaArg(ABI, P->getType());
+});
+}
+
 void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
   const CXXRecordDecl *Lambda = MD->getParent();
 
   // Start building arguments for forwarding call
   CallArgList CallArgs;
+  SmallVector ArgList;
 
   QualType LambdaType = getContext().getRecordType(Lambda);
   QualType ThisType = getContext().getPointerType(LambdaType);
   Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture");
   CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType);
+  ArgList.push_back(ThisPtr.getPointer());
 
   // Add the rest of the parameters.
-  for (auto *Param : MD->parameters())
+  for (auto *Param : MD->parameters()) {
 EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc());
 
+if (Param->getType()->isReferenceType())
+  ArgList.push_back(Builder.CreateLoad(GetAddrOfLocalVar(Param)));
+else
+  ArgList.push_back(GetAddrOfLocalVar(Param).getPointer());
+  }
+
   const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
   // For a generic lambda, find the corresponding call operator specialization
   // to which the call to the static-invoker shall be forwarded.
@@ -3031,9 +3051,81 @@
 assert(CorrespondingCallOpSpecialization);
 CallOp = cast(CorrespondingCallOpSpecialization);
   }
+
+  // Special lambda forwarding when there are inalloca parameters.
+  if (hasInAllocaArg(getTarget(), CGM.getCXXABI(), MD)) {
+EmitInAllocaForwardingCallToLambda(MD, CallOp, ArgList, CallArgs);
+return;
+  }
+
   EmitForwardingCallToLambda(CallOp, CallArgs);
 }
 
+void CodeGenFunction::EmitInAllocaForwardingCallToLambda(
+const CXXMethodDecl *MD, const CXXMethodDecl *CallOp,
+ArrayRef ArgList,
+CallArgList ) {
+  const CGFunctionInfo  =
+CGM.getTypes().arrangeCXXMethodDeclaration(CallOp);
+
+  // Create new call op function with different calling convention.
+  CodeGenFunction CGF(CGM);
+  CGF.CurGD = GlobalDecl(CallOp);
+  llvm::Function *CallOpFn =
+cast(CGM.GetAddrOfFunction(GlobalDecl(CallOp)));
+
+  std::string ImplName = (CallOpFn->getName() + ".impl").str();
+  llvm::Function *ImplFn = CallOpFn->getParent()->getFunction(ImplName);
+  if (!ImplFn) {
+// Generate the function.
+ImplFn = llvm::Function::Create(CGM.getTypes().GetFunctionType(FnInfo), 
+llvm::GlobalValue::InternalLinkage,
+ImplName, CGM.getModule());
+ImplFn->setCallingConv(llvm::CallingConv::C);
+CGF.GenerateCode(CGF.CurGD, ImplFn, FnInfo);
+CGM.SetLLVMFunctionAttributesForDefinition(CallOp, ImplFn);
+  }
+
+  // Deactivate any cleanups that we're supposed to do immediately before
+  // the call.
+  if (!CallArgs.getCleanupsToDeactivate().empty()) {
+ArrayRef Cleanups =
+  CallArgs.getCleanupsToDeactivate();
+for (const auto  : llvm::reverse(Cleanups)) {
+  DeactivateCleanupBlock(I.Cleanup, I.IsActiveIP);
+  I.IsActiveIP->eraseFromParent();
+}
+  }
+
+  // Get the args to pass to the call op. This only works because we're assuming
+  // there are two arguments; this, and the inalloca one.
+  SmallVector NewArgList;
+  

[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-03 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CodeGenModule.cpp:3590-3593
+  getTarget().getCXXABI().isMicrosoft() &&
+  llvm::any_of(cast(FD)->parameters(), [&](ParmVarDecl 
*P) {
+return isInAllocaArgument(getCXXABI(), P->getType());
+})) {

rnk wrote:
> akhuang wrote:
> > akhuang wrote:
> > > rnk wrote:
> > > > akhuang wrote:
> > > > > rnk wrote:
> > > > > > For simplicity, what if we always emitted the call operator for all 
> > > > > > lambda static invokers into the IR first? So, this logic would then 
> > > > > > become almost exactly the same as the emitCXXStructor logic above.
> > > > > > 
> > > > > > Later, in EmitLambdaStaticInvokeBody, we can detect the inalloca 
> > > > > > case and start the cloning.
> > > > > > For simplicity, what if we always emitted the call operator for all 
> > > > > > lambda static invokers into the IR first? So, this logic would then 
> > > > > > become almost exactly the same as the emitCXXStructor logic above.
> > > > > 
> > > > > Do you know where this should happen? I couldn't really figure out a 
> > > > > place other than here for emitting the call operator. 
> > > > > 
> > > > > If I do the cloning inside the normal EmitLambdaStaticInvokeBody path 
> > > > > it's a bit annoying because StartFunction/EndFunction get called 
> > > > > before/after cloning.
> > > > > Do you know where this should happen? I couldn't really figure out a 
> > > > > place other than here for emitting the call operator.
> > > > 
> > > > Yes, I think you should do that here, just like we do for constructors. 
> > > > If it's a hack, it's one we already have. The main impact is that we 
> > > > emit the call operator in the IR first. That may require updating some 
> > > > tests, but it's nice to do the same thing on all platforms, and we'd 
> > > > need to do it to handle forwarding varargs lambdas anyway, which are 
> > > > present on all platforms.
> > > > 
> > > > I also think it's OK to delete all the IR from StartFunction after its 
> > > > been generated, that doesn't seem like a big deal. How does the varargs 
> > > > cloning logic handle this situation?
> > > Oh, ok, I see what you mean. 
> > > 
> > > I'll try to upload a version with the cloning function inside 
> > > EmitLambdaStaticInvokeBody. I think there's some stuff in Start/End 
> > > Function that prevent you from simply deleting the code. (I don't think 
> > > it's an issue for the varargs cloning because that isn't called within 
> > > `EmitGlobalFunctionDefinition`. )
> > Actually, hm, trying to do the function cloning inside 
> > `EmitLambdaStaticInvokeBody`/`GenerateCode` might not work because 
> > `FinishFunction` does various things like emit the return statement, which 
> > won't work if we just cloned the function.
> If it doesn't work at all, I'm OK with doing this here, but I would like to 
> try to move as much logic as possible out of `EmitGlobalDefinition`.
Yeah, it doesn't seem ideal.. I guess the logic can also be moved into 
`EmitGlobalFunctionDefinition` (or a new CodeGenModule wrapper function) but 
that doesn't seem much better.

I don't think cloning the function in `GenerateCode` between StartFunction and 
FinishFunction will work though. Otherwise maybe can go back to trying a 
different method like changing the CXXMethodDecl from the call op and emitting 
it through the normal codegen path. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

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


[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-03 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 473082.
akhuang added a comment.

moved some stuff around


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

Files:
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,7 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+// CHECK: define internal x86_thiscallcc void @"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z"
+// CHECK-SAME: (ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: %1 = getelementptr inbounds <{ %class.A, [3 x i8] }>, ptr %0, i32 0, i32 0
+// CHECK: ret void
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3554,6 +3554,18 @@
 EmitGlobalFunctionDefinition(GD, GV);
 }
 
+static bool isInAllocaArg(CGCXXABI , QualType T) {
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
+}
+
+static bool hasInAllocaArg(const TargetInfo , CGCXXABI , const CXXMethodDecl *MD) {
+  return TI.getCXXABI().isMicrosoft() && 
+llvm::any_of(MD->parameters(), [&](ParmVarDecl *P) {
+return isInAllocaArg(CGABI, P->getType());
+  });
+}
+
 void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
   const auto *D = cast(GD.getDecl());
 
@@ -3580,6 +3592,14 @@
   // This is necessary for the generation of certain thunks.
   if (isa(Method) || isa(Method))
 ABI->emitCXXStructor(GD);
+  // Special path for emitting lambda static invokers with inalloca parameters.
+  else if (Method->isLambdaStaticInvoker() && 
+   hasInAllocaArg(getTarget(), getCXXABI(), Method)) {
+// Emit the call operator definition before emitting a static invoker.
+const CXXMethodDecl *CallOp = Method->getParent()->getLambdaCallOperator();
+EmitGlobalFunctionDefinition(GlobalDecl(CallOp), nullptr);
+CodeGenFunction(*this).EmitClonedLambdaStaticInvoke(Method);
+  }
   else if (FD->isMultiVersion())
 EmitMultiVersionFunctionDefinition(GD, GV);
   else
Index: clang/lib/CodeGen/CodeGenFunction.h
===
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2223,6 +2223,8 @@
   void EmitLambdaBlockInvokeBody();
   void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
   void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
+  void EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD);
+
   void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) {
 EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
   }
Index: clang/lib/CodeGen/CGClass.cpp
===
--- clang/lib/CodeGen/CGClass.cpp
+++ clang/lib/CodeGen/CGClass.cpp
@@ -26,8 +26,10 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/TargetBuiltins.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Metadata.h"
+#include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/SanitizerStats.h"
 
 using namespace clang;
@@ -3044,3 +3046,38 @@
 
   EmitLambdaDelegatingInvokeBody(MD);
 }
+
+void CodeGenFunction::EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD) {
+  llvm::Function *Fn =
+cast(CGM.GetAddrOfFunction(GlobalDecl(MD)));
+
+  const CXXMethodDecl *CallOp = MD->getParent()->getLambdaCallOperator();
+  llvm::Function *CallOpFn =
+cast(CGM.GetAddrOfFunction(GlobalDecl(CallOp)));
+
+  // Clone from call operator, which we've made sure is already emitted.
+  llvm::ValueToValueMapTy VMap;
+
+  for (llvm::Argument  : CallOpFn->args()) {
+// Don't copy the %this argument.
+if (I.getName().equals("this")) {
+  VMap[] = llvm::Constant::getNullValue(I.getType());
+} else {
+  // Try to map the inalloca arg from the call op fn to the invoker fn.
+  for (llvm::Argument  : Fn->args()) {
+if (DestI.getType() == I.getType()) {
+  VMap[] = 
+  break;
+}
+  }
+}
+  }
+
+  Fn->setAttributes(CallOpFn->getAttributes());

[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-03 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CodeGenModule.cpp:3590-3593
+  getTarget().getCXXABI().isMicrosoft() &&
+  llvm::any_of(cast(FD)->parameters(), [&](ParmVarDecl 
*P) {
+return isInAllocaArgument(getCXXABI(), P->getType());
+})) {

akhuang wrote:
> rnk wrote:
> > akhuang wrote:
> > > rnk wrote:
> > > > For simplicity, what if we always emitted the call operator for all 
> > > > lambda static invokers into the IR first? So, this logic would then 
> > > > become almost exactly the same as the emitCXXStructor logic above.
> > > > 
> > > > Later, in EmitLambdaStaticInvokeBody, we can detect the inalloca case 
> > > > and start the cloning.
> > > > For simplicity, what if we always emitted the call operator for all 
> > > > lambda static invokers into the IR first? So, this logic would then 
> > > > become almost exactly the same as the emitCXXStructor logic above.
> > > 
> > > Do you know where this should happen? I couldn't really figure out a 
> > > place other than here for emitting the call operator. 
> > > 
> > > If I do the cloning inside the normal EmitLambdaStaticInvokeBody path 
> > > it's a bit annoying because StartFunction/EndFunction get called 
> > > before/after cloning.
> > > Do you know where this should happen? I couldn't really figure out a 
> > > place other than here for emitting the call operator.
> > 
> > Yes, I think you should do that here, just like we do for constructors. If 
> > it's a hack, it's one we already have. The main impact is that we emit the 
> > call operator in the IR first. That may require updating some tests, but 
> > it's nice to do the same thing on all platforms, and we'd need to do it to 
> > handle forwarding varargs lambdas anyway, which are present on all 
> > platforms.
> > 
> > I also think it's OK to delete all the IR from StartFunction after its been 
> > generated, that doesn't seem like a big deal. How does the varargs cloning 
> > logic handle this situation?
> Oh, ok, I see what you mean. 
> 
> I'll try to upload a version with the cloning function inside 
> EmitLambdaStaticInvokeBody. I think there's some stuff in Start/End Function 
> that prevent you from simply deleting the code. (I don't think it's an issue 
> for the varargs cloning because that isn't called within 
> `EmitGlobalFunctionDefinition`. )
Actually, hm, trying to do the function cloning inside 
`EmitLambdaStaticInvokeBody`/`GenerateCode` might not work because 
`FinishFunction` does various things like emit the return statement, which 
won't work if we just cloned the function.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

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


[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-02 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CodeGenModule.cpp:3590-3593
+  getTarget().getCXXABI().isMicrosoft() &&
+  llvm::any_of(cast(FD)->parameters(), [&](ParmVarDecl 
*P) {
+return isInAllocaArgument(getCXXABI(), P->getType());
+})) {

rnk wrote:
> akhuang wrote:
> > rnk wrote:
> > > For simplicity, what if we always emitted the call operator for all 
> > > lambda static invokers into the IR first? So, this logic would then 
> > > become almost exactly the same as the emitCXXStructor logic above.
> > > 
> > > Later, in EmitLambdaStaticInvokeBody, we can detect the inalloca case and 
> > > start the cloning.
> > > For simplicity, what if we always emitted the call operator for all 
> > > lambda static invokers into the IR first? So, this logic would then 
> > > become almost exactly the same as the emitCXXStructor logic above.
> > 
> > Do you know where this should happen? I couldn't really figure out a place 
> > other than here for emitting the call operator. 
> > 
> > If I do the cloning inside the normal EmitLambdaStaticInvokeBody path it's 
> > a bit annoying because StartFunction/EndFunction get called before/after 
> > cloning.
> > Do you know where this should happen? I couldn't really figure out a place 
> > other than here for emitting the call operator.
> 
> Yes, I think you should do that here, just like we do for constructors. If 
> it's a hack, it's one we already have. The main impact is that we emit the 
> call operator in the IR first. That may require updating some tests, but it's 
> nice to do the same thing on all platforms, and we'd need to do it to handle 
> forwarding varargs lambdas anyway, which are present on all platforms.
> 
> I also think it's OK to delete all the IR from StartFunction after its been 
> generated, that doesn't seem like a big deal. How does the varargs cloning 
> logic handle this situation?
Oh, ok, I see what you mean. 

I'll try to upload a version with the cloning function inside 
EmitLambdaStaticInvokeBody. I think there's some stuff in Start/End Function 
that prevent you from simply deleting the code. (I don't think it's an issue 
for the varargs cloning because that isn't called within 
`EmitGlobalFunctionDefinition`. )


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

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


[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-02 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/CodeGen/CodeGenModule.cpp:3590-3593
+  getTarget().getCXXABI().isMicrosoft() &&
+  llvm::any_of(cast(FD)->parameters(), [&](ParmVarDecl 
*P) {
+return isInAllocaArgument(getCXXABI(), P->getType());
+})) {

rnk wrote:
> For simplicity, what if we always emitted the call operator for all lambda 
> static invokers into the IR first? So, this logic would then become almost 
> exactly the same as the emitCXXStructor logic above.
> 
> Later, in EmitLambdaStaticInvokeBody, we can detect the inalloca case and 
> start the cloning.
> For simplicity, what if we always emitted the call operator for all lambda 
> static invokers into the IR first? So, this logic would then become almost 
> exactly the same as the emitCXXStructor logic above.

Do you know where this should happen? I couldn't really figure out a place 
other than here for emitting the call operator. 

If I do the cloning inside the normal EmitLambdaStaticInvokeBody path it's a 
bit annoying because StartFunction/EndFunction get called before/after cloning.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

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


[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-02 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 472761.
akhuang added a comment.

update


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

Files:
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,7 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+// CHECK: define internal x86_thiscallcc void @"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z"
+// CHECK-SAME: (ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: %1 = getelementptr inbounds <{ %class.A, [3 x i8] }>, ptr %0, i32 0, i32 0
+// CHECK: ret void
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3554,6 +3554,11 @@
 EmitGlobalFunctionDefinition(GD, GV);
 }
 
+static bool isInAllocaArgument(CGCXXABI , QualType T) {
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
+}
+
 void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
   const auto *D = cast(GD.getDecl());
 
@@ -3580,6 +3585,25 @@
   // This is necessary for the generation of certain thunks.
   if (isa(Method) || isa(Method))
 ABI->emitCXXStructor(GD);
+  // Hack for lambda forwarding calls with inalloca parameters.
+  else if (isa(FD) && cast(FD)->isLambdaStaticInvoker() &&
+  getTarget().getCXXABI().isMicrosoft() &&
+  llvm::any_of(cast(FD)->parameters(), [&](ParmVarDecl *P) {
+return isInAllocaArgument(getCXXABI(), P->getType());
+})) {
+// If the call op is not yet emitted, emit that.
+const CXXRecordDecl *Lambda = cast(FD)->getParent();
+const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
+const CGFunctionInfo  =
+  getTypes().arrangeCXXMethodDeclaration(CallOp);
+llvm::Function *CallOpFn = cast(
+  GetAddrOfFunction(GlobalDecl(CallOp),
+getTypes().GetFunctionType(CallOpFnInfo)));
+if (CallOpFn->isDeclaration())
+  EmitGlobalFunctionDefinition(GlobalDecl(CallOp), nullptr);
+
+CodeGenFunction(*this).EmitClonedLambdaStaticInvoke(cast(FD));
+  }
   else if (FD->isMultiVersion())
 EmitMultiVersionFunctionDefinition(GD, GV);
   else
Index: clang/lib/CodeGen/CodeGenFunction.h
===
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2223,6 +2223,8 @@
   void EmitLambdaBlockInvokeBody();
   void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
   void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
+  void EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD);
+
   void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) {
 EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
   }
Index: clang/lib/CodeGen/CGClass.cpp
===
--- clang/lib/CodeGen/CGClass.cpp
+++ clang/lib/CodeGen/CGClass.cpp
@@ -26,8 +26,10 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/TargetBuiltins.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Metadata.h"
+#include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/SanitizerStats.h"
 
 using namespace clang;
@@ -3044,3 +3046,38 @@
 
   EmitLambdaDelegatingInvokeBody(MD);
 }
+
+void CodeGenFunction::EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD) {
+  llvm::Function *Fn =
+cast(CGM.GetAddrOfFunction(GlobalDecl(MD)));
+
+  const CXXMethodDecl *CallOp = MD->getParent()->getLambdaCallOperator();
+  llvm::Function *CallOpFn =
+cast(CGM.GetAddrOfFunction(GlobalDecl(CallOp)));
+
+  // Clone from call operator.
+  llvm::ValueToValueMapTy VMap;
+
+  for (llvm::Argument  : CallOpFn->args()) {
+// Don't copy the %this argument.
+if (I.getName().equals("this")) {
+  VMap[] = llvm::PoisonValue::get(I.getType());
+} else {
+  // Try to map the inalloca arg from the call op fn to the invoker fn.
+  for (llvm::Argument  : Fn->args()) {
+if 

[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-01 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 472450.
akhuang added a comment.

update


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

Files:
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,7 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+// CHECK: define internal x86_thiscallcc void @"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z"
+// CHECK-SAME: (ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: %1 = getelementptr inbounds <{ %class.A, [3 x i8] }>, ptr %0, i32 0, i32 0
+// CHECK: ret void
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3554,6 +3554,11 @@
 EmitGlobalFunctionDefinition(GD, GV);
 }
 
+static bool isInAllocaArgument(CGCXXABI , QualType T) {
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
+}
+
 void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
   const auto *D = cast(GD.getDecl());
 
@@ -3580,6 +3585,25 @@
   // This is necessary for the generation of certain thunks.
   if (isa(Method) || isa(Method))
 ABI->emitCXXStructor(GD);
+  // Hack for lambda forwarding calls with inalloca parameters.
+  else if (isa(FD) && cast(FD)->isLambdaStaticInvoker() &&
+  getTarget().getCXXABI().isMicrosoft() &&
+  llvm::any_of(cast(FD)->parameters(), [&](ParmVarDecl *P) {
+return isInAllocaArgument(getCXXABI(), P->getType());
+})) {
+// If the call op is not yet emitted, emit that.
+const CXXRecordDecl *Lambda = cast(FD)->getParent();
+const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
+const CGFunctionInfo  =
+  getTypes().arrangeCXXMethodDeclaration(CallOp);
+llvm::Function *CallOpFn = cast(
+  GetAddrOfFunction(GlobalDecl(CallOp),
+getTypes().GetFunctionType(CallOpFnInfo)));
+if (CallOpFn->isDeclaration())
+  EmitGlobalFunctionDefinition(GlobalDecl(CallOp), nullptr);
+
+CodeGenFunction(*this).EmitClonedLambdaStaticInvoke(cast(FD));
+  }
   else if (FD->isMultiVersion())
 EmitMultiVersionFunctionDefinition(GD, GV);
   else
Index: clang/lib/CodeGen/CodeGenFunction.h
===
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2223,6 +2223,8 @@
   void EmitLambdaBlockInvokeBody();
   void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
   void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
+  void EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD);
+
   void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) {
 EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
   }
Index: clang/lib/CodeGen/CGClass.cpp
===
--- clang/lib/CodeGen/CGClass.cpp
+++ clang/lib/CodeGen/CGClass.cpp
@@ -26,8 +26,10 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/TargetBuiltins.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Metadata.h"
+#include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/SanitizerStats.h"
 
 using namespace clang;
@@ -3044,3 +3046,46 @@
 
   EmitLambdaDelegatingInvokeBody(MD);
 }
+
+void CodeGenFunction::EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD) {
+  const CGFunctionInfo  = CGM.getTypes().arrangeCXXMethodDeclaration(MD);
+  llvm::Type *InvokerTy = CGM.getTypes().GetFunctionType(InvokerFnInfo);
+  GlobalDecl GD = GlobalDecl(MD);
+  llvm::Function *InvokerFn = cast(CGM.GetAddrOfFunction(GD, InvokerTy));
+
+  const CXXRecordDecl *Lambda = MD->getParent();
+  const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
+  const CGFunctionInfo  =
+CGM.getTypes().arrangeCXXMethodDeclaration(CallOp);
+  llvm::Function *CallOpFn = cast(
+CGM.GetAddrOfFunction(GlobalDecl(CallOp),
+  CGM.getTypes().GetFunctionType(CallOpFnInfo)));
+
+  // 

[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-11-01 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 472447.
akhuang added a comment.

update


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

Files:
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,7 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+// CHECK: define internal x86_thiscallcc void @"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z"
+// CHECK-SAME: (ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: %1 = getelementptr inbounds <{ %class.A, [3 x i8] }>, ptr %0, i32 0, i32 0
+// CHECK: ret void
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3554,6 +3554,11 @@
 EmitGlobalFunctionDefinition(GD, GV);
 }
 
+static bool isInAllocaArgument(CGCXXABI , QualType T) {
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
+}
+
 void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
   const auto *D = cast(GD.getDecl());
 
@@ -3580,6 +3585,25 @@
   // This is necessary for the generation of certain thunks.
   if (isa(Method) || isa(Method))
 ABI->emitCXXStructor(GD);
+  // Hack for lambda forwarding calls with inalloca parameters.
+  else if (isa(FD) && cast(FD)->isLambdaStaticInvoker() &&
+  getTarget().getCXXABI().isMicrosoft() &&
+  llvm::any_of(cast(FD)->parameters(), [&](ParmVarDecl *P) {
+return isInAllocaArgument(getCXXABI(), P->getType());
+})) {
+// If the call op is not yet emitted, emit that.
+const CXXRecordDecl *Lambda = cast(FD)->getParent();
+const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
+const CGFunctionInfo  =
+  getTypes().arrangeCXXMethodDeclaration(CallOp);
+llvm::Function *CallOpFn = cast(
+  GetAddrOfFunction(GlobalDecl(CallOp),
+getTypes().GetFunctionType(CallOpFnInfo)));
+if (CallOpFn->isDeclaration())
+  EmitGlobalFunctionDefinition(GlobalDecl(CallOp), nullptr);
+
+CodeGenFunction(*this).EmitClonedLambdaStaticInvoke(cast(FD));
+  }
   else if (FD->isMultiVersion())
 EmitMultiVersionFunctionDefinition(GD, GV);
   else
Index: clang/lib/CodeGen/CodeGenFunction.h
===
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2223,6 +2223,8 @@
   void EmitLambdaBlockInvokeBody();
   void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
   void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
+  void EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD);
+
   void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) {
 EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
   }
Index: clang/lib/CodeGen/CGClass.cpp
===
--- clang/lib/CodeGen/CGClass.cpp
+++ clang/lib/CodeGen/CGClass.cpp
@@ -26,8 +26,10 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/TargetBuiltins.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Metadata.h"
+#include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/SanitizerStats.h"
 
 using namespace clang;
@@ -3044,3 +3046,46 @@
 
   EmitLambdaDelegatingInvokeBody(MD);
 }
+
+void CodeGenFunction::EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD) {
+  const CGFunctionInfo  = CGM.getTypes().arrangeCXXMethodDeclaration(MD);
+  llvm::Type *InvokerTy = CGM.getTypes().GetFunctionType(InvokerFnInfo);
+  GlobalDecl GD = GlobalDecl(MD);
+  llvm::Function *InvokerFn = cast(CGM.GetAddrOfFunction(GD, InvokerTy));
+
+  const CXXRecordDecl *Lambda = MD->getParent();
+  const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
+  const CGFunctionInfo  =
+CGM.getTypes().arrangeCXXMethodDeclaration(CallOp);
+  llvm::Function *CallOpFn = cast(
+CGM.GetAddrOfFunction(GlobalDecl(CallOp),
+  

[PATCH] D136998: Try to implement lambdas with inalloca parameters by inlining the call operator function.

2022-10-28 Thread Amy Huang via Phabricator via cfe-commits
akhuang created this revision.
Herald added a subscriber: nlopes.
Herald added a project: All.
akhuang requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136998

Files:
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,7 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+// CHECK: define internal void @"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z"
+// CHECK-SAME: (ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: %1 = getelementptr inbounds <{ %class.A, [3 x i8] }>, ptr %0, i32 0, i32 0
+// CHECK: ret void
Index: clang/lib/CodeGen/CodeGenFunction.h
===
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2223,6 +2223,8 @@
   void EmitLambdaBlockInvokeBody();
   void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
   void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
+  void EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD);
+
   void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) {
 EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
   }
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1327,6 +1327,11 @@
   return ResTy;
 }
 
+static bool isInAllocaArgument(CGCXXABI , QualType T) {
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
+}
+
 void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo ) {
   assert(Fn && "generating code for null Function");
@@ -1482,6 +1487,17 @@
   // a quick pass now to see if we can.
   if (!CurFn->doesNotThrow())
 TryMarkNoThrow(CurFn);
+
+  // If 32-bit Windows, and there's an inalloca parameter, don't use the
+  // emitted lambda static invoker function because we can't forward inalloca
+  // parameters. Instead copy the body from the call operator.
+  if (isa(FD) && isLambdaCallOperator(cast(FD)) && 
+  CGM.getTarget().getCXXABI().isMicrosoft() &&
+  llvm::any_of(cast(FD)->parameters(), [&](ParmVarDecl *P) {
+return isInAllocaArgument(CGM.getCXXABI(), P->getType());
+})) {
+EmitClonedLambdaStaticInvoke(cast(FD));
+  }
 }
 
 /// ContainsLabel - Return true if the statement contains a label in it.  If
Index: clang/lib/CodeGen/CGClass.cpp
===
--- clang/lib/CodeGen/CGClass.cpp
+++ clang/lib/CodeGen/CGClass.cpp
@@ -26,8 +26,10 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/TargetBuiltins.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Metadata.h"
+#include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/SanitizerStats.h"
 
 using namespace clang;
@@ -3044,3 +3046,48 @@
 
   EmitLambdaDelegatingInvokeBody(MD);
 }
+
+void CodeGenFunction::EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD) {
+  const CGFunctionInfo  = CGM.getTypes().arrangeCXXMethodDeclaration(MD);
+  llvm::Type *Ty = CGM.getTypes().GetFunctionType(FnInfo);
+  llvm::Function *Fn = cast(CGM.GetAddrOfFunction(GlobalDecl(MD), Ty));
+
+  // Loop through all the __invoke functions.
+  const CXXRecordDecl *Lambda = MD->getParent();
+
+  CallingConv CCs[] =
+{ CC_C, CC_X86StdCall, CC_X86FastCall, CC_X86ThisCall, CC_X86VectorCall };
+  for (CallingConv CC : CCs) {
+const CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker(CC);
+if (!Invoker)
+  continue;
+
+const CGFunctionInfo  =
+  CGM.getTypes().arrangeCXXMethodDeclaration(Invoker);
+llvm::Function *InvokerFn = cast(
+  CGM.GetAddrOfFunction(GlobalDecl(Invoker),
+CGM.getTypes().GetFunctionType(InvokerFnInfo)));
+
+if (InvokerFn->isDeclaration())
+  continue;
+
+// Clone from call operator.
+llvm::ValueToValueMapTy VMap;
+
+// Don't copy the %this argument.
+for (llvm::Argument  : Fn->args()) {
+  if 

[PATCH] D136188: Update docs for -fuse-ctor-homing

2022-10-27 Thread Amy Huang via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGe8433a2b06d5: Update docs for -fuse-ctor-homing (authored by 
akhuang).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136188

Files:
  clang/docs/UsersManual.rst


Index: clang/docs/UsersManual.rst
===
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2841,11 +2841,16 @@
   Clang supports a number of optimizations to reduce the size of debug
   information in the binary. They work based on the assumption that
   the debug type information can be spread out over multiple
-  compilation units.  For instance, Clang will not emit type
-  definitions for types that are not needed by a module and could be
-  replaced with a forward declaration.  Further, Clang will only emit
-  type info for a dynamic C++ class in the module that contains the
-  vtable for the class.
+  compilation units.  Specifically, the optimizations are:
+- will not emit type definitions for types that are not needed by a
+  module and could be replaced with a forward declaration.
+- will only emit type info for a dynamic C++ class in the module that
+  contains the vtable for the class.
+- will only emit type info for a C++ class (non-trivial, non-aggregate)
+  in the modules that contain a definition for one of its constructors.
+- will only emit type definitions for types that are the subject of explicit
+  template instantiation declarations in the presence of an explicit
+  instantiation definition for the type.
 
   The **-fstandalone-debug** option turns off these optimizations.
   This is useful when working with 3rd-party libraries that don't come
@@ -2858,19 +2863,6 @@
**-fno-standalone-debug** option can be used to get to turn on the
vtable-based optimization described above.
 
-.. option:: -fuse-ctor-homing
-
-   This optimization is similar to the optimizations that are enabled as part
-   of -fno-standalone-debug. Here, Clang only emits type info for a
-   non-trivial, non-aggregate C++ class in the modules that contain a
-   definition of one of its constructors. This relies on the additional
-   assumption that all classes that are not trivially constructible have a
-   non-trivial constructor that is used somewhere. The negation,
-   -fno-use-ctor-homing, ensures that constructor homing is not used.
-
-   This flag is not enabled by default, and needs to be used with -cc1 or
-   -Xclang.
-
 .. option:: -g
 
   Generate complete debug info.


Index: clang/docs/UsersManual.rst
===
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2841,11 +2841,16 @@
   Clang supports a number of optimizations to reduce the size of debug
   information in the binary. They work based on the assumption that
   the debug type information can be spread out over multiple
-  compilation units.  For instance, Clang will not emit type
-  definitions for types that are not needed by a module and could be
-  replaced with a forward declaration.  Further, Clang will only emit
-  type info for a dynamic C++ class in the module that contains the
-  vtable for the class.
+  compilation units.  Specifically, the optimizations are:
+- will not emit type definitions for types that are not needed by a
+  module and could be replaced with a forward declaration.
+- will only emit type info for a dynamic C++ class in the module that
+  contains the vtable for the class.
+- will only emit type info for a C++ class (non-trivial, non-aggregate)
+  in the modules that contain a definition for one of its constructors.
+- will only emit type definitions for types that are the subject of explicit
+  template instantiation declarations in the presence of an explicit
+  instantiation definition for the type.
 
   The **-fstandalone-debug** option turns off these optimizations.
   This is useful when working with 3rd-party libraries that don't come
@@ -2858,19 +2863,6 @@
**-fno-standalone-debug** option can be used to get to turn on the
vtable-based optimization described above.
 
-.. option:: -fuse-ctor-homing
-
-   This optimization is similar to the optimizations that are enabled as part
-   of -fno-standalone-debug. Here, Clang only emits type info for a
-   non-trivial, non-aggregate C++ class in the modules that contain a
-   definition of one of its constructors. This relies on the additional
-   assumption that all classes that are not trivially constructible have a
-   non-trivial constructor that is used somewhere. The negation,
-   -fno-use-ctor-homing, ensures that constructor homing is not used.
-
-   This flag is not enabled by default, and needs to be used with -cc1 or
-   -Xclang.
-
 .. option:: -g
 
   Generate complete debug info.
___
cfe-commits mailing list

[PATCH] D136188: Update docs for -fuse-ctor-homing

2022-10-27 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 471240.
akhuang added a comment.

Add another debug info strategy to the description


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136188

Files:
  clang/docs/UsersManual.rst


Index: clang/docs/UsersManual.rst
===
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2841,11 +2841,16 @@
   Clang supports a number of optimizations to reduce the size of debug
   information in the binary. They work based on the assumption that
   the debug type information can be spread out over multiple
-  compilation units.  For instance, Clang will not emit type
-  definitions for types that are not needed by a module and could be
-  replaced with a forward declaration.  Further, Clang will only emit
-  type info for a dynamic C++ class in the module that contains the
-  vtable for the class.
+  compilation units.  Specifically, the optimizations are:
+- will not emit type definitions for types that are not needed by a
+  module and could be replaced with a forward declaration.
+- will only emit type info for a dynamic C++ class in the module that
+  contains the vtable for the class.
+- will only emit type info for a C++ class (non-trivial, non-aggregate)
+  in the modules that contain a definition for one of its constructors.
+- will only emit type definitions for types that are the subject of explicit
+  template instantiation declarations in the presence of an explicit
+  instantiation definition for the type.
 
   The **-fstandalone-debug** option turns off these optimizations.
   This is useful when working with 3rd-party libraries that don't come
@@ -2858,19 +2863,6 @@
**-fno-standalone-debug** option can be used to get to turn on the
vtable-based optimization described above.
 
-.. option:: -fuse-ctor-homing
-
-   This optimization is similar to the optimizations that are enabled as part
-   of -fno-standalone-debug. Here, Clang only emits type info for a
-   non-trivial, non-aggregate C++ class in the modules that contain a
-   definition of one of its constructors. This relies on the additional
-   assumption that all classes that are not trivially constructible have a
-   non-trivial constructor that is used somewhere. The negation,
-   -fno-use-ctor-homing, ensures that constructor homing is not used.
-
-   This flag is not enabled by default, and needs to be used with -cc1 or
-   -Xclang.
-
 .. option:: -g
 
   Generate complete debug info.


Index: clang/docs/UsersManual.rst
===
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2841,11 +2841,16 @@
   Clang supports a number of optimizations to reduce the size of debug
   information in the binary. They work based on the assumption that
   the debug type information can be spread out over multiple
-  compilation units.  For instance, Clang will not emit type
-  definitions for types that are not needed by a module and could be
-  replaced with a forward declaration.  Further, Clang will only emit
-  type info for a dynamic C++ class in the module that contains the
-  vtable for the class.
+  compilation units.  Specifically, the optimizations are:
+- will not emit type definitions for types that are not needed by a
+  module and could be replaced with a forward declaration.
+- will only emit type info for a dynamic C++ class in the module that
+  contains the vtable for the class.
+- will only emit type info for a C++ class (non-trivial, non-aggregate)
+  in the modules that contain a definition for one of its constructors.
+- will only emit type definitions for types that are the subject of explicit
+  template instantiation declarations in the presence of an explicit
+  instantiation definition for the type.
 
   The **-fstandalone-debug** option turns off these optimizations.
   This is useful when working with 3rd-party libraries that don't come
@@ -2858,19 +2863,6 @@
**-fno-standalone-debug** option can be used to get to turn on the
vtable-based optimization described above.
 
-.. option:: -fuse-ctor-homing
-
-   This optimization is similar to the optimizations that are enabled as part
-   of -fno-standalone-debug. Here, Clang only emits type info for a
-   non-trivial, non-aggregate C++ class in the modules that contain a
-   definition of one of its constructors. This relies on the additional
-   assumption that all classes that are not trivially constructible have a
-   non-trivial constructor that is used somewhere. The negation,
-   -fno-use-ctor-homing, ensures that constructor homing is not used.
-
-   This flag is not enabled by default, and needs to be used with -cc1 or
-   -Xclang.
-
 .. option:: -g
 
   Generate complete debug info.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[PATCH] D136188: Update docs for -fuse-ctor-homing

2022-10-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 468687.
akhuang added a comment.

Move ctor homing info to fstandalone-debug.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136188

Files:
  clang/docs/UsersManual.rst


Index: clang/docs/UsersManual.rst
===
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2841,11 +2841,13 @@
   Clang supports a number of optimizations to reduce the size of debug
   information in the binary. They work based on the assumption that
   the debug type information can be spread out over multiple
-  compilation units.  For instance, Clang will not emit type
-  definitions for types that are not needed by a module and could be
-  replaced with a forward declaration.  Further, Clang will only emit
-  type info for a dynamic C++ class in the module that contains the
-  vtable for the class.
+  compilation units.  Specifically, the optimizations are:
+- Clang will not emit type definitions for types that are not needed by a
+  module and could be replaced with a forward declaration.
+- Clang will only emit type info for a dynamic C++ class in the module that
+  contains the vtable for the class.
+- Clang will only emit type info for a C++ class (non-trivial, non-aggregate)
+  in the modules that contain a definition for one of its constructors.
 
   The **-fstandalone-debug** option turns off these optimizations.
   This is useful when working with 3rd-party libraries that don't come
@@ -2858,19 +2860,6 @@
**-fno-standalone-debug** option can be used to get to turn on the
vtable-based optimization described above.
 
-.. option:: -fuse-ctor-homing
-
-   This optimization is similar to the optimizations that are enabled as part
-   of -fno-standalone-debug. Here, Clang only emits type info for a
-   non-trivial, non-aggregate C++ class in the modules that contain a
-   definition of one of its constructors. This relies on the additional
-   assumption that all classes that are not trivially constructible have a
-   non-trivial constructor that is used somewhere. The negation,
-   -fno-use-ctor-homing, ensures that constructor homing is not used.
-
-   This flag is not enabled by default, and needs to be used with -cc1 or
-   -Xclang.
-
 .. option:: -g
 
   Generate complete debug info.


Index: clang/docs/UsersManual.rst
===
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2841,11 +2841,13 @@
   Clang supports a number of optimizations to reduce the size of debug
   information in the binary. They work based on the assumption that
   the debug type information can be spread out over multiple
-  compilation units.  For instance, Clang will not emit type
-  definitions for types that are not needed by a module and could be
-  replaced with a forward declaration.  Further, Clang will only emit
-  type info for a dynamic C++ class in the module that contains the
-  vtable for the class.
+  compilation units.  Specifically, the optimizations are:
+- Clang will not emit type definitions for types that are not needed by a
+  module and could be replaced with a forward declaration.
+- Clang will only emit type info for a dynamic C++ class in the module that
+  contains the vtable for the class.
+- Clang will only emit type info for a C++ class (non-trivial, non-aggregate)
+  in the modules that contain a definition for one of its constructors.
 
   The **-fstandalone-debug** option turns off these optimizations.
   This is useful when working with 3rd-party libraries that don't come
@@ -2858,19 +2860,6 @@
**-fno-standalone-debug** option can be used to get to turn on the
vtable-based optimization described above.
 
-.. option:: -fuse-ctor-homing
-
-   This optimization is similar to the optimizations that are enabled as part
-   of -fno-standalone-debug. Here, Clang only emits type info for a
-   non-trivial, non-aggregate C++ class in the modules that contain a
-   definition of one of its constructors. This relies on the additional
-   assumption that all classes that are not trivially constructible have a
-   non-trivial constructor that is used somewhere. The negation,
-   -fno-use-ctor-homing, ensures that constructor homing is not used.
-
-   This flag is not enabled by default, and needs to be used with -cc1 or
-   -Xclang.
-
 .. option:: -g
 
   Generate complete debug info.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136188: Update docs for -fuse-ctor-homing

2022-10-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

Actually, maybe I should add some of this info to the -fstandalone-debug 
section.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136188

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


[PATCH] D136188: Update docs for -fuse-ctor-homing

2022-10-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 468677.
akhuang edited the summary of this revision.
akhuang added a comment.

Remove documentation paragraph.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136188

Files:
  clang/docs/UsersManual.rst


Index: clang/docs/UsersManual.rst
===
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2858,19 +2858,6 @@
**-fno-standalone-debug** option can be used to get to turn on the
vtable-based optimization described above.
 
-.. option:: -fuse-ctor-homing
-
-   This optimization is similar to the optimizations that are enabled as part
-   of -fno-standalone-debug. Here, Clang only emits type info for a
-   non-trivial, non-aggregate C++ class in the modules that contain a
-   definition of one of its constructors. This relies on the additional
-   assumption that all classes that are not trivially constructible have a
-   non-trivial constructor that is used somewhere. The negation,
-   -fno-use-ctor-homing, ensures that constructor homing is not used.
-
-   This flag is not enabled by default, and needs to be used with -cc1 or
-   -Xclang.
-
 .. option:: -g
 
   Generate complete debug info.


Index: clang/docs/UsersManual.rst
===
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2858,19 +2858,6 @@
**-fno-standalone-debug** option can be used to get to turn on the
vtable-based optimization described above.
 
-.. option:: -fuse-ctor-homing
-
-   This optimization is similar to the optimizations that are enabled as part
-   of -fno-standalone-debug. Here, Clang only emits type info for a
-   non-trivial, non-aggregate C++ class in the modules that contain a
-   definition of one of its constructors. This relies on the additional
-   assumption that all classes that are not trivially constructible have a
-   non-trivial constructor that is used somewhere. The negation,
-   -fno-use-ctor-homing, ensures that constructor homing is not used.
-
-   This flag is not enabled by default, and needs to be used with -cc1 or
-   -Xclang.
-
 .. option:: -g
 
   Generate complete debug info.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136188: Update docs for -fuse-ctor-homing

2022-10-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

In D136188#3866266 , @dblaikie wrote:

> (not sure whether to discuss this here or on the bug)
>
> Should we remove the documentation? Part of the principles of "cc1" flags is 
> that their implementation details, not to be publicly used and maybe not to 
> be publicly documented either?

That sounds good to me, I guess this paragraph is really only here for 
"-fno-use-ctor-homing" which doesn't seem like it needs to be documented here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136188

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


[PATCH] D136188: Update docs for -fuse-ctor-homing

2022-10-18 Thread Amy Huang via Phabricator via cfe-commits
akhuang created this revision.
akhuang added a reviewer: rnk.
Herald added a project: All.
akhuang requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Update docs to reflect the fact that this flag is on by default now.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136188

Files:
  clang/docs/UsersManual.rst


Index: clang/docs/UsersManual.rst
===
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2860,16 +2860,12 @@
 
 .. option:: -fuse-ctor-homing
 
-   This optimization is similar to the optimizations that are enabled as part
-   of -fno-standalone-debug. Here, Clang only emits type info for a
-   non-trivial, non-aggregate C++ class in the modules that contain a
-   definition of one of its constructors. This relies on the additional
-   assumption that all classes that are not trivially constructible have a
-   non-trivial constructor that is used somewhere. The negation,
-   -fno-use-ctor-homing, ensures that constructor homing is not used.
-
-   This flag is not enabled by default, and needs to be used with -cc1 or
-   -Xclang.
+   This optimization is enabled by default as part of -fno-standalone-debug.
+   Clang only emits type info for a non-trivial, non-aggregate C++ class in
+   the modules that contain a definition of one of its constructors. This
+   relies on the additional assumption that all classes that are not trivially
+   constructible have a non-trivial constructor that is used somewhere. This
+   can be disabled using the cc1 flag -fno-use-ctor-homing.
 
 .. option:: -g
 


Index: clang/docs/UsersManual.rst
===
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2860,16 +2860,12 @@
 
 .. option:: -fuse-ctor-homing
 
-   This optimization is similar to the optimizations that are enabled as part
-   of -fno-standalone-debug. Here, Clang only emits type info for a
-   non-trivial, non-aggregate C++ class in the modules that contain a
-   definition of one of its constructors. This relies on the additional
-   assumption that all classes that are not trivially constructible have a
-   non-trivial constructor that is used somewhere. The negation,
-   -fno-use-ctor-homing, ensures that constructor homing is not used.
-
-   This flag is not enabled by default, and needs to be used with -cc1 or
-   -Xclang.
+   This optimization is enabled by default as part of -fno-standalone-debug.
+   Clang only emits type info for a non-trivial, non-aggregate C++ class in
+   the modules that contain a definition of one of its constructors. This
+   relies on the additional assumption that all classes that are not trivially
+   constructible have a non-trivial constructor that is used somewhere. This
+   can be disabled using the cc1 flag -fno-use-ctor-homing.
 
 .. option:: -g
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135730: Make inalloca lambda parameters work (for 32-bit windows).

2022-10-11 Thread Amy Huang via Phabricator via cfe-commits
akhuang created this revision.
Herald added a project: All.
akhuang requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This fixes a bug where inalloca arguments can't be used as parameters in
non-capturing lambdas.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135730

Files:
  clang/lib/CodeGen/CGClass.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp


Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  
2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable 
parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | 
FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,14 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+// CHECK-LABEL: define dso_local noundef ptr @"?fn1@@YAP6AXVA@@@ZXZ"
+// CHECK-LABEL: define internal x86_thiscallcc noundef ptr 
@"??B@?0??fn1@@YAP6AXVA@@@ZXZ@QBEP6A?A?@@0@ZXZ"
+// CHECK-LABEL: define internal void 
@"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z"
+// CHECK: %argmem = alloca inalloca <{ %class.A, [3 x i8] }>, align 4
+// CHECK: %[[V1:[0-9]+]] = getelementptr inbounds
+// CHECK: %[[V2:[0-9]+]] = load %class.A, ptr %[[V1]], align 4
+// CHECK: %[[V3:[0-9]+]] = getelementptr inbounds
+// CHECK: store %class.A %[[V2]], ptr %[[V3]], align 4
+// CHECK: call x86_thiscallcc void 
@"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0@Z"
+// CHECK-SAME: ptr noundef %unused.capture, ptr inalloca(<{ %class.A, [3 x i8] 
}>) %argmem
+// CHECK-LABEL: define internal x86_thiscallcc void 
@"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0@Z"
Index: clang/lib/CodeGen/CGClass.cpp
===
--- clang/lib/CodeGen/CGClass.cpp
+++ clang/lib/CodeGen/CGClass.cpp
@@ -3015,8 +3015,24 @@
   CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType);
 
   // Add the rest of the parameters.
-  for (auto *Param : MD->parameters())
-EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc());
+  for (auto *Param : MD->parameters()) {
+// If there's an inalloca param type, use a reference to the inalloca type
+// in the forwarding call instead.
+const CXXRecordDecl *RD = Param->getType()->getAsCXXRecordDecl();
+if (RD && CGM.getCXXABI().getRecordArgABI(RD) == 
CGCXXABI::RAA_DirectInMemory) {
+  QualType ParamAsRefType = 
+getContext().getLValueReferenceType(Param->getType());
+  ParmVarDecl *ParamAsRef = ParmVarDecl::Create(
+  Param->getASTContext(), Param->getDeclContext(),
+  Param->getBeginLoc(), Param->getEndLoc(), Param->getIdentifier(),
+  ParamAsRefType, Param->getTypeSourceInfo(),
+  Param->getStorageClass(), Param->getDefaultArg());
+  setAddrOfLocalVar(ParamAsRef, GetAddrOfLocalVar(Param));
+  EmitDelegateCallArg(CallArgs, ParamAsRef, Param->getBeginLoc());
+} else {
+  EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc());
+}
+  }
 
   const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
   // For a generic lambda, find the corresponding call operator specialization


Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,14 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+// CHECK-LABEL: define dso_local noundef ptr @"?fn1@@YAP6AXVA@@@ZXZ"
+// CHECK-LABEL: define internal x86_thiscallcc noundef ptr @"??B@?0??fn1@@YAP6AXVA@@@ZXZ@QBEP6A?A?@@0@ZXZ"
+// CHECK-LABEL: define internal void @"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z"
+// CHECK: %argmem = alloca inalloca <{ %class.A, [3 x i8] }>, align 4
+// CHECK: %[[V1:[0-9]+]] = getelementptr inbounds
+// CHECK: %[[V2:[0-9]+]] = load %class.A, ptr %[[V1]], align 4
+// CHECK: %[[V3:[0-9]+]] = getelementptr inbounds
+// CHECK: store %class.A %[[V2]], ptr %[[V3]], align 4
+// CHECK: call x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0@Z"
+// CHECK-SAME: ptr noundef %unused.capture, ptr inalloca(<{ %class.A, [3 x i8] }>) %argmem
+// CHECK-LABEL: define internal x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0@Z"
Index: clang/lib/CodeGen/CGClass.cpp
===
--- clang/lib/CodeGen/CGClass.cpp
+++ 

[PATCH] D133457: Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd.

2022-10-07 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

In D133457#3832590 , @mstorsjo wrote:

> @akhuang I noticed that 
> https://github.com/llvm/llvm-project/blob/main/clang/lib/Driver/ToolChains/MSVC.cpp#L199-L200
>  has got an explicit check for `Args.hasArg(options::OPT__SLASH_MD, 
> options::OPT__SLASH_MDd)` - I think that this would need to be amended to 
> handle these cases too - or is that inferred from here somehow?

You're right, those cases aren't being handled right now. I'll upload a patch 
for that.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133457

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


[PATCH] D133959: Add clang flag equivalent to clang-cl /Zl flag

2022-09-22 Thread Amy Huang via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3283f71069a0: Add clang flag equivalent to clang-cl /Zl flag 
(authored by akhuang).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133959

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-runtime-flags.c


Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -97,6 +97,9 @@
 
 // RUN: %clang_cl -### /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
 // RUN: %clang_cl -### /MT /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl 
%s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static \
+// RUN:   -fms-omit-default-lib -- %s 2>&1 | FileCheck \
+// RUN:   -check-prefix=CHECK-MTZl %s
 // CHECK-MTZl-NOT: "-D_DEBUG"
 // CHECK-MTZl: "-D_MT"
 // CHECK-MTZl-NOT: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4499,7 +4499,7 @@
 llvm_unreachable("Unexpected option ID.");
   }
 
-  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+  if (Args.hasArg(options::OPT_fms_omit_default_lib)) {
 CmdArgs.push_back("-D_VC_NODEFAULTLIB");
   } else {
 CmdArgs.push_back(FlagForCRT.data());
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2227,6 +2227,8 @@
 to the cl flags /MT and /MTd which use the multithread, static version. "dll"
 and "dll_dbg" correspond to the cl flags /MD and /MDd which use the 
multithread,
 dll version.}]>;
+def fms_omit_default_lib : Joined<["-"], "fms-omit-default-lib">,
+  Group, Flags<[NoXarchOption, CoreOption]>;
 defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
   LangOpts<"DelayedTemplateParsing">, DefaultFalse,
   PosFlag,
@@ -6784,7 +6786,7 @@
   HelpText<"Volatile loads and stores have acquire and release semantics">;
 def _SLASH_clang : CLJoined<"clang:">,
   HelpText<"Pass  to the clang driver">, MetaVarName<"">;
-def _SLASH_Zl : CLFlag<"Zl">,
+def _SLASH_Zl : CLFlag<"Zl">, Alias,
   HelpText<"Do not let object file auto-link default libraries">;
 
 def _SLASH_Yc : CLJoined<"Yc">,


Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -97,6 +97,9 @@
 
 // RUN: %clang_cl -### /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
 // RUN: %clang_cl -### /MT /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static \
+// RUN:   -fms-omit-default-lib -- %s 2>&1 | FileCheck \
+// RUN:   -check-prefix=CHECK-MTZl %s
 // CHECK-MTZl-NOT: "-D_DEBUG"
 // CHECK-MTZl: "-D_MT"
 // CHECK-MTZl-NOT: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4499,7 +4499,7 @@
 llvm_unreachable("Unexpected option ID.");
   }
 
-  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+  if (Args.hasArg(options::OPT_fms_omit_default_lib)) {
 CmdArgs.push_back("-D_VC_NODEFAULTLIB");
   } else {
 CmdArgs.push_back(FlagForCRT.data());
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2227,6 +2227,8 @@
 to the cl flags /MT and /MTd which use the multithread, static version. "dll"
 and "dll_dbg" correspond to the cl flags /MD and /MDd which use the multithread,
 dll version.}]>;
+def fms_omit_default_lib : Joined<["-"], "fms-omit-default-lib">,
+  Group, Flags<[NoXarchOption, CoreOption]>;
 defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
   LangOpts<"DelayedTemplateParsing">, DefaultFalse,
   PosFlag,
@@ -6784,7 +6786,7 @@
   HelpText<"Volatile loads and stores have acquire and release semantics">;
 def _SLASH_clang : CLJoined<"clang:">,
   HelpText<"Pass  to the clang driver">, MetaVarName<"">;
-def _SLASH_Zl : CLFlag<"Zl">,
+def _SLASH_Zl : CLFlag<"Zl">, Alias,
   HelpText<"Do not let object file auto-link default libraries">;
 
 def _SLASH_Yc : CLJoined<"Yc">,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133959: Add clang flag equivalent to clang-cl /Zl flag

2022-09-22 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 462230.
akhuang marked an inline comment as done.
akhuang added a comment.

Fix flag name in test case


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133959

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-runtime-flags.c


Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -97,6 +97,9 @@
 
 // RUN: %clang_cl -### /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
 // RUN: %clang_cl -### /MT /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl 
%s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static \
+// RUN:   -fms-omit-default-lib -- %s 2>&1 | FileCheck \
+// RUN:   -check-prefix=CHECK-MTZl %s
 // CHECK-MTZl-NOT: "-D_DEBUG"
 // CHECK-MTZl: "-D_MT"
 // CHECK-MTZl-NOT: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4499,7 +4499,7 @@
 llvm_unreachable("Unexpected option ID.");
   }
 
-  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+  if (Args.hasArg(options::OPT_fms_omit_default_lib)) {
 CmdArgs.push_back("-D_VC_NODEFAULTLIB");
   } else {
 CmdArgs.push_back(FlagForCRT.data());
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2227,6 +2227,8 @@
 to the cl flags /MT and /MTd which use the multithread, static version. "dll"
 and "dll_dbg" correspond to the cl flags /MD and /MDd which use the 
multithread,
 dll version.}]>;
+def fms_omit_default_lib : Joined<["-"], "fms-omit-default-lib">,
+  Group, Flags<[NoXarchOption, CoreOption]>;
 defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
   LangOpts<"DelayedTemplateParsing">, DefaultFalse,
   PosFlag,
@@ -6784,7 +6786,7 @@
   HelpText<"Volatile loads and stores have acquire and release semantics">;
 def _SLASH_clang : CLJoined<"clang:">,
   HelpText<"Pass  to the clang driver">, MetaVarName<"">;
-def _SLASH_Zl : CLFlag<"Zl">,
+def _SLASH_Zl : CLFlag<"Zl">, Alias,
   HelpText<"Do not let object file auto-link default libraries">;
 
 def _SLASH_Yc : CLJoined<"Yc">,


Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -97,6 +97,9 @@
 
 // RUN: %clang_cl -### /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
 // RUN: %clang_cl -### /MT /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static \
+// RUN:   -fms-omit-default-lib -- %s 2>&1 | FileCheck \
+// RUN:   -check-prefix=CHECK-MTZl %s
 // CHECK-MTZl-NOT: "-D_DEBUG"
 // CHECK-MTZl: "-D_MT"
 // CHECK-MTZl-NOT: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4499,7 +4499,7 @@
 llvm_unreachable("Unexpected option ID.");
   }
 
-  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+  if (Args.hasArg(options::OPT_fms_omit_default_lib)) {
 CmdArgs.push_back("-D_VC_NODEFAULTLIB");
   } else {
 CmdArgs.push_back(FlagForCRT.data());
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2227,6 +2227,8 @@
 to the cl flags /MT and /MTd which use the multithread, static version. "dll"
 and "dll_dbg" correspond to the cl flags /MD and /MDd which use the multithread,
 dll version.}]>;
+def fms_omit_default_lib : Joined<["-"], "fms-omit-default-lib">,
+  Group, Flags<[NoXarchOption, CoreOption]>;
 defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
   LangOpts<"DelayedTemplateParsing">, DefaultFalse,
   PosFlag,
@@ -6784,7 +6786,7 @@
   HelpText<"Volatile loads and stores have acquire and release semantics">;
 def _SLASH_clang : CLJoined<"clang:">,
   HelpText<"Pass  to the clang driver">, MetaVarName<"">;
-def _SLASH_Zl : CLFlag<"Zl">,
+def _SLASH_Zl : CLFlag<"Zl">, Alias,
   HelpText<"Do not let object file auto-link default libraries">;
 
 def _SLASH_Yc : CLJoined<"Yc">,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133959: Add clang flag equivalent to clang-cl /Zl flag

2022-09-21 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 462042.
akhuang marked an inline comment as done.
akhuang added a comment.

Change name of flag, and alias /Zl to this flag.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133959

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-runtime-flags.c


Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -97,6 +97,9 @@
 
 // RUN: %clang_cl -### /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
 // RUN: %clang_cl -### /MT /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl 
%s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static \
+// RUN:   -fms-omit-default-lib-name -- %s 2>&1 | FileCheck \
+// RUN:   -check-prefix=CHECK-MTZl %s
 // CHECK-MTZl-NOT: "-D_DEBUG"
 // CHECK-MTZl: "-D_MT"
 // CHECK-MTZl-NOT: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4499,7 +4499,7 @@
 llvm_unreachable("Unexpected option ID.");
   }
 
-  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+  if (Args.hasArg(options::OPT_fms_omit_default_lib)) {
 CmdArgs.push_back("-D_VC_NODEFAULTLIB");
   } else {
 CmdArgs.push_back(FlagForCRT.data());
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -,6 +,8 @@
 to the cl flags /MT and /MTd which use the multithread, static version. "dll"
 and "dll_dbg" correspond to the cl flags /MD and /MDd which use the 
multithread,
 dll version.}]>;
+def fms_omit_default_lib : Joined<["-"], "fms-omit-default-lib">,
+  Group, Flags<[NoXarchOption, CoreOption]>;
 defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
   LangOpts<"DelayedTemplateParsing">, DefaultFalse,
   PosFlag,
@@ -6779,7 +6781,7 @@
   HelpText<"Volatile loads and stores have acquire and release semantics">;
 def _SLASH_clang : CLJoined<"clang:">,
   HelpText<"Pass  to the clang driver">, MetaVarName<"">;
-def _SLASH_Zl : CLFlag<"Zl">,
+def _SLASH_Zl : CLFlag<"Zl">, Alias,
   HelpText<"Do not let object file auto-link default libraries">;
 
 def _SLASH_Yc : CLJoined<"Yc">,


Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -97,6 +97,9 @@
 
 // RUN: %clang_cl -### /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
 // RUN: %clang_cl -### /MT /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static \
+// RUN:   -fms-omit-default-lib-name -- %s 2>&1 | FileCheck \
+// RUN:   -check-prefix=CHECK-MTZl %s
 // CHECK-MTZl-NOT: "-D_DEBUG"
 // CHECK-MTZl: "-D_MT"
 // CHECK-MTZl-NOT: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4499,7 +4499,7 @@
 llvm_unreachable("Unexpected option ID.");
   }
 
-  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+  if (Args.hasArg(options::OPT_fms_omit_default_lib)) {
 CmdArgs.push_back("-D_VC_NODEFAULTLIB");
   } else {
 CmdArgs.push_back(FlagForCRT.data());
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -,6 +,8 @@
 to the cl flags /MT and /MTd which use the multithread, static version. "dll"
 and "dll_dbg" correspond to the cl flags /MD and /MDd which use the multithread,
 dll version.}]>;
+def fms_omit_default_lib : Joined<["-"], "fms-omit-default-lib">,
+  Group, Flags<[NoXarchOption, CoreOption]>;
 defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
   LangOpts<"DelayedTemplateParsing">, DefaultFalse,
   PosFlag,
@@ -6779,7 +6781,7 @@
   HelpText<"Volatile loads and stores have acquire and release semantics">;
 def _SLASH_clang : CLJoined<"clang:">,
   HelpText<"Pass  to the clang driver">, MetaVarName<"">;
-def _SLASH_Zl : CLFlag<"Zl">,
+def _SLASH_Zl : CLFlag<"Zl">, Alias,
   HelpText<"Do not let object file auto-link default libraries">;
 
 def _SLASH_Yc : CLJoined<"Yc">,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133959: Add clang flag equivalent to clang-cl /Zl flag

2022-09-21 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

In D133959#3793283 , @hans wrote:

> Could the new flag be marked as an Alias in the tablegen, so that we don't 
> need to do any code changes for it?

It appears before _SLASH_Zl in the file so we'd have to move it out of place. 
We could alias /Zl to the new flag.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133959

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


[PATCH] D133959: Add clang flag equivalent to clang-cl /Zl flag

2022-09-15 Thread Amy Huang via Phabricator via cfe-commits
akhuang created this revision.
akhuang added reviewers: mstorsjo, hans.
Herald added a project: All.
akhuang requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

The /Zl flag omits default C runtime library name from obj files.
This patch just adds an equivalent clang driver flag.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133959

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-runtime-flags.c


Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -97,6 +97,9 @@
 
 // RUN: %clang_cl -### /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
 // RUN: %clang_cl -### /MT /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl 
%s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static \
+// RUN:   -fms-omit-default-lib-name -- %s 2>&1 | FileCheck \
+// RUN:   -check-prefix=CHECK-MTZl %s
 // CHECK-MTZl-NOT: "-D_DEBUG"
 // CHECK-MTZl: "-D_MT"
 // CHECK-MTZl-NOT: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4490,7 +4490,8 @@
 llvm_unreachable("Unexpected option ID.");
   }
 
-  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+  if (Args.hasArg(options::OPT__SLASH_Zl) ||
+Args.hasArg(options::OPT_fms_omit_default_lib_name)) {
 CmdArgs.push_back("-D_VC_NODEFAULTLIB");
   } else {
 CmdArgs.push_back(FlagForCRT.data());
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2219,6 +2219,9 @@
 to the cl flags /MT and /MTd which use the multithread, static version. "dll"
 and "dll_dbg" correspond to the cl flags /MD and /MDd which use the 
multithread,
 dll version.}]>;
+def fms_omit_default_lib_name : Joined<["-"], "fms-omit-default-lib-name">,
+  Group, Flags<[NoXarchOption, CoreOption]>,
+  HelpText<"Omit the default C runtime library name from the .obj file.">;
 defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
   LangOpts<"DelayedTemplateParsing">, DefaultFalse,
   PosFlag,


Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -97,6 +97,9 @@
 
 // RUN: %clang_cl -### /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
 // RUN: %clang_cl -### /MT /Zl -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTZl %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static \
+// RUN:   -fms-omit-default-lib-name -- %s 2>&1 | FileCheck \
+// RUN:   -check-prefix=CHECK-MTZl %s
 // CHECK-MTZl-NOT: "-D_DEBUG"
 // CHECK-MTZl: "-D_MT"
 // CHECK-MTZl-NOT: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4490,7 +4490,8 @@
 llvm_unreachable("Unexpected option ID.");
   }
 
-  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+  if (Args.hasArg(options::OPT__SLASH_Zl) ||
+Args.hasArg(options::OPT_fms_omit_default_lib_name)) {
 CmdArgs.push_back("-D_VC_NODEFAULTLIB");
   } else {
 CmdArgs.push_back(FlagForCRT.data());
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2219,6 +2219,9 @@
 to the cl flags /MT and /MTd which use the multithread, static version. "dll"
 and "dll_dbg" correspond to the cl flags /MD and /MDd which use the multithread,
 dll version.}]>;
+def fms_omit_default_lib_name : Joined<["-"], "fms-omit-default-lib-name">,
+  Group, Flags<[NoXarchOption, CoreOption]>,
+  HelpText<"Omit the default C runtime library name from the .obj file.">;
 defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
   LangOpts<"DelayedTemplateParsing">, DefaultFalse,
   PosFlag,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133457: Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd.

2022-09-15 Thread Amy Huang 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 rGfda44bedd64d: Add Clang driver flags equivalent to cls 
/MD, /MT, /MDd, /MTd. (authored by akhuang).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133457

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-runtime-flags.c

Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -10,6 +10,8 @@
 
 // RUN: %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
 // RUN: %clang_cl -### /MT -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static -- %s \
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-MT %s
 // CHECK-MT-NOT: "-D_DEBUG"
 // CHECK-MT: "-D_MT"
 // CHECK-MT-NOT: "-D_DLL"
@@ -19,6 +21,8 @@
 
 // RUN: %clang_cl -### /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
 // RUN: %clang_cl -### /LD /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static_dbg \
+// RUN:   -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
 // CHECK-MTd: "-D_DEBUG"
 // CHECK-MTd: "-D_MT"
 // CHECK-MTd-NOT: "-D_DLL"
@@ -27,6 +31,8 @@
 // CHECK-MTd: "--dependent-lib=oldnames"
 
 // RUN: %clang_cl -### /MD -- %s 2>&1 | FileCheck -check-prefix=CHECK-MD %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll -- %s \
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-MD %s
 // CHECK-MD-NOT: "-D_DEBUG"
 // CHECK-MD: "-D_MT"
 // CHECK-MD: "-D_DLL"
@@ -34,6 +40,8 @@
 // CHECK-MD: "--dependent-lib=oldnames"
 
 // RUN: %clang_cl -### /MDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll_dbg -- \
+// RUN:   %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
 // CHECK-MDd: "-D_DEBUG"
 // CHECK-MDd: "-D_MT"
 // CHECK-MDd: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4437,6 +4437,71 @@
   RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
 }
 
+static void ProcessVSRuntimeLibrary(const ArgList ,
+ArgStringList ) {
+  unsigned RTOptionID = options::OPT__SLASH_MT;
+
+  if (Args.hasArg(options::OPT__SLASH_LDd))
+// The /LDd option implies /MTd. The dependent lib part can be overridden,
+// but defining _DEBUG is sticky.
+RTOptionID = options::OPT__SLASH_MTd;
+
+  if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
+RTOptionID = A->getOption().getID();
+
+  if (Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+RTOptionID = llvm::StringSwitch(A->getValue())
+ .Case("static", options::OPT__SLASH_MT)
+ .Case("static_dbg", options::OPT__SLASH_MTd)
+ .Case("dll", options::OPT__SLASH_MD)
+ .Case("dll_dbg", options::OPT__SLASH_MDd)
+ .Default(options::OPT__SLASH_MT);
+  }
+
+  StringRef FlagForCRT;
+  switch (RTOptionID) {
+  case options::OPT__SLASH_MD:
+if (Args.hasArg(options::OPT__SLASH_LDd))
+  CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+FlagForCRT = "--dependent-lib=msvcrt";
+break;
+  case options::OPT__SLASH_MDd:
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+FlagForCRT = "--dependent-lib=msvcrtd";
+break;
+  case options::OPT__SLASH_MT:
+if (Args.hasArg(options::OPT__SLASH_LDd))
+  CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+FlagForCRT = "--dependent-lib=libcmt";
+break;
+  case options::OPT__SLASH_MTd:
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+FlagForCRT = "--dependent-lib=libcmtd";
+break;
+  default:
+llvm_unreachable("Unexpected option ID.");
+  }
+
+  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+CmdArgs.push_back("-D_VC_NODEFAULTLIB");
+  } else {
+CmdArgs.push_back(FlagForCRT.data());
+
+// This provides POSIX compatibility (maps 'open' to '_open'), which most
+// users want.  The /Za flag to cl.exe turns this off, but it's not
+// implemented in clang.
+CmdArgs.push_back("--dependent-lib=oldnames");
+  }
+}
+
 void Clang::ConstructJob(Compilation , const JobAction ,
  const InputInfo , const InputInfoList ,
  const ArgList , const char *LinkingOutput) 

[PATCH] D133457: Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd.

2022-09-15 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 460456.
akhuang added a comment.

ran clang-format


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133457

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-runtime-flags.c

Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -10,6 +10,8 @@
 
 // RUN: %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
 // RUN: %clang_cl -### /MT -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static -- %s \
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-MT %s
 // CHECK-MT-NOT: "-D_DEBUG"
 // CHECK-MT: "-D_MT"
 // CHECK-MT-NOT: "-D_DLL"
@@ -19,6 +21,8 @@
 
 // RUN: %clang_cl -### /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
 // RUN: %clang_cl -### /LD /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static_dbg \
+// RUN:   -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
 // CHECK-MTd: "-D_DEBUG"
 // CHECK-MTd: "-D_MT"
 // CHECK-MTd-NOT: "-D_DLL"
@@ -27,6 +31,8 @@
 // CHECK-MTd: "--dependent-lib=oldnames"
 
 // RUN: %clang_cl -### /MD -- %s 2>&1 | FileCheck -check-prefix=CHECK-MD %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll -- %s \
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-MD %s
 // CHECK-MD-NOT: "-D_DEBUG"
 // CHECK-MD: "-D_MT"
 // CHECK-MD: "-D_DLL"
@@ -34,6 +40,8 @@
 // CHECK-MD: "--dependent-lib=oldnames"
 
 // RUN: %clang_cl -### /MDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll_dbg -- \
+// RUN:   %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
 // CHECK-MDd: "-D_DEBUG"
 // CHECK-MDd: "-D_MT"
 // CHECK-MDd: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4437,6 +4437,71 @@
   RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
 }
 
+static void ProcessVSRuntimeLibrary(const ArgList ,
+ArgStringList ) {
+  unsigned RTOptionID = options::OPT__SLASH_MT;
+
+  if (Args.hasArg(options::OPT__SLASH_LDd))
+// The /LDd option implies /MTd. The dependent lib part can be overridden,
+// but defining _DEBUG is sticky.
+RTOptionID = options::OPT__SLASH_MTd;
+
+  if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
+RTOptionID = A->getOption().getID();
+
+  if (Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+RTOptionID = llvm::StringSwitch(A->getValue())
+ .Case("static", options::OPT__SLASH_MT)
+ .Case("static_dbg", options::OPT__SLASH_MTd)
+ .Case("dll", options::OPT__SLASH_MD)
+ .Case("dll_dbg", options::OPT__SLASH_MDd)
+ .Default(options::OPT__SLASH_MT);
+  }
+
+  StringRef FlagForCRT;
+  switch (RTOptionID) {
+  case options::OPT__SLASH_MD:
+if (Args.hasArg(options::OPT__SLASH_LDd))
+  CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+FlagForCRT = "--dependent-lib=msvcrt";
+break;
+  case options::OPT__SLASH_MDd:
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+FlagForCRT = "--dependent-lib=msvcrtd";
+break;
+  case options::OPT__SLASH_MT:
+if (Args.hasArg(options::OPT__SLASH_LDd))
+  CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+FlagForCRT = "--dependent-lib=libcmt";
+break;
+  case options::OPT__SLASH_MTd:
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+FlagForCRT = "--dependent-lib=libcmtd";
+break;
+  default:
+llvm_unreachable("Unexpected option ID.");
+  }
+
+  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+CmdArgs.push_back("-D_VC_NODEFAULTLIB");
+  } else {
+CmdArgs.push_back(FlagForCRT.data());
+
+// This provides POSIX compatibility (maps 'open' to '_open'), which most
+// users want.  The /Za flag to cl.exe turns this off, but it's not
+// implemented in clang.
+CmdArgs.push_back("--dependent-lib=oldnames");
+  }
+}
+
 void Clang::ConstructJob(Compilation , const JobAction ,
  const InputInfo , const InputInfoList ,
  const ArgList , const char *LinkingOutput) const {
@@ -6478,6 +6543,9 @@
   if (IsMSVCCompat)
 CmdArgs.push_back("-fms-compatibility");
 
+  if (Triple.isWindowsMSVCEnvironment() && !D.IsCLMode())
+

[PATCH] D133457: Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd.

2022-09-15 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/Driver/ToolChains/Clang.cpp:4493
+
+  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+CmdArgs.push_back("-D_VC_NODEFAULTLIB");

mstorsjo wrote:
> If I understand correctly, we still don't have any corresponding gcc style 
> driver flag for this? Would you consider adding that in a separate, later 
> patch?
Yep, I can add that too. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133457

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


[PATCH] D133457: Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd.

2022-09-14 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 460271.
akhuang marked 3 inline comments as done.
akhuang added a comment.

more comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133457

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-runtime-flags.c

Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -10,6 +10,8 @@
 
 // RUN: %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
 // RUN: %clang_cl -### /MT -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static -- %s \
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-MT %s
 // CHECK-MT-NOT: "-D_DEBUG"
 // CHECK-MT: "-D_MT"
 // CHECK-MT-NOT: "-D_DLL"
@@ -19,6 +21,8 @@
 
 // RUN: %clang_cl -### /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
 // RUN: %clang_cl -### /LD /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static_dbg \
+// RUN:   -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
 // CHECK-MTd: "-D_DEBUG"
 // CHECK-MTd: "-D_MT"
 // CHECK-MTd-NOT: "-D_DLL"
@@ -27,6 +31,8 @@
 // CHECK-MTd: "--dependent-lib=oldnames"
 
 // RUN: %clang_cl -### /MD -- %s 2>&1 | FileCheck -check-prefix=CHECK-MD %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll -- %s \
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-MD %s
 // CHECK-MD-NOT: "-D_DEBUG"
 // CHECK-MD: "-D_MT"
 // CHECK-MD: "-D_DLL"
@@ -34,6 +40,8 @@
 // CHECK-MD: "--dependent-lib=oldnames"
 
 // RUN: %clang_cl -### /MDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll_dbg -- \
+// RUN:   %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
 // CHECK-MDd: "-D_DEBUG"
 // CHECK-MDd: "-D_MT"
 // CHECK-MDd: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4437,6 +4437,71 @@
   RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
 }
 
+static void ProcessVSRuntimeLibrary(const ArgList ,
+ArgStringList ) {
+  unsigned RTOptionID = options::OPT__SLASH_MT;
+
+  if (Args.hasArg(options::OPT__SLASH_LDd))
+// The /LDd option implies /MTd. The dependent lib part can be overridden,
+// but defining _DEBUG is sticky.
+RTOptionID = options::OPT__SLASH_MTd;
+
+  if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
+RTOptionID = A->getOption().getID();
+
+  if (Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+RTOptionID = llvm::StringSwitch(A->getValue())
+  .Case("static", options::OPT__SLASH_MT)
+  .Case("static_dbg", options::OPT__SLASH_MTd)
+  .Case("dll", options::OPT__SLASH_MD)
+  .Case("dll_dbg", options::OPT__SLASH_MDd)
+  .Default(options::OPT__SLASH_MT);
+  }
+
+  StringRef FlagForCRT;
+  switch (RTOptionID) {
+  case options::OPT__SLASH_MD:
+if (Args.hasArg(options::OPT__SLASH_LDd))
+  CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+FlagForCRT = "--dependent-lib=msvcrt";
+break;
+  case options::OPT__SLASH_MDd:
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+FlagForCRT = "--dependent-lib=msvcrtd";
+break;
+  case options::OPT__SLASH_MT:
+if (Args.hasArg(options::OPT__SLASH_LDd))
+  CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+FlagForCRT = "--dependent-lib=libcmt";
+break;
+  case options::OPT__SLASH_MTd:
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+FlagForCRT = "--dependent-lib=libcmtd";
+break;
+  default:
+llvm_unreachable("Unexpected option ID.");
+  }
+
+  if (Args.hasArg(options::OPT__SLASH_Zl)) {
+CmdArgs.push_back("-D_VC_NODEFAULTLIB");
+  } else {
+CmdArgs.push_back(FlagForCRT.data());
+
+// This provides POSIX compatibility (maps 'open' to '_open'), which most
+// users want.  The /Za flag to cl.exe turns this off, but it's not
+// implemented in clang.
+CmdArgs.push_back("--dependent-lib=oldnames");
+  }
+}
+
 void Clang::ConstructJob(Compilation , const JobAction ,
  const InputInfo , const InputInfoList ,
  const ArgList , const char *LinkingOutput) const {
@@ -6478,6 +6543,9 @@
   if (IsMSVCCompat)
 CmdArgs.push_back("-fms-compatibility");
 
+  if (Triple.isWindowsMSVCEnvironment() && !D.IsCLMode())
+ProcessVSRuntimeLibrary(Args, 

[PATCH] D133457: Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd.

2022-09-14 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 460154.
akhuang marked an inline comment as done.
akhuang added a comment.

Address comments, more cleanup


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133457

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-runtime-flags.c

Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -10,6 +10,8 @@
 
 // RUN: %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
 // RUN: %clang_cl -### /MT -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static -- %s \
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-MT %s
 // CHECK-MT-NOT: "-D_DEBUG"
 // CHECK-MT: "-D_MT"
 // CHECK-MT-NOT: "-D_DLL"
@@ -19,6 +21,8 @@
 
 // RUN: %clang_cl -### /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
 // RUN: %clang_cl -### /LD /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static_dbg \
+// RUN:   -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
 // CHECK-MTd: "-D_DEBUG"
 // CHECK-MTd: "-D_MT"
 // CHECK-MTd-NOT: "-D_DLL"
@@ -27,6 +31,8 @@
 // CHECK-MTd: "--dependent-lib=oldnames"
 
 // RUN: %clang_cl -### /MD -- %s 2>&1 | FileCheck -check-prefix=CHECK-MD %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll -- %s \
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-MD %s
 // CHECK-MD-NOT: "-D_DEBUG"
 // CHECK-MD: "-D_MT"
 // CHECK-MD: "-D_DLL"
@@ -34,6 +40,8 @@
 // CHECK-MD: "--dependent-lib=oldnames"
 
 // RUN: %clang_cl -### /MDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll_dbg -- \
+// RUN:   %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
 // CHECK-MDd: "-D_DEBUG"
 // CHECK-MDd: "-D_MT"
 // CHECK-MDd: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4437,6 +4437,71 @@
   RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
 }
 
+static void ProcessVSRuntimeLibrary(const ArgList ,
+ArgStringList ) {
+  unsigned RTOptionID = options::OPT__SLASH_MT;
+
+  if (Args.hasArg(options::OPT__SLASH_LDd))
+// The /LDd option implies /MTd. The dependent lib part can be overridden,
+// but defining _DEBUG is sticky.
+RTOptionID = options::OPT__SLASH_MTd;
+
+  if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
+RTOptionID = A->getOption().getID();
+
+  if (Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+StringRef Val = A->getValue();
+if (Val == "static")  RTOptionID = options::OPT__SLASH_MT;
+else if (Val == "static_dbg") RTOptionID = options::OPT__SLASH_MTd;
+else if (Val == "dll")RTOptionID = options::OPT__SLASH_MD;
+else if (Val == "dll_dbg")RTOptionID = options::OPT__SLASH_MDd;
+else llvm_unreachable("Unexpected option ID.");
+  }
+
+  StringRef FlagForCRT;
+  switch (RTOptionID) {
+  case options::OPT__SLASH_MD:
+if (Args.hasArg(options::OPT__SLASH_LDd))
+  CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+FlagForCRT = "--dependent-lib=msvcrt";
+break;
+  case options::OPT__SLASH_MDd:
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+FlagForCRT = "--dependent-lib=msvcrtd";
+break;
+  case options::OPT__SLASH_MT:
+if (Args.hasArg(options::OPT__SLASH_LDd))
+  CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+FlagForCRT = "--dependent-lib=libcmt";
+break;
+  case options::OPT__SLASH_MTd:
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+FlagForCRT = "--dependent-lib=libcmtd";
+break;
+  default:
+llvm_unreachable("Unexpected option ID.");
+  }
+
+  if (/*IsClangCL && */Args.hasArg(options::OPT__SLASH_Zl)) {
+CmdArgs.push_back("-D_VC_NODEFAULTLIB");
+  } else {
+CmdArgs.push_back(FlagForCRT.data());
+
+// This provides POSIX compatibility (maps 'open' to '_open'), which most
+// users want.  The /Za flag to cl.exe turns this off, but it's not
+// implemented in clang.
+CmdArgs.push_back("--dependent-lib=oldnames");
+  }
+}
+
 void Clang::ConstructJob(Compilation , const JobAction ,
  const InputInfo , const InputInfoList ,
  const ArgList , const char *LinkingOutput) const {
@@ -6478,6 +6543,9 @@
   if (IsMSVCCompat)
 

[PATCH] D133457: Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd.

2022-09-14 Thread Amy Huang via Phabricator via cfe-commits
akhuang marked 3 inline comments as done.
akhuang added inline comments.



Comment at: clang/lib/Driver/ToolChains/Clang.cpp:4442
+bool IsClangCL) {
+  unsigned RTOptionID = 0; // MT=0, MTd=1, MD=2, MDd=3
+  bool HasLDdFlag = IsClangCL && Args.hasArg(options::OPT__SLASH_LDd);

hans wrote:
> Could this be an enum, or reuse existing values like the /Mx option ids?
Oh, right, resuing the options::OPT__SLASH_ flags makes more sense.



Comment at: clang/lib/Driver/ToolChains/Clang.cpp:4461
+  } else {
+if (Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+  StringRef Val = A->getValue();

hans wrote:
> Is there a getLastArg() variant that allows getting the last argument of 
> either the /Mx options or -fms-runtime-lib, so we don't need to check 
> IsClangCL?
Actually, I think I can just remove the IsClangCL option since this function 
now runs either in `AddClangCLArgs` or under `!IsCLMode()`. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133457

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


[PATCH] D133457: Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd.

2022-09-12 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/Driver/ToolChains/Clang.cpp:6480
 
+  // Process Windows runtime flags (equivalent to cl flags /MD, /MDd, /MT, 
/MTd)
+  if (Triple.isOSWindows()) {

hans wrote:
> Could we somehow re-use the logic in Clang::AddClangCLArgs()? Perhaps the 
> main switch from that could be extracted to a function that could be called 
> from here?
Put it in a separate function; I guess it's a bit messy as some clang-cl flags 
aren't implemented for clang.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133457

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


[PATCH] D133457: Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd.

2022-09-12 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 459577.
akhuang marked 2 inline comments as done.
akhuang added a comment.

Clean up test, add doc brief to new flag, try to put the flag logic in a 
separate function


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133457

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-runtime-flags.c

Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -10,6 +10,8 @@
 
 // RUN: %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
 // RUN: %clang_cl -### /MT -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static -- %s \
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-MT %s
 // CHECK-MT-NOT: "-D_DEBUG"
 // CHECK-MT: "-D_MT"
 // CHECK-MT-NOT: "-D_DLL"
@@ -19,6 +21,8 @@
 
 // RUN: %clang_cl -### /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
 // RUN: %clang_cl -### /LD /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static_dbg \
+// RUN:   -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
 // CHECK-MTd: "-D_DEBUG"
 // CHECK-MTd: "-D_MT"
 // CHECK-MTd-NOT: "-D_DLL"
@@ -27,6 +31,8 @@
 // CHECK-MTd: "--dependent-lib=oldnames"
 
 // RUN: %clang_cl -### /MD -- %s 2>&1 | FileCheck -check-prefix=CHECK-MD %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll -- %s \
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-MD %s
 // CHECK-MD-NOT: "-D_DEBUG"
 // CHECK-MD: "-D_MT"
 // CHECK-MD: "-D_DLL"
@@ -34,6 +40,8 @@
 // CHECK-MD: "--dependent-lib=oldnames"
 
 // RUN: %clang_cl -### /MDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll_dbg -- \
+// RUN:   %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
 // CHECK-MDd: "-D_DEBUG"
 // CHECK-MDd: "-D_MT"
 // CHECK-MDd: "-D_DLL"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4436,6 +4436,82 @@
   RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
 }
 
+static void ProcessVSRuntimeLibrary(const ArgList ,
+ArgStringList ,
+bool IsClangCL) {
+  unsigned RTOptionID = 0; // MT=0, MTd=1, MD=2, MDd=3
+  bool HasLDdFlag = IsClangCL && Args.hasArg(options::OPT__SLASH_LDd);
+
+  if (Args.hasArg(options::OPT__SLASH_LDd))
+// The /LDd option implies /MTd. The dependent lib part can be overridden,
+// but defining _DEBUG is sticky.
+RTOptionID = 1; // options::OPT__SLASH_MTd;
+
+  if (IsClangCL) {
+if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group)) {
+  switch (A->getOption().getID()) {
+  case options::OPT__SLASH_MT:  RTOptionID = 0; break;
+  case options::OPT__SLASH_MTd: RTOptionID = 1; break;
+  case options::OPT__SLASH_MD:  RTOptionID = 2; break;
+  case options::OPT__SLASH_MDd: RTOptionID = 3; break;
+  default: llvm_unreachable("Unexpected option ID.");
+  }
+}
+  } else {
+if (Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+  StringRef Val = A->getValue();
+  if (Val == "static")  RTOptionID = 0;
+  else if (Val == "static_dbg") RTOptionID = 1;
+  else if (Val == "dll")RTOptionID = 2;
+  else if (Val == "dll_dbg")RTOptionID = 3;
+  else llvm_unreachable("Unexpected option ID.");
+}
+  }
+
+  StringRef FlagForCRT;
+  switch (RTOptionID) {
+  case 2:  // MD
+if (HasLDdFlag)
+  CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+FlagForCRT = "--dependent-lib=msvcrt";
+break;
+  case 3:  // MDd
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+FlagForCRT = "--dependent-lib=msvcrtd";
+break;
+  case 0:  // MT
+if (HasLDdFlag)
+  CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+FlagForCRT = "--dependent-lib=libcmt";
+break;
+  case 1:  // MTd
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+FlagForCRT = "--dependent-lib=libcmtd";
+break;
+  default:
+llvm_unreachable("Unexpected option ID.");
+  }
+
+  if (IsClangCL && Args.hasArg(options::OPT__SLASH_Zl)) {
+CmdArgs.push_back("-D_VC_NODEFAULTLIB");
+  } else {
+CmdArgs.push_back(FlagForCRT.data());
+
+// This provides POSIX compatibility (maps 'open' to '_open'), which most
+// users want.  The /Za flag to cl.exe turns this off, 

[PATCH] D133457: Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd. This will allow selecting the MS C runtime library without having to use cc1 flags.

2022-09-07 Thread Amy Huang via Phabricator via cfe-commits
akhuang created this revision.
Herald added a project: All.
akhuang requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133457

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cl-runtime-flags.c


Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -95,3 +95,39 @@
 // CHECK-MTZl-SAME: "-D_VC_NODEFAULTLIB"
 // CHECK-MTZl-NOT: "--dependent-lib=libcmt"
 // CHECK-MTZl-NOT: "--dependent-lib=oldnames"
+
+// Check for clang versions of the /MD and /MT flags.
+
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static -- %s 
\
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-CLANG-STATIC %s
+// CHECK-CLANG-STATIC-NOT: "-D_DEBUG"
+// CHECK-CLANG-STATIC: "-D_MT"
+// CHECK-CLANG-STATIC-NOT: "-D_DLL"
+// CHECK-CLANG-STATIC: "-flto-visibility-public-std"
+// CHECK-CLANG-STATIC: "--dependent-lib=libcmt"
+// CHECK-CLANG-STATIC: "--dependent-lib=oldnames"
+
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static_dbg \
+// RUN:   -- %s 2>&1 | FileCheck -check-prefix=CHECK-CLANG-STATIC-DBG %s
+// CHECK-CLANG-STATIC-DBG: "-D_DEBUG"
+// CHECK-CLANG-STATIC-DBG: "-D_MT"
+// CHECK-CLANG-STATIC-DBG-NOT: "-D_DLL"
+// CHECK-CLANG-STATIC-DBG: "-flto-visibility-public-std"
+// CHECK-CLANG-STATIC-DBG: "--dependent-lib=libcmtd"
+// CHECK-CLANG-STATIC-DBG: "--dependent-lib=oldnames"
+
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll -- %s \
+// RUN:   2>&1 | FileCheck -check-prefix=CHECK-CLANG-DLL %s
+// CHECK-CLANG-DLL-NOT: "-D_DEBUG"
+// CHECK-CLANG-DLL: "-D_MT"
+// CHECK-CLANG-DLL: "-D_DLL"
+// CHECK-CLANG-DLL: "--dependent-lib=msvcrt"
+// CHECK-CLANG-DLL: "--dependent-lib=oldnames"
+
+// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll_dbg -- \
+// RUN:   %s 2>&1 | FileCheck -check-prefix=CHECK-CLANG-DLL-DBG %s
+// CHECK-CLANG-DLL-DBG: "-D_DEBUG"
+// CHECK-CLANG-DLL-DBG: "-D_MT"
+// CHECK-CLANG-DLL-DBG: "-D_DLL"
+// CHECK-CLANG-DLL-DBG: "--dependent-lib=msvcrtd"
+// CHECK-CLANG-DLL-DBG: "--dependent-lib=oldnames"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -6477,6 +6477,35 @@
   if (IsMSVCCompat)
 CmdArgs.push_back("-fms-compatibility");
 
+  // Process Windows runtime flags (equivalent to cl flags /MD, /MDd, /MT, 
/MTd)
+  if (Triple.isOSWindows()) {
+if (Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+  StringRef Val = A->getValue();
+  if (Val == "dll") {
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+CmdArgs.push_back("--dependent-lib=msvcrt");
+  } else if (Val == "dll_dbg") {
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-D_DLL");
+CmdArgs.push_back("--dependent-lib=msvcrtd");
+  } else if (Val == "static") {
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+CmdArgs.push_back("--dependent-lib=libcmt");
+  } else if (Val == "static_dbg") {
+CmdArgs.push_back("-D_DEBUG");
+CmdArgs.push_back("-D_MT");
+CmdArgs.push_back("-flto-visibility-public-std");
+CmdArgs.push_back("--dependent-lib=libcmtd");
+  } else {
+D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << Val;
+  }
+  CmdArgs.push_back("--dependent-lib=oldnames");
+}
+  }
+
   // Handle -fgcc-version, if present.
   VersionTuple GNUCVer;
   if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) {
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2205,6 +2205,8 @@
   HelpText<"Dot-separated value representing the Microsoft compiler "
"version number to report in _MSC_VER (0 = don't define it "
"(default))">;
+def fms_runtime_lib_EQ : Joined<["-"], "fms-runtime-lib=">, Group,
+  Flags<[NoXarchOption, CoreOption]>, HelpText<"Select Windows run-time 
library">;
 defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
   LangOpts<"DelayedTemplateParsing">, DefaultFalse,
   PosFlag,


Index: clang/test/Driver/cl-runtime-flags.c
===
--- clang/test/Driver/cl-runtime-flags.c
+++ clang/test/Driver/cl-runtime-flags.c
@@ -95,3 +95,39 @@
 // CHECK-MTZl-SAME: "-D_VC_NODEFAULTLIB"
 // CHECK-MTZl-NOT: "--dependent-lib=libcmt"
 // CHECK-MTZl-NOT: "--dependent-lib=oldnames"
+
+// Check for clang versions of the 

[PATCH] D131704: [Clang] Tighten restrictions on enum out of range diagnostic

2022-08-11 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

We're seeing this warning in code with global constants, e.g.

  const Enum x = static_cast(-1);

is this intended?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131704

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


[PATCH] D130123: [Phabricator] extend ptr32 support to be applied on typedef

2022-07-19 Thread Amy Huang via Phabricator via cfe-commits
akhuang accepted this revision.
akhuang added a comment.
This revision is now accepted and ready to land.

Looks good, thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130123

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


[PATCH] D116256: [-fms-extensions] Make some exception specification warnings/errors compatible with what cl.exe does

2022-01-07 Thread Amy Huang 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 rG28d2977ff236: [-fms-extensions] Make some exception 
specification warnings/errors compatible… (authored by akhuang).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116256

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaExceptionSpec.cpp
  clang/test/SemaCXX/MicrosoftCompatibility.cpp


Index: clang/test/SemaCXX/MicrosoftCompatibility.cpp
===
--- clang/test/SemaCXX/MicrosoftCompatibility.cpp
+++ clang/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -2,6 +2,8 @@
 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 
-Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions 
-fms-compatibility-version=19.27
 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 
-Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions 
-fms-compatibility-version=19.00
 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 
-Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions 
-fms-compatibility-version=18.00
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++17 
-Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions
+
 
 #if defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT
 char16_t x;
@@ -350,6 +352,7 @@
 void foo(); // expected-note {{previous declaration}}
 void foo() throw(); // expected-warning {{exception specification in 
declaration does not match previous declaration}}
 
+#if __cplusplus < 201703L
 void r6() throw(...); // expected-note {{previous declaration}}
 void r6() throw(int); // expected-warning {{exception specification in 
declaration does not match previous declaration}}
 
@@ -362,6 +365,7 @@
   virtual void f2() throw(...);
   virtual void f3();
 };
+#endif
 
 class A {
   virtual ~A() throw();
@@ -377,14 +381,14 @@
 #endif
 };
 
-}
+void f4() throw(); // expected-note {{previous declaration is here}}
+void f4() {}   // expected-warning {{'f4' is missing exception 
specification 'throw()'}}
 
-namespace PR25265 {
-struct S {
-  int fn() throw(); // expected-note {{previous declaration is here}}
-};
+__declspec(nothrow) void f5();
+void f5() {}
 
-int S::fn() { return 0; } // expected-warning {{is missing exception 
specification}}
+void f6() noexcept; // expected-note {{previous declaration is here}}
+void f6() {}// expected-error {{'f6' is missing exception 
specification 'noexcept'}}
 }
 
 namespace PR43265 {
Index: clang/lib/Sema/SemaExceptionSpec.cpp
===
--- clang/lib/Sema/SemaExceptionSpec.cpp
+++ clang/lib/Sema/SemaExceptionSpec.cpp
@@ -391,9 +391,8 @@
 NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
   }
 
-  if (getLangOpts().MSVCCompat && ESI.Type != EST_DependentNoexcept) {
-// Allow missing exception specifications in redeclarations as an 
extension.
-DiagID = diag::ext_ms_missing_exception_specification;
+  if (getLangOpts().MSVCCompat && isDynamicExceptionSpec(ESI.Type)) {
+DiagID = diag::ext_missing_exception_specification;
 ReturnValueOnError = false;
   } else if (New->isReplaceableGlobalAllocationFunction() &&
  ESI.Type != EST_DependentNoexcept) {
@@ -402,6 +401,10 @@
 DiagID = diag::ext_missing_exception_specification;
 ReturnValueOnError = false;
   } else if (ESI.Type == EST_NoThrow) {
+// Don't emit any warning for missing 'nothrow' in MSVC.
+if (getLangOpts().MSVCCompat) {
+  return false;
+}
 // Allow missing attribute 'nothrow' in redeclarations, since this is a 
very
 // common omission.
 DiagID = diag::ext_missing_exception_specification;
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1695,9 +1695,6 @@
 def ext_missing_exception_specification : ExtWarn<
   err_missing_exception_specification.Text>,
   InGroup>;
-def ext_ms_missing_exception_specification : ExtWarn<
-  err_missing_exception_specification.Text>,
-  InGroup;
 def err_noexcept_needs_constant_expression : Error<
   "argument to noexcept specifier must be a constant expression">;
 def err_exception_spec_not_parsed : Error<


Index: clang/test/SemaCXX/MicrosoftCompatibility.cpp
===
--- clang/test/SemaCXX/MicrosoftCompatibility.cpp
+++ clang/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -2,6 +2,8 @@
 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions 

[PATCH] D116256: [-fms-extensions] Make some exception specification warnings/errors compatible with what cl.exe does

2022-01-06 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 397930.
akhuang marked an inline comment as done.
akhuang added a comment.

Add std=c++17 to the test.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116256

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaExceptionSpec.cpp
  clang/test/SemaCXX/MicrosoftCompatibility.cpp


Index: clang/test/SemaCXX/MicrosoftCompatibility.cpp
===
--- clang/test/SemaCXX/MicrosoftCompatibility.cpp
+++ clang/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -2,6 +2,8 @@
 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 
-Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions 
-fms-compatibility-version=19.27
 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 
-Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions 
-fms-compatibility-version=19.00
 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 
-Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions 
-fms-compatibility-version=18.00
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++17 
-Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions
+
 
 #if defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT
 char16_t x;
@@ -350,6 +352,7 @@
 void foo(); // expected-note {{previous declaration}}
 void foo() throw(); // expected-warning {{exception specification in 
declaration does not match previous declaration}}
 
+#if __cplusplus < 201703L
 void r6() throw(...); // expected-note {{previous declaration}}
 void r6() throw(int); // expected-warning {{exception specification in 
declaration does not match previous declaration}}
 
@@ -362,6 +365,7 @@
   virtual void f2() throw(...);
   virtual void f3();
 };
+#endif
 
 class A {
   virtual ~A() throw();
@@ -377,14 +381,14 @@
 #endif
 };
 
-}
+void f4() throw(); // expected-note {{previous declaration is here}}
+void f4() {}   // expected-warning {{'f4' is missing exception 
specification 'throw()'}}
 
-namespace PR25265 {
-struct S {
-  int fn() throw(); // expected-note {{previous declaration is here}}
-};
+__declspec(nothrow) void f5();
+void f5() {}
 
-int S::fn() { return 0; } // expected-warning {{is missing exception 
specification}}
+void f6() noexcept; // expected-note {{previous declaration is here}}
+void f6() {}// expected-error {{'f6' is missing exception 
specification 'noexcept'}}
 }
 
 namespace PR43265 {
Index: clang/lib/Sema/SemaExceptionSpec.cpp
===
--- clang/lib/Sema/SemaExceptionSpec.cpp
+++ clang/lib/Sema/SemaExceptionSpec.cpp
@@ -391,9 +391,8 @@
 NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
   }
 
-  if (getLangOpts().MSVCCompat && ESI.Type != EST_DependentNoexcept) {
-// Allow missing exception specifications in redeclarations as an 
extension.
-DiagID = diag::ext_ms_missing_exception_specification;
+  if (getLangOpts().MSVCCompat && isDynamicExceptionSpec(ESI.Type)) {
+DiagID = diag::ext_missing_exception_specification;
 ReturnValueOnError = false;
   } else if (New->isReplaceableGlobalAllocationFunction() &&
  ESI.Type != EST_DependentNoexcept) {
@@ -402,6 +401,10 @@
 DiagID = diag::ext_missing_exception_specification;
 ReturnValueOnError = false;
   } else if (ESI.Type == EST_NoThrow) {
+// Don't emit any warning for missing 'nothrow' in MSVC.
+if (getLangOpts().MSVCCompat) {
+  return false;
+}
 // Allow missing attribute 'nothrow' in redeclarations, since this is a 
very
 // common omission.
 DiagID = diag::ext_missing_exception_specification;
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1695,9 +1695,6 @@
 def ext_missing_exception_specification : ExtWarn<
   err_missing_exception_specification.Text>,
   InGroup>;
-def ext_ms_missing_exception_specification : ExtWarn<
-  err_missing_exception_specification.Text>,
-  InGroup;
 def err_noexcept_needs_constant_expression : Error<
   "argument to noexcept specifier must be a constant expression">;
 def err_exception_spec_not_parsed : Error<


Index: clang/test/SemaCXX/MicrosoftCompatibility.cpp
===
--- clang/test/SemaCXX/MicrosoftCompatibility.cpp
+++ clang/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -2,6 +2,8 @@
 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions -fms-compatibility-version=19.27
 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions 

[PATCH] D116256: [-fms-extensions] Make some exception specification warnings/errors compatible with what cl.exe does

2022-01-05 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

In D116256#3215801 , @thakis wrote:

> Thanks for the patch! This looks roughly right to me.
>
> Maybe the list of ESTs that are allowed to be mismatched should be opt-in 
> instead of opt-out? (i.e. instead of checking for "not EST_BasicNoexcept /  
> EST_DependentNoexcept", check for EST_NoThrow (I think?) Not sure which way 
> is better.
>
> (Looks like the old code was added for https://llvm.org/PR25265)
>
> Could you check that we still emit the warning on line 5 in 
> https://godbolt.org/z/bxfx8jsjd ? The test is mostly from 
> https://docs.microsoft.com/en-us/cpp/build/reference/zc-noexcepttypes?view=msvc-170
>  -- it feels like we might want to have different behavior in c++17 (and 
> later) and c++14 (and earlier) for some of the diags, possibly. Looks like 
> MSVC also has an error on line 15 by default (with /std:c++17, it seems to 
> accept it with /std:c++14), while we only warn.
>
> (I'm a bit surprised the `noexcept` bit doesn't make it into the mangled name 
> in the ms abi, but we're consistent with msvc about this so that's all good.)

It did not still emit the warning but I've changed it now. I'm not sure why 
https://llvm.org/PR25265 added a new warning 
(ext_ms_missing_exception_specification) instead of just using 
ext_missing_exception_specification; I guess I'll get rid of it anyway.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116256

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


[PATCH] D116256: [-fms-extensions] Make some exception specification warnings/errors compatible with what cl.exe does

2022-01-05 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 397760.
akhuang marked an inline comment as done.
akhuang added a comment.

Fix warning behavior


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116256

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaExceptionSpec.cpp
  clang/test/SemaCXX/MicrosoftCompatibility.cpp


Index: clang/test/SemaCXX/MicrosoftCompatibility.cpp
===
--- clang/test/SemaCXX/MicrosoftCompatibility.cpp
+++ clang/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -377,14 +377,14 @@
 #endif
 };
 
-}
+void f4() throw(); // expected-note {{previous declaration is here}}
+void f4() {}   // expected-warning {{'f4' is missing exception 
specification 'throw()'}}
 
-namespace PR25265 {
-struct S {
-  int fn() throw(); // expected-note {{previous declaration is here}}
-};
+__declspec(nothrow) void f5();
+void f5() {}
 
-int S::fn() { return 0; } // expected-warning {{is missing exception 
specification}}
+void f6() noexcept; // expected-note {{previous declaration is here}}
+void f6() {}// expected-error {{'f6' is missing exception 
specification 'noexcept'}}
 }
 
 namespace PR43265 {
Index: clang/lib/Sema/SemaExceptionSpec.cpp
===
--- clang/lib/Sema/SemaExceptionSpec.cpp
+++ clang/lib/Sema/SemaExceptionSpec.cpp
@@ -391,9 +391,8 @@
 NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
   }
 
-  if (getLangOpts().MSVCCompat && ESI.Type != EST_DependentNoexcept) {
-// Allow missing exception specifications in redeclarations as an 
extension.
-DiagID = diag::ext_ms_missing_exception_specification;
+  if (getLangOpts().MSVCCompat && isDynamicExceptionSpec(ESI.Type)) {
+DiagID = diag::ext_missing_exception_specification;
 ReturnValueOnError = false;
   } else if (New->isReplaceableGlobalAllocationFunction() &&
  ESI.Type != EST_DependentNoexcept) {
@@ -402,6 +401,10 @@
 DiagID = diag::ext_missing_exception_specification;
 ReturnValueOnError = false;
   } else if (ESI.Type == EST_NoThrow) {
+// Don't emit any warning for missing 'nothrow' in MSVC.
+if (getLangOpts().MSVCCompat) {
+  return false;
+}
 // Allow missing attribute 'nothrow' in redeclarations, since this is a 
very
 // common omission.
 DiagID = diag::ext_missing_exception_specification;
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1695,9 +1695,6 @@
 def ext_missing_exception_specification : ExtWarn<
   err_missing_exception_specification.Text>,
   InGroup>;
-def ext_ms_missing_exception_specification : ExtWarn<
-  err_missing_exception_specification.Text>,
-  InGroup;
 def err_noexcept_needs_constant_expression : Error<
   "argument to noexcept specifier must be a constant expression">;
 def err_exception_spec_not_parsed : Error<


Index: clang/test/SemaCXX/MicrosoftCompatibility.cpp
===
--- clang/test/SemaCXX/MicrosoftCompatibility.cpp
+++ clang/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -377,14 +377,14 @@
 #endif
 };
 
-}
+void f4() throw(); // expected-note {{previous declaration is here}}
+void f4() {}   // expected-warning {{'f4' is missing exception specification 'throw()'}}
 
-namespace PR25265 {
-struct S {
-  int fn() throw(); // expected-note {{previous declaration is here}}
-};
+__declspec(nothrow) void f5();
+void f5() {}
 
-int S::fn() { return 0; } // expected-warning {{is missing exception specification}}
+void f6() noexcept; // expected-note {{previous declaration is here}}
+void f6() {}// expected-error {{'f6' is missing exception specification 'noexcept'}}
 }
 
 namespace PR43265 {
Index: clang/lib/Sema/SemaExceptionSpec.cpp
===
--- clang/lib/Sema/SemaExceptionSpec.cpp
+++ clang/lib/Sema/SemaExceptionSpec.cpp
@@ -391,9 +391,8 @@
 NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
   }
 
-  if (getLangOpts().MSVCCompat && ESI.Type != EST_DependentNoexcept) {
-// Allow missing exception specifications in redeclarations as an extension.
-DiagID = diag::ext_ms_missing_exception_specification;
+  if (getLangOpts().MSVCCompat && isDynamicExceptionSpec(ESI.Type)) {
+DiagID = diag::ext_missing_exception_specification;
 ReturnValueOnError = false;
   } else if (New->isReplaceableGlobalAllocationFunction() &&
  ESI.Type != EST_DependentNoexcept) {
@@ -402,6 +401,10 @@
 DiagID = diag::ext_missing_exception_specification;
 ReturnValueOnError = false;
   } else if (ESI.Type == EST_NoThrow) {
+// Don't emit any warning for missing 'nothrow' in MSVC.
+if 

[PATCH] D116256: [-fms-extensions] Make some exception specification warnings/errors compatible with what cl.exe does

2021-12-23 Thread Amy Huang via Phabricator via cfe-commits
akhuang created this revision.
akhuang added reviewers: hans, thakis.
akhuang requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Make clang-cl error when a function definition is missing 'noexcept',
and succeed without warnings when missing '__declspec(nothrow)' or 'throw'.

Fixes pr52860


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D116256

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaExceptionSpec.cpp
  clang/test/SemaCXX/MicrosoftCompatibility.cpp


Index: clang/test/SemaCXX/MicrosoftCompatibility.cpp
===
--- clang/test/SemaCXX/MicrosoftCompatibility.cpp
+++ clang/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -377,14 +377,14 @@
 #endif
 };
 
-}
+void f4() throw();
+void f4() {}
 
-namespace PR25265 {
-struct S {
-  int fn() throw(); // expected-note {{previous declaration is here}}
-};
+__declspec(nothrow) void f5();
+void f5() {}
 
-int S::fn() { return 0; } // expected-warning {{is missing exception 
specification}}
+void f6() noexcept; // expected-note {{previous declaration is here}}
+void f6() {}// expected-error {{'f6' is missing exception 
specification 'noexcept'}}
 }
 
 namespace PR43265 {
Index: clang/lib/Sema/SemaExceptionSpec.cpp
===
--- clang/lib/Sema/SemaExceptionSpec.cpp
+++ clang/lib/Sema/SemaExceptionSpec.cpp
@@ -391,10 +391,11 @@
 NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
   }
 
-  if (getLangOpts().MSVCCompat && ESI.Type != EST_DependentNoexcept) {
-// Allow missing exception specifications in redeclarations as an 
extension.
-DiagID = diag::ext_ms_missing_exception_specification;
-ReturnValueOnError = false;
+  if (getLangOpts().MSVCCompat &&
+  !(ESI.Type == EST_DependentNoexcept || ESI.Type == EST_BasicNoexcept)) {
+// Allow missing exception specifications in redeclarations as an extension
+// without a warning.
+return false;
   } else if (New->isReplaceableGlobalAllocationFunction() &&
  ESI.Type != EST_DependentNoexcept) {
 // Allow missing exception specifications in redeclarations as an 
extension,
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1695,9 +1695,6 @@
 def ext_missing_exception_specification : ExtWarn<
   err_missing_exception_specification.Text>,
   InGroup>;
-def ext_ms_missing_exception_specification : ExtWarn<
-  err_missing_exception_specification.Text>,
-  InGroup;
 def err_noexcept_needs_constant_expression : Error<
   "argument to noexcept specifier must be a constant expression">;
 def err_exception_spec_not_parsed : Error<


Index: clang/test/SemaCXX/MicrosoftCompatibility.cpp
===
--- clang/test/SemaCXX/MicrosoftCompatibility.cpp
+++ clang/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -377,14 +377,14 @@
 #endif
 };
 
-}
+void f4() throw();
+void f4() {}
 
-namespace PR25265 {
-struct S {
-  int fn() throw(); // expected-note {{previous declaration is here}}
-};
+__declspec(nothrow) void f5();
+void f5() {}
 
-int S::fn() { return 0; } // expected-warning {{is missing exception specification}}
+void f6() noexcept; // expected-note {{previous declaration is here}}
+void f6() {}// expected-error {{'f6' is missing exception specification 'noexcept'}}
 }
 
 namespace PR43265 {
Index: clang/lib/Sema/SemaExceptionSpec.cpp
===
--- clang/lib/Sema/SemaExceptionSpec.cpp
+++ clang/lib/Sema/SemaExceptionSpec.cpp
@@ -391,10 +391,11 @@
 NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
   }
 
-  if (getLangOpts().MSVCCompat && ESI.Type != EST_DependentNoexcept) {
-// Allow missing exception specifications in redeclarations as an extension.
-DiagID = diag::ext_ms_missing_exception_specification;
-ReturnValueOnError = false;
+  if (getLangOpts().MSVCCompat &&
+  !(ESI.Type == EST_DependentNoexcept || ESI.Type == EST_BasicNoexcept)) {
+// Allow missing exception specifications in redeclarations as an extension
+// without a warning.
+return false;
   } else if (New->isReplaceableGlobalAllocationFunction() &&
  ESI.Type != EST_DependentNoexcept) {
 // Allow missing exception specifications in redeclarations as an extension,
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1695,9 +1695,6 @@
 def ext_missing_exception_specification : ExtWarn<
   err_missing_exception_specification.Text>,
   InGroup>;
-def 

[PATCH] D110670: [Sema] Allow comparisons between different ms ptr size address space types.

2021-10-05 Thread Amy Huang via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGc7104e506619: [Sema] Allow comparisons between different ms 
ptr size address space types. (authored by akhuang).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110670

Files:
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/CodeGen/ms-mixed-ptr-sizes.c
  clang/test/Sema/MicrosoftExtensions.cpp


Index: clang/test/Sema/MicrosoftExtensions.cpp
===
--- /dev/null
+++ clang/test/Sema/MicrosoftExtensions.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wmicrosoft -verify 
-fms-extensions
+// RUN: %clang_cc1 -triple x86_64-windows %s -fsyntax-only -Wmicrosoft -verify 
-fms-extensions
+// expected-no-diagnostics
+
+// Check that __ptr32/__ptr64 can be compared.
+int test_ptr_comparison(int *__ptr32 __uptr p32u, int *__ptr32 __sptr p32s,
+int *__ptr64 p64) {
+  return (p32u == p32s) +
+ (p32u == p64) +
+ (p32s == p64);
+}
Index: clang/test/CodeGen/ms-mixed-ptr-sizes.c
===
--- clang/test/CodeGen/ms-mixed-ptr-sizes.c
+++ clang/test/CodeGen/ms-mixed-ptr-sizes.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -emit-llvm -O2 
< %s | FileCheck %s --check-prefix=X64
-// RUN: %clang_cc1 -triple i386-pc-win32 -fms-extensions -emit-llvm -O2 < %s | 
FileCheck %s --check-prefix=X86
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -emit-llvm -O2 
< %s | FileCheck %s --check-prefixes=X64,ALL
+// RUN: %clang_cc1 -triple i386-pc-win32 -fms-extensions -emit-llvm -O2 < %s | 
FileCheck %s --check-prefixes=X86,ALL
 
 struct Foo {
   int * __ptr32 p32;
@@ -47,3 +47,39 @@
   f->p32 = (int * __ptr32)i;
   use_foo(f);
 }
+
+int test_compare1(int *__ptr32 __uptr i, int *__ptr64 j) {
+  // ALL-LABEL: define dso_local i32 @test_compare1
+  // X64: %{{.+}} = addrspacecast i32* %j to i32 addrspace(271)*
+  // X64: %cmp = icmp eq i32 addrspace(271)* %{{.+}}, %i
+  // X86: %{{.+}} = addrspacecast i32 addrspace(272)* %j to i32 addrspace(271)*
+  // X86: %cmp = icmp eq i32 addrspace(271)* %{{.+}}, %i
+  return (i == j);
+}
+
+int test_compare2(int *__ptr32 __sptr i, int *__ptr64 j) {
+  // ALL-LABEL: define dso_local i32 @test_compare2
+  // X64: %{{.+}} = addrspacecast i32* %j to i32 addrspace(270)*
+  // X64: %cmp = icmp eq i32 addrspace(270)* %{{.+}}, %i
+  // X86: %{{.+}} = addrspacecast i32 addrspace(272)* %j to i32*
+  // X86: %cmp = icmp eq i32* %{{.+}}, %i
+  return (i == j);
+}
+
+int test_compare3(int *__ptr32 __uptr i, int *__ptr64 j) {
+  // ALL-LABEL: define dso_local i32 @test_compare3
+  // X64: %{{.+}} = addrspacecast i32 addrspace(271)* %i to i32*
+  // X64: %cmp = icmp eq i32* %{{.+}}, %j
+  // X86: %{{.+}} = addrspacecast i32 addrspace(271)* %i to i32 addrspace(272)*
+  // X86: %cmp = icmp eq i32 addrspace(272)* %{{.+}}, %j
+  return (j == i);
+}
+
+int test_compare4(int *__ptr32 __sptr i, int *__ptr64 j) {
+  // ALL-LABEL: define dso_local i32 @test_compare4
+  // X64: %{{.+}} = addrspacecast i32 addrspace(270)* %i to i32*
+  // X64: %cmp = icmp eq i32* %{{.+}}, %j
+  // X86: %{{.+}} = addrspacecast i32* %i to i32 addrspace(272)*
+  // X86: %cmp = icmp eq i32 addrspace(272)* %{{.+}}, %j
+  return (j == i);
+}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -6674,8 +6674,15 @@
   } else if (Steps.size() == 1) {
 bool MaybeQ1 = Q1.isAddressSpaceSupersetOf(Q2);
 bool MaybeQ2 = Q2.isAddressSpaceSupersetOf(Q1);
-if (MaybeQ1 == MaybeQ2)
-  return QualType(); // No unique best address space.
+if (MaybeQ1 == MaybeQ2) {
+  // Exception for ptr size address spaces. Should be able to choose
+  // either address space during comparison.
+  if (isPtrSizeAddressSpace(Q1.getAddressSpace()) ||
+  isPtrSizeAddressSpace(Q2.getAddressSpace()))
+MaybeQ1 = true;
+  else
+return QualType(); // No unique best address space.
+}
 Quals.setAddressSpace(MaybeQ1 ? Q1.getAddressSpace()
   : Q2.getAddressSpace());
   } else {


Index: clang/test/Sema/MicrosoftExtensions.cpp
===
--- /dev/null
+++ clang/test/Sema/MicrosoftExtensions.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
+// RUN: %clang_cc1 -triple x86_64-windows %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
+// expected-no-diagnostics
+
+// Check that __ptr32/__ptr64 can be compared.
+int test_ptr_comparison(int *__ptr32 __uptr p32u, int *__ptr32 __sptr 

[PATCH] D110670: [Sema] Allow comparisons between different ms ptr size address space types.

2021-10-04 Thread Amy Huang via Phabricator via cfe-commits
akhuang updated this revision to Diff 376936.
akhuang added a comment.

add test


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110670

Files:
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/CodeGen/ms-mixed-ptr-sizes.c
  clang/test/Sema/MicrosoftExtensions.cpp


Index: clang/test/Sema/MicrosoftExtensions.cpp
===
--- /dev/null
+++ clang/test/Sema/MicrosoftExtensions.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wmicrosoft -verify 
-fms-extensions
+// RUN: %clang_cc1 -triple x86_64-windows %s -fsyntax-only -Wmicrosoft -verify 
-fms-extensions
+// expected-no-diagnostics
+
+// Check that __ptr32/__ptr64 can be compared.
+int test_ptr_comparison(int *__ptr32 __uptr p32u, int *__ptr32 __sptr p32s,
+int *__ptr64 p64) {
+  return (p32u == p32s) +
+ (p32u == p64) +
+ (p32s == p64);
+}
Index: clang/test/CodeGen/ms-mixed-ptr-sizes.c
===
--- clang/test/CodeGen/ms-mixed-ptr-sizes.c
+++ clang/test/CodeGen/ms-mixed-ptr-sizes.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -emit-llvm -O2 
< %s | FileCheck %s --check-prefix=X64
-// RUN: %clang_cc1 -triple i386-pc-win32 -fms-extensions -emit-llvm -O2 < %s | 
FileCheck %s --check-prefix=X86
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -emit-llvm -O2 
< %s | FileCheck %s --check-prefixes=X64,ALL
+// RUN: %clang_cc1 -triple i386-pc-win32 -fms-extensions -emit-llvm -O2 < %s | 
FileCheck %s --check-prefixes=X86,ALL
 
 struct Foo {
   int * __ptr32 p32;
@@ -47,3 +47,39 @@
   f->p32 = (int * __ptr32)i;
   use_foo(f);
 }
+
+int test_compare1(int *__ptr32 __uptr i, int *__ptr64 j) {
+  // ALL-LABEL: define dso_local i32 @test_compare1
+  // X64: %{{.+}} = addrspacecast i32* %j to i32 addrspace(271)*
+  // X64: %cmp = icmp eq i32 addrspace(271)* %{{.+}}, %i
+  // X86: %{{.+}} = addrspacecast i32 addrspace(272)* %j to i32 addrspace(271)*
+  // X86: %cmp = icmp eq i32 addrspace(271)* %{{.+}}, %i
+  return (i == j);
+}
+
+int test_compare2(int *__ptr32 __sptr i, int *__ptr64 j) {
+  // ALL-LABEL: define dso_local i32 @test_compare2
+  // X64: %{{.+}} = addrspacecast i32* %j to i32 addrspace(270)*
+  // X64: %cmp = icmp eq i32 addrspace(270)* %{{.+}}, %i
+  // X86: %{{.+}} = addrspacecast i32 addrspace(272)* %j to i32*
+  // X86: %cmp = icmp eq i32* %{{.+}}, %i
+  return (i == j);
+}
+
+int test_compare3(int *__ptr32 __uptr i, int *__ptr64 j) {
+  // ALL-LABEL: define dso_local i32 @test_compare3
+  // X64: %{{.+}} = addrspacecast i32 addrspace(271)* %i to i32*
+  // X64: %cmp = icmp eq i32* %{{.+}}, %j
+  // X86: %{{.+}} = addrspacecast i32 addrspace(271)* %i to i32 addrspace(272)*
+  // X86: %cmp = icmp eq i32 addrspace(272)* %{{.+}}, %j
+  return (j == i);
+}
+
+int test_compare4(int *__ptr32 __sptr i, int *__ptr64 j) {
+  // ALL-LABEL: define dso_local i32 @test_compare4
+  // X64: %{{.+}} = addrspacecast i32 addrspace(270)* %i to i32*
+  // X64: %cmp = icmp eq i32* %{{.+}}, %j
+  // X86: %{{.+}} = addrspacecast i32* %i to i32 addrspace(272)*
+  // X86: %cmp = icmp eq i32 addrspace(272)* %{{.+}}, %j
+  return (j == i);
+}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -6674,8 +6674,15 @@
   } else if (Steps.size() == 1) {
 bool MaybeQ1 = Q1.isAddressSpaceSupersetOf(Q2);
 bool MaybeQ2 = Q2.isAddressSpaceSupersetOf(Q1);
-if (MaybeQ1 == MaybeQ2)
-  return QualType(); // No unique best address space.
+if (MaybeQ1 == MaybeQ2) {
+  // Exception for ptr size address spaces. Should be able to choose
+  // either address space during comparison.
+  if (isPtrSizeAddressSpace(Q1.getAddressSpace()) ||
+  isPtrSizeAddressSpace(Q2.getAddressSpace()))
+MaybeQ1 = true;
+  else
+return QualType(); // No unique best address space.
+}
 Quals.setAddressSpace(MaybeQ1 ? Q1.getAddressSpace()
   : Q2.getAddressSpace());
   } else {


Index: clang/test/Sema/MicrosoftExtensions.cpp
===
--- /dev/null
+++ clang/test/Sema/MicrosoftExtensions.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
+// RUN: %clang_cc1 -triple x86_64-windows %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
+// expected-no-diagnostics
+
+// Check that __ptr32/__ptr64 can be compared.
+int test_ptr_comparison(int *__ptr32 __uptr p32u, int *__ptr32 __sptr p32s,
+int *__ptr64 p64) {
+  return (p32u == p32s) +
+ (p32u == p64) +
+ (p32s == 

[PATCH] D110670: [Sema] Allow comparisons between different ms ptr size address space types.

2021-09-30 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/Sema/SemaExprCXX.cpp:6682
+  isPtrSizeAddressSpace(Q2.getAddressSpace()))
+MaybeQ1 = true;
+  else

aaron.ballman wrote:
> akhuang wrote:
> > aaron.ballman wrote:
> > > I'm pretty sure this is correct based on my inspection of what code MSVC 
> > > is generating. But it would be helpful to have some codegen tests in 
> > > Clang for this functionality as well.
> > ha, I apparently didn't check that the behavior actually matches.. 
> > apparently in MSVC a ptr32 isn't equivalent to a ptr64
> Oh! I had tested this:
> ```
> int test1(int * __ptr32 __uptr p32u, int * __ptr32 __sptr p32s,
>  int * __ptr64 p64) {
>   return (p32u == p64);
> }
> 
> int test2(int * __ptr32 __uptr p32u, int * __ptr32 __sptr p32s,
>  int * __ptr64 p64) {
>   return (p64 == p32u);
> }
> ```
> to see whether the order of the operands mattered as to which conversion 
> "won" and I thought I saw that your patch generates the same code that MSVC 
> does. However, I could have messed my testing up somehow, so double-checking 
> is a good idea.
Whoops, you're right, I was not specifying __sptr/__uptr and I guess clang and 
msvc have different defaults for sign/zero extension. 

Will add tests. Also, thanks for reviewing! 



Comment at: clang/test/Sema/MicrosoftExtensions.cpp:9-10
+  return (p32u == p32s) +
+ (p32u == p64) +
+ (p32s == p64);
+}

aaron.ballman wrote:
> (Side question, not directly about this patch but sorta related.) Should 
> there be a diagnostic about conversion potentially causing a possible loss of 
> data (on the 64-bit target)?
Hmm, it seems reasonable, but I also don't know how motivated I am to add a 
diagnostic -- 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110670

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


[PATCH] D110668: [clang-cl] Accept `#pragma warning(disable : N)` for some N

2021-09-29 Thread Amy Huang via Phabricator via cfe-commits
akhuang added a comment.

Seems like there are also errors in chrome builds and the llvm compiler-rt 
build, will just revert it for now --


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110668

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


[PATCH] D110670: [Sema] Allow comparisons between different ms ptr size address space types.

2021-09-29 Thread Amy Huang via Phabricator via cfe-commits
akhuang added inline comments.



Comment at: clang/lib/Sema/SemaExprCXX.cpp:6682
+  isPtrSizeAddressSpace(Q2.getAddressSpace()))
+MaybeQ1 = true;
+  else

aaron.ballman wrote:
> I'm pretty sure this is correct based on my inspection of what code MSVC is 
> generating. But it would be helpful to have some codegen tests in Clang for 
> this functionality as well.
ha, I apparently didn't check that the behavior actually matches.. apparently 
in MSVC a ptr32 isn't equivalent to a ptr64


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110670

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


  1   2   3   4   5   >