diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 17fd3b19638f..8997e408a2d7 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 396b66c26172..1f08ba773dfb 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(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 10168792cd73..56c87eac339d 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 d2f7642451b2..bef154955b9b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -396,7 +396,8 @@ public: /// 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 000000000000..8777634debca --- /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 {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: cir.store align(8) %[[GLOBAL_A]], %{{.*}} : !cir.ptr>, !cir.ptr>> + // 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 +}