Skip to content

Commit 4e24f30

Browse files
mmhaLukacma
authored andcommitted
[CIR] Add Aggregate Expression LValue Visitors (llvm#163410)
This patch implements visitors for MemberExpr, UnaryDeref, StringLiteral and CompoundLiteralExpr inside aggregate expressions.
1 parent 6fc4dca commit 4e24f30

File tree

4 files changed

+169
-13
lines changed

4 files changed

+169
-13
lines changed

clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -170,19 +170,10 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
170170
void VisitConstantExpr(ConstantExpr *e) {
171171
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitConstantExpr");
172172
}
173-
void VisitMemberExpr(MemberExpr *e) {
174-
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitMemberExpr");
175-
}
176-
void VisitUnaryDeref(UnaryOperator *e) {
177-
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitUnaryDeref");
178-
}
179-
void VisitStringLiteral(StringLiteral *e) {
180-
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitStringLiteral");
181-
}
182-
void VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
183-
cgf.cgm.errorNYI(e->getSourceRange(),
184-
"AggExprEmitter: VisitCompoundLiteralExpr");
185-
}
173+
void VisitMemberExpr(MemberExpr *e) { emitAggLoadOfLValue(e); }
174+
void VisitUnaryDeref(UnaryOperator *e) { emitAggLoadOfLValue(e); }
175+
void VisitStringLiteral(StringLiteral *e) { emitAggLoadOfLValue(e); }
176+
void VisitCompoundLiteralExpr(CompoundLiteralExpr *e);
186177
void VisitPredefinedExpr(const PredefinedExpr *e) {
187178
cgf.cgm.errorNYI(e->getSourceRange(),
188179
"AggExprEmitter: VisitPredefinedExpr");
@@ -325,6 +316,31 @@ void AggExprEmitter::emitAggLoadOfLValue(const Expr *e) {
325316
emitFinalDestCopy(e->getType(), lv);
326317
}
327318

319+
void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
320+
if (dest.isPotentiallyAliased() && e->getType().isPODType(cgf.getContext())) {
321+
// For a POD type, just emit a load of the lvalue + a copy, because our
322+
// compound literal might alias the destination.
323+
emitAggLoadOfLValue(e);
324+
return;
325+
}
326+
327+
AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
328+
329+
// Block-scope compound literals are destroyed at the end of the enclosing
330+
// scope in C.
331+
bool destruct =
332+
!cgf.getLangOpts().CPlusPlus && !slot.isExternallyDestructed();
333+
if (destruct)
334+
slot.setExternallyDestructed();
335+
336+
cgf.emitAggExpr(e->getInitializer(), slot);
337+
338+
if (destruct)
339+
if ([[maybe_unused]] QualType::DestructionKind dtorKind =
340+
e->getType().isDestructedType())
341+
cgf.cgm.errorNYI(e->getSourceRange(), "compound literal with destructor");
342+
}
343+
328344
void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
329345
QualType arrayQTy, Expr *e,
330346
ArrayRef<Expr *> args, Expr *arrayFiller) {

clang/lib/CIR/CodeGen/CIRGenValue.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ class AggValueSlot {
390390

391391
IsZeroed_t isZeroed() const { return IsZeroed_t(zeroedFlag); }
392392

393+
IsAliased_t isPotentiallyAliased() const { return IsAliased_t(aliasedFlag); }
394+
393395
RValue asRValue() const {
394396
if (isIgnored())
395397
return RValue::getIgnored();
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -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 -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 -emit-llvm %s -o %t.ll
6+
// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
7+
8+
struct Point {
9+
int x, y;
10+
};
11+
12+
struct Line {
13+
struct Point start;
14+
struct Point end;
15+
};
16+
17+
// AggExprEmitter::VisitMemberExpr
18+
void test_member_in_array(void) {
19+
struct Line line = {{1, 2}, {3, 4}};
20+
struct Point arr[1] = {line.start};
21+
}
22+
23+
// CIR-LABEL: cir.func{{.*}} @test_member_in_array
24+
// CIR: %[[LINE:.*]] = cir.alloca !rec_Line{{.*}}, ["line", init]
25+
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!rec_Point x 1>{{.*}}, ["arr", init]
26+
// CIR: %[[MEMBER:.*]] = cir.get_member %[[LINE]][0] {name = "start"}
27+
// CIR: cir.copy
28+
29+
// LLVM-LABEL: define{{.*}} @test_member_in_array
30+
// LLVM: %[[LINE:.*]] = alloca %struct.Line
31+
// LLVM: %[[ARR:.*]] = alloca [1 x %struct.Point]
32+
// LLVM: %[[MEMBER:.*]] = getelementptr{{.*}}%struct.Line{{.*}}%[[LINE]]{{.*}}i32 0, i32 0
33+
// LLVM: call void @llvm.memcpy
34+
35+
// OGCG-LABEL: define{{.*}} @test_member_in_array
36+
// OGCG: %[[LINE:.*]] = alloca %struct.Line
37+
// OGCG: %[[ARR:.*]] = alloca [1 x %struct.Point]
38+
// OGCG: %[[MEMBER:.*]] = getelementptr{{.*}}%struct.Line{{.*}}%[[LINE]]{{.*}}i32 0, i32 0
39+
// OGCG: call void @llvm.memcpy
40+
41+
// AggExprEmitter::VisitMemberExpr
42+
void test_member_arrow_in_array(void) {
43+
struct Line *line_ptr;
44+
struct Point arr[1] = {line_ptr->start};
45+
}
46+
47+
// CIR-LABEL: cir.func{{.*}} @test_member_arrow_in_array
48+
// CIR: %[[PTR:.*]] = cir.alloca !cir.ptr<!rec_Line>{{.*}}, ["line_ptr"]
49+
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!rec_Point x 1>{{.*}}, ["arr", init]
50+
// CIR: %[[LOADED:.*]] = cir.load{{.*}}%[[PTR]]
51+
// CIR: %[[MEMBER:.*]] = cir.get_member %[[LOADED]][0] {name = "start"}
52+
// CIR: cir.copy
53+
54+
// LLVM-LABEL: define{{.*}} @test_member_arrow_in_array
55+
// LLVM: %[[PTR:.*]] = alloca ptr
56+
// LLVM: %[[ARR:.*]] = alloca [1 x %struct.Point]
57+
// LLVM: %[[LOADED:.*]] = load ptr{{.*}}%[[PTR]]
58+
// LLVM: %[[MEMBER:.*]] = getelementptr{{.*}}%struct.Line{{.*}}%[[LOADED]]{{.*}}i32 0, i32 0
59+
// LLVM: call void @llvm.memcpy
60+
61+
// OGCG-LABEL: define{{.*}} @test_member_arrow_in_array
62+
// OGCG: %[[PTR:.*]] = alloca ptr
63+
// OGCG: %[[ARR:.*]] = alloca [1 x %struct.Point]
64+
// OGCG: %[[LOADED:.*]] = load ptr{{.*}}%[[PTR]]
65+
// OGCG: %[[MEMBER:.*]] = getelementptr{{.*}}%struct.Line{{.*}}%[[LOADED]]{{.*}}i32 0, i32 0
66+
// OGCG: call void @llvm.memcpy
67+
68+
// AggExprEmitter::VisitUnaryDeref
69+
void test_deref_in_array(void) {
70+
struct Point *ptr;
71+
struct Point arr[1] = {*ptr};
72+
}
73+
74+
// CIR-LABEL: cir.func{{.*}} @test_deref_in_array
75+
// CIR: %[[PTR:.*]] = cir.alloca !cir.ptr<!rec_Point>{{.*}}, ["ptr"]
76+
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!rec_Point x 1>{{.*}}, ["arr", init]
77+
// CIR: %[[LOADED:.*]] = cir.load{{.*}}%[[PTR]]
78+
// CIR: cir.copy
79+
80+
// LLVM-LABEL: define{{.*}} @test_deref_in_array
81+
// LLVM: %[[PTR:.*]] = alloca ptr
82+
// LLVM: %[[ARR:.*]] = alloca [1 x %struct.Point]
83+
// LLVM: %[[LOADED:.*]] = load ptr{{.*}}%[[PTR]]
84+
// LLVM: call void @llvm.memcpy
85+
86+
// OGCG-LABEL: define{{.*}} @test_deref_in_array
87+
// OGCG: %[[PTR:.*]] = alloca ptr
88+
// OGCG: %[[ARR:.*]] = alloca [1 x %struct.Point]
89+
// OGCG: %[[LOADED:.*]] = load ptr{{.*}}%[[PTR]]
90+
// OGCG: call void @llvm.memcpy
91+
92+
// AggExprEmitter::VisitStringLiteral
93+
void test_string_array_in_array(void) {
94+
char matrix[2][6] = {"hello", "world"};
95+
}
96+
97+
// CIR-LABEL: cir.func{{.*}} @test_string_array_in_array
98+
// CIR: cir.alloca !cir.array<!cir.array<!s8i x 6> x 2>, {{.*}}, ["matrix", init]
99+
// CIR: cir.get_global
100+
// CIR: cir.copy
101+
// CIR: cir.get_global
102+
// CIR: cir.copy
103+
104+
// LLVM-LABEL: define{{.*}} @test_string_array_in_array
105+
// LLVM: alloca [2 x [6 x i8]]
106+
// LLVM: call void @llvm.memcpy
107+
// LLVM: call void @llvm.memcpy
108+
109+
// OGCG-LABEL: define{{.*}} @test_string_array_in_array
110+
// OGCG: alloca [2 x [6 x i8]]
111+
// OGCG: call void @llvm.memcpy{{.*}}@__const.test_string_array_in_array

clang/test/CIR/CodeGen/compound_literal.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,30 @@ void foo3() {
9797
// OGCG: %[[TMP:.*]] = load <4 x i32>, ptr %[[CL_ADDR]], align 16
9898
// OGCG: store <4 x i32> %[[TMP]], ptr %[[A_ADDR]], align 16
9999

100+
struct Point {
101+
int x, y;
102+
};
103+
104+
void foo4() {
105+
Point p = (Point){5, 10};
106+
}
107+
108+
// CIR-LABEL: @_Z4foo4v
109+
// CIR: %[[P:.*]] = cir.alloca !rec_Point, !cir.ptr<!rec_Point>, ["p", init]
110+
// CIR: %[[P_X:.*]] = cir.get_member %[[P]][0] {name = "x"}
111+
// CIR: %[[FIVE:.*]] = cir.const #cir.int<5> : !s32i
112+
// CIR: cir.store{{.*}} %[[FIVE]], %[[P_X]]
113+
// CIR: %[[P_Y:.*]] = cir.get_member %[[P]][1] {name = "y"}
114+
// CIR: %[[TEN:.*]] = cir.const #cir.int<10> : !s32i
115+
// CIR: cir.store{{.*}} %[[TEN]], %[[P_Y]]
116+
117+
// LLVM-LABEL: @_Z4foo4v
118+
// LLVM: %[[P:.*]] = alloca %struct.Point
119+
// LLVM: %[[P_X:.*]] = getelementptr %struct.Point, ptr %[[P]], i32 0, i32 0
120+
// LLVM: store i32 5, ptr %[[P_X]]
121+
// LLVM: %[[P_Y:.*]] = getelementptr %struct.Point, ptr %[[P]], i32 0, i32 1
122+
// LLVM: store i32 10, ptr %[[P_Y]]
123+
124+
// OGCG-LABEL: @_Z4foo4v
125+
// OGCG: %[[P:.*]] = alloca %struct.Point
126+
// OGCG: call void @llvm.memcpy{{.*}}(ptr{{.*}} %[[P]], ptr{{.*}} @__const._Z4foo4v.p

0 commit comments

Comments
 (0)