@@ -2394,6 +2394,185 @@ 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 condExprInt;
2409+ if (cgf.constantFoldsToSimpleInteger (condExpr, condExprInt)) {
2410+ bool condExprBool = condExprInt.getBoolValue ();
2411+ const Expr *live = e->getTrueExpr (), *dead = e->getFalseExpr ();
2412+ if (!condExprBool)
2413+ std::swap (live, dead);
2414+
2415+ if (!cgf.containsLabel (dead)) {
2416+ // If the true case is live, we need to track its region.
2417+ assert (!cir::MissingFeatures::incrementProfileCounter ());
2418+ assert (!cir::MissingFeatures::pgoUse ());
2419+ // If a throw expression we emit it and return an undefined lvalue
2420+ // because it can't be used.
2421+ if (auto *throwExpr = dyn_cast<CXXThrowExpr>(live->IgnoreParens ())) {
2422+ cgf.emitCXXThrowExpr (throwExpr);
2423+ // Return an undefined lvalue - the throw terminates execution
2424+ // so this value will never actually be used
2425+ mlir::Type elemTy = cgf.convertType (dead->getType ());
2426+ mlir::Type ptrTy = cir::PointerType::get (elemTy);
2427+ mlir::Value undefPtr = cgf.getBuilder ().getNullValue (
2428+ ptrTy, cgf.getLoc (throwExpr->getSourceRange ()));
2429+ return cgf.makeAddrLValue (Address (undefPtr, elemTy, CharUnits::One ()),
2430+ dead->getType ());
2431+ }
2432+ return cgf.emitLValue (live);
2433+ }
2434+ }
2435+ return std::nullopt ;
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 patchVoidOrThrowSites = [&] {
2468+ if (insertPoints.empty ())
2469+ return ;
2470+ // If both arms are void, so be it.
2471+ if (!yieldTy)
2472+ yieldTy = VoidTy;
2473+
2474+ // Insert required yields.
2475+ for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2476+ mlir::OpBuilder::InsertionGuard guard (builder);
2477+ builder.restoreInsertionPoint (toInsert);
2478+
2479+ // Block does not return: build empty yield.
2480+ if (mlir::isa<cir::VoidType>(yieldTy)) {
2481+ cir::YieldOp::create (builder, loc);
2482+ } else { // Block returns: set null yield value.
2483+ mlir::Value op0 = builder.getNullValue (yieldTy, loc);
2484+ cir::YieldOp::create (builder, loc, op0);
2485+ }
2486+ }
2487+ };
2488+
2489+ auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc,
2490+ const Expr *expr, std::optional<LValue> &resultLV) {
2491+ CIRGenFunction::LexicalScope lexScope{*this , loc, b.getInsertionBlock ()};
2492+ curLexScope->setAsTernary ();
2493+
2494+ assert (!cir::MissingFeatures::incrementProfileCounter ());
2495+ eval.beginEvaluation ();
2496+ resultLV = branchGenFunc (*this , expr);
2497+ mlir::Value resultPtr = resultLV ? resultLV->getPointer () : mlir::Value ();
2498+ eval.endEvaluation ();
2499+
2500+ if (resultPtr) {
2501+ yieldTy = resultPtr.getType ();
2502+ cir::YieldOp::create (b, loc, resultPtr);
2503+ } else {
2504+ // If LHS or RHS is a void expression we need
2505+ // to patch arms as to properly match yield types.
2506+ // If the current block's terminator is an UnreachableOp (from a throw),
2507+ // we don't need a yield
2508+ if (builder.getInsertionBlock ()->mightHaveTerminator ()) {
2509+ mlir::Operation *terminator =
2510+ builder.getInsertionBlock ()->getTerminator ();
2511+ if (isa_and_nonnull<cir::UnreachableOp>(terminator))
2512+ insertPoints.push_back (b.saveInsertionPoint ());
2513+ }
2514+ }
2515+ };
2516+
2517+ info.result = cir::TernaryOp::create (
2518+ builder, loc, condV,
2519+ /* trueBuilder=*/
2520+ [&](mlir::OpBuilder &b, mlir::Location loc) {
2521+ emitBranch (b, loc, e->getTrueExpr (), info.lhs );
2522+ },
2523+ /* falseBuilder=*/
2524+ [&](mlir::OpBuilder &b, mlir::Location loc) {
2525+ emitBranch (b, loc, e->getFalseExpr (), info.rhs );
2526+ patchVoidOrThrowSites ();
2527+ })
2528+ .getResult ();
2529+
2530+ return info;
2531+ }
2532+
2533+ LValue CIRGenFunction::emitConditionalOperatorLValue (
2534+ const AbstractConditionalOperator *expr) {
2535+ if (!expr->isGLValue ()) {
2536+ // ?: here should be an aggregate.
2537+ assert (hasAggregateEvaluationKind (expr->getType ()) &&
2538+ " Unexpected conditional operator!" );
2539+ return emitAggExprToLValue (expr);
2540+ }
2541+
2542+ OpaqueValueMapping binding (*this , expr);
2543+ if (std::optional<LValue> res =
2544+ handleConditionalOperatorLValueSimpleCase (*this , expr))
2545+ return *res;
2546+
2547+ ConditionalInfo info =
2548+ emitConditionalBlocks (expr, [](CIRGenFunction &cgf, const Expr *e) {
2549+ return emitLValueOrThrowExpression (cgf, e);
2550+ });
2551+
2552+ if ((info.lhs && !info.lhs ->isSimple ()) ||
2553+ (info.rhs && !info.rhs ->isSimple ())) {
2554+ cgm.errorNYI (expr->getSourceRange (),
2555+ " unsupported conditional operator with non-simple lvalue" );
2556+ return LValue ();
2557+ }
2558+
2559+ if (info.lhs && info.rhs ) {
2560+ Address lhsAddr = info.lhs ->getAddress ();
2561+ Address rhsAddr = info.rhs ->getAddress ();
2562+ Address result (info.result , lhsAddr.getElementType (),
2563+ std::min (lhsAddr.getAlignment (), rhsAddr.getAlignment ()));
2564+ AlignmentSource alignSource =
2565+ std::max (info.lhs ->getBaseInfo ().getAlignmentSource (),
2566+ info.rhs ->getBaseInfo ().getAlignmentSource ());
2567+ assert (!cir::MissingFeatures::opTBAA ());
2568+ return makeAddrLValue (result, expr->getType (), LValueBaseInfo (alignSource));
2569+ }
2570+
2571+ assert ((info.lhs || info.rhs ) &&
2572+ " both operands of glvalue conditional are throw-expressions?" );
2573+ return info.lhs ? *info.lhs : *info.rhs ;
2574+ }
2575+
23972576// / An LValue is a candidate for having its loads and stores be made atomic if
23982577// / we are operating under /volatile:ms *and* the LValue itself is volatile and
23992578// / performing such an operation can be performed without a libcall.
0 commit comments