[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.
This commit is contained in:
parent
1ea11e4262
commit
8a25f9534a
@ -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; }
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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).
|
||||
|
||||
35
clang/test/CIR/CodeGen/non-odr-use-non-ref.cpp
Normal file
35
clang/test/CIR/CodeGen/non-odr-use-non-ref.cpp
Normal file
@ -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
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user