[clang] [CIR] Upstream CastOp and scalar conversions (PR #130690)

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 12 08:11:19 PDT 2025


================
@@ -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) ||
----------------
erichkeane wrote:

I realize this made sense in the case of 'switching from this function to another' in the incubator, but I think this should probably be an assert instead.

https://github.com/llvm/llvm-project/pull/130690


More information about the cfe-commits mailing list