Skip to content

Commit 4a4582d

Browse files
authored
[CIR] Upstream BinAssign for ComplexType (#144868)
This change adds support for the BinAssign op and LValueToRValue for ComplexType #141365
1 parent 5f2135d commit 4a4582d

File tree

5 files changed

+124
-11
lines changed

5 files changed

+124
-11
lines changed

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -997,10 +997,9 @@ LValue CIRGenFunction::emitBinaryOperatorLValue(const BinaryOperator *e) {
997997
}
998998

999999
case cir::TEK_Complex: {
1000-
assert(!cir::MissingFeatures::complexType());
1001-
cgm.errorNYI(e->getSourceRange(), "complex l-values");
1002-
return {};
1000+
return emitComplexAssignmentLValue(e);
10031001
}
1002+
10041003
case cir::TEK_Aggregate:
10051004
cgm.errorNYI(e->getSourceRange(), "aggregate lvalues");
10061005
return {};

clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
1919
// Utilities
2020
//===--------------------------------------------------------------------===//
2121

22+
LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val);
23+
24+
mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy);
25+
26+
mlir::Value emitConstant(const CIRGenFunction::ConstantEmission &constant,
27+
Expr *e);
28+
2229
/// Given an expression with complex type that represents a value l-value,
2330
/// this method emits the address of the l-value, then loads and returns the
2431
/// result.
@@ -27,18 +34,18 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
2734
}
2835

2936
mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc);
30-
3137
/// Store the specified real/imag parts into the
3238
/// specified value pointer.
3339
void emitStoreOfComplex(mlir::Location loc, mlir::Value val, LValue lv,
3440
bool isInit);
3541

42+
mlir::Value VisitBinAssign(const BinaryOperator *e);
3643
mlir::Value VisitCallExpr(const CallExpr *e);
37-
mlir::Value VisitInitListExpr(InitListExpr *e);
38-
44+
mlir::Value VisitDeclRefExpr(DeclRefExpr *e);
45+
mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
46+
mlir::Value VisitInitListExpr(const InitListExpr *e);
3947
mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
4048
};
41-
4249
} // namespace
4350

4451
static const ComplexType *getComplexType(QualType type) {
@@ -48,6 +55,46 @@ static const ComplexType *getComplexType(QualType type) {
4855
return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
4956
}
5057

58+
LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
59+
mlir::Value &value) {
60+
assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
61+
e->getRHS()->getType()) &&
62+
"Invalid assignment");
63+
64+
// Emit the RHS. __block variables need the RHS evaluated first.
65+
value = Visit(e->getRHS());
66+
67+
// Compute the address to store into.
68+
LValue lhs = cgf.emitLValue(e->getLHS());
69+
70+
// Store the result value into the LHS lvalue.
71+
emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs, /*isInit*/ false);
72+
return lhs;
73+
}
74+
75+
mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
76+
QualType destTy) {
77+
switch (ck) {
78+
case CK_LValueToRValue:
79+
return Visit(op);
80+
default:
81+
cgf.cgm.errorNYI("ComplexType Cast");
82+
break;
83+
}
84+
return {};
85+
}
86+
87+
mlir::Value ComplexExprEmitter::emitConstant(
88+
const CIRGenFunction::ConstantEmission &constant, Expr *e) {
89+
assert(constant && "not a constant");
90+
if (constant.isReference())
91+
return emitLoadOfLValue(constant.getReferenceLValue(cgf, e),
92+
e->getExprLoc());
93+
94+
mlir::TypedAttr valueAttr = constant.getValue();
95+
return builder.getConstant(cgf.getLoc(e->getSourceRange()), valueAttr);
96+
}
97+
5198
mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
5299
SourceLocation loc) {
53100
assert(lv.isSimple() && "non-simple complex l-value?");
@@ -70,14 +117,44 @@ void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
70117
builder.createStore(loc, val, destAddr);
71118
}
72119

120+
mlir::Value ComplexExprEmitter::VisitBinAssign(const BinaryOperator *e) {
121+
mlir::Value value;
122+
LValue lv = emitBinAssignLValue(e, value);
123+
124+
// The result of an assignment in C is the assigned r-value.
125+
if (!cgf.getLangOpts().CPlusPlus)
126+
return value;
127+
128+
// If the lvalue is non-volatile, return the computed value of the
129+
// assignment.
130+
if (!lv.isVolatile())
131+
return value;
132+
133+
return emitLoadOfLValue(lv, e->getExprLoc());
134+
}
135+
73136
mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
74137
if (e->getCallReturnType(cgf.getContext())->isReferenceType())
75138
return emitLoadOfLValue(e);
76139

77140
return cgf.emitCallExpr(e).getValue();
78141
}
79142

80-
mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) {
143+
mlir::Value ComplexExprEmitter::VisitDeclRefExpr(DeclRefExpr *e) {
144+
if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
145+
return emitConstant(constant, e);
146+
return emitLoadOfLValue(e);
147+
}
148+
149+
mlir::Value ComplexExprEmitter::VisitImplicitCastExpr(ImplicitCastExpr *e) {
150+
// Unlike for scalars, we don't have to worry about function->ptr demotion
151+
// here.
152+
if (e->changesVolatileQualification())
153+
return emitLoadOfLValue(e);
154+
return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());
155+
}
156+
157+
mlir::Value ComplexExprEmitter::VisitInitListExpr(const InitListExpr *e) {
81158
mlir::Location loc = cgf.getLoc(e->getExprLoc());
82159
if (e->getNumInits() == 2) {
83160
mlir::Value real = cgf.emitScalarExpr(e->getInit(0));
@@ -127,6 +204,17 @@ ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) {
127204
return builder.create<cir::ConstantOp>(loc, complexAttr);
128205
}
129206

207+
LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) {
208+
assert(e->getOpcode() == BO_Assign && "Expected assign op");
209+
210+
mlir::Value value; // ignored
211+
LValue lvalue = ComplexExprEmitter(*this).emitBinAssignLValue(e, value);
212+
if (getLangOpts().OpenMP)
213+
cgm.errorNYI("emitComplexAssignmentLValue OpenMP");
214+
215+
return lvalue;
216+
}
217+
130218
mlir::Value CIRGenFunction::emitComplexExpr(const Expr *e) {
131219
assert(e && getComplexType(e->getType()) &&
132220
"Invalid complex expression to emit");

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,8 @@ class CIRGenFunction : public CIRGenTypeCache {
870870
/// returning the result.
871871
mlir::Value emitComplexExpr(const Expr *e);
872872

873+
LValue emitComplexAssignmentLValue(const BinaryOperator *e);
874+
873875
void emitCompoundStmt(const clang::CompoundStmt &s);
874876

875877
void emitCompoundStmtWithoutScope(const clang::CompoundStmt &s);

clang/lib/CIR/CodeGen/CIRGenValue.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,7 @@ class LValue {
182182
bool isSimple() const { return lvType == Simple; }
183183
bool isVectorElt() const { return lvType == VectorElt; }
184184
bool isBitField() const { return lvType == BitField; }
185-
186-
// TODO: Add support for volatile
187-
bool isVolatile() const { return false; }
185+
bool isVolatile() const { return quals.hasVolatile(); }
188186

189187
unsigned getVRQualifiers() const {
190188
return quals.getCVRQualifiers() & ~clang::Qualifiers::Const;

clang/test/CIR/CodeGen/complex.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,29 @@ void foo14() {
230230
// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 1
231231
// OGCG: store i32 0, ptr %[[C_REAL_PTR]], align 4
232232
// OGCG: store i32 2, ptr %[[C_IMAG_PTR]], align 4
233+
234+
void foo15() {
235+
int _Complex a;
236+
int _Complex b = a;
237+
}
238+
239+
// CIR: %[[COMPLEX_A:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a"]
240+
// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init]
241+
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[COMPLEX_A]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
242+
// CIR: cir.store{{.*}} %[[TMP_A]], %[[COMPLEX_B]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
243+
244+
// LLVM: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, i64 1, align 4
245+
// LLVM: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, i64 1, align 4
246+
// LLVM: %[[TMP_A:.*]] = load { i32, i32 }, ptr %[[COMPLEX_A]], align 4
247+
// LLVM: store { i32, i32 } %[[TMP_A]], ptr %[[COMPLEX_B]], align 4
248+
249+
// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4
250+
// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4
251+
// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 0
252+
// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4
253+
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 1
254+
// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4
255+
// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 0
256+
// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1
257+
// OGCG: store i32 %[[A_REAL]], ptr %[[B_REAL_PTR]], align 4
258+
// OGCG: store i32 %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 4

0 commit comments

Comments
 (0)