-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[CIR] Upstream BinAssign for ComplexType #144868
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CIR] Upstream BinAssign for ComplexType #144868
Conversation
@llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) ChangesThis change adds support for the BinAssign op and LValueToRValue for ComplexType Full diff: https://github.com/llvm/llvm-project/pull/144868.diff 5 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 4f2046ad26d72..c31754dc11d69 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -997,10 +997,9 @@ LValue CIRGenFunction::emitBinaryOperatorLValue(const BinaryOperator *e) {
}
case cir::TEK_Complex: {
- assert(!cir::MissingFeatures::complexType());
- cgm.errorNYI(e->getSourceRange(), "complex l-values");
- return {};
+ return emitComplexAssignmentLValue(e);
}
+
case cir::TEK_Aggregate:
cgm.errorNYI(e->getSourceRange(), "aggregate lvalues");
return {};
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 12e8e27948cf7..bcfe2e3768e7a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -19,6 +19,13 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
// Utilities
//===--------------------------------------------------------------------===//
+ LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val);
+
+ mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy);
+
+ mlir::Value emitConstant(const CIRGenFunction::ConstantEmission &constant,
+ Expr *e);
+
/// Given an expression with complex type that represents a value l-value,
/// this method emits the address of the l-value, then loads and returns the
/// result.
@@ -27,18 +34,18 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
}
mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc);
-
/// Store the specified real/imag parts into the
/// specified value pointer.
void emitStoreOfComplex(mlir::Location loc, mlir::Value val, LValue lv,
bool isInit);
+ mlir::Value VisitBinAssign(const BinaryOperator *e);
mlir::Value VisitCallExpr(const CallExpr *e);
- mlir::Value VisitInitListExpr(InitListExpr *e);
-
+ mlir::Value VisitDeclRefExpr(DeclRefExpr *e);
+ mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
+ mlir::Value VisitInitListExpr(const InitListExpr *e);
mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
};
-
} // namespace
static const ComplexType *getComplexType(QualType type) {
@@ -48,6 +55,48 @@ static const ComplexType *getComplexType(QualType type) {
return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
}
+LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
+ mlir::Value &value) {
+ assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
+ e->getRHS()->getType()) &&
+ "Invalid assignment");
+
+ // Emit the RHS. __block variables need the RHS evaluated first.
+ value = Visit(e->getRHS());
+
+ // Compute the address to store into.
+ LValue lhs = cgf.emitLValue(e->getLHS());
+
+ // Store the result value into the LHS lvalue.
+ emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs, /*isInit*/ false);
+ return lhs;
+}
+
+mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
+ QualType destTy) {
+ switch (ck) {
+ case CK_LValueToRValue: {
+ return Visit(op);
+ }
+ default:
+ cgf.cgm.errorNYI("ComplexType Cast");
+ break;
+ }
+
+ return {};
+}
+
+mlir::Value ComplexExprEmitter::emitConstant(
+ const CIRGenFunction::ConstantEmission &constant, Expr *e) {
+ assert(constant && "not a constant");
+ if (constant.isReference())
+ return emitLoadOfLValue(constant.getReferenceLValue(cgf, e),
+ e->getExprLoc());
+
+ mlir::TypedAttr valueAttr = constant.getValue();
+ return builder.getConstant(cgf.getLoc(e->getSourceRange()), valueAttr);
+}
+
mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
SourceLocation loc) {
assert(lv.isSimple() && "non-simple complex l-value?");
@@ -70,6 +119,22 @@ void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
builder.createStore(loc, val, destAddr);
}
+mlir::Value ComplexExprEmitter::VisitBinAssign(const BinaryOperator *e) {
+ mlir::Value value;
+ LValue lv = emitBinAssignLValue(e, value);
+
+ // The result of an assignment in C is the assigned r-value.
+ if (!cgf.getLangOpts().CPlusPlus)
+ return value;
+
+ // If the lvalue is non-volatile, return the computed value of the
+ // assignment.
+ if (!lv.isVolatile())
+ return value;
+
+ return emitLoadOfLValue(lv, e->getExprLoc());
+}
+
mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
if (e->getCallReturnType(cgf.getContext())->isReferenceType())
return emitLoadOfLValue(e);
@@ -77,7 +142,21 @@ mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
return cgf.emitCallExpr(e).getValue();
}
-mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) {
+mlir::Value ComplexExprEmitter::VisitDeclRefExpr(DeclRefExpr *e) {
+ if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
+ return emitConstant(constant, e);
+ return emitLoadOfLValue(e);
+}
+
+mlir::Value ComplexExprEmitter::VisitImplicitCastExpr(ImplicitCastExpr *e) {
+ // Unlike for scalars, we don't have to worry about function->ptr demotion
+ // here.
+ if (e->changesVolatileQualification())
+ return emitLoadOfLValue(e);
+ return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());
+}
+
+mlir::Value ComplexExprEmitter::VisitInitListExpr(const InitListExpr *e) {
mlir::Location loc = cgf.getLoc(e->getExprLoc());
if (e->getNumInits() == 2) {
mlir::Value real = cgf.emitScalarExpr(e->getInit(0));
@@ -127,6 +206,17 @@ ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) {
return builder.create<cir::ConstantOp>(loc, complexAttr);
}
+LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) {
+ assert(e->getOpcode() == BO_Assign && "Expected assign op");
+
+ mlir::Value value; // ignored
+ LValue lvalue = ComplexExprEmitter(*this).emitBinAssignLValue(e, value);
+ if (getLangOpts().OpenMP)
+ cgm.errorNYI("emitComplexAssignmentLValue OpenMP");
+
+ return lvalue;
+}
+
mlir::Value CIRGenFunction::emitComplexExpr(const Expr *e) {
assert(e && getComplexType(e->getType()) &&
"Invalid complex expression to emit");
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 6c490a72b2e93..82aa7ec9cb220 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -870,6 +870,8 @@ class CIRGenFunction : public CIRGenTypeCache {
/// returning the result.
mlir::Value emitComplexExpr(const Expr *e);
+ LValue emitComplexAssignmentLValue(const BinaryOperator *e);
+
void emitCompoundStmt(const clang::CompoundStmt &s);
void emitCompoundStmtWithoutScope(const clang::CompoundStmt &s);
diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h b/clang/lib/CIR/CodeGen/CIRGenValue.h
index 7180d92f8c314..a5a457ddafa9c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenValue.h
+++ b/clang/lib/CIR/CodeGen/CIRGenValue.h
@@ -182,9 +182,7 @@ class LValue {
bool isSimple() const { return lvType == Simple; }
bool isVectorElt() const { return lvType == VectorElt; }
bool isBitField() const { return lvType == BitField; }
-
- // TODO: Add support for volatile
- bool isVolatile() const { return false; }
+ bool isVolatile() const { return quals.hasVolatile(); }
unsigned getVRQualifiers() const {
return quals.getCVRQualifiers() & ~clang::Qualifiers::Const;
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index 721db235b37de..cfeed345b4f11 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -230,3 +230,29 @@ void foo14() {
// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 1
// OGCG: store i32 0, ptr %[[C_REAL_PTR]], align 4
// OGCG: store i32 2, ptr %[[C_IMAG_PTR]], align 4
+
+void foo15() {
+ int _Complex a;
+ int _Complex b = a;
+}
+
+// CIR: %[[COMPLEX_A:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a"]
+// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init]
+// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[COMPLEX_A]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR: cir.store{{.*}} %[[TMP_A]], %[[COMPLEX_B]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
+
+// LLVM: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[TMP_A:.*]] = load { i32, i32 }, ptr %[[COMPLEX_A]], align 4
+// LLVM: store { i32, i32 } %[[TMP_A]], ptr %[[COMPLEX_B]], align 4
+
+// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 0
+// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 1
+// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 0
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1
+// OGCG: store i32 %[[A_REAL]], ptr %[[B_REAL_PTR]], align 4
+// OGCG: store i32 %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 4
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm with one nit
mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op, | ||
QualType destTy) { | ||
switch (ck) { | ||
case CK_LValueToRValue: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Braces aren't needed here.
This change adds support for the BinAssign op and LValueToRValue for ComplexType llvm#141365
This change adds support for the BinAssign op and LValueToRValue for ComplexType
#141365