@@ -2394,6 +2394,180 @@ LValue CIRGenFunction::emitPredefinedLValue(const PredefinedExpr *e) {
23942394 return emitStringLiteralLValue (sl, gvName);
23952395}
23962396
2397+ LValue CIRGenFunction::emitOpaqueValueLValue (const OpaqueValueExpr *e) {
2398+ assert (OpaqueValueMappingData::shouldBindAsLValue (e));
2399+ return getOrCreateOpaqueLValueMapping (e);
2400+ }
2401+
2402+ namespace {
2403+ // Handle the case where the condition is a constant evaluatable simple integer,
2404+ // which means we don't have to separately handle the true/false blocks.
2405+ std::optional<LValue> handleConditionalOperatorLValueSimpleCase (
2406+ CIRGenFunction &cgf, const AbstractConditionalOperator *e) {
2407+ const Expr *condExpr = e->getCond ();
2408+ llvm::APSInt condExprVal;
2409+ if (!cgf.constantFoldsToSimpleInteger (condExpr, condExprVal))
2410+ return std::nullopt ;
2411+
2412+ const Expr *live = e->getTrueExpr (), *dead = e->getFalseExpr ();
2413+ if (!condExprVal.getBoolValue ())
2414+ std::swap (live, dead);
2415+
2416+ if (cgf.containsLabel (dead))
2417+ return std::nullopt ;
2418+
2419+ // If the true case is live, we need to track its region.
2420+ assert (!cir::MissingFeatures::incrementProfileCounter ());
2421+ assert (!cir::MissingFeatures::pgoUse ());
2422+ // If a throw expression we emit it and return an undefined lvalue
2423+ // because it can't be used.
2424+ if (auto *throwExpr = dyn_cast<CXXThrowExpr>(live->IgnoreParens ())) {
2425+ cgf.emitCXXThrowExpr (throwExpr);
2426+ // Return an undefined lvalue - the throw terminates execution
2427+ // so this value will never actually be used
2428+ mlir::Type elemTy = cgf.convertType (dead->getType ());
2429+ mlir::Value undefPtr =
2430+ cgf.getBuilder ().getNullPtr (cgf.getBuilder ().getPointerTo (elemTy),
2431+ cgf.getLoc (throwExpr->getSourceRange ()));
2432+ return cgf.makeAddrLValue (Address (undefPtr, elemTy, CharUnits::One ()),
2433+ dead->getType ());
2434+ }
2435+ return cgf.emitLValue (live);
2436+ }
2437+
2438+ // / Emit the operand of a glvalue conditional operator. This is either a glvalue
2439+ // / or a (possibly-parenthesized) throw-expression. If this is a throw, no
2440+ // / LValue is returned and the current block has been terminated.
2441+ static std::optional<LValue> emitLValueOrThrowExpression (CIRGenFunction &cgf,
2442+ const Expr *operand) {
2443+ if (auto *throwExpr = dyn_cast<CXXThrowExpr>(operand->IgnoreParens ())) {
2444+ cgf.emitCXXThrowExpr (throwExpr);
2445+ return std::nullopt ;
2446+ }
2447+
2448+ return cgf.emitLValue (operand);
2449+ }
2450+ } // namespace
2451+
2452+ // Create and generate the 3 blocks for a conditional operator.
2453+ // Leaves the 'current block' in the continuation basic block.
2454+ template <typename FuncTy>
2455+ CIRGenFunction::ConditionalInfo
2456+ CIRGenFunction::emitConditionalBlocks (const AbstractConditionalOperator *e,
2457+ const FuncTy &branchGenFunc) {
2458+ ConditionalInfo info;
2459+ ConditionalEvaluation eval (*this );
2460+ mlir::Location loc = getLoc (e->getSourceRange ());
2461+ CIRGenBuilderTy &builder = getBuilder ();
2462+
2463+ mlir::Value condV = emitOpOnBoolExpr (loc, e->getCond ());
2464+ SmallVector<mlir::OpBuilder::InsertPoint, 2 > insertPoints{};
2465+ mlir::Type yieldTy{};
2466+
2467+ auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc,
2468+ const Expr *expr, std::optional<LValue> &resultLV) {
2469+ CIRGenFunction::LexicalScope lexScope{*this , loc, b.getInsertionBlock ()};
2470+ curLexScope->setAsTernary ();
2471+
2472+ assert (!cir::MissingFeatures::incrementProfileCounter ());
2473+ eval.beginEvaluation ();
2474+ resultLV = branchGenFunc (*this , expr);
2475+ mlir::Value resultPtr = resultLV ? resultLV->getPointer () : mlir::Value ();
2476+ eval.endEvaluation ();
2477+
2478+ if (resultPtr) {
2479+ yieldTy = resultPtr.getType ();
2480+ cir::YieldOp::create (b, loc, resultPtr);
2481+ } else {
2482+ // If LHS or RHS is a void expression we need
2483+ // to patch arms as to properly match yield types.
2484+ // If the current block's terminator is an UnreachableOp (from a throw),
2485+ // we don't need a yield
2486+ if (builder.getInsertionBlock ()->mightHaveTerminator ()) {
2487+ mlir::Operation *terminator =
2488+ builder.getInsertionBlock ()->getTerminator ();
2489+ if (isa_and_nonnull<cir::UnreachableOp>(terminator))
2490+ insertPoints.push_back (b.saveInsertionPoint ());
2491+ }
2492+ }
2493+ };
2494+
2495+ info.result = cir::TernaryOp::create (
2496+ builder, loc, condV,
2497+ /* trueBuilder=*/
2498+ [&](mlir::OpBuilder &b, mlir::Location loc) {
2499+ emitBranch (b, loc, e->getTrueExpr (), info.lhs );
2500+ },
2501+ /* falseBuilder=*/
2502+ [&](mlir::OpBuilder &b, mlir::Location loc) {
2503+ emitBranch (b, loc, e->getFalseExpr (), info.rhs );
2504+ })
2505+ .getResult ();
2506+
2507+ // If both arms are void, so be it.
2508+ if (!yieldTy)
2509+ yieldTy = VoidTy;
2510+
2511+ // Insert required yields.
2512+ for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2513+ mlir::OpBuilder::InsertionGuard guard (builder);
2514+ builder.restoreInsertionPoint (toInsert);
2515+
2516+ // Block does not return: build empty yield.
2517+ if (!yieldTy) {
2518+ cir::YieldOp::create (builder, loc);
2519+ } else { // Block returns: set null yield value.
2520+ mlir::Value op0 = builder.getNullValue (yieldTy, loc);
2521+ cir::YieldOp::create (builder, loc, op0);
2522+ }
2523+ }
2524+
2525+ return info;
2526+ }
2527+
2528+ LValue CIRGenFunction::emitConditionalOperatorLValue (
2529+ const AbstractConditionalOperator *expr) {
2530+ if (!expr->isGLValue ()) {
2531+ // ?: here should be an aggregate.
2532+ assert (hasAggregateEvaluationKind (expr->getType ()) &&
2533+ " Unexpected conditional operator!" );
2534+ return emitAggExprToLValue (expr);
2535+ }
2536+
2537+ OpaqueValueMapping binding (*this , expr);
2538+ if (std::optional<LValue> res =
2539+ handleConditionalOperatorLValueSimpleCase (*this , expr))
2540+ return *res;
2541+
2542+ ConditionalInfo info =
2543+ emitConditionalBlocks (expr, [](CIRGenFunction &cgf, const Expr *e) {
2544+ return emitLValueOrThrowExpression (cgf, e);
2545+ });
2546+
2547+ if ((info.lhs && !info.lhs ->isSimple ()) ||
2548+ (info.rhs && !info.rhs ->isSimple ())) {
2549+ cgm.errorNYI (expr->getSourceRange (),
2550+ " unsupported conditional operator with non-simple lvalue" );
2551+ return LValue ();
2552+ }
2553+
2554+ if (info.lhs && info.rhs ) {
2555+ Address lhsAddr = info.lhs ->getAddress ();
2556+ Address rhsAddr = info.rhs ->getAddress ();
2557+ Address result (info.result , lhsAddr.getElementType (),
2558+ std::min (lhsAddr.getAlignment (), rhsAddr.getAlignment ()));
2559+ AlignmentSource alignSource =
2560+ std::max (info.lhs ->getBaseInfo ().getAlignmentSource (),
2561+ info.rhs ->getBaseInfo ().getAlignmentSource ());
2562+ assert (!cir::MissingFeatures::opTBAA ());
2563+ return makeAddrLValue (result, expr->getType (), LValueBaseInfo (alignSource));
2564+ }
2565+
2566+ assert ((info.lhs || info.rhs ) &&
2567+ " both operands of glvalue conditional are throw-expressions?" );
2568+ return info.lhs ? *info.lhs : *info.rhs ;
2569+ }
2570+
23972571// / An LValue is a candidate for having its loads and stores be made atomic if
23982572// / we are operating under /volatile:ms *and* the LValue itself is volatile and
23992573// / performing such an operation can be performed without a libcall.
0 commit comments