================
@@ -90,24 +89,279 @@ 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");
+      auto boolType = cgf.getContext().getBOOLType();
+      auto cirBoolType = cgf.convertType(boolType);
+      CharUnits alignment = cgf.getContext().getTypeAlignInChars(boolType);
+      auto addr =
+          builder.createAlloca(loc, builder.getPointerTo(cirBoolType),
+                               cirBoolType, {}, cgf.cgm.getSize(alignment));
+      return builder.createLoad(loc, addr);
+    }
+
+    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");
+        CharUnits alignment = cgf.getContext().getTypeAlignInChars(dstType);
+        auto addr =
+            builder.createAlloca(src.getLoc(), builder.getPointerTo(dstTy),
+                                 dstTy, {}, cgf.cgm.getSize(alignment));
+        return builder.createLoad(src.getLoc(), addr);
+      } 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() || dstType->isFixedPointType()) {
+      cgf.getCIRGenModule().errorNYI(loc, "fixed point conversions");
+      return nullptr;
+    }
+
     srcType = srcType.getCanonicalType();
     dstType = dstType.getCanonicalType();
-    if (srcType == dstType)
+    if (srcType == dstType) {
+      if (opts.emitImplicitIntegerSignChangeChecks)
+        cgf.getCIRGenModule().errorNYI(loc,
+                                       "implicit integer sign change checks");
       return src;
+    }
 
-    cgf.getCIRGenModule().errorNYI(loc,
-                                   "emitScalarConversion for unequal types");
-    return {};
+    if (dstType->isVoidType())
+      return nullptr;
+
+    mlir::Type mlirSrcType = src.getType();
+
+    // Handle conversions to bool first, they are special: comparisons against
+    // 0.
+    if (dstType->isBooleanType())
+      return emitConversionToBool(src, srcType, cgf.getLoc(loc));
+
+    mlir::Type mlirDstType = cgf.convertType(dstType);
+
+    if (srcType->isHalfType() &&
+        !cgf.getContext().getLangOpts().NativeHalfType) {
+      // Cast to FP using the intrinsic if the half type itself isn't 
supported.
+      if (mlir::isa<cir::CIRFPTypeInterface>(mlirDstType)) {
+        if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
+          cgf.getCIRGenModule().errorNYI(loc,
+                                         "cast via llvm.convert.from.fp16");
+      } else {
+        // Cast to other types through float, using either the intrinsic or
+        // FPExt, depending on whether the half type itself is supported (as
+        // opposed to operations on half, available with NativeHalfType).
+        if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
+          cgf.getCIRGenModule().errorNYI(loc,
+                                         "cast via llvm.convert.from.fp16");
+          // FIXME(cir): For now lets pretend we shouldn't use the conversion
+          // intrinsics and insert a cast here unconditionally.
+        }
+        src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
+                                 cgf.FloatTy);
+        srcType = cgf.getContext().FloatTy;
+        mlirSrcType = cgf.FloatTy;
+      }
+    }
+
+    // TODO(cir): LLVM codegen ignore conversions like int -> uint,
+    // is there anything to be done for CIR here?
+    if (mlirSrcType == mlirDstType) {
+      if (opts.emitImplicitIntegerSignChangeChecks)
+        cgf.getCIRGenModule().errorNYI(loc,
+                                       "implicit integer sign change checks");
+      return src;
+    }
+
+    // Handle pointer conversions next: pointers can only be converted to/from
+    // other pointers and integers. Check for pointer types in terms of LLVM, 
as
+    // some native types (like Obj-C id) may map to a pointer type.
+    if (isa_cast<cir::PointerType>(mlirDstType)) {
+      cgf.getCIRGenModule().errorNYI(loc, "pointer casts");
+      CharUnits alignment = cgf.getContext().getTypeAlignInChars(dstType);
+      auto addr =
+          builder.createAlloca(src.getLoc(), builder.getPointerTo(dstPT), 
dstPT,
+                               {}, cgf.cgm.getSize(alignment));
+      return builder.createLoad(src.getLoc(), addr);
----------------
erichkeane wrote:

Wonder if there is use of a `createDummyValue` function in builder that does 
all this for us?

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

Reply via email to