-
Notifications
You must be signed in to change notification settings - Fork 15k
[CIR][NFC] Reorder GenExprComplex and add errors for unhandled visitors #156241
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][NFC] Reorder GenExprComplex and add errors for unhandled visitors #156241
Conversation
@llvm/pr-subscribers-clangir Author: Amr Hesham (AmrDeveloper) Changes
Issue: #141365 Patch is 47.74 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/156241.diff 2 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index cbdd525068f5d..36ea5d08c2948 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -6,6 +6,16 @@
using namespace clang;
using namespace clang::CIRGen;
+#ifndef NDEBUG
+/// Return the complex type that we are meant to emit.
+static const ComplexType *getComplexType(QualType type) {
+ type = type.getCanonicalType();
+ if (const ComplexType *comp = dyn_cast<ComplexType>(type))
+ return comp;
+ return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
+}
+#endif // NDEBUG
+
namespace {
class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
CIRGenFunction &cgf;
@@ -19,13 +29,6 @@ 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.
@@ -48,20 +51,75 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
mlir::Value emitScalarToComplexCast(mlir::Value value, QualType srcType,
QualType destType, SourceLocation loc);
+ //===--------------------------------------------------------------------===//
+ // Visitor Methods
+ //===--------------------------------------------------------------------===//
+
+ mlir::Value Visit(Expr *e) {
+ return StmtVisitor<ComplexExprEmitter, mlir::Value>::Visit(e);
+ }
+
+ mlir::Value VisitStmt(Stmt *s) {
+ cgf.cgm.errorNYI(s->getBeginLoc(), "ComplexExprEmitter VisitStmt");
+ return {};
+ }
+
+ mlir::Value VisitExpr(Expr *e);
+ mlir::Value VisitConstantExpr(ConstantExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitConstantExpr");
+ return {};
+ }
+
+ mlir::Value VisitParenExpr(ParenExpr *pe) { return Visit(pe->getSubExpr()); }
+ mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
+ return Visit(ge->getResultExpr());
+ }
+ mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
mlir::Value
- VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
- mlir::Value VisitArraySubscriptExpr(Expr *e);
- mlir::Value VisitBinAssign(const BinaryOperator *e);
- mlir::Value VisitBinComma(const BinaryOperator *e);
- mlir::Value VisitCallExpr(const CallExpr *e);
- mlir::Value VisitCastExpr(CastExpr *e);
- mlir::Value VisitChooseExpr(ChooseExpr *e);
- mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e);
- mlir::Value VisitDeclRefExpr(DeclRefExpr *e);
- mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *e);
- mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
- mlir::Value VisitInitListExpr(InitListExpr *e);
+ VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe) {
+ return Visit(pe->getReplacement());
+ }
+ mlir::Value VisitCoawaitExpr(CoawaitExpr *s) {
+ cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoawaitExpr");
+ return {};
+ }
+ mlir::Value VisitCoyieldExpr(CoyieldExpr *s) {
+ cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoyieldExpr");
+ return {};
+ }
+ mlir::Value VisitUnaryCoawait(const UnaryOperator *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitUnaryCoawait");
+ return {};
+ }
+
+ mlir::Value 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);
+ }
+ // l-values.
+ mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
+ if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
+ return emitConstant(constant, e);
+ return emitLoadOfLValue(e);
+ }
+ mlir::Value VisitObjCIvarRefExpr(ObjCIvarRefExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitObjCIvarRefExpr");
+ return {};
+ }
+ mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitObjCMessageExpr");
+ return {};
+ }
+ mlir::Value VisitArraySubscriptExpr(Expr *e) { return emitLoadOfLValue(e); }
mlir::Value VisitMemberExpr(MemberExpr *me) {
if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(me)) {
cgf.emitIgnoredExpr(me->getBase());
@@ -69,45 +127,99 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
}
return emitLoadOfLValue(me);
}
+ mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitOpaqueValueExpr");
+ return {};
+ }
- mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
- return emitLoadOfLValue(e);
+ mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitPseudoObjectExpr");
+ return {};
}
- mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
- mlir::Value VisitParenExpr(ParenExpr *e);
- mlir::Value
- VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e);
+ mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy);
+ mlir::Value 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 VisitCastExpr(CastExpr *e) {
+ if (const auto *ece = dyn_cast<ExplicitCastExpr>(e)) {
+ // Bind VLAs in the cast type.
+ if (ece->getType()->isVariablyModifiedType()) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "VisitCastExpr Bind VLAs in the cast type");
+ return {};
+ }
+ }
- mlir::Value VisitPrePostIncDec(const UnaryOperator *e, cir::UnaryOpKind op,
- bool isPre);
+ if (e->changesVolatileQualification())
+ return emitLoadOfLValue(e);
+
+ return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());
+ }
+ mlir::Value VisitCallExpr(const CallExpr *e);
+ mlir::Value VisitStmtExpr(const StmtExpr *e);
+ // Operators.
+ mlir::Value VisitPrePostIncDec(const UnaryOperator *e, cir::UnaryOpKind op,
+ bool isPre) {
+ LValue lv = cgf.emitLValue(e->getSubExpr());
+ return cgf.emitComplexPrePostIncDec(e, lv, op, isPre);
+ }
mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {
return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, false);
}
-
mlir::Value VisitUnaryPostInc(const UnaryOperator *e) {
return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, false);
}
-
mlir::Value VisitUnaryPreDec(const UnaryOperator *e) {
return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, true);
}
-
mlir::Value VisitUnaryPreInc(const UnaryOperator *e) {
return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, true);
}
-
- mlir::Value VisitUnaryDeref(const Expr *e);
+ mlir::Value VisitUnaryDeref(const Expr *e) { return emitLoadOfLValue(e); }
mlir::Value VisitUnaryPlus(const UnaryOperator *e);
-
+ mlir::Value VisitUnaryMinus(const UnaryOperator *e);
mlir::Value VisitPlusMinus(const UnaryOperator *e, cir::UnaryOpKind kind,
QualType promotionType);
-
- mlir::Value VisitUnaryMinus(const UnaryOperator *e);
-
mlir::Value VisitUnaryNot(const UnaryOperator *e);
+ // LNot,Real,Imag never return complex.
+ mlir::Value VisitUnaryExtension(const UnaryOperator *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitUnaryExtension");
+ return {};
+ }
+ mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
+ cgf.cgm.errorNYI(dae->getExprLoc(),
+ "ComplexExprEmitter VisitCXXDefaultArgExpr");
+ return {};
+ }
+ mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
+ cgf.cgm.errorNYI(die->getExprLoc(),
+ "ComplexExprEmitter VisitCXXDefaultInitExpr");
+ return {};
+ }
+ mlir::Value VisitExprWithCleanups(ExprWithCleanups *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitExprWithCleanups");
+ return {};
+ }
+ mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {
+ mlir::Location loc = cgf.getLoc(e->getExprLoc());
+ mlir::Type complexTy = cgf.convertType(e->getType());
+ return builder.getNullValue(complexTy, loc);
+ }
+ mlir::Value VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitImplicitValueInitExpr");
+ return {};
+ }
struct BinOpInfo {
mlir::Location loc;
@@ -121,14 +233,11 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
QualType promotionTy = QualType());
mlir::Value emitPromoted(const Expr *e, QualType promotionTy);
-
mlir::Value emitPromotedComplexOperand(const Expr *e, QualType promotionTy);
-
LValue emitCompoundAssignLValue(
const CompoundAssignOperator *e,
mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &),
RValue &value);
-
mlir::Value emitCompoundAssign(
const CompoundAssignOperator *e,
mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &));
@@ -166,52 +275,179 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
HANDLEBINOP(Div)
#undef HANDLEBINOP
+ mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitCXXRewrittenBinaryOperator");
+ return {};
+ }
+
// Compound assignments.
mlir::Value VisitBinAddAssign(const CompoundAssignOperator *e) {
return emitCompoundAssign(e, &ComplexExprEmitter::emitBinAdd);
}
-
mlir::Value VisitBinSubAssign(const CompoundAssignOperator *e) {
return emitCompoundAssign(e, &ComplexExprEmitter::emitBinSub);
}
-
mlir::Value VisitBinMulAssign(const CompoundAssignOperator *e) {
return emitCompoundAssign(e, &ComplexExprEmitter::emitBinMul);
}
-
mlir::Value VisitBinDivAssign(const CompoundAssignOperator *e) {
return emitCompoundAssign(e, &ComplexExprEmitter::emitBinDiv);
}
+ // GCC rejects rem/and/or/xor for integer complex.
+ // Logical and/or always return int, never complex.
+
+ // No comparisons produce a complex result.
+
+ LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val);
+ mlir::Value VisitBinAssign(const BinaryOperator *e);
+ mlir::Value VisitBinComma(const BinaryOperator *e);
+
+ mlir::Value
+ VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
+ mlir::Value VisitChooseExpr(ChooseExpr *e);
+
+ mlir::Value VisitInitListExpr(InitListExpr *e);
+
+ mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
+ return emitLoadOfLValue(e);
+ }
+
mlir::Value VisitVAArgExpr(VAArgExpr *e);
+
+ mlir::Value VisitAtomicExpr(AtomicExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitAtomicExpr");
+ return {};
+ }
+
+ mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitPackIndexingExpr");
+ return {};
+ }
};
} // namespace
-#ifndef NDEBUG
-// Only used in asserts
-static const ComplexType *getComplexType(QualType type) {
- type = type.getCanonicalType();
- if (const ComplexType *comp = dyn_cast<ComplexType>(type))
- return comp;
- return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
+//===----------------------------------------------------------------------===//
+// Utilities
+//===----------------------------------------------------------------------===//
+
+/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to
+/// load the real and imaginary pieces, returning them as Real/Imag.
+mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
+ SourceLocation loc) {
+ assert(lv.isSimple() && "non-simple complex l-value?");
+ if (lv.getType()->isAtomicType())
+ cgf.cgm.errorNYI(loc, "emitLoadOfLValue with Atomic LV");
+
+ const Address srcAddr = lv.getAddress();
+ return builder.createLoad(cgf.getLoc(loc), srcAddr);
}
-#endif // NDEBUG
-LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
- mlir::Value &value) {
- assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
- e->getRHS()->getType()) &&
- "Invalid assignment");
+/// EmitStoreOfComplex - Store the specified real/imag parts into the
+/// specified value pointer.
+void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
+ LValue lv, bool isInit) {
+ if (lv.getType()->isAtomicType() ||
+ (!isInit && cgf.isLValueSuitableForInlineAtomic(lv))) {
+ cgf.cgm.errorNYI(loc, "StoreOfComplex with Atomic LV");
+ return;
+ }
- // Emit the RHS. __block variables need the RHS evaluated first.
- value = Visit(e->getRHS());
+ const Address destAddr = lv.getAddress();
+ builder.createStore(loc, val, destAddr);
+}
- // Compute the address to store into.
- LValue lhs = cgf.emitLValue(e->getLHS());
+//===----------------------------------------------------------------------===//
+// Visitor Methods
+//===----------------------------------------------------------------------===//
- // Store the result value into the LHS lvalue.
- emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs, /*isInit*/ false);
- return lhs;
+mlir::Value ComplexExprEmitter::VisitExpr(Expr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitExpr");
+ return {};
+}
+
+mlir::Value
+ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) {
+ auto ty = mlir::cast<cir::ComplexType>(cgf.convertType(il->getType()));
+ mlir::Type elementTy = ty.getElementType();
+ mlir::Location loc = cgf.getLoc(il->getExprLoc());
+
+ mlir::TypedAttr realValueAttr;
+ mlir::TypedAttr imagValueAttr;
+
+ if (mlir::isa<cir::IntType>(elementTy)) {
+ llvm::APInt imagValue = cast<IntegerLiteral>(il->getSubExpr())->getValue();
+ realValueAttr = cir::IntAttr::get(elementTy, 0);
+ imagValueAttr = cir::IntAttr::get(elementTy, imagValue);
+ } else {
+ assert(mlir::isa<cir::FPTypeInterface>(elementTy) &&
+ "Expected complex element type to be floating-point");
+
+ llvm::APFloat imagValue =
+ cast<FloatingLiteral>(il->getSubExpr())->getValue();
+ realValueAttr = cir::FPAttr::get(
+ elementTy, llvm::APFloat::getZero(imagValue.getSemantics()));
+ imagValueAttr = cir::FPAttr::get(elementTy, imagValue);
+ }
+
+ auto complexAttr = cir::ConstComplexAttr::get(realValueAttr, imagValueAttr);
+ return builder.create<cir::ConstantOp>(loc, complexAttr);
+}
+
+mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
+ if (e->getCallReturnType(cgf.getContext())->isReferenceType())
+ return emitLoadOfLValue(e);
+ return cgf.emitCallExpr(e).getComplexValue();
+}
+
+mlir::Value ComplexExprEmitter::VisitStmtExpr(const StmtExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitExpr");
+ return {};
+}
+
+mlir::Value ComplexExprEmitter::emitComplexToComplexCast(mlir::Value val,
+ QualType srcType,
+ QualType destType,
+ SourceLocation loc) {
+ if (srcType == destType)
+ return val;
+
+ // Get the src/dest element type.
+ QualType srcElemTy = srcType->castAs<ComplexType>()->getElementType();
+ QualType destElemTy = destType->castAs<ComplexType>()->getElementType();
+
+ cir::CastKind castOpKind;
+ if (srcElemTy->isFloatingType() && destElemTy->isFloatingType())
+ castOpKind = cir::CastKind::float_complex;
+ else if (srcElemTy->isFloatingType() && destElemTy->isIntegerType())
+ castOpKind = cir::CastKind::float_complex_to_int_complex;
+ else if (srcElemTy->isIntegerType() && destElemTy->isFloatingType())
+ castOpKind = cir::CastKind::int_complex_to_float_complex;
+ else if (srcElemTy->isIntegerType() && destElemTy->isIntegerType())
+ castOpKind = cir::CastKind::int_complex;
+ else
+ llvm_unreachable("unexpected src type or dest type");
+
+ return builder.createCast(cgf.getLoc(loc), castOpKind, val,
+ cgf.convertType(destType));
+}
+
+mlir::Value ComplexExprEmitter::emitScalarToComplexCast(mlir::Value val,
+ QualType srcType,
+ QualType destType,
+ SourceLocation loc) {
+ cir::CastKind castOpKind;
+ if (srcType->isFloatingType())
+ castOpKind = cir::CastKind::float_to_complex;
+ else if (srcType->isIntegerType())
+ castOpKind = cir::CastKind::int_to_complex;
+ else
+ llvm_unreachable("unexpected src type");
+
+ return builder.createCast(cgf.getLoc(loc), castOpKind, val,
+ cgf.convertType(destType));
}
mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
@@ -334,6 +570,14 @@ mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e) {
return result;
}
+mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) {
+ QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
+ mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy);
+ if (!promotionTy.isNull())
+ return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType());
+ return result;
+}
+
mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e,
cir::UnaryOpKind kind,
QualType promotionType) {
@@ -349,258 +593,149 @@ mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e,
return builder.createUnaryOp(cgf.getLoc(e->getExprLoc()), kind, op);
}
-mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) {
- QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
- mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy);
- if (!promotionTy.isNull())
- return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType());
- return result;
+mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) {
+ mlir::Value op = Visit(e->getSubExpr());
+ return builder.createNot(op);
}
-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::emitBinAdd(const BinOpInfo &op) {
+ assert(!cir::MissingFeatures::fastMathFlags());
+ assert(!cir::MissingFeatures::cgFPOptionsRAII());
-mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
- ...
[truncated]
|
@llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) Changes
Issue: #141365 Patch is 47.74 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/156241.diff 2 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index cbdd525068f5d..36ea5d08c2948 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -6,6 +6,16 @@
using namespace clang;
using namespace clang::CIRGen;
+#ifndef NDEBUG
+/// Return the complex type that we are meant to emit.
+static const ComplexType *getComplexType(QualType type) {
+ type = type.getCanonicalType();
+ if (const ComplexType *comp = dyn_cast<ComplexType>(type))
+ return comp;
+ return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
+}
+#endif // NDEBUG
+
namespace {
class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
CIRGenFunction &cgf;
@@ -19,13 +29,6 @@ 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.
@@ -48,20 +51,75 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
mlir::Value emitScalarToComplexCast(mlir::Value value, QualType srcType,
QualType destType, SourceLocation loc);
+ //===--------------------------------------------------------------------===//
+ // Visitor Methods
+ //===--------------------------------------------------------------------===//
+
+ mlir::Value Visit(Expr *e) {
+ return StmtVisitor<ComplexExprEmitter, mlir::Value>::Visit(e);
+ }
+
+ mlir::Value VisitStmt(Stmt *s) {
+ cgf.cgm.errorNYI(s->getBeginLoc(), "ComplexExprEmitter VisitStmt");
+ return {};
+ }
+
+ mlir::Value VisitExpr(Expr *e);
+ mlir::Value VisitConstantExpr(ConstantExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitConstantExpr");
+ return {};
+ }
+
+ mlir::Value VisitParenExpr(ParenExpr *pe) { return Visit(pe->getSubExpr()); }
+ mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
+ return Visit(ge->getResultExpr());
+ }
+ mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
mlir::Value
- VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
- mlir::Value VisitArraySubscriptExpr(Expr *e);
- mlir::Value VisitBinAssign(const BinaryOperator *e);
- mlir::Value VisitBinComma(const BinaryOperator *e);
- mlir::Value VisitCallExpr(const CallExpr *e);
- mlir::Value VisitCastExpr(CastExpr *e);
- mlir::Value VisitChooseExpr(ChooseExpr *e);
- mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e);
- mlir::Value VisitDeclRefExpr(DeclRefExpr *e);
- mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *e);
- mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
- mlir::Value VisitInitListExpr(InitListExpr *e);
+ VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe) {
+ return Visit(pe->getReplacement());
+ }
+ mlir::Value VisitCoawaitExpr(CoawaitExpr *s) {
+ cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoawaitExpr");
+ return {};
+ }
+ mlir::Value VisitCoyieldExpr(CoyieldExpr *s) {
+ cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoyieldExpr");
+ return {};
+ }
+ mlir::Value VisitUnaryCoawait(const UnaryOperator *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitUnaryCoawait");
+ return {};
+ }
+
+ mlir::Value 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);
+ }
+ // l-values.
+ mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
+ if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
+ return emitConstant(constant, e);
+ return emitLoadOfLValue(e);
+ }
+ mlir::Value VisitObjCIvarRefExpr(ObjCIvarRefExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitObjCIvarRefExpr");
+ return {};
+ }
+ mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitObjCMessageExpr");
+ return {};
+ }
+ mlir::Value VisitArraySubscriptExpr(Expr *e) { return emitLoadOfLValue(e); }
mlir::Value VisitMemberExpr(MemberExpr *me) {
if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(me)) {
cgf.emitIgnoredExpr(me->getBase());
@@ -69,45 +127,99 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
}
return emitLoadOfLValue(me);
}
+ mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitOpaqueValueExpr");
+ return {};
+ }
- mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
- return emitLoadOfLValue(e);
+ mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitPseudoObjectExpr");
+ return {};
}
- mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
- mlir::Value VisitParenExpr(ParenExpr *e);
- mlir::Value
- VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e);
+ mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy);
+ mlir::Value 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 VisitCastExpr(CastExpr *e) {
+ if (const auto *ece = dyn_cast<ExplicitCastExpr>(e)) {
+ // Bind VLAs in the cast type.
+ if (ece->getType()->isVariablyModifiedType()) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "VisitCastExpr Bind VLAs in the cast type");
+ return {};
+ }
+ }
- mlir::Value VisitPrePostIncDec(const UnaryOperator *e, cir::UnaryOpKind op,
- bool isPre);
+ if (e->changesVolatileQualification())
+ return emitLoadOfLValue(e);
+
+ return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());
+ }
+ mlir::Value VisitCallExpr(const CallExpr *e);
+ mlir::Value VisitStmtExpr(const StmtExpr *e);
+ // Operators.
+ mlir::Value VisitPrePostIncDec(const UnaryOperator *e, cir::UnaryOpKind op,
+ bool isPre) {
+ LValue lv = cgf.emitLValue(e->getSubExpr());
+ return cgf.emitComplexPrePostIncDec(e, lv, op, isPre);
+ }
mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {
return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, false);
}
-
mlir::Value VisitUnaryPostInc(const UnaryOperator *e) {
return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, false);
}
-
mlir::Value VisitUnaryPreDec(const UnaryOperator *e) {
return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, true);
}
-
mlir::Value VisitUnaryPreInc(const UnaryOperator *e) {
return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, true);
}
-
- mlir::Value VisitUnaryDeref(const Expr *e);
+ mlir::Value VisitUnaryDeref(const Expr *e) { return emitLoadOfLValue(e); }
mlir::Value VisitUnaryPlus(const UnaryOperator *e);
-
+ mlir::Value VisitUnaryMinus(const UnaryOperator *e);
mlir::Value VisitPlusMinus(const UnaryOperator *e, cir::UnaryOpKind kind,
QualType promotionType);
-
- mlir::Value VisitUnaryMinus(const UnaryOperator *e);
-
mlir::Value VisitUnaryNot(const UnaryOperator *e);
+ // LNot,Real,Imag never return complex.
+ mlir::Value VisitUnaryExtension(const UnaryOperator *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitUnaryExtension");
+ return {};
+ }
+ mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
+ cgf.cgm.errorNYI(dae->getExprLoc(),
+ "ComplexExprEmitter VisitCXXDefaultArgExpr");
+ return {};
+ }
+ mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
+ cgf.cgm.errorNYI(die->getExprLoc(),
+ "ComplexExprEmitter VisitCXXDefaultInitExpr");
+ return {};
+ }
+ mlir::Value VisitExprWithCleanups(ExprWithCleanups *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitExprWithCleanups");
+ return {};
+ }
+ mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {
+ mlir::Location loc = cgf.getLoc(e->getExprLoc());
+ mlir::Type complexTy = cgf.convertType(e->getType());
+ return builder.getNullValue(complexTy, loc);
+ }
+ mlir::Value VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitImplicitValueInitExpr");
+ return {};
+ }
struct BinOpInfo {
mlir::Location loc;
@@ -121,14 +233,11 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
QualType promotionTy = QualType());
mlir::Value emitPromoted(const Expr *e, QualType promotionTy);
-
mlir::Value emitPromotedComplexOperand(const Expr *e, QualType promotionTy);
-
LValue emitCompoundAssignLValue(
const CompoundAssignOperator *e,
mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &),
RValue &value);
-
mlir::Value emitCompoundAssign(
const CompoundAssignOperator *e,
mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &));
@@ -166,52 +275,179 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
HANDLEBINOP(Div)
#undef HANDLEBINOP
+ mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitCXXRewrittenBinaryOperator");
+ return {};
+ }
+
// Compound assignments.
mlir::Value VisitBinAddAssign(const CompoundAssignOperator *e) {
return emitCompoundAssign(e, &ComplexExprEmitter::emitBinAdd);
}
-
mlir::Value VisitBinSubAssign(const CompoundAssignOperator *e) {
return emitCompoundAssign(e, &ComplexExprEmitter::emitBinSub);
}
-
mlir::Value VisitBinMulAssign(const CompoundAssignOperator *e) {
return emitCompoundAssign(e, &ComplexExprEmitter::emitBinMul);
}
-
mlir::Value VisitBinDivAssign(const CompoundAssignOperator *e) {
return emitCompoundAssign(e, &ComplexExprEmitter::emitBinDiv);
}
+ // GCC rejects rem/and/or/xor for integer complex.
+ // Logical and/or always return int, never complex.
+
+ // No comparisons produce a complex result.
+
+ LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val);
+ mlir::Value VisitBinAssign(const BinaryOperator *e);
+ mlir::Value VisitBinComma(const BinaryOperator *e);
+
+ mlir::Value
+ VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
+ mlir::Value VisitChooseExpr(ChooseExpr *e);
+
+ mlir::Value VisitInitListExpr(InitListExpr *e);
+
+ mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
+ return emitLoadOfLValue(e);
+ }
+
mlir::Value VisitVAArgExpr(VAArgExpr *e);
+
+ mlir::Value VisitAtomicExpr(AtomicExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitAtomicExpr");
+ return {};
+ }
+
+ mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(),
+ "ComplexExprEmitter VisitPackIndexingExpr");
+ return {};
+ }
};
} // namespace
-#ifndef NDEBUG
-// Only used in asserts
-static const ComplexType *getComplexType(QualType type) {
- type = type.getCanonicalType();
- if (const ComplexType *comp = dyn_cast<ComplexType>(type))
- return comp;
- return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
+//===----------------------------------------------------------------------===//
+// Utilities
+//===----------------------------------------------------------------------===//
+
+/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to
+/// load the real and imaginary pieces, returning them as Real/Imag.
+mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
+ SourceLocation loc) {
+ assert(lv.isSimple() && "non-simple complex l-value?");
+ if (lv.getType()->isAtomicType())
+ cgf.cgm.errorNYI(loc, "emitLoadOfLValue with Atomic LV");
+
+ const Address srcAddr = lv.getAddress();
+ return builder.createLoad(cgf.getLoc(loc), srcAddr);
}
-#endif // NDEBUG
-LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
- mlir::Value &value) {
- assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
- e->getRHS()->getType()) &&
- "Invalid assignment");
+/// EmitStoreOfComplex - Store the specified real/imag parts into the
+/// specified value pointer.
+void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
+ LValue lv, bool isInit) {
+ if (lv.getType()->isAtomicType() ||
+ (!isInit && cgf.isLValueSuitableForInlineAtomic(lv))) {
+ cgf.cgm.errorNYI(loc, "StoreOfComplex with Atomic LV");
+ return;
+ }
- // Emit the RHS. __block variables need the RHS evaluated first.
- value = Visit(e->getRHS());
+ const Address destAddr = lv.getAddress();
+ builder.createStore(loc, val, destAddr);
+}
- // Compute the address to store into.
- LValue lhs = cgf.emitLValue(e->getLHS());
+//===----------------------------------------------------------------------===//
+// Visitor Methods
+//===----------------------------------------------------------------------===//
- // Store the result value into the LHS lvalue.
- emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs, /*isInit*/ false);
- return lhs;
+mlir::Value ComplexExprEmitter::VisitExpr(Expr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitExpr");
+ return {};
+}
+
+mlir::Value
+ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) {
+ auto ty = mlir::cast<cir::ComplexType>(cgf.convertType(il->getType()));
+ mlir::Type elementTy = ty.getElementType();
+ mlir::Location loc = cgf.getLoc(il->getExprLoc());
+
+ mlir::TypedAttr realValueAttr;
+ mlir::TypedAttr imagValueAttr;
+
+ if (mlir::isa<cir::IntType>(elementTy)) {
+ llvm::APInt imagValue = cast<IntegerLiteral>(il->getSubExpr())->getValue();
+ realValueAttr = cir::IntAttr::get(elementTy, 0);
+ imagValueAttr = cir::IntAttr::get(elementTy, imagValue);
+ } else {
+ assert(mlir::isa<cir::FPTypeInterface>(elementTy) &&
+ "Expected complex element type to be floating-point");
+
+ llvm::APFloat imagValue =
+ cast<FloatingLiteral>(il->getSubExpr())->getValue();
+ realValueAttr = cir::FPAttr::get(
+ elementTy, llvm::APFloat::getZero(imagValue.getSemantics()));
+ imagValueAttr = cir::FPAttr::get(elementTy, imagValue);
+ }
+
+ auto complexAttr = cir::ConstComplexAttr::get(realValueAttr, imagValueAttr);
+ return builder.create<cir::ConstantOp>(loc, complexAttr);
+}
+
+mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
+ if (e->getCallReturnType(cgf.getContext())->isReferenceType())
+ return emitLoadOfLValue(e);
+ return cgf.emitCallExpr(e).getComplexValue();
+}
+
+mlir::Value ComplexExprEmitter::VisitStmtExpr(const StmtExpr *e) {
+ cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitExpr");
+ return {};
+}
+
+mlir::Value ComplexExprEmitter::emitComplexToComplexCast(mlir::Value val,
+ QualType srcType,
+ QualType destType,
+ SourceLocation loc) {
+ if (srcType == destType)
+ return val;
+
+ // Get the src/dest element type.
+ QualType srcElemTy = srcType->castAs<ComplexType>()->getElementType();
+ QualType destElemTy = destType->castAs<ComplexType>()->getElementType();
+
+ cir::CastKind castOpKind;
+ if (srcElemTy->isFloatingType() && destElemTy->isFloatingType())
+ castOpKind = cir::CastKind::float_complex;
+ else if (srcElemTy->isFloatingType() && destElemTy->isIntegerType())
+ castOpKind = cir::CastKind::float_complex_to_int_complex;
+ else if (srcElemTy->isIntegerType() && destElemTy->isFloatingType())
+ castOpKind = cir::CastKind::int_complex_to_float_complex;
+ else if (srcElemTy->isIntegerType() && destElemTy->isIntegerType())
+ castOpKind = cir::CastKind::int_complex;
+ else
+ llvm_unreachable("unexpected src type or dest type");
+
+ return builder.createCast(cgf.getLoc(loc), castOpKind, val,
+ cgf.convertType(destType));
+}
+
+mlir::Value ComplexExprEmitter::emitScalarToComplexCast(mlir::Value val,
+ QualType srcType,
+ QualType destType,
+ SourceLocation loc) {
+ cir::CastKind castOpKind;
+ if (srcType->isFloatingType())
+ castOpKind = cir::CastKind::float_to_complex;
+ else if (srcType->isIntegerType())
+ castOpKind = cir::CastKind::int_to_complex;
+ else
+ llvm_unreachable("unexpected src type");
+
+ return builder.createCast(cgf.getLoc(loc), castOpKind, val,
+ cgf.convertType(destType));
}
mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
@@ -334,6 +570,14 @@ mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e) {
return result;
}
+mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) {
+ QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
+ mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy);
+ if (!promotionTy.isNull())
+ return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType());
+ return result;
+}
+
mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e,
cir::UnaryOpKind kind,
QualType promotionType) {
@@ -349,258 +593,149 @@ mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e,
return builder.createUnaryOp(cgf.getLoc(e->getExprLoc()), kind, op);
}
-mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) {
- QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
- mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy);
- if (!promotionTy.isNull())
- return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType());
- return result;
+mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) {
+ mlir::Value op = Visit(e->getSubExpr());
+ return builder.createNot(op);
}
-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::emitBinAdd(const BinOpInfo &op) {
+ assert(!cir::MissingFeatures::fastMathFlags());
+ assert(!cir::MissingFeatures::cgFPOptionsRAII());
-mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
- ...
[truncated]
|
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. Thanks for handling this!
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
complex-mul-div
.Issue: #141365