Skip to content

[CIR] Upstream Cast kinds for ComplexType #149717

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

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,12 @@ def CIR_CastKind : CIR_I32EnumAttr<"CastKind", "cast kind", [
// CK_BlockPointerToObjCPointerCast
// CK_AnyPointerToBlockPointerCast
// CK_ObjCObjectLValueCast
// I32EnumAttrCase<"float_to_complex", 44>,
// I32EnumAttrCase<"float_complex_to_real", 45>,
// I32EnumAttrCase<"float_complex_to_bool", 46>,
I32EnumAttrCase<"float_to_complex", 44>,
I32EnumAttrCase<"float_complex_to_real", 45>,
I32EnumAttrCase<"float_complex_to_bool", 46>,
I32EnumAttrCase<"float_complex", 47>,
// I32EnumAttrCase<"float_complex_to_int_complex", 48>,
// I32EnumAttrCase<"int_to_complex", 49>,
I32EnumAttrCase<"float_complex_to_int_complex", 48>,
I32EnumAttrCase<"int_to_complex", 49>,
I32EnumAttrCase<"int_complex_to_real", 50>,
I32EnumAttrCase<"int_complex_to_bool", 51>,
I32EnumAttrCase<"int_complex", 52>,
Expand Down
152 changes: 148 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,20 @@ 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);

/// 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);
Expand Down Expand Up @@ -164,14 +173,106 @@ LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
QualType destTy) {
switch (ck) {
case CK_Dependent:
llvm_unreachable("dependent cast kind in IR gen!");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we improve this message, so that it is clear why this should never come here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can change it to something like "dependent type must be resolved before the Codegen" 🤔 @xlauko


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: {
cgf.cgm.errorNYI("ComplexExprEmitter::emitCast CK_LValueBitCast");
return {};
}

case CK_LValueToRValueBitCast: {
cgf.cgm.errorNYI("ComplexExprEmitter::emitCast CK_LValueToRValueBitCast");
return {};
}

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::emitConstant(
Expand Down Expand Up @@ -207,6 +308,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());
Expand Down
38 changes: 38 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
// Utilities
//===--------------------------------------------------------------------===//

mlir::Value emitComplexToScalarConversion(mlir::Location loc,
mlir::Value value, CastKind kind,
QualType destTy);

mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
return builder.createFloatingCast(result, cgf.convertType(promotionType));
}
Expand Down Expand Up @@ -1135,6 +1139,31 @@ LValue ScalarExprEmitter::emitCompoundAssignLValue(
return lhsLV;
}

mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
mlir::Value value,
CastKind kind,
QualType destTy) {
cir::CastKind castOpKind;
switch (kind) {
case CK_FloatingComplexToReal:
castOpKind = cir::CastKind::float_complex_to_real;
break;
case CK_IntegralComplexToReal:
castOpKind = cir::CastKind::int_complex_to_real;
break;
case CK_FloatingComplexToBoolean:
castOpKind = cir::CastKind::float_complex_to_bool;
break;
case CK_IntegralComplexToBoolean:
castOpKind = cir::CastKind::int_complex_to_bool;
break;
default:
llvm_unreachable("invalid complex-to-scalar cast kind");
}

return builder.createCast(lov, castOpKind, value, cgf.convertType(destTy));
}

mlir::Value ScalarExprEmitter::emitPromoted(const Expr *e,
QualType promotionType) {
e = e->IgnoreParens();
Expand Down Expand Up @@ -1758,6 +1787,15 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
ce->getExprLoc(), opts);
}

case CK_FloatingComplexToReal:
case CK_IntegralComplexToReal:
case CK_FloatingComplexToBoolean:
case CK_IntegralComplexToBoolean: {
mlir::Value value = cgf.emitComplexExpr(subExpr);
return emitComplexToScalarConversion(cgf.getLoc(ce->getExprLoc()), value,
kind, destTy);
}

case CK_FloatingRealToComplex:
case CK_FloatingComplexCast:
case CK_IntegralRealToComplex:
Expand Down
98 changes: 98 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,104 @@ LogicalResult cir::CastOp::verify() {
return emitOpError() << "requires two types differ in addrspace only";
return success();
}
case cir::CastKind::float_to_complex: {
if (!mlir::isa<cir::FPTypeInterface>(srcType))
return emitOpError() << "requires !cir.float type for source";
auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
if (!resComplexTy)
return emitOpError() << "requires !cir.complex type for result";
if (srcType != resComplexTy.getElementType())
return emitOpError() << "requires source type match result element type";
return success();
}
case cir::CastKind::int_to_complex: {
if (!mlir::isa<cir::IntType>(srcType))
return emitOpError() << "requires !cir.int type for source";
auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
if (!resComplexTy)
return emitOpError() << "requires !cir.complex type for result";
if (srcType != resComplexTy.getElementType())
return emitOpError() << "requires source type match result element type";
return success();
}
case cir::CastKind::float_complex_to_real: {
auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
if (!srcComplexTy)
return emitOpError() << "requires !cir.complex type for source";
if (!mlir::isa<cir::FPTypeInterface>(resType))
return emitOpError() << "requires !cir.float type for result";
if (srcComplexTy.getElementType() != resType)
return emitOpError() << "requires source element type match result type";
return success();
}
case cir::CastKind::int_complex_to_real: {
auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
if (!srcComplexTy)
return emitOpError() << "requires !cir.complex type for source";
if (!mlir::isa<cir::IntType>(resType))
return emitOpError() << "requires !cir.int type for result";
if (srcComplexTy.getElementType() != resType)
return emitOpError() << "requires source element type match result type";
return success();
}
case cir::CastKind::float_complex_to_bool: {
auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
return emitOpError()
<< "requires floating point !cir.complex type for source";
if (!mlir::isa<cir::BoolType>(resType))
return emitOpError() << "requires !cir.bool type for result";
return success();
}
case cir::CastKind::int_complex_to_bool: {
auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
return emitOpError()
<< "requires floating point !cir.complex type for source";
if (!mlir::isa<cir::BoolType>(resType))
return emitOpError() << "requires !cir.bool type for result";
return success();
}
case cir::CastKind::float_complex: {
auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
return emitOpError()
<< "requires floating point !cir.complex type for source";
auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
return emitOpError()
<< "requires floating point !cir.complex type for result";
return success();
}
case cir::CastKind::float_complex_to_int_complex: {
auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
return emitOpError()
<< "requires floating point !cir.complex type for source";
auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
if (!resComplexTy || !resComplexTy.isIntegerComplex())
return emitOpError() << "requires integer !cir.complex type for result";
return success();
}
case cir::CastKind::int_complex: {
auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
return emitOpError() << "requires integer !cir.complex type for source";
auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
if (!resComplexTy || !resComplexTy.isIntegerComplex())
return emitOpError() << "requires integer !cir.complex type for result";
return success();
}
case cir::CastKind::int_complex_to_float_complex: {
auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
return emitOpError() << "requires integer !cir.complex type for source";
auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
return emitOpError()
<< "requires floating point !cir.complex type for result";
return success();
}
default:
llvm_unreachable("Unknown CastOp kind?");
}
Expand Down
Loading