Skip to content

Commit 65bde89

Browse files
authored
[CIR] Upstream CompoundLiteralExpr for Scalar (#148943)
Upstream CompoundLiteralExpr for Scalar as a prerequisite for CompoundLiteralExpr for ComplexType
1 parent 802ea0e commit 65bde89

File tree

6 files changed

+188
-0
lines changed

6 files changed

+188
-0
lines changed

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,67 @@ LValue CIRGenFunction::emitMemberExpr(const MemberExpr *e) {
10541054
llvm_unreachable("Unhandled member declaration!");
10551055
}
10561056

1057+
/// Evaluate an expression into a given memory location.
1058+
void CIRGenFunction::emitAnyExprToMem(const Expr *e, Address location,
1059+
Qualifiers quals, bool isInit) {
1060+
// FIXME: This function should take an LValue as an argument.
1061+
switch (getEvaluationKind(e->getType())) {
1062+
case cir::TEK_Complex: {
1063+
LValue lv = makeAddrLValue(location, e->getType());
1064+
emitComplexExprIntoLValue(e, lv, isInit);
1065+
return;
1066+
}
1067+
1068+
case cir::TEK_Aggregate: {
1069+
emitAggExpr(e, AggValueSlot::forAddr(location, quals,
1070+
AggValueSlot::IsDestructed_t(isInit),
1071+
AggValueSlot::IsAliased_t(!isInit),
1072+
AggValueSlot::MayOverlap));
1073+
return;
1074+
}
1075+
1076+
case cir::TEK_Scalar: {
1077+
RValue rv = RValue::get(emitScalarExpr(e));
1078+
LValue lv = makeAddrLValue(location, e->getType());
1079+
emitStoreThroughLValue(rv, lv);
1080+
return;
1081+
}
1082+
}
1083+
1084+
llvm_unreachable("bad evaluation kind");
1085+
}
1086+
1087+
LValue CIRGenFunction::emitCompoundLiteralLValue(const CompoundLiteralExpr *e) {
1088+
if (e->isFileScope()) {
1089+
cgm.errorNYI(e->getSourceRange(), "emitCompoundLiteralLValue: FileScope");
1090+
return {};
1091+
}
1092+
1093+
if (e->getType()->isVariablyModifiedType()) {
1094+
cgm.errorNYI(e->getSourceRange(),
1095+
"emitCompoundLiteralLValue: VariablyModifiedType");
1096+
return {};
1097+
}
1098+
1099+
Address declPtr = createMemTemp(e->getType(), getLoc(e->getSourceRange()),
1100+
".compoundliteral");
1101+
const Expr *initExpr = e->getInitializer();
1102+
LValue result = makeAddrLValue(declPtr, e->getType(), AlignmentSource::Decl);
1103+
1104+
emitAnyExprToMem(initExpr, declPtr, e->getType().getQualifiers(),
1105+
/*Init*/ true);
1106+
1107+
// Block-scope compound literals are destroyed at the end of the enclosing
1108+
// scope in C.
1109+
if (!getLangOpts().CPlusPlus && e->getType().isDestructedType()) {
1110+
cgm.errorNYI(e->getSourceRange(),
1111+
"emitCompoundLiteralLValue: non C++ DestructedType");
1112+
return {};
1113+
}
1114+
1115+
return result;
1116+
}
1117+
10571118
LValue CIRGenFunction::emitCallExprLValue(const CallExpr *e) {
10581119
RValue rv = emitCallExpr(e);
10591120

clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
5252
mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *e);
5353
mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
5454
mlir::Value VisitInitListExpr(const InitListExpr *e);
55+
56+
mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
57+
return emitLoadOfLValue(e);
58+
}
59+
5560
mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
5661
mlir::Value VisitParenExpr(ParenExpr *e);
5762
mlir::Value
@@ -467,6 +472,15 @@ mlir::Value CIRGenFunction::emitComplexPrePostIncDec(const UnaryOperator *e,
467472
return isPre ? incVal : inVal;
468473
}
469474

475+
void CIRGenFunction::emitComplexExprIntoLValue(const Expr *e, LValue dest,
476+
bool isInit) {
477+
assert(e && getComplexType(e->getType()) &&
478+
"Invalid complex expression to emit");
479+
ComplexExprEmitter emitter(*this);
480+
mlir::Value value = emitter.Visit(const_cast<Expr *>(e));
481+
emitter.emitStoreOfComplex(getLoc(e->getExprLoc()), value, dest, isInit);
482+
}
483+
470484
mlir::Value CIRGenFunction::emitLoadOfComplex(LValue src, SourceLocation loc) {
471485
return ComplexExprEmitter(*this).emitLoadOfLValue(src, loc);
472486
}

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
233233

234234
mlir::Value VisitMemberExpr(MemberExpr *e);
235235

236+
mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
237+
return emitLoadOfLValue(e);
238+
}
239+
236240
mlir::Value VisitInitListExpr(InitListExpr *e);
237241

238242
mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,8 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
698698
return emitStringLiteralLValue(cast<StringLiteral>(e));
699699
case Expr::MemberExprClass:
700700
return emitMemberExpr(cast<MemberExpr>(e));
701+
case Expr::CompoundLiteralExprClass:
702+
return emitCompoundLiteralLValue(cast<CompoundLiteralExpr>(e));
701703
case Expr::BinaryOperatorClass:
702704
return emitBinaryOperatorLValue(cast<BinaryOperator>(e));
703705
case Expr::CompoundAssignOperatorClass: {

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,11 @@ class CIRGenFunction : public CIRGenTypeCache {
757757
RValue emitAnyExpr(const clang::Expr *e,
758758
AggValueSlot aggSlot = AggValueSlot::ignored());
759759

760+
/// Emits the code necessary to evaluate an arbitrary expression into the
761+
/// given memory location.
762+
void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals,
763+
bool isInitializer);
764+
760765
/// Similarly to emitAnyExpr(), however, the result will always be accessible
761766
/// even if no aggregate location is provided.
762767
RValue emitAnyExprToTemp(const clang::Expr *e);
@@ -828,6 +833,7 @@ class CIRGenFunction : public CIRGenTypeCache {
828833
mlir::Value emitCheckedArgForAssume(const Expr *e);
829834

830835
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e);
836+
LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e);
831837

832838
void emitConstructorBody(FunctionArgList &args);
833839
void emitDestructorBody(FunctionArgList &args);
@@ -930,6 +936,8 @@ class CIRGenFunction : public CIRGenTypeCache {
930936
/// returning the result.
931937
mlir::Value emitComplexExpr(const Expr *e);
932938

939+
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit);
940+
933941
mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv,
934942
bool isInc, bool isPre);
935943

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
3+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
4+
// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
5+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
6+
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
7+
8+
int foo() {
9+
int e = (int){1};
10+
return e;
11+
}
12+
13+
// CIR: %[[RET:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
14+
// CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e", init]
15+
// CIR: %[[COMPOUND:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, [".compoundliteral", init]
16+
// CIR: %[[VALUE:.*]] = cir.const #cir.int<1> : !s32i
17+
// CIR: cir.store{{.*}} %[[VALUE]], %[[COMPOUND]] : !s32i, !cir.ptr<!s32i>
18+
// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[COMPOUND]] : !cir.ptr<!s32i>, !s32i
19+
// CIR: cir.store{{.*}} %[[TMP]], %[[INIT]] : !s32i, !cir.ptr<!s32i>
20+
// CIR: %[[TMP_2:.*]] = cir.load{{.*}} %[[INIT]] : !cir.ptr<!s32i>, !s32i
21+
// CIR: cir.store %[[TMP_2]], %[[RET]] : !s32i, !cir.ptr<!s32i>
22+
// CIR: %[[TMP_3:.*]] = cir.load %[[RET]] : !cir.ptr<!s32i>, !s32i
23+
// CIR: cir.return %[[TMP_3]] : !s32i
24+
25+
// LLVM: %[[RET:.*]] = alloca i32, i64 1, align 4
26+
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
27+
// LLVM: %[[COMPOUND:.*]] = alloca i32, i64 1, align 4
28+
// LLVM: store i32 1, ptr %[[COMPOUND]], align 4
29+
// LLVM: %[[TMP:.*]] = load i32, ptr %[[COMPOUND]], align 4
30+
// LLVM: store i32 %[[TMP]], ptr %[[INIT]], align 4
31+
// LLVM: %[[TMP_2:.*]] = load i32, ptr %[[INIT]], align 4
32+
// LLVM: store i32 %[[TMP_2]], ptr %[[RET]], align 4
33+
// LLVM: %[[TMP_3:.*]] = load i32, ptr %[[RET]], align 4
34+
// LLVM: ret i32 %[[TMP_3]]
35+
36+
// OGCG: %[[INIT:.*]] = alloca i32, align 4
37+
// OGCG: %[[COMPOUND:.*]] = alloca i32, align 4
38+
// OGCG: store i32 1, ptr %[[COMPOUND]], align 4
39+
// OGCG: %[[TMP:.*]] = load i32, ptr %[[COMPOUND]], align 4
40+
// OGCG: store i32 %[[TMP]], ptr %[[INIT]], align 4
41+
// OGCG: %[[TMP_2:.*]] = load i32, ptr %[[INIT]], align 4
42+
// OGCG: ret i32 %[[TMP_2]]
43+
44+
void foo2() {
45+
int _Complex a = (int _Complex) { 1, 2};
46+
}
47+
48+
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a", init]
49+
// CIR: %[[CL_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, [".compoundliteral"]
50+
// CIR: %[[COMPLEX:.*]] = cir.const #cir.const_complex<#cir.int<1> : !s32i, #cir.int<2> : !s32i> : !cir.complex<!s32i>
51+
// CIR: cir.store{{.*}} %[[COMPLEX]], %[[CL_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
52+
// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[CL_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
53+
// CIR: cir.store{{.*}} %[[TMP]], %[[A_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
54+
55+
// LLVM: %[[A_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
56+
// LLVM: %[[CL_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
57+
// LLVM: store { i32, i32 } { i32 1, i32 2 }, ptr %[[CL_ADDR]], align 4
58+
// LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[CL_ADDR]], align 4
59+
// LLVM: store { i32, i32 } %[[TMP]], ptr %[[A_ADDR]], align 4
60+
61+
// OGCG: %[[A_ADDR:.*]] = alloca { i32, i32 }, align 4
62+
// OGCG: %[[CL_ADDR:.*]] = alloca { i32, i32 }, align 4
63+
// OGCG: %[[CL_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CL_ADDR]], i32 0, i32 0
64+
// OGCG: %[[CL_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CL_ADDR]], i32 0, i32 1
65+
// OGCG: store i32 1, ptr %[[CL_REAL_PTR]], align 4
66+
// OGCG: store i32 2, ptr %[[CL_IMAG_PTR]], align 4
67+
// OGCG: %[[CL_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CL_ADDR]], i32 0, i32 0
68+
// OGCG: %[[CL_REAL:.*]] = load i32, ptr %[[CL_REAL_PTR]], align 4
69+
// OGCG: %[[CL_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CL_ADDR]], i32 0, i32 1
70+
// OGCG: %[[CL_IMAG:.*]] = load i32, ptr %[[CL_IMAG_PTR]], align 4
71+
// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[A_ADDR]], i32 0, i32 0
72+
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[A_ADDR]], i32 0, i32 1
73+
// OGCG: store i32 %[[CL_REAL]], ptr %[[A_REAL_PTR]], align 4
74+
// OGCG: store i32 %[[CL_IMAG]], ptr %[[A_IMAG_PTR]], align 4
75+
76+
void foo3() {
77+
typedef int vi4 __attribute__((vector_size(16)));
78+
auto a = (vi4){10, 20, 30, 40};
79+
}
80+
81+
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a", init]
82+
// CIR: %[[CL_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, [".compoundliteral", init]
83+
// CIR: %[[VEC:.*]] = cir.const #cir.const_vector<[#cir.int<10> : !s32i, #cir.int<20> : !s32i, #cir.int<30> : !s32i, #cir.int<40> : !s32i]> : !cir.vector<4 x !s32i>
84+
// CIR: cir.store{{.*}} %[[VEC]], %[[CL_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
85+
// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[CL_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
86+
// CIR: cir.store{{.*}} %[[TMP]], %[[A_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
87+
88+
// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
89+
// LLVM: %[[CL_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
90+
// LLVM: store <4 x i32> <i32 10, i32 20, i32 30, i32 40>, ptr %[[CL_ADDR]], align 16
91+
// LLVM: %[[TMP:.*]] = load <4 x i32>, ptr %[[CL_ADDR]], align 16
92+
// LLVM: store <4 x i32> %[[TMP]], ptr %[[A_ADDR]], align 16
93+
94+
// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16
95+
// OGCG: %[[CL_ADDR:.*]] = alloca <4 x i32>, align 16
96+
// OGCG: store <4 x i32> <i32 10, i32 20, i32 30, i32 40>, ptr %[[CL_ADDR]], align 16
97+
// OGCG: %[[TMP:.*]] = load <4 x i32>, ptr %[[CL_ADDR]], align 16
98+
// OGCG: store <4 x i32> %[[TMP]], ptr %[[A_ADDR]], align 16
99+

0 commit comments

Comments
 (0)