================ @@ -90,20 +89,259 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { builder.getCIRBoolAttr(e->getValue())); } - mlir::Value VisitCastExpr(CastExpr *E); + mlir::Value VisitCastExpr(CastExpr *e); + + mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) { + return VisitCastExpr(e); + } + + /// Perform a pointer to boolean conversion. + mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) { + // TODO(cir): comparing the ptr to null is done when lowering CIR to LLVM. + // We might want to have a separate pass for these types of conversions. + return cgf.getBuilder().createPtrToBoolCast(v); + } + + mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) { + auto boolTy = builder.getBoolTy(); + return builder.create<cir::CastOp>(loc, boolTy, + cir::CastKind::float_to_bool, src); + } + + mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) { + // Because of the type rules of C, we often end up computing a + // logical value, then zero extending it to int, then wanting it + // as a logical value again. + // TODO: optimize this common case here or leave it for later + // CIR passes? + mlir::Type boolTy = cgf.convertType(cgf.getContext().BoolTy); + return builder.create<cir::CastOp>(loc, boolTy, cir::CastKind::int_to_bool, + srcVal); + } + + /// Convert the specified expression value to a boolean (!cir.bool) truth + /// value. This is equivalent to "Val != 0". + mlir::Value emitConversionToBool(mlir::Value src, QualType srcType, + mlir::Location loc) { + assert(srcType.isCanonical() && "EmitScalarConversion strips typedefs"); + + if (srcType->isRealFloatingType()) + return emitFloatToBoolConversion(src, loc); + + if (llvm::isa<MemberPointerType>(srcType)) + cgf.getCIRGenModule().errorNYI(loc, "member pointer to bool conversion"); + + if (srcType->isIntegerType()) + return emitIntToBoolConversion(src, loc); + + assert(::mlir::isa<cir::PointerType>(src.getType())); + return emitPointerToBoolConversion(src, srcType); + } + + // Emit a conversion from the specified type to the specified destination + // type, both of which are CIR scalar types. + struct ScalarConversionOpts { + bool treatBooleanAsSigned; + bool emitImplicitIntegerTruncationChecks; + bool emitImplicitIntegerSignChangeChecks; + + ScalarConversionOpts() + : treatBooleanAsSigned(false), + emitImplicitIntegerTruncationChecks(false), + emitImplicitIntegerSignChangeChecks(false) {} + + ScalarConversionOpts(clang::SanitizerSet sanOpts) + : treatBooleanAsSigned(false), + emitImplicitIntegerTruncationChecks( + sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)), + emitImplicitIntegerSignChangeChecks( + sanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {} + }; + + // Conversion from bool, integral, or floating-point to integral or + // floating-point. Conversions involving other types are handled elsewhere. + // Conversion to bool is handled elsewhere because that's a comparison against + // zero, not a simple cast. This handles both individual scalars and vectors. + mlir::Value emitScalarCast(mlir::Value src, QualType srcType, + QualType dstType, mlir::Type srcTy, + mlir::Type dstTy, ScalarConversionOpts opts) { + assert(!srcType->isMatrixType() && !dstType->isMatrixType() && + "Internal error: matrix types not handled by this function."); + if (mlir::isa<mlir::IntegerType>(srcTy) || + mlir::isa<mlir::IntegerType>(dstTy)) + llvm_unreachable("Obsolete code. Don't use mlir::IntegerType with CIR."); + + mlir::Type fullDstTy = dstTy; + assert(!cir::MissingFeatures::vectorType()); + + std::optional<cir::CastKind> castKind; + + if (mlir::isa<cir::BoolType>(srcTy)) { + if (opts.treatBooleanAsSigned) + cgf.getCIRGenModule().errorNYI("signed bool"); + if (cgf.getBuilder().isInt(dstTy)) + castKind = cir::CastKind::bool_to_int; + else if (mlir::isa<cir::CIRFPTypeInterface>(dstTy)) + castKind = cir::CastKind::bool_to_float; + else + llvm_unreachable("Internal error: Cast to unexpected type"); + } else if (cgf.getBuilder().isInt(srcTy)) { + if (cgf.getBuilder().isInt(dstTy)) + castKind = cir::CastKind::integral; + else if (mlir::isa<cir::CIRFPTypeInterface>(dstTy)) + castKind = cir::CastKind::int_to_float; + else + llvm_unreachable("Internal error: Cast to unexpected type"); + } else if (mlir::isa<cir::CIRFPTypeInterface>(srcTy)) { + if (cgf.getBuilder().isInt(dstTy)) { + // If we can't recognize overflow as undefined behavior, assume that + // overflow saturates. This protects against normal optimizations if we + // are compiling with non-standard FP semantics. + if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow) + cgf.getCIRGenModule().errorNYI("strict float cast overflow"); + assert(!cir::MissingFeatures::fpConstraints()); + castKind = cir::CastKind::float_to_int; + } else if (mlir::isa<cir::CIRFPTypeInterface>(dstTy)) { + cgf.getCIRGenModule().errorNYI("floating point casts"); + } else { + llvm_unreachable("Internal error: Cast to unexpected type"); + } + } else { + llvm_unreachable("Internal error: Cast from unexpected type"); + } + + assert(castKind.has_value() && "Internal error: CastKind not set."); + return builder.create<cir::CastOp>(src.getLoc(), fullDstTy, *castKind, src); + } /// Emit a conversion from the specified type to the specified destination /// type, both of which are CIR scalar types. /// TODO: do we need ScalarConversionOpts here? Should be done in another /// pass. - mlir::Value emitScalarConversion(mlir::Value src, QualType srcType, - QualType dstType, SourceLocation loc) { - // No sort of type conversion is implemented yet, but the path for implicit - // paths goes through here even if the type isn't being changed. + mlir::Value + emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType, + SourceLocation loc, + ScalarConversionOpts opts = ScalarConversionOpts()) { + // All conversions involving fixed point types should be handled by the + // emitFixedPoint family functions. This is done to prevent bloating up + // this function more, and although fixed point numbers are represented by + // integers, we do not want to follow any logic that assumes they should be + // treated as integers. + // TODO(leonardchan): When necessary, add another if statement checking for + // conversions to fixed point types from other types. + // conversions to fixed point types from other types. + if (srcType->isFixedPointType()) + cgf.getCIRGenModule().errorNYI(loc, "fixed point conversions"); ---------------- erichkeane wrote:
These also need to return something. Otherwise this would fall into the below and it isn't clear it would fall into anything even vaguely sensible. https://github.com/llvm/llvm-project/pull/130690 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits