Skip to content

Commit 1c9368e

Browse files
authored
[CIR] Upstream non-record array init handling (#169429)
This upstreams the code to handle member initialization for non-record arrays.
1 parent dbcf568 commit 1c9368e

File tree

4 files changed

+79
-2
lines changed

4 files changed

+79
-2
lines changed

clang/lib/CIR/CodeGen/CIRGenCXXABI.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ class CIRGenCXXABI {
192192
QualType elementType,
193193
const CXXDestructorDecl *dtor) = 0;
194194

195+
virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
196+
FunctionArgList &args) const = 0;
197+
195198
/// Checks if ABI requires extra virtual offset for vtable field.
196199
virtual bool
197200
isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,

clang/lib/CIR/CodeGen/CIRGenClass.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,24 @@ static void emitMemberInitializer(CIRGenFunction &cgf,
111111
// NOTE(cir): CodeGen allows record types to be memcpy'd if applicable,
112112
// whereas ClangIR wants to represent all object construction explicitly.
113113
if (!baseElementTy->isRecordType()) {
114-
cgf.cgm.errorNYI(memberInit->getSourceRange(),
115-
"emitMemberInitializer: array of non-record type");
114+
unsigned srcArgIndex =
115+
cgf.cgm.getCXXABI().getSrcArgforCopyCtor(constructor, args);
116+
cir::LoadOp srcPtr = cgf.getBuilder().createLoad(
117+
cgf.getLoc(memberInit->getSourceLocation()),
118+
cgf.getAddrOfLocalVar(args[srcArgIndex]));
119+
LValue thisRhslv = cgf.makeNaturalAlignAddrLValue(srcPtr, recordTy);
120+
LValue src = cgf.emitLValueForFieldInitialization(thisRhslv, field,
121+
field->getName());
122+
123+
// Copy the aggregate.
124+
cgf.emitAggregateCopy(lhs, src, fieldType,
125+
cgf.getOverlapForFieldInit(field),
126+
lhs.isVolatileQualified());
127+
// Ensure that we destroy the objects if an exception is thrown later in
128+
// the constructor.
129+
QualType::DestructionKind dtorKind = fieldType.isDestructedType();
130+
assert(!cgf.needsEHCleanup(dtorKind) &&
131+
"Arrays of non-record types shouldn't need EH cleanup");
116132
return;
117133
}
118134
}

clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
123123
return true;
124124
}
125125

126+
size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
127+
FunctionArgList &args) const override {
128+
assert(!args.empty() && "expected the arglist to not be empty!");
129+
return args.size() - 1;
130+
}
131+
126132
void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) override;
127133

128134
mlir::Value
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
3+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fclangir -emit-llvm %s -o %t-cir.ll
4+
// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
5+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -emit-llvm %s -o %t.ll
6+
// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
7+
8+
struct HasScalarArrayMember {
9+
int arr[2][2];
10+
HasScalarArrayMember(const HasScalarArrayMember &);
11+
};
12+
13+
HasScalarArrayMember::HasScalarArrayMember(const HasScalarArrayMember &) = default;
14+
15+
// CIR-LABEL: cir.func dso_local @_ZN20HasScalarArrayMemberC2ERKS_(
16+
// CIR-NEXT: %[[THIS:.*]] = cir.alloca !cir.ptr<!rec_HasScalarArrayMember>
17+
// CIR-NEXT: %[[OTHER:.*]] = cir.alloca !cir.ptr<!rec_HasScalarArrayMember>
18+
// CIR-NEXT: cir.store %arg0, %[[THIS]]
19+
// CIR-NEXT: cir.store %arg1, %[[OTHER]]
20+
// CIR-NEXT: %[[THIS_LOAD:.*]] = cir.load{{.*}} %[[THIS]]
21+
// CIR-NEXT: %[[THIS_ARR:.*]] = cir.get_member %[[THIS_LOAD]][0] {name = "arr"}
22+
// CIR-NEXT: %[[OTHER_LOAD:.*]] = cir.load{{.*}} %[[OTHER]]
23+
// CIR-NEXT: %[[OTHER_ARR:.*]] = cir.get_member %[[OTHER_LOAD]][0] {name = "arr"}
24+
// CIR-NEXT: cir.copy %[[OTHER_ARR]] to %[[THIS_ARR]] : !cir.ptr<!cir.array<!cir.array<!s32i x 2> x 2>>
25+
// CIR-NEXT: cir.return
26+
27+
// LLVM-LABEL: define {{.*}} @_ZN20HasScalarArrayMemberC2ERKS_(
28+
// LLVM-SAME: ptr %[[ARG0:.*]], ptr %[[ARG1:.*]])
29+
// LLVM-NEXT: %[[THIS:.*]] = alloca ptr
30+
// LLVM-NEXT: %[[OTHER:.*]] = alloca ptr
31+
// LLVM-NEXT: store ptr %[[ARG0]], ptr %[[THIS]]
32+
// LLVM-NEXT: store ptr %[[ARG1]], ptr %[[OTHER]]
33+
// LLVM-NEXT: %[[THIS_LOAD:.*]] = load ptr, ptr %[[THIS]]
34+
// LLVM-NEXT: %[[THIS_ARR:.*]] = getelementptr %struct.HasScalarArrayMember, ptr %[[THIS_LOAD]], i32 0, i32 0
35+
// LLVM-NEXT: %[[OTHER_LOAD:.*]] = load ptr, ptr %[[OTHER]]
36+
// LLVM-NEXT: %[[OTHER_ARR:.*]] = getelementptr %struct.HasScalarArrayMember, ptr %[[OTHER_LOAD]], i32 0, i32 0
37+
// LLVM-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr %[[THIS_ARR]], ptr %[[OTHER_ARR]], i32 16, i1 false)
38+
// LLVM-NEXT: ret void
39+
40+
// OGCG-LABEL: define {{.*}} @_ZN20HasScalarArrayMemberC2ERKS_(
41+
// OGCG-SAME: ptr {{.*}} %[[ARG0:.*]], ptr {{.*}} %[[ARG1:.*]])
42+
// OGCG-NEXT: entry:
43+
// OGCG-NEXT: %[[THIS:.*]] = alloca ptr
44+
// OGCG-NEXT: %[[OTHER:.*]] = alloca ptr
45+
// OGCG-NEXT: store ptr %[[ARG0]], ptr %[[THIS]]
46+
// OGCG-NEXT: store ptr %[[ARG1]], ptr %[[OTHER]]
47+
// OGCG-NEXT: %[[THIS_LOAD:.*]] = load ptr, ptr %[[THIS]]
48+
// OGCG-NEXT: %[[THIS_ARR:.*]] = getelementptr inbounds nuw %struct.HasScalarArrayMember, ptr %[[THIS_LOAD]], i32 0, i32 0
49+
// OGCG-NEXT: %[[OTHER_LOAD:.*]] = load ptr, ptr %[[OTHER]]
50+
// OGCG-NEXT: %[[OTHER_ARR:.*]] = getelementptr inbounds nuw %struct.HasScalarArrayMember, ptr %[[OTHER_LOAD]], i32 0, i32 0
51+
// OGCG-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}} %[[THIS_ARR]], ptr {{.*}} %[[OTHER_ARR]], i64 16, i1 false)
52+
// OGCG-NEXT: ret void

0 commit comments

Comments
 (0)