Author: Erich Keane
Date: 2026-03-11T06:26:13-07:00
New Revision: 8a25f9534a4176ff7b514b54952933f7d4d156b4

URL: 
https://github.com/llvm/llvm-project/commit/8a25f9534a4176ff7b514b54952933f7d4d156b4
DIFF: 
https://github.com/llvm/llvm-project/commit/8a25f9534a4176ff7b514b54952933f7d4d156b4.diff

LOG: [CIR] Implement non-odr use of reference type lowering (#185720)

This is used somewhat rarely, but is a pretty simple emission of
pointers, and ends up using infrastructure we already have.
Additionally, this is the first use of `getNaturalTypeAlignment` that
uses the `pointee` argument, so this adds the implementation there,
which includes some alignment work for CXXRecordDecls, so this
implements that as well.

Added: 
    clang/test/CIR/CodeGen/non-odr-use-non-ref.cpp

Modified: 
    clang/include/clang/CIR/MissingFeatures.h
    clang/lib/CIR/CodeGen/CIRGenExpr.cpp
    clang/lib/CIR/CodeGen/CIRGenModule.cpp
    clang/lib/CIR/CodeGen/CIRGenModule.h

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 17fd3b19638fd..8997e408a2d79 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -206,7 +206,6 @@ struct MissingFeatures {
   static bool aggValueSlotGC() { return false; }
   static bool aggValueSlotMayOverlap() { return false; }
   static bool aggValueSlotVolatile() { return false; }
-  static bool alignCXXRecordDecl() { return false; }
   static bool allocToken() { return false; }
   static bool appleArm64CXXABI() { return false; }
   static bool appleKext() { return false; }

diff  --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 396b66c261727..1f08ba773dfb5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -902,8 +902,17 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr 
*e) {
           addr = addr.withElementType(builder, varTy);
         }
       } else {
-        cgm.errorNYI(e->getSourceRange(),
-                     "emitDeclRefLValue: non-odr reference type");
+        // Should we be using the alignment of the constant pointer we emitted?
+        CharUnits alignment =
+            cgm.getNaturalTypeAlignment(e->getType(),
+                                        /*BaseInfo=*/nullptr,
+                                        /*forPointeeType=*/true);
+        // Classic codegen passes TBAA as null-ptr to the above function, so it
+        // probably needs to deal with that.
+        assert(!cir::MissingFeatures::opTBAA());
+        mlir::Value ptrVal = getBuilder().getConstant(
+            getLoc(e->getSourceRange()), mlir::cast<mlir::TypedAttr>(val));
+        addr = makeNaturalAddressForPointer(ptrVal, ty, alignment);
       }
       return makeAddrLValue(addr, ty, AlignmentSource::Decl);
     }

diff  --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 10168792cd730..56c87eac339d0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -176,7 +176,8 @@ CharUnits CIRGenModule::getClassPointerAlignment(const 
CXXRecordDecl *rd) {
 }
 
 CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t,
-                                                LValueBaseInfo *baseInfo) {
+                                                LValueBaseInfo *baseInfo,
+                                                bool forPointeeType) {
   assert(!cir::MissingFeatures::opTBAA());
 
   // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but
@@ -193,6 +194,8 @@ CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t,
     }
   }
 
+  bool alignForArray = t->isArrayType();
+
   // Analyze the base element type, so we don't get confused by incomplete
   // array types.
   t = astContext.getBaseElementType(t);
@@ -213,10 +216,13 @@ CharUnits CIRGenModule::getNaturalTypeAlignment(QualType 
t,
     *baseInfo = LValueBaseInfo(AlignmentSource::Type);
 
   CharUnits alignment;
+  const CXXRecordDecl *rd = nullptr;
   if (t.getQualifiers().hasUnaligned()) {
     alignment = CharUnits::One();
+  } else if (forPointeeType && !alignForArray &&
+             (rd = t->getAsCXXRecordDecl())) {
+    alignment = getClassPointerAlignment(rd);
   } else {
-    assert(!cir::MissingFeatures::alignCXXRecordDecl());
     alignment = astContext.getTypeAlignInChars(t);
   }
 

diff  --git a/clang/lib/CIR/CodeGen/CIRGenModule.h 
b/clang/lib/CIR/CodeGen/CIRGenModule.h
index d2f7642451b22..bef154955b9b6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -396,7 +396,8 @@ class CIRGenModule : public CIRGenTypeCache {
   /// FIXME: this could likely be a common helper and not necessarily related
   /// with codegen.
   clang::CharUnits getNaturalTypeAlignment(clang::QualType t,
-                                           LValueBaseInfo *baseInfo = nullptr);
+                                           LValueBaseInfo *baseInfo = nullptr,
+                                           bool forPointeeType = false);
 
   /// Returns the minimum object size for an object of the given class type
   /// (or a class derived from it).

diff  --git a/clang/test/CIR/CodeGen/non-odr-use-non-ref.cpp 
b/clang/test/CIR/CodeGen/non-odr-use-non-ref.cpp
new file mode 100644
index 0000000000000..8777634debca3
--- /dev/null
+++ b/clang/test/CIR/CodeGen/non-odr-use-non-ref.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+
+static int a[10]{};
+// CIR: cir.global "private" internal dso_local @_ZL1a = #cir.zero : 
!cir.array<!s32i x 10> {alignment = 16 : i64}
+// LLVM: @_ZL1a = internal global [10 x i32] zeroinitializer, align 16
+
+struct NonTrivialDestructor {
+  ~NonTrivialDestructor();
+};
+struct BiggerNonTrivialDestructor {
+  int array[12];
+  ~BiggerNonTrivialDestructor();
+};
+
+void use() {
+  for (int i : a) {}
+  // This happens 3x (range + begin + end), but they all use the same code, sox
+  // only test it 1x. Ensure the alignment is correct.
+  // CIR: %[[GLOBAL_A:.*]] = cir.const #cir.global_view<@_ZL1a> : 
!cir.ptr<!cir.array<!s32i x 10>>
+  // CIR: cir.store align(8) %[[GLOBAL_A]], %{{.*}} : 
!cir.ptr<!cir.array<!s32i x 10>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 10>>>
+  // LLVM: store ptr getelementptr inbounds nuw (i8, ptr @_ZL1a, i64 40), ptr 
%{{.*}}, align 8
+
+  // Make sure we get alignment correct here.
+  NonTrivialDestructor a;
+  // CIR-DAG: cir.call @_ZN20NonTrivialDestructorD1Ev{{.*}}llvm.align = 1
+  // LLVM-DAG: call void @_ZN20NonTrivialDestructorD1Ev(ptr {{.*}}align 1
+  BiggerNonTrivialDestructor b;
+  // CIR-DAG: cir.call @_ZN26BiggerNonTrivialDestructorD1Ev{{.*}}llvm.align = 4
+  // LLVM-DAG: call void @_ZN26BiggerNonTrivialDestructorD1Ev(ptr {{.*}}align 4
+}


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

Reply via email to