llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: adams381

<details>
<summary>Changes</summary>

Replace errorNYI for isParamDestroyedInCallee with working
implementation: create aggregate temp, mark externally destructed,
emit expr.  Unblocks [[trivial_abi]] types on Itanium ABI.

Adds trivial-abi.cpp test covering 17 cases from
CodeGenCXX/trivial_abi.cpp with CIR/LLVM/OGCG checks.

Made with [Cursor](https://cursor.com)

---
Full diff: https://github.com/llvm/llvm-project/pull/191257.diff


2 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+18-5) 
- (added) clang/test/CIR/CodeGen/trivial-abi.cpp (+362) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 876fef687b477..ee89fdf0fd653 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -1311,13 +1311,26 @@ void CIRGenFunction::emitCallArg(CallArgList &args, 
const clang::Expr *e,
 
   bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
 
-  // In the Microsoft C++ ABI, aggregate arguments are destructed by the 
callee.
-  // However, we still have to push an EH-only cleanup in case we unwind before
-  // we make it to the call.
+  // For callee-destructed parameters (trivial_abi, MS ABI), create an
+  // aggregate temp and let the callee destroy it.
   if (argType->isRecordType() &&
       argType->castAsRecordDecl()->isParamDestroyedInCallee()) {
-    assert(!cir::MissingFeatures::msabi());
-    cgm.errorNYI(e->getSourceRange(), "emitCallArg: msabi is NYI");
+    AggValueSlot slot = createAggTemp(argType, getLoc(e->getSourceRange()),
+                                      getCounterAggTmpAsString());
+
+    bool destroyedInCallee = true;
+    if (const auto *rd = argType->getAsCXXRecordDecl())
+      destroyedInCallee = rd->hasNonTrivialDestructor();
+
+    if (destroyedInCallee)
+      slot.setExternallyDestructed();
+
+    emitAggExpr(e, slot);
+    RValue rv = slot.asRValue();
+    args.add(rv, argType);
+
+    assert(!cir::MissingFeatures::ehCleanupScope());
+    return;
   }
 
   if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
diff --git a/clang/test/CIR/CodeGen/trivial-abi.cpp 
b/clang/test/CIR/CodeGen/trivial-abi.cpp
new file mode 100644
index 0000000000000..0d942f865bb3c
--- /dev/null
+++ b/clang/test/CIR/CodeGen/trivial-abi.cpp
@@ -0,0 +1,362 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++11 
-fcxx-exceptions -fexceptions -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++11 
-fcxx-exceptions -fexceptions -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++11 
-fcxx-exceptions -fexceptions -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+// All 17 cases from clang/test/CodeGenCXX/trivial_abi.cpp, adapted for
+// x86_64-unknown-linux-gnu with CIR/LLVM/OGCG checks.
+
+struct __attribute__((trivial_abi)) Small {
+  int *p;
+  Small();
+  ~Small();
+  Small(const Small &) noexcept;
+  Small &operator=(const Small &);
+};
+
+struct __attribute__((trivial_abi)) Large {
+  int *p;
+  int a[128];
+  Large();
+  ~Large();
+  Large(const Large &) noexcept;
+  Large &operator=(const Large &);
+};
+
+struct Trivial { int a; };
+
+struct NonTrivial {
+  NonTrivial();
+  ~NonTrivial();
+  int a;
+};
+
+// --- Case 17: PR42961 lambda returning Small via __invoke ---
+// CIR emits lambda internals before user functions, so this CIR check
+// must come first to match CIR emission order.
+
+Small (*fp)() = []() -> Small { return Small(); };
+
+// CIR-LABEL: cir.func {{.*}} @{{.*}}__invokeEv
+// CIR:   cir.call @{{.*}}clEv
+
+// --- Case 1: D0::m0 thunk returning trivial_abi Small ---
+
+struct B0 { virtual Small m0(); };
+struct B1 { virtual Small m0(); };
+struct D0 : B0, B1 { Small m0() override; };
+Small D0::m0() { return {}; }
+
+// CIR-LABEL: cir.func {{.*}} @_ZThn8_N2D02m0Ev
+// CIR:   cir.call @_ZN2D02m0Ev
+
+// --- Case 2: testParamSmall ---
+
+void testParamSmall(Small a) noexcept {}
+
+// CIR-LABEL: cir.func {{.*}} @_Z14testParamSmall5Small
+// CIR:   cir.return
+
+// --- Case 3: testReturnSmall ---
+
+Small testReturnSmall() {
+  Small t;
+  return t;
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z15testReturnSmallv
+// CIR:   cir.call @_ZN5SmallC1Ev
+
+// --- Case 4: testCallSmall0 (local copy + callee-destructed param) ---
+
+void testCallSmall0() {
+  Small t;
+  testParamSmall(t);
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z14testCallSmall0v
+// CIR:   cir.call @_ZN5SmallC1Ev
+// CIR:   cir.call @_ZN5SmallC1ERKS_
+// CIR:   cir.call @_Z14testParamSmall5Small
+
+// --- Case 5: testCallSmall1 (pass returned value directly) ---
+
+void testCallSmall1() {
+  testParamSmall(testReturnSmall());
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z14testCallSmall1v
+// CIR:   cir.call @_Z15testReturnSmallv
+// CIR:   cir.call @_Z14testParamSmall5Small
+
+// --- Case 6: testIgnoredSmall (discard return, must destruct) ---
+
+void testIgnoredSmall() {
+  testReturnSmall();
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z16testIgnoredSmallv
+// CIR:   cir.call @_Z15testReturnSmallv
+// CIR:   cir.call @_ZN5SmallD1Ev
+
+// --- Case 7: testParamLarge ---
+
+void testParamLarge(Large a) noexcept {}
+
+// CIR-LABEL: cir.func {{.*}} @_Z14testParamLarge5Large
+// CIR:   cir.return
+
+// --- Case 8: testReturnLarge ---
+
+Large testReturnLarge() {
+  Large t;
+  return t;
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z15testReturnLargev
+// CIR:   cir.call @_ZN5LargeC1Ev
+
+// --- Case 9: testCallLarge0 (local copy + callee-destructed param) ---
+
+void testCallLarge0() {
+  Large t;
+  testParamLarge(t);
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z14testCallLarge0v
+// CIR:   cir.call @_ZN5LargeC1Ev
+// CIR:   cir.call @_ZN5LargeC1ERKS_
+// CIR:   cir.call @_Z14testParamLarge5Large
+
+// --- Case 10: testCallLarge1 (pass returned value directly) ---
+
+void testCallLarge1() {
+  testParamLarge(testReturnLarge());
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z14testCallLarge1v
+// CIR:   cir.call @_Z15testReturnLargev
+// CIR:   cir.call @_Z14testParamLarge5Large
+
+// --- Case 11: testIgnoredLarge (discard return, must destruct) ---
+
+void testIgnoredLarge() {
+  testReturnLarge();
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z16testIgnoredLargev
+// CIR:   cir.call @_Z15testReturnLargev
+// CIR:   cir.call @_ZN5LargeD1Ev
+
+// --- Case 12: testReturnHasTrivial ---
+
+Trivial testReturnHasTrivial() {
+  Trivial t;
+  return t;
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z20testReturnHasTrivialv
+// CIR:   cir.return
+
+// --- Case 13: testReturnHasNonTrivial ---
+
+NonTrivial testReturnHasNonTrivial() {
+  NonTrivial t;
+  return t;
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z23testReturnHasNonTrivialv
+// CIR:   cir.call @_ZN10NonTrivialC1Ev
+
+// --- Case 14: testExceptionSmall ---
+// CIR does not emit invoke/landingpad; the non-unwinding call sequence
+// is tested here.  OGCG verifies the full EH path.
+
+void calleeExceptionSmall(Small, Small);
+
+void testExceptionSmall() {
+  calleeExceptionSmall(Small(), Small());
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z18testExceptionSmallv
+// CIR:   cir.call @_ZN5SmallC1Ev
+// CIR:   cir.call @_ZN5SmallC1Ev
+// CIR:   cir.call @_Z20calleeExceptionSmall5SmallS_
+
+// --- Case 15: testExceptionLarge ---
+
+void calleeExceptionLarge(Large, Large);
+
+void testExceptionLarge() {
+  calleeExceptionLarge(Large(), Large());
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z18testExceptionLargev
+// CIR:   cir.call @_ZN5LargeC1Ev
+// CIR:   cir.call @_ZN5LargeC1Ev
+// CIR:   cir.call @_Z20calleeExceptionLarge5LargeS_
+
+// --- Case 16: GH93040 packed trivial_abi with placement new ---
+
+void* operator new(unsigned long, void*);
+namespace GH93040 {
+struct [[clang::trivial_abi]] S {
+  char a;
+  int x;
+  __attribute((aligned(2))) char y;
+  S();
+} __attribute((packed));
+S f();
+void g(S* s) { new(s) S(f()); }
+}
+
+// CIR-LABEL: cir.func {{.*}} @_ZN7GH930401gEPNS_1SE
+// CIR:   cir.call @_ZN7GH930401fEv
+
+// =======================================================================
+// LLVM checks (CIR -> LLVM lowering output)
+// =======================================================================
+
+// LLVM emits lambda __invoke early (internal linkage).
+// LLVM-LABEL: define {{.*}} @{{.*}}__invokeEv
+// LLVM:   call {{.*}} @{{.*}}clEv
+
+// LLVM-LABEL: define {{.*}} @_ZN2D02m0Ev(
+// LLVM-LABEL: define {{.*}} @_ZThn8_N2D02m0Ev(
+// LLVM:   getelementptr i8, ptr {{.*}}, i64 -8
+// LLVM:   call {{.*}} @_ZN2D02m0Ev(
+
+// LLVM-LABEL: define {{.*}} void @_Z14testParamSmall5Small(
+// LLVM:   ret void
+
+// LLVM-LABEL: define {{.*}} @_Z15testReturnSmallv(
+// LLVM:   call void @_ZN5SmallC1Ev(
+
+// LLVM-LABEL: define {{.*}} void @_Z14testCallSmall0v(
+// LLVM:   call void @_ZN5SmallC1Ev(
+// LLVM:   call void @_ZN5SmallC1ERKS_(
+// LLVM:   call void @_Z14testParamSmall5Small(
+
+// LLVM-LABEL: define {{.*}} void @_Z14testCallSmall1v(
+// LLVM:   call {{.*}} @_Z15testReturnSmallv(
+// LLVM:   call void @_Z14testParamSmall5Small(
+
+// LLVM-LABEL: define {{.*}} void @_Z16testIgnoredSmallv(
+// LLVM:   call {{.*}} @_Z15testReturnSmallv(
+// LLVM:   call void @_ZN5SmallD1Ev(
+
+// LLVM-LABEL: define {{.*}} void @_Z14testParamLarge5Large(
+// LLVM:   ret void
+
+// LLVM-LABEL: define {{.*}} @_Z15testReturnLargev(
+// LLVM:   call void @_ZN5LargeC1Ev(
+
+// LLVM-LABEL: define {{.*}} void @_Z14testCallLarge0v(
+// LLVM:   call void @_ZN5LargeC1Ev(
+// LLVM:   call void @_ZN5LargeC1ERKS_(
+// LLVM:   call void @_Z14testParamLarge5Large(
+
+// LLVM-LABEL: define {{.*}} void @_Z14testCallLarge1v(
+// LLVM:   call {{.*}} @_Z15testReturnLargev(
+// LLVM:   call void @_Z14testParamLarge5Large(
+
+// LLVM-LABEL: define {{.*}} void @_Z16testIgnoredLargev(
+// LLVM:   call {{.*}} @_Z15testReturnLargev(
+// LLVM:   call void @_ZN5LargeD1Ev(
+
+// LLVM-LABEL: define {{.*}} @_Z20testReturnHasTrivialv(
+// LLVM:   ret
+
+// LLVM-LABEL: define {{.*}} @_Z23testReturnHasNonTrivialv(
+// LLVM:   call void @_ZN10NonTrivialC1Ev(
+
+// LLVM-LABEL: define {{.*}} void @_Z18testExceptionSmallv(
+// LLVM:   call void @_ZN5SmallC1Ev(
+// LLVM:   call void @_ZN5SmallC1Ev(
+// LLVM:   call void @_Z20calleeExceptionSmall5SmallS_(
+
+// LLVM-LABEL: define {{.*}} void @_Z18testExceptionLargev(
+// LLVM:   call void @_ZN5LargeC1Ev(
+// LLVM:   call void @_ZN5LargeC1Ev(
+// LLVM:   call void @_Z20calleeExceptionLarge5LargeS_(
+
+// LLVM-LABEL: define {{.*}} void @_ZN7GH930401gEPNS_1SE(
+// LLVM:   call {{.*}} @_ZN7GH930401fEv(
+
+// =======================================================================
+// OGCG checks (classic codegen)
+// =======================================================================
+
+// OGCG-LABEL: define {{.*}} @_ZN2D02m0Ev(
+// OGCG-LABEL: define {{.*}} @_ZThn8_N2D02m0Ev(
+// OGCG:   getelementptr inbounds i8, ptr {{.*}}, i64 -8
+// OGCG:   {{.*}}call {{.*}} @_ZN2D02m0Ev(
+
+// OGCG-LABEL: define {{.*}} void @_Z14testParamSmall5Small(ptr %a.coerce)
+// OGCG:   call {{.*}} @_ZN5SmallD1Ev(
+// OGCG:   ret void
+
+// OGCG-LABEL: define {{.*}} ptr @_Z15testReturnSmallv(
+// OGCG:   call {{.*}} @_ZN5SmallC1Ev(
+
+// OGCG-LABEL: define {{.*}} void @_Z14testCallSmall0v(
+// OGCG:   call {{.*}} @_ZN5SmallC1Ev(
+// OGCG:   call {{.*}} @_ZN5SmallC1ERKS_(
+// OGCG:   call void @_Z14testParamSmall5Small(
+
+// OGCG-LABEL: define {{.*}} void @_Z14testCallSmall1v(
+// OGCG:   call {{.*}} @_Z15testReturnSmallv()
+// OGCG:   call void @_Z14testParamSmall5Small(
+
+// OGCG-LABEL: define {{.*}} void @_Z16testIgnoredSmallv(
+// OGCG:   call {{.*}} @_Z15testReturnSmallv()
+// OGCG:   call {{.*}} @_ZN5SmallD1Ev(
+
+// OGCG-LABEL: define {{.*}} void @_Z14testParamLarge5Large(ptr noundef 
byval(%struct.Large) align 8 %a)
+// OGCG:   call {{.*}} @_ZN5LargeD1Ev(
+// OGCG:   ret void
+
+// OGCG-LABEL: define {{.*}} void @_Z15testReturnLargev(ptr 
{{.*}}sret(%struct.Large)
+// OGCG:   call {{.*}} @_ZN5LargeC1Ev(
+
+// OGCG-LABEL: define {{.*}} void @_Z14testCallLarge0v(
+// OGCG:   call {{.*}} @_ZN5LargeC1Ev(
+// OGCG:   call {{.*}} @_ZN5LargeC1ERKS_(
+// OGCG:   call void @_Z14testParamLarge5Large(
+
+// OGCG-LABEL: define {{.*}} void @_Z14testCallLarge1v(
+// OGCG:   call void @_Z15testReturnLargev(
+// OGCG:   call void @_Z14testParamLarge5Large(
+
+// OGCG-LABEL: define {{.*}} void @_Z16testIgnoredLargev(
+// OGCG:   call void @_Z15testReturnLargev(
+// OGCG:   call {{.*}} @_ZN5LargeD1Ev(
+
+// OGCG-LABEL: define {{.*}} i32 @_Z20testReturnHasTrivialv(
+// OGCG:   ret i32
+
+// OGCG-LABEL: define {{.*}} void @_Z23testReturnHasNonTrivialv(ptr 
{{.*}}sret(%struct.NonTrivial)
+// OGCG:   call {{.*}} @_ZN10NonTrivialC1Ev(
+
+// OGCG-LABEL: define {{.*}} void @_Z18testExceptionSmallv() {{.*}} 
personality ptr @__gxx_personality_v0
+// OGCG:   call {{.*}} @_ZN5SmallC1Ev(
+// OGCG:   invoke {{.*}} @_ZN5SmallC1Ev(
+// OGCG:   call void @_Z20calleeExceptionSmall5SmallS_(
+// OGCG:   landingpad
+// OGCG:   call {{.*}} @_ZN5SmallD1Ev(
+
+// OGCG-LABEL: define {{.*}} void @_Z18testExceptionLargev() {{.*}} 
personality ptr @__gxx_personality_v0
+// OGCG:   call {{.*}} @_ZN5LargeC1Ev(
+// OGCG:   invoke {{.*}} @_ZN5LargeC1Ev(
+// OGCG:   call void @_Z20calleeExceptionLarge5LargeS_(
+// OGCG:   landingpad
+// OGCG:   call {{.*}} @_ZN5LargeD1Ev(
+
+// OGCG-LABEL: define {{.*}} void @_ZN7GH930401gEPNS_1SE(
+// OGCG:   call void @_ZN7GH930401fEv(ptr {{.*}}sret(
+
+// Lambda __invoke comes last in OGCG (internal linkage).
+// OGCG-LABEL: define {{.*}} @{{.*}}__invokeEv
+// OGCG:   call {{.*}} @{{.*}}clEv

``````````

</details>


https://github.com/llvm/llvm-project/pull/191257
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to