================ @@ -121,29 +359,159 @@ mlir::Value CIRGenFunction::emitScalarExpr(const Expr *e) { return ScalarExprEmitter(*this, builder).Visit(const_cast<Expr *>(e)); } +[[maybe_unused]] static bool MustVisitNullValue(const Expr *e) { + // If a null pointer expression's type is the C++0x nullptr_t, then + // it's not necessarily a simple constant and it must be evaluated + // for its potential side effects. + return e->getType()->isNullPtrType(); +} + // Emit code for an explicit or implicit cast. Implicit // casts have to handle a more broad range of conversions than explicit // casts, as they handle things like function to ptr-to-function decay // etc. mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) { - Expr *e = ce->getSubExpr(); + Expr *subExpr = ce->getSubExpr(); QualType destTy = ce->getType(); CastKind kind = ce->getCastKind(); + // These cases are generally not written to ignore the result of evaluating + // their sub-expressions, so we clear this now. + ignoreResultAssign = false; + switch (kind) { + case clang::CK_Dependent: + llvm_unreachable("dependent cast kind in CIR gen!"); + case clang::CK_BuiltinFnToFnPtr: + llvm_unreachable("builtin functions are handled elsewhere"); + + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + case CK_BitCast: { + mlir::Value src = Visit(const_cast<Expr *>(subExpr)); + mlir::Type dstTy = cgf.convertType(destTy); + + assert(!cir::MissingFeatures::addressSpace()); + + if (cgf.sanOpts.has(SanitizerKind::CFIUnrelatedCast)) + cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(), + "sanitizer support"); + + if (cgf.cgm.getCodeGenOpts().StrictVTablePointers) + cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(), + "strict vtable pointers"); + + // Update heapallocsite metadata when there is an explicit pointer cast. + assert(!cir::MissingFeatures::addHeapAllocSiteMetadata()); + + // If Src is a fixed vector and Dst is a scalable vector, and both have the + // same element type, use the llvm.vector.insert intrinsic to perform the + // bitcast. + assert(!cir::MissingFeatures::scalableVectors()); + + // If Src is a scalable vector and Dst is a fixed vector, and both have the + // same element type, use the llvm.vector.extract intrinsic to perform the + // bitcast. + assert(!cir::MissingFeatures::scalableVectors()); + + // Perform VLAT <-> VLST bitcast through memory. + // TODO: since the llvm.experimental.vector.{insert,extract} intrinsics + // require the element types of the vectors to be the same, we + // need to keep this around for bitcasts between VLAT <-> VLST where + // the element types of the vectors are not the same, until we figure + // out a better way of doing these casts. + assert(!cir::MissingFeatures::scalableVectors()); + + return cgf.getBuilder().createBitcast(cgf.getLoc(subExpr->getSourceRange()), + src, dstTy); + } + + case CK_AtomicToNonAtomic: + cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(), + "CastExpr: ", ce->getCastKindName()); + break; + case CK_NonAtomicToAtomic: + case CK_UserDefinedConversion: + return Visit(const_cast<Expr *>(subExpr)); + case CK_NoOp: { + auto v = Visit(const_cast<Expr *>(subExpr)); + if (v) { + // CK_NoOp can model a pointer qualification conversion, which can remove + // an array bound and change the IR type. + // FIXME: Once pointee types are removed from IR, remove this. + mlir::Type t = cgf.convertType(destTy); + if (t != v.getType()) + cgf.getCIRGenModule().errorNYI("pointer qualification conversion"); + } + return v; + } + + case CK_NullToPointer: { + if (MustVisitNullValue(subExpr)) + cgf.getCIRGenModule().errorNYI( + subExpr->getSourceRange(), + "ignored expression on null to pointer cast"); + + // Note that DestTy is used as the MLIR type instead of a custom + // nullptr type. + mlir::Type ty = cgf.convertType(destTy); + return builder.getNullPtr(ty, cgf.getLoc(subExpr->getExprLoc())); + } + case CK_LValueToRValue: - assert(cgf.getContext().hasSameUnqualifiedType(e->getType(), destTy)); - assert(e->isGLValue() && "lvalue-to-rvalue applied to r-value!"); - return Visit(const_cast<Expr *>(e)); + assert(cgf.getContext().hasSameUnqualifiedType(subExpr->getType(), destTy)); + assert(subExpr->isGLValue() && "lvalue-to-rvalue applied to r-value!"); + return Visit(const_cast<Expr *>(subExpr)); case CK_IntegralCast: { - assert(!cir::MissingFeatures::scalarConversionOpts()); - return emitScalarConversion(Visit(e), e->getType(), destTy, - ce->getExprLoc()); + ScalarConversionOpts opts; + if (auto *ice = dyn_cast<ImplicitCastExpr>(ce)) { + if (!ice->isPartOfExplicitCast()) + opts = ScalarConversionOpts(cgf.sanOpts); + } + return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy, + ce->getExprLoc(), opts); + } + + case CK_FloatingRealToComplex: + case CK_FloatingComplexCast: + case CK_IntegralRealToComplex: + case CK_IntegralComplexCast: + case CK_IntegralComplexToFloatingComplex: + case CK_FloatingComplexToIntegralComplex: + llvm_unreachable("scalar cast to non-scalar value"); + + case CK_PointerToIntegral: { + assert(!destTy->isBooleanType() && "bool should use PointerToBool"); + if (cgf.cgm.getCodeGenOpts().StrictVTablePointers) + llvm_unreachable("NYI"); ---------------- erichkeane wrote:
see above about unreachable/assert/NYI. 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