================
@@ -21,6 +25,94 @@ using namespace clang::CodeGen;
 
 namespace {
 
+/// True if \p Ty is a record whose fields (or bases) include a field that
+///  is empty for layout, or that contain such a field transitively through
+///  member or base types.
+static bool recordTypeHasEmptyFieldForLayout(ASTContext &Ctx, QualType Ty) {
+  const RecordDecl *RD = Ty->getAsRecordDecl();
+  if (!RD)
+    return false;
+
+  if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+    for (const auto &B : CXXRD->bases()) {
+      if (recordTypeHasEmptyFieldForLayout(Ctx, B.getType()))
+        return true;
+    }
+  }
+
+  for (const FieldDecl *FD : RD->fields()) {
+    if (isEmptyFieldForLayout(Ctx, FD))
+      return true;
+    if (recordTypeHasEmptyFieldForLayout(Ctx, FD->getType()))
+      return true;
+  }
+  return false;
+}
+
+/// Build a LLVM struct for AMDGPU aggregate return coercion: one element per
+/// non-empty base subobject and per field, ordered by \c ASTRecordLayout
+/// offsets (matching in-object layout). Nested records that also need this
+/// coercion use a nested coerce type; otherwise \c ConvertType is used.
+static llvm::Type *buildAMDGPUAggregateReturnCoerceType(CodeGenTypes &CGT,
+                                                        ASTContext &Ctx,
+                                                        QualType Ty) {
+  if (!recordTypeHasEmptyFieldForLayout(Ctx, Ty))
+    return nullptr;
+
+  const RecordDecl *RD = Ty->getAsRecordDecl();
+  if (!RD || !RD->getDefinition() || RD->isUnion())
+    return nullptr;
+  assert(!RD->hasFlexibleArrayMember());
+
+  // Vtable and dynamic-class layout are not represented here; use the normal
+  // LLVM record type as the coerce-to type.
+  if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+    if (CXXRD->isDynamicClass())
+      return nullptr;
+
+  const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
+
+  struct CoerceMember {
+    CharUnits Offset;
+    QualType Ty;
+  };
+  llvm::SmallVector<CoerceMember, 16> Members;
+
+  if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+    for (const CXXBaseSpecifier &B : CXXRD->bases()) {
+      const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
+      if (!BaseDecl || BaseDecl->isEmpty())
+        continue;
+      BaseDecl = BaseDecl->getDefinition();
+      CharUnits Off = B.isVirtual() ? Layout.getVBaseClassOffset(BaseDecl)
----------------
arsenm wrote:

In particular virtual base seems untested?

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

Reply via email to