================ @@ -948,6 +950,165 @@ void CIRGenFunction::emitIgnoredExpr(const Expr *e) { emitLValue(e); } +// Handle the case where the condition is a constant evaluatable simple integer, +// which means we don't have to separately handle the true/false blocks. +static std::optional<LValue> handleConditionalOperatorLValueSimpleCase( + CIRGenFunction &cgf, const AbstractConditionalOperator *e) { + const Expr *condExpr = e->getCond(); + bool condExprBool = false; + if (cgf.constantFoldsToSimpleInteger(condExpr, condExprBool)) { + const Expr *live = e->getTrueExpr(), *dead = e->getFalseExpr(); + if (!condExprBool) + std::swap(live, dead); + + if (!cgf.containsLabel(dead)) { + // If the true case is live, we need to track its region. + if (condExprBool) { + assert(!cir::MissingFeatures::incrementProfileCounter()); + } + // If a throw expression we emit it and return an undefined lvalue + // because it can't be used. + if (isa<CXXThrowExpr>(live->IgnoreParens())) { + assert(!cir::MissingFeatures::throwOp()); + cgf.cgm.errorNYI(live->getSourceRange(), + "throw expressions in conditional operator"); + return std::nullopt; + } + return cgf.emitLValue(live); + } + } + return std::nullopt; +} + +/// Emit the operand of a glvalue conditional operator. This is either a glvalue +/// or a (possibly-parenthesized) throw-expression. If this is a throw, no +/// LValue is returned and the current block has been terminated. +static std::optional<LValue> emitLValueOrThrowExpression(CIRGenFunction &cgf, + const Expr *operand) { + if (isa<CXXThrowExpr>(operand->IgnoreParens())) { + assert(!cir::MissingFeatures::throwOp()); + cgf.cgm.errorNYI(operand->getSourceRange(), + "throw expressions in conditional operator"); + return std::nullopt; + } + + return cgf.emitLValue(operand); +} + +// Create and generate the 3 blocks for a conditional operator. +// Leaves the 'current block' in the continuation basic block. +template <typename FuncTy> +CIRGenFunction::ConditionalInfo +CIRGenFunction::emitConditionalBlocks(const AbstractConditionalOperator *e, + const FuncTy &branchGenFunc) { + ConditionalInfo info; + CIRGenFunction &cgf = *this; + ConditionalEvaluation eval(cgf); + mlir::Location loc = cgf.getLoc(e->getSourceRange()); + CIRGenBuilderTy &builder = cgf.getBuilder(); + Expr *trueExpr = e->getTrueExpr(); + Expr *falseExpr = e->getFalseExpr(); + + mlir::Value condV = cgf.emitOpOnBoolExpr(loc, e->getCond()); + SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{}; + mlir::Type yieldTy{}; + + auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *expr, + std::optional<LValue> &branchInfo) { + CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()}; + cgf.curLexScope->setAsTernary(); + + assert(!cir::MissingFeatures::incrementProfileCounter()); + eval.begin(cgf); + branchInfo = branchGenFunc(cgf, expr); + mlir::Value branch = branchInfo->getPointer(); + eval.end(cgf); + + if (branch) { + yieldTy = branch.getType(); + b.create<cir::YieldOp>(loc, branch); + } else { + // If LHS or RHS is a throw or void expression we need to patch + // arms as to properly match yield types. + insertPoints.push_back(b.saveInsertionPoint()); + } + }; + + info.result = builder + .create<cir::TernaryOp>( + loc, condV, /*trueBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + emitBranch(b, loc, trueExpr, info.lhs); + }, + /*falseBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + emitBranch(b, loc, falseExpr, info.rhs); + }) + .getResult(); + + if (!insertPoints.empty()) { + // If both arms are void, so be it. + if (!yieldTy) + yieldTy = cgf.VoidTy; + + // Insert required yields. + for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) { + mlir::OpBuilder::InsertionGuard guard(builder); + builder.restoreInsertionPoint(toInsert); + + // Block does not return: build empty yield. + if (mlir::isa<cir::VoidType>(yieldTy)) { + builder.create<cir::YieldOp>(loc); + } else { // Block returns: set null yield value. + mlir::Value op0 = builder.getNullValue(yieldTy, loc); + builder.create<cir::YieldOp>(loc, op0); + } + } + } + return info; +} + +LValue CIRGenFunction::emitConditionalOperatorLValue( ---------------- andykaylor wrote:
It doesn't look like this is called from anywhere in this patch. In the incubator, it is called from emitLValue(), and the fact that you didn't need that here makes me suspect this is entirely duplicated somewhere else (maybe in the VisitAbstractConditionalOperator implementation?). https://github.com/llvm/llvm-project/pull/138156 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits