|
18 | 18 | #include "clang/AST/CharUnits.h" |
19 | 19 | #include "clang/AST/Decl.h" |
20 | 20 | #include "clang/AST/Expr.h" |
| 21 | +#include "clang/AST/ExprCXX.h" |
21 | 22 | #include "clang/CIR/Dialect/IR/CIRDialect.h" |
22 | 23 | #include "clang/CIR/MissingFeatures.h" |
23 | 24 |
|
@@ -474,6 +475,90 @@ void CIRGenFunction::emitIgnoredExpr(const Expr *e) { |
474 | 475 | emitLValue(e); |
475 | 476 | } |
476 | 477 |
|
| 478 | +/// Emit an `if` on a boolean condition, filling `then` and `else` into |
| 479 | +/// appropriated regions. |
| 480 | +mlir::LogicalResult CIRGenFunction::emitIfOnBoolExpr(const Expr *cond, |
| 481 | + const Stmt *thenS, |
| 482 | + const Stmt *elseS) { |
| 483 | + mlir::Location thenLoc = getLoc(thenS->getSourceRange()); |
| 484 | + std::optional<mlir::Location> elseLoc; |
| 485 | + if (elseS) |
| 486 | + elseLoc = getLoc(elseS->getSourceRange()); |
| 487 | + |
| 488 | + mlir::LogicalResult resThen = mlir::success(), resElse = mlir::success(); |
| 489 | + emitIfOnBoolExpr( |
| 490 | + cond, /*thenBuilder=*/ |
| 491 | + [&](mlir::OpBuilder &, mlir::Location) { |
| 492 | + LexicalScope lexScope{*this, thenLoc, builder.getInsertionBlock()}; |
| 493 | + resThen = emitStmt(thenS, /*useCurrentScope=*/true); |
| 494 | + }, |
| 495 | + thenLoc, |
| 496 | + /*elseBuilder=*/ |
| 497 | + [&](mlir::OpBuilder &, mlir::Location) { |
| 498 | + assert(elseLoc && "Invalid location for elseS."); |
| 499 | + LexicalScope lexScope{*this, *elseLoc, builder.getInsertionBlock()}; |
| 500 | + resElse = emitStmt(elseS, /*useCurrentScope=*/true); |
| 501 | + }, |
| 502 | + elseLoc); |
| 503 | + |
| 504 | + return mlir::LogicalResult::success(resThen.succeeded() && |
| 505 | + resElse.succeeded()); |
| 506 | +} |
| 507 | + |
| 508 | +/// Emit an `if` on a boolean condition, filling `then` and `else` into |
| 509 | +/// appropriated regions. |
| 510 | +cir::IfOp CIRGenFunction::emitIfOnBoolExpr( |
| 511 | + const clang::Expr *cond, BuilderCallbackRef thenBuilder, |
| 512 | + mlir::Location thenLoc, BuilderCallbackRef elseBuilder, |
| 513 | + std::optional<mlir::Location> elseLoc) { |
| 514 | + // Attempt to be as accurate as possible with IfOp location, generate |
| 515 | + // one fused location that has either 2 or 4 total locations, depending |
| 516 | + // on else's availability. |
| 517 | + SmallVector<mlir::Location, 2> ifLocs{thenLoc}; |
| 518 | + if (elseLoc) |
| 519 | + ifLocs.push_back(*elseLoc); |
| 520 | + mlir::Location loc = mlir::FusedLoc::get(&getMLIRContext(), ifLocs); |
| 521 | + |
| 522 | + // Emit the code with the fully general case. |
| 523 | + mlir::Value condV = emitOpOnBoolExpr(loc, cond); |
| 524 | + return builder.create<cir::IfOp>(loc, condV, elseLoc.has_value(), |
| 525 | + /*thenBuilder=*/thenBuilder, |
| 526 | + /*elseBuilder=*/elseBuilder); |
| 527 | +} |
| 528 | + |
| 529 | +/// TODO(cir): see EmitBranchOnBoolExpr for extra ideas). |
| 530 | +mlir::Value CIRGenFunction::emitOpOnBoolExpr(mlir::Location loc, |
| 531 | + const Expr *cond) { |
| 532 | + assert(!cir::MissingFeatures::pgoUse()); |
| 533 | + assert(!cir::MissingFeatures::generateDebugInfo()); |
| 534 | + cond = cond->IgnoreParens(); |
| 535 | + |
| 536 | + // In LLVM the condition is reversed here for efficient codegen. |
| 537 | + // This should be done in CIR prior to LLVM lowering, if we do now |
| 538 | + // we can make CIR based diagnostics misleading. |
| 539 | + // cir.ternary(!x, t, f) -> cir.ternary(x, f, t) |
| 540 | + assert(!cir::MissingFeatures::shouldReverseUnaryCondOnBoolExpr()); |
| 541 | + |
| 542 | + if (isa<ConditionalOperator>(cond)) { |
| 543 | + cgm.errorNYI(cond->getExprLoc(), "Ternary NYI"); |
| 544 | + assert(!cir::MissingFeatures::ternaryOp()); |
| 545 | + return createDummyValue(loc, cond->getType()); |
| 546 | + } |
| 547 | + |
| 548 | + if (isa<CXXThrowExpr>(cond)) { |
| 549 | + cgm.errorNYI("NYI"); |
| 550 | + return createDummyValue(loc, cond->getType()); |
| 551 | + } |
| 552 | + |
| 553 | + // If the branch has a condition wrapped by __builtin_unpredictable, |
| 554 | + // create metadata that specifies that the branch is unpredictable. |
| 555 | + // Don't bother if not optimizing because that metadata would not be used. |
| 556 | + assert(!cir::MissingFeatures::insertBuiltinUnpredictable()); |
| 557 | + |
| 558 | + // Emit the code with the fully general case. |
| 559 | + return evaluateExprAsBool(cond); |
| 560 | +} |
| 561 | + |
477 | 562 | mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty, |
478 | 563 | mlir::Location loc, CharUnits alignment, |
479 | 564 | bool insertIntoFnEntryBlock, |
|
0 commit comments