aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp257
1 files changed, 244 insertions, 13 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 6756a7c..3aa170e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -34,11 +34,20 @@ public:
}
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);
+ /// Emit a cast from complex value Val to DestType.
+ mlir::Value emitComplexToComplexCast(mlir::Value value, QualType srcType,
+ QualType destType, SourceLocation loc);
+
+ /// Emit a cast from scalar value Val to DestType.
+ mlir::Value emitScalarToComplexCast(mlir::Value value, QualType srcType,
+ QualType destType, SourceLocation loc);
+
mlir::Value
VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
mlir::Value VisitArraySubscriptExpr(Expr *e);
@@ -51,7 +60,7 @@ public:
mlir::Value VisitDeclRefExpr(DeclRefExpr *e);
mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *e);
mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
- mlir::Value VisitInitListExpr(const InitListExpr *e);
+ mlir::Value VisitInitListExpr(InitListExpr *e);
mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
return emitLoadOfLValue(e);
@@ -82,6 +91,14 @@ public:
}
mlir::Value VisitUnaryDeref(const Expr *e);
+
+ mlir::Value VisitUnaryPlus(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);
struct BinOpInfo {
@@ -101,6 +118,7 @@ public:
mlir::Value emitBinAdd(const BinOpInfo &op);
mlir::Value emitBinSub(const BinOpInfo &op);
+ mlir::Value emitBinMul(const BinOpInfo &op);
QualType getPromotionType(QualType ty, bool isDivOpCode = false) {
if (auto *complexTy = ty->getAs<ComplexType>()) {
@@ -133,16 +151,20 @@ public:
HANDLEBINOP(Add)
HANDLEBINOP(Sub)
+ HANDLEBINOP(Mul)
#undef HANDLEBINOP
};
} // 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());
}
+#endif // NDEBUG
LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
mlir::Value &value) {
@@ -164,14 +186,148 @@ LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
QualType destTy) {
switch (ck) {
+ case CK_Dependent:
+ llvm_unreachable("dependent type must be resolved before the CIR codegen");
+
case CK_NoOp:
case CK_LValueToRValue:
return Visit(op);
- default:
- break;
+
+ case CK_AtomicToNonAtomic:
+ case CK_NonAtomicToAtomic:
+ case CK_UserDefinedConversion: {
+ cgf.cgm.errorNYI(
+ "ComplexExprEmitter::emitCast Atmoic & UserDefinedConversion");
+ return {};
}
- cgf.cgm.errorNYI("ComplexType Cast");
- return {};
+
+ case CK_LValueBitCast: {
+ LValue origLV = cgf.emitLValue(op);
+ Address addr =
+ origLV.getAddress().withElementType(builder, cgf.convertType(destTy));
+ LValue destLV = cgf.makeAddrLValue(addr, destTy);
+ return emitLoadOfLValue(destLV, op->getExprLoc());
+ }
+
+ case CK_LValueToRValueBitCast: {
+ LValue sourceLVal = cgf.emitLValue(op);
+ Address addr = sourceLVal.getAddress().withElementType(
+ builder, cgf.convertTypeForMem(destTy));
+ LValue destLV = cgf.makeAddrLValue(addr, destTy);
+ assert(!cir::MissingFeatures::opTBAA());
+ return emitLoadOfLValue(destLV, op->getExprLoc());
+ }
+
+ case CK_BitCast:
+ case CK_BaseToDerived:
+ case CK_DerivedToBase:
+ case CK_UncheckedDerivedToBase:
+ case CK_Dynamic:
+ case CK_ToUnion:
+ case CK_ArrayToPointerDecay:
+ case CK_FunctionToPointerDecay:
+ case CK_NullToPointer:
+ case CK_NullToMemberPointer:
+ case CK_BaseToDerivedMemberPointer:
+ case CK_DerivedToBaseMemberPointer:
+ case CK_MemberPointerToBoolean:
+ case CK_ReinterpretMemberPointer:
+ case CK_ConstructorConversion:
+ case CK_IntegralToPointer:
+ case CK_PointerToIntegral:
+ case CK_PointerToBoolean:
+ case CK_ToVoid:
+ case CK_VectorSplat:
+ case CK_IntegralCast:
+ case CK_BooleanToSignedIntegral:
+ case CK_IntegralToBoolean:
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ case CK_FloatingToBoolean:
+ case CK_FloatingCast:
+ case CK_CPointerToObjCPointerCast:
+ case CK_BlockPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
+ case CK_ObjCObjectLValueCast:
+ case CK_FloatingComplexToReal:
+ case CK_FloatingComplexToBoolean:
+ case CK_IntegralComplexToReal:
+ case CK_IntegralComplexToBoolean:
+ case CK_ARCProduceObject:
+ case CK_ARCConsumeObject:
+ case CK_ARCReclaimReturnedObject:
+ case CK_ARCExtendBlockObject:
+ case CK_CopyAndAutoreleaseBlockObject:
+ case CK_BuiltinFnToFnPtr:
+ case CK_ZeroToOCLOpaqueType:
+ case CK_AddressSpaceConversion:
+ case CK_IntToOCLSampler:
+ case CK_FloatingToFixedPoint:
+ case CK_FixedPointToFloating:
+ case CK_FixedPointCast:
+ case CK_FixedPointToBoolean:
+ case CK_FixedPointToIntegral:
+ case CK_IntegralToFixedPoint:
+ case CK_MatrixCast:
+ case CK_HLSLVectorTruncation:
+ case CK_HLSLArrayRValue:
+ case CK_HLSLElementwiseCast:
+ case CK_HLSLAggregateSplatCast:
+ llvm_unreachable("invalid cast kind for complex value");
+
+ case CK_FloatingRealToComplex:
+ case CK_IntegralRealToComplex: {
+ assert(!cir::MissingFeatures::cgFPOptionsRAII());
+ return emitScalarToComplexCast(cgf.emitScalarExpr(op), op->getType(),
+ destTy, op->getExprLoc());
+ }
+
+ case CK_FloatingComplexCast:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_IntegralComplexCast:
+ case CK_IntegralComplexToFloatingComplex: {
+ assert(!cir::MissingFeatures::cgFPOptionsRAII());
+ return emitComplexToComplexCast(Visit(op), op->getType(), destTy,
+ op->getExprLoc());
+ }
+ }
+
+ llvm_unreachable("unknown cast resulting in complex value");
+}
+
+mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e) {
+ QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
+ mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Plus, promotionTy);
+ if (!promotionTy.isNull()) {
+ cgf.cgm.errorNYI("ComplexExprEmitter::VisitUnaryPlus emitUnPromotedValue");
+ return {};
+ }
+ return result;
+}
+
+mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e,
+ cir::UnaryOpKind kind,
+ QualType promotionType) {
+ assert(kind == cir::UnaryOpKind::Plus ||
+ kind == cir::UnaryOpKind::Minus &&
+ "Invalid UnaryOp kind for ComplexType Plus or Minus");
+
+ mlir::Value op;
+ if (!promotionType.isNull())
+ op = cgf.emitPromotedComplexExpr(e->getSubExpr(), promotionType);
+ else
+ op = Visit(e->getSubExpr());
+ 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()) {
+ cgf.cgm.errorNYI("ComplexExprEmitter::VisitUnaryMinus emitUnPromotedValue");
+ return {};
+ }
+ return result;
}
mlir::Value ComplexExprEmitter::emitConstant(
@@ -207,6 +363,49 @@ void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
builder.createStore(loc, val, destAddr);
}
+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::VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e) {
mlir::Value condValue = Visit(e->getCond());
@@ -304,7 +503,7 @@ mlir::Value ComplexExprEmitter::VisitImplicitCastExpr(ImplicitCastExpr *e) {
return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());
}
-mlir::Value ComplexExprEmitter::VisitInitListExpr(const InitListExpr *e) {
+mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) {
mlir::Location loc = cgf.getLoc(e->getExprLoc());
if (e->getNumInits() == 2) {
mlir::Value real = cgf.emitScalarExpr(e->getInit(0));
@@ -312,10 +511,8 @@ mlir::Value ComplexExprEmitter::VisitInitListExpr(const InitListExpr *e) {
return builder.createComplexCreate(loc, real, imag);
}
- if (e->getNumInits() == 1) {
- cgf.cgm.errorNYI("Create Complex with InitList with size 1");
- return {};
- }
+ if (e->getNumInits() == 1)
+ return Visit(e->getInit(0));
assert(e->getNumInits() == 0 && "Unexpected number of inits");
mlir::Type complexTy = cgf.convertType(e->getType());
@@ -385,13 +582,22 @@ mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,
return emitBin##OP(emitBinOps(bo, promotionTy));
HANDLE_BINOP(Add)
HANDLE_BINOP(Sub)
+ HANDLE_BINOP(Mul)
#undef HANDLE_BINOP
default:
break;
}
- } else if (isa<UnaryOperator>(e)) {
- cgf.cgm.errorNYI("emitPromoted UnaryOperator");
- return {};
+ } else if (const auto *unaryOp = dyn_cast<UnaryOperator>(e)) {
+ switch (unaryOp->getOpcode()) {
+ case UO_Minus:
+ case UO_Plus: {
+ auto kind = unaryOp->getOpcode() == UO_Plus ? cir::UnaryOpKind::Plus
+ : cir::UnaryOpKind::Minus;
+ return VisitPlusMinus(unaryOp, kind, promotionTy);
+ }
+ default:
+ break;
+ }
}
mlir::Value result = Visit(const_cast<Expr *>(e));
@@ -436,6 +642,31 @@ mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) {
return builder.create<cir::ComplexSubOp>(op.loc, op.lhs, op.rhs);
}
+static cir::ComplexRangeKind
+getComplexRangeAttr(LangOptions::ComplexRangeKind range) {
+ switch (range) {
+ case LangOptions::CX_Full:
+ return cir::ComplexRangeKind::Full;
+ case LangOptions::CX_Improved:
+ return cir::ComplexRangeKind::Improved;
+ case LangOptions::CX_Promoted:
+ return cir::ComplexRangeKind::Promoted;
+ case LangOptions::CX_Basic:
+ return cir::ComplexRangeKind::Basic;
+ case LangOptions::CX_None:
+ // The default value for ComplexRangeKind is Full is no option is selected
+ return cir::ComplexRangeKind::Full;
+ }
+}
+
+mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) {
+ assert(!cir::MissingFeatures::fastMathFlags());
+ assert(!cir::MissingFeatures::cgFPOptionsRAII());
+ cir::ComplexRangeKind rangeKind =
+ getComplexRangeAttr(op.fpFeatures.getComplexRange());
+ return builder.create<cir::ComplexMulOp>(op.loc, op.lhs, op.rhs, rangeKind);
+}
+
LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) {
assert(e->getOpcode() == BO_Assign && "Expected assign op");