clang 22.0.0git
CIRGenStmt.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Emit Stmt nodes as CIR code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenBuilder.h"
14#include "CIRGenFunction.h"
15
16#include "mlir/IR/Builders.h"
17#include "mlir/IR/Location.h"
18#include "mlir/Support/LLVM.h"
19#include "clang/AST/ExprCXX.h"
20#include "clang/AST/Stmt.h"
23
24using namespace clang;
25using namespace clang::CIRGen;
26using namespace cir;
27
28static mlir::LogicalResult emitStmtWithResult(CIRGenFunction &cgf,
29 const Stmt *exprResult,
30 AggValueSlot slot,
31 Address *lastValue) {
32 // We have to special case labels here. They are statements, but when put
33 // at the end of a statement expression, they yield the value of their
34 // subexpression. Handle this by walking through all labels we encounter,
35 // emitting them before we evaluate the subexpr.
36 // Similar issues arise for attributed statements.
37 while (!isa<Expr>(exprResult)) {
38 if (const auto *ls = dyn_cast<LabelStmt>(exprResult)) {
39 if (cgf.emitLabel(*ls->getDecl()).failed())
40 return mlir::failure();
41 exprResult = ls->getSubStmt();
42 } else if (const auto *as = dyn_cast<AttributedStmt>(exprResult)) {
43 // FIXME: Update this if we ever have attributes that affect the
44 // semantics of an expression.
45 exprResult = as->getSubStmt();
46 } else {
47 llvm_unreachable("Unknown value statement");
48 }
49 }
50
51 const Expr *e = cast<Expr>(exprResult);
52 QualType exprTy = e->getType();
53 if (cgf.hasAggregateEvaluationKind(exprTy)) {
54 cgf.emitAggExpr(e, slot);
55 } else {
56 // We can't return an RValue here because there might be cleanups at
57 // the end of the StmtExpr. Because of that, we have to emit the result
58 // here into a temporary alloca.
59 cgf.emitAnyExprToMem(e, *lastValue, Qualifiers(),
60 /*IsInit*/ false);
61 }
62
63 return mlir::success();
64}
65
67 const CompoundStmt &s, Address *lastValue, AggValueSlot slot) {
68 mlir::LogicalResult result = mlir::success();
69 const Stmt *exprResult = s.getStmtExprResult();
70 assert((!lastValue || (lastValue && exprResult)) &&
71 "If lastValue is not null then the CompoundStmt must have a "
72 "StmtExprResult");
73
74 for (const Stmt *curStmt : s.body()) {
75 const bool saveResult = lastValue && exprResult == curStmt;
76 if (saveResult) {
77 if (emitStmtWithResult(*this, exprResult, slot, lastValue).failed())
78 result = mlir::failure();
79 } else {
80 if (emitStmt(curStmt, /*useCurrentScope=*/false).failed())
81 result = mlir::failure();
82 }
83 }
84 return result;
85}
86
88 Address *lastValue,
89 AggValueSlot slot) {
90 // Add local scope to track new declared variables.
92 mlir::Location scopeLoc = getLoc(s.getSourceRange());
93 mlir::OpBuilder::InsertPoint scopeInsPt;
94 builder.create<cir::ScopeOp>(
95 scopeLoc, [&](mlir::OpBuilder &b, mlir::Type &type, mlir::Location loc) {
96 scopeInsPt = b.saveInsertionPoint();
97 });
98 mlir::OpBuilder::InsertionGuard guard(builder);
99 builder.restoreInsertionPoint(scopeInsPt);
100 LexicalScope lexScope(*this, scopeLoc, builder.getInsertionBlock());
101 return emitCompoundStmtWithoutScope(s, lastValue, slot);
102}
103
107
108// Build CIR for a statement. useCurrentScope should be true if no new scopes
109// need to be created when finding a compound statement.
110mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
111 bool useCurrentScope,
113 if (mlir::succeeded(emitSimpleStmt(s, useCurrentScope)))
114 return mlir::success();
115
116 switch (s->getStmtClass()) {
118 case Stmt::CXXCatchStmtClass:
119 case Stmt::SEHExceptStmtClass:
120 case Stmt::SEHFinallyStmtClass:
121 case Stmt::MSDependentExistsStmtClass:
122 llvm_unreachable("invalid statement class to emit generically");
123 case Stmt::BreakStmtClass:
124 case Stmt::NullStmtClass:
125 case Stmt::CompoundStmtClass:
126 case Stmt::ContinueStmtClass:
127 case Stmt::DeclStmtClass:
128 case Stmt::ReturnStmtClass:
129 llvm_unreachable("should have emitted these statements as simple");
130
131#define STMT(Type, Base)
132#define ABSTRACT_STMT(Op)
133#define EXPR(Type, Base) case Stmt::Type##Class:
134#include "clang/AST/StmtNodes.inc"
135 {
136 assert(builder.getInsertionBlock() &&
137 "expression emission must have an insertion point");
138
140
141 // Classic codegen has a check here to see if the emitter created a new
142 // block that isn't used (comparing the incoming and outgoing insertion
143 // points) and deletes the outgoing block if it's not used. In CIR, we
144 // will handle that during the cir.canonicalize pass.
145 return mlir::success();
146 }
147 case Stmt::IfStmtClass:
148 return emitIfStmt(cast<IfStmt>(*s));
149 case Stmt::SwitchStmtClass:
151 case Stmt::ForStmtClass:
152 return emitForStmt(cast<ForStmt>(*s));
153 case Stmt::WhileStmtClass:
155 case Stmt::DoStmtClass:
156 return emitDoStmt(cast<DoStmt>(*s));
157 case Stmt::CXXTryStmtClass:
159 case Stmt::CXXForRangeStmtClass:
161 case Stmt::OpenACCComputeConstructClass:
163 case Stmt::OpenACCLoopConstructClass:
165 case Stmt::OpenACCCombinedConstructClass:
167 case Stmt::OpenACCDataConstructClass:
169 case Stmt::OpenACCEnterDataConstructClass:
171 case Stmt::OpenACCExitDataConstructClass:
173 case Stmt::OpenACCHostDataConstructClass:
175 case Stmt::OpenACCWaitConstructClass:
177 case Stmt::OpenACCInitConstructClass:
179 case Stmt::OpenACCShutdownConstructClass:
181 case Stmt::OpenACCSetConstructClass:
183 case Stmt::OpenACCUpdateConstructClass:
185 case Stmt::OpenACCCacheConstructClass:
187 case Stmt::OpenACCAtomicConstructClass:
189 case Stmt::GCCAsmStmtClass:
190 case Stmt::MSAsmStmtClass:
191 return emitAsmStmt(cast<AsmStmt>(*s));
192 case Stmt::OMPScopeDirectiveClass:
193 case Stmt::OMPErrorDirectiveClass:
194 case Stmt::LabelStmtClass:
195 case Stmt::AttributedStmtClass:
196 case Stmt::GotoStmtClass:
197 case Stmt::DefaultStmtClass:
198 case Stmt::CaseStmtClass:
199 case Stmt::SEHLeaveStmtClass:
200 case Stmt::SYCLKernelCallStmtClass:
201 case Stmt::CoroutineBodyStmtClass:
203 case Stmt::CoreturnStmtClass:
204 case Stmt::IndirectGotoStmtClass:
205 case Stmt::OMPParallelDirectiveClass:
206 case Stmt::OMPTaskwaitDirectiveClass:
207 case Stmt::OMPTaskyieldDirectiveClass:
208 case Stmt::OMPBarrierDirectiveClass:
209 case Stmt::CapturedStmtClass:
210 case Stmt::ObjCAtTryStmtClass:
211 case Stmt::ObjCAtThrowStmtClass:
212 case Stmt::ObjCAtSynchronizedStmtClass:
213 case Stmt::ObjCForCollectionStmtClass:
214 case Stmt::ObjCAutoreleasePoolStmtClass:
215 case Stmt::SEHTryStmtClass:
216 case Stmt::OMPMetaDirectiveClass:
217 case Stmt::OMPCanonicalLoopClass:
218 case Stmt::OMPSimdDirectiveClass:
219 case Stmt::OMPTileDirectiveClass:
220 case Stmt::OMPUnrollDirectiveClass:
221 case Stmt::OMPFuseDirectiveClass:
222 case Stmt::OMPForDirectiveClass:
223 case Stmt::OMPForSimdDirectiveClass:
224 case Stmt::OMPSectionsDirectiveClass:
225 case Stmt::OMPSectionDirectiveClass:
226 case Stmt::OMPSingleDirectiveClass:
227 case Stmt::OMPMasterDirectiveClass:
228 case Stmt::OMPCriticalDirectiveClass:
229 case Stmt::OMPParallelForDirectiveClass:
230 case Stmt::OMPParallelForSimdDirectiveClass:
231 case Stmt::OMPParallelMasterDirectiveClass:
232 case Stmt::OMPParallelSectionsDirectiveClass:
233 case Stmt::OMPTaskDirectiveClass:
234 case Stmt::OMPTaskgroupDirectiveClass:
235 case Stmt::OMPFlushDirectiveClass:
236 case Stmt::OMPDepobjDirectiveClass:
237 case Stmt::OMPScanDirectiveClass:
238 case Stmt::OMPOrderedDirectiveClass:
239 case Stmt::OMPAtomicDirectiveClass:
240 case Stmt::OMPTargetDirectiveClass:
241 case Stmt::OMPTeamsDirectiveClass:
242 case Stmt::OMPCancellationPointDirectiveClass:
243 case Stmt::OMPCancelDirectiveClass:
244 case Stmt::OMPTargetDataDirectiveClass:
245 case Stmt::OMPTargetEnterDataDirectiveClass:
246 case Stmt::OMPTargetExitDataDirectiveClass:
247 case Stmt::OMPTargetParallelDirectiveClass:
248 case Stmt::OMPTargetParallelForDirectiveClass:
249 case Stmt::OMPTaskLoopDirectiveClass:
250 case Stmt::OMPTaskLoopSimdDirectiveClass:
251 case Stmt::OMPMaskedTaskLoopDirectiveClass:
252 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
253 case Stmt::OMPMasterTaskLoopDirectiveClass:
254 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
255 case Stmt::OMPParallelGenericLoopDirectiveClass:
256 case Stmt::OMPParallelMaskedDirectiveClass:
257 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
258 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
259 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
260 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
261 case Stmt::OMPDistributeDirectiveClass:
262 case Stmt::OMPDistributeParallelForDirectiveClass:
263 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
264 case Stmt::OMPDistributeSimdDirectiveClass:
265 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
266 case Stmt::OMPTargetParallelForSimdDirectiveClass:
267 case Stmt::OMPTargetSimdDirectiveClass:
268 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
269 case Stmt::OMPTargetUpdateDirectiveClass:
270 case Stmt::OMPTeamsDistributeDirectiveClass:
271 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
272 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
273 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
274 case Stmt::OMPTeamsGenericLoopDirectiveClass:
275 case Stmt::OMPTargetTeamsDirectiveClass:
276 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
277 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
278 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
279 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
280 case Stmt::OMPInteropDirectiveClass:
281 case Stmt::OMPDispatchDirectiveClass:
282 case Stmt::OMPGenericLoopDirectiveClass:
283 case Stmt::OMPReverseDirectiveClass:
284 case Stmt::OMPInterchangeDirectiveClass:
285 case Stmt::OMPAssumeDirectiveClass:
286 case Stmt::OMPMaskedDirectiveClass:
287 case Stmt::OMPStripeDirectiveClass:
288 case Stmt::ObjCAtCatchStmtClass:
289 case Stmt::ObjCAtFinallyStmtClass:
290 cgm.errorNYI(s->getSourceRange(),
291 std::string("emitStmt: ") + s->getStmtClassName());
292 return mlir::failure();
293 }
294
295 llvm_unreachable("Unexpected statement class");
296}
297
298mlir::LogicalResult CIRGenFunction::emitSimpleStmt(const Stmt *s,
299 bool useCurrentScope) {
300 switch (s->getStmtClass()) {
301 default:
302 return mlir::failure();
303 case Stmt::DeclStmtClass:
304 return emitDeclStmt(cast<DeclStmt>(*s));
305 case Stmt::CompoundStmtClass:
306 if (useCurrentScope)
309 case Stmt::GotoStmtClass:
310 return emitGotoStmt(cast<GotoStmt>(*s));
311 case Stmt::ContinueStmtClass:
313
314 // NullStmt doesn't need any handling, but we need to say we handled it.
315 case Stmt::NullStmtClass:
316 break;
317
318 case Stmt::LabelStmtClass:
320 case Stmt::CaseStmtClass:
321 case Stmt::DefaultStmtClass:
322 // If we reached here, we must not handling a switch case in the top level.
324 /*buildingTopLevelCase=*/false);
325 break;
326
327 case Stmt::BreakStmtClass:
329 case Stmt::ReturnStmtClass:
331 }
332
333 return mlir::success();
334}
335
337
338 if (emitLabel(*s.getDecl()).failed())
339 return mlir::failure();
340
341 if (getContext().getLangOpts().EHAsynch && s.isSideEntry())
342 getCIRGenModule().errorNYI(s.getSourceRange(), "IsEHa: not implemented.");
343
344 return emitStmt(s.getSubStmt(), /*useCurrentScope*/ true);
345}
346
347// Add a terminating yield on a body region if no other terminators are used.
348static void terminateBody(CIRGenBuilderTy &builder, mlir::Region &r,
349 mlir::Location loc) {
350 if (r.empty())
351 return;
352
354 unsigned numBlocks = r.getBlocks().size();
355 for (auto &block : r.getBlocks()) {
356 // Already cleanup after return operations, which might create
357 // empty blocks if emitted as last stmt.
358 if (numBlocks != 1 && block.empty() && block.hasNoPredecessors() &&
359 block.hasNoSuccessors())
360 eraseBlocks.push_back(&block);
361
362 if (block.empty() ||
363 !block.back().hasTrait<mlir::OpTrait::IsTerminator>()) {
364 mlir::OpBuilder::InsertionGuard guardCase(builder);
365 builder.setInsertionPointToEnd(&block);
366 builder.createYield(loc);
367 }
368 }
369
370 for (auto *b : eraseBlocks)
371 b->erase();
372}
373
374mlir::LogicalResult CIRGenFunction::emitIfStmt(const IfStmt &s) {
375 mlir::LogicalResult res = mlir::success();
376 // The else branch of a consteval if statement is always the only branch
377 // that can be runtime evaluated.
378 const Stmt *constevalExecuted;
379 if (s.isConsteval()) {
380 constevalExecuted = s.isNegatedConsteval() ? s.getThen() : s.getElse();
381 if (!constevalExecuted) {
382 // No runtime code execution required
383 return res;
384 }
385 }
386
387 // C99 6.8.4.1: The first substatement is executed if the expression
388 // compares unequal to 0. The condition must be a scalar type.
389 auto ifStmtBuilder = [&]() -> mlir::LogicalResult {
390 if (s.isConsteval())
391 return emitStmt(constevalExecuted, /*useCurrentScope=*/true);
392
393 if (s.getInit())
394 if (emitStmt(s.getInit(), /*useCurrentScope=*/true).failed())
395 return mlir::failure();
396
397 if (s.getConditionVariable())
398 emitDecl(*s.getConditionVariable());
399
400 // If the condition folds to a constant and this is an 'if constexpr',
401 // we simplify it early in CIRGen to avoid emitting the full 'if'.
402 bool condConstant;
403 if (constantFoldsToBool(s.getCond(), condConstant, s.isConstexpr())) {
404 if (s.isConstexpr()) {
405 // Handle "if constexpr" explicitly here to avoid generating some
406 // ill-formed code since in CIR the "if" is no longer simplified
407 // in this lambda like in Clang but postponed to other MLIR
408 // passes.
409 if (const Stmt *executed = condConstant ? s.getThen() : s.getElse())
410 return emitStmt(executed, /*useCurrentScope=*/true);
411 // There is nothing to execute at runtime.
412 // TODO(cir): there is still an empty cir.scope generated by the caller.
413 return mlir::success();
414 }
415 }
416
419 return emitIfOnBoolExpr(s.getCond(), s.getThen(), s.getElse());
420 };
421
422 // TODO: Add a new scoped symbol table.
423 // LexicalScope ConditionScope(*this, S.getCond()->getSourceRange());
424 // The if scope contains the full source range for IfStmt.
425 mlir::Location scopeLoc = getLoc(s.getSourceRange());
426 builder.create<cir::ScopeOp>(
427 scopeLoc, /*scopeBuilder=*/
428 [&](mlir::OpBuilder &b, mlir::Location loc) {
429 LexicalScope lexScope{*this, scopeLoc, builder.getInsertionBlock()};
430 res = ifStmtBuilder();
431 });
432
433 return res;
434}
435
436mlir::LogicalResult CIRGenFunction::emitDeclStmt(const DeclStmt &s) {
437 assert(builder.getInsertionBlock() && "expected valid insertion point");
438
439 for (const Decl *i : s.decls())
440 emitDecl(*i, /*evaluateConditionDecl=*/true);
441
442 return mlir::success();
443}
444
445mlir::LogicalResult CIRGenFunction::emitReturnStmt(const ReturnStmt &s) {
446 mlir::Location loc = getLoc(s.getSourceRange());
447 const Expr *rv = s.getRetValue();
448
449 if (getContext().getLangOpts().ElideConstructors && s.getNRVOCandidate() &&
450 s.getNRVOCandidate()->isNRVOVariable()) {
453 } else if (!rv) {
454 // No return expression. Do nothing.
455 } else if (rv->getType()->isVoidType()) {
456 // Make sure not to return anything, but evaluate the expression
457 // for side effects.
458 if (rv) {
459 emitAnyExpr(rv);
460 }
461 } else if (cast<FunctionDecl>(curGD.getDecl())
462 ->getReturnType()
463 ->isReferenceType()) {
464 // If this function returns a reference, take the address of the
465 // expression rather than the value.
467 builder.CIRBaseBuilderTy::createStore(loc, result.getValue(), *fnRetAlloca);
468 } else {
469 mlir::Value value = nullptr;
471 case cir::TEK_Scalar:
472 value = emitScalarExpr(rv);
473 if (value) { // Change this to an assert once emitScalarExpr is complete
474 builder.CIRBaseBuilderTy::createStore(loc, value, *fnRetAlloca);
475 }
476 break;
477 case cir::TEK_Complex:
478 getCIRGenModule().errorNYI(s.getSourceRange(),
479 "complex function return type");
480 break;
487 break;
488 }
489 }
490
491 auto *retBlock = curLexScope->getOrCreateRetBlock(*this, loc);
492 // This should emit a branch through the cleanup block if one exists.
493 builder.create<cir::BrOp>(loc, retBlock);
495 if (ehStack.stable_begin() != currentCleanupStackDepth)
496 cgm.errorNYI(s.getSourceRange(), "return with cleanup stack");
497
498 // Insert the new block to continue codegen after branch to ret block.
499 builder.createBlock(builder.getBlock()->getParent());
500
501 return mlir::success();
502}
503
504mlir::LogicalResult CIRGenFunction::emitGotoStmt(const clang::GotoStmt &s) {
505 // FIXME: LLVM codegen inserts emit a stop point here for debug info
506 // sake when the insertion point is available, but doesn't do
507 // anything special when there isn't. We haven't implemented debug
508 // info support just yet, look at this again once we have it.
510
511 cir::GotoOp::create(builder, getLoc(s.getSourceRange()),
512 s.getLabel()->getName());
513
514 // A goto marks the end of a block, create a new one for codegen after
515 // emitGotoStmt can resume building in that block.
516 // Insert the new block to continue codegen after goto.
517 builder.createBlock(builder.getBlock()->getParent());
518
519 return mlir::success();
520}
521
522mlir::LogicalResult
524 builder.createContinue(getLoc(s.getKwLoc()));
525
526 // Insert the new block to continue codegen after the continue statement.
527 builder.createBlock(builder.getBlock()->getParent());
528
529 return mlir::success();
530}
531
532mlir::LogicalResult CIRGenFunction::emitLabel(const clang::LabelDecl &d) {
533 // Create a new block to tag with a label and add a branch from
534 // the current one to it. If the block is empty just call attach it
535 // to this label.
536 mlir::Block *currBlock = builder.getBlock();
537 mlir::Block *labelBlock = currBlock;
538
539 if (!currBlock->empty()) {
540 {
541 mlir::OpBuilder::InsertionGuard guard(builder);
542 labelBlock = builder.createBlock(builder.getBlock()->getParent());
543 }
544 builder.create<cir::BrOp>(getLoc(d.getSourceRange()), labelBlock);
545 }
546
547 builder.setInsertionPointToEnd(labelBlock);
548 builder.create<cir::LabelOp>(getLoc(d.getSourceRange()), d.getName());
549 builder.setInsertionPointToEnd(labelBlock);
550
551 // FIXME: emit debug info for labels, incrementProfileCounter
555 return mlir::success();
556}
557
559 builder.createBreak(getLoc(s.getKwLoc()));
560
561 // Insert the new block to continue codegen after the break statement.
562 builder.createBlock(builder.getBlock()->getParent());
563
564 return mlir::success();
565}
566
567template <typename T>
568mlir::LogicalResult
570 mlir::ArrayAttr value, CaseOpKind kind,
571 bool buildingTopLevelCase) {
572
574 "only case or default stmt go here");
575
576 mlir::LogicalResult result = mlir::success();
577
578 mlir::Location loc = getLoc(stmt->getBeginLoc());
579
580 enum class SubStmtKind { Case, Default, Other };
581 SubStmtKind subStmtKind = SubStmtKind::Other;
582 const Stmt *sub = stmt->getSubStmt();
583
584 mlir::OpBuilder::InsertPoint insertPoint;
585 builder.create<CaseOp>(loc, value, kind, insertPoint);
586
587 {
588 mlir::OpBuilder::InsertionGuard guardSwitch(builder);
589 builder.restoreInsertionPoint(insertPoint);
590
591 if (isa<DefaultStmt>(sub) && isa<CaseStmt>(stmt)) {
592 subStmtKind = SubStmtKind::Default;
593 builder.createYield(loc);
594 } else if (isa<CaseStmt>(sub) && isa<DefaultStmt, CaseStmt>(stmt)) {
595 subStmtKind = SubStmtKind::Case;
596 builder.createYield(loc);
597 } else {
598 result = emitStmt(sub, /*useCurrentScope=*/!isa<CompoundStmt>(sub));
599 }
600
601 insertPoint = builder.saveInsertionPoint();
602 }
603
604 // If the substmt is default stmt or case stmt, try to handle the special case
605 // to make it into the simple form. e.g.
606 //
607 // swtich () {
608 // case 1:
609 // default:
610 // ...
611 // }
612 //
613 // we prefer generating
614 //
615 // cir.switch() {
616 // cir.case(equal, 1) {
617 // cir.yield
618 // }
619 // cir.case(default) {
620 // ...
621 // }
622 // }
623 //
624 // than
625 //
626 // cir.switch() {
627 // cir.case(equal, 1) {
628 // cir.case(default) {
629 // ...
630 // }
631 // }
632 // }
633 //
634 // We don't need to revert this if we find the current switch can't be in
635 // simple form later since the conversion itself should be harmless.
636 if (subStmtKind == SubStmtKind::Case) {
637 result = emitCaseStmt(*cast<CaseStmt>(sub), condType, buildingTopLevelCase);
638 } else if (subStmtKind == SubStmtKind::Default) {
639 result = emitDefaultStmt(*cast<DefaultStmt>(sub), condType,
640 buildingTopLevelCase);
641 } else if (buildingTopLevelCase) {
642 // If we're building a top level case, try to restore the insert point to
643 // the case we're building, then we can attach more random stmts to the
644 // case to make generating `cir.switch` operation to be a simple form.
645 builder.restoreInsertionPoint(insertPoint);
646 }
647
648 return result;
649}
650
651mlir::LogicalResult CIRGenFunction::emitCaseStmt(const CaseStmt &s,
652 mlir::Type condType,
653 bool buildingTopLevelCase) {
654 cir::CaseOpKind kind;
655 mlir::ArrayAttr value;
656 llvm::APSInt intVal = s.getLHS()->EvaluateKnownConstInt(getContext());
657
658 // If the case statement has an RHS value, it is representing a GNU
659 // case range statement, where LHS is the beginning of the range
660 // and RHS is the end of the range.
661 if (const Expr *rhs = s.getRHS()) {
662 llvm::APSInt endVal = rhs->EvaluateKnownConstInt(getContext());
663 value = builder.getArrayAttr({cir::IntAttr::get(condType, intVal),
664 cir::IntAttr::get(condType, endVal)});
665 kind = cir::CaseOpKind::Range;
666 } else {
667 value = builder.getArrayAttr({cir::IntAttr::get(condType, intVal)});
668 kind = cir::CaseOpKind::Equal;
669 }
670
671 return emitCaseDefaultCascade(&s, condType, value, kind,
672 buildingTopLevelCase);
673}
674
676 mlir::Type condType,
677 bool buildingTopLevelCase) {
678 return emitCaseDefaultCascade(&s, condType, builder.getArrayAttr({}),
679 cir::CaseOpKind::Default, buildingTopLevelCase);
680}
681
682mlir::LogicalResult CIRGenFunction::emitSwitchCase(const SwitchCase &s,
683 bool buildingTopLevelCase) {
684 assert(!condTypeStack.empty() &&
685 "build switch case without specifying the type of the condition");
686
687 if (s.getStmtClass() == Stmt::CaseStmtClass)
689 buildingTopLevelCase);
690
691 if (s.getStmtClass() == Stmt::DefaultStmtClass)
693 buildingTopLevelCase);
694
695 llvm_unreachable("expect case or default stmt");
696}
697
698mlir::LogicalResult
700 ArrayRef<const Attr *> forAttrs) {
701 cir::ForOp forOp;
702
703 // TODO(cir): pass in array of attributes.
704 auto forStmtBuilder = [&]() -> mlir::LogicalResult {
705 mlir::LogicalResult loopRes = mlir::success();
706 // Evaluate the first pieces before the loop.
707 if (s.getInit())
708 if (emitStmt(s.getInit(), /*useCurrentScope=*/true).failed())
709 return mlir::failure();
710 if (emitStmt(s.getRangeStmt(), /*useCurrentScope=*/true).failed())
711 return mlir::failure();
712 if (emitStmt(s.getBeginStmt(), /*useCurrentScope=*/true).failed())
713 return mlir::failure();
714 if (emitStmt(s.getEndStmt(), /*useCurrentScope=*/true).failed())
715 return mlir::failure();
716
718 // From LLVM: if there are any cleanups between here and the loop-exit
719 // scope, create a block to stage a loop exit along.
720 // We probably already do the right thing because of ScopeOp, but make
721 // sure we handle all cases.
723
724 forOp = builder.createFor(
725 getLoc(s.getSourceRange()),
726 /*condBuilder=*/
727 [&](mlir::OpBuilder &b, mlir::Location loc) {
728 assert(!cir::MissingFeatures::createProfileWeightsForLoop());
729 assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
730 mlir::Value condVal = evaluateExprAsBool(s.getCond());
731 builder.createCondition(condVal);
732 },
733 /*bodyBuilder=*/
734 [&](mlir::OpBuilder &b, mlir::Location loc) {
735 // https://en.cppreference.com/w/cpp/language/for
736 // In C++ the scope of the init-statement and the scope of
737 // statement are one and the same.
738 bool useCurrentScope = true;
739 if (emitStmt(s.getLoopVarStmt(), useCurrentScope).failed())
740 loopRes = mlir::failure();
741 if (emitStmt(s.getBody(), useCurrentScope).failed())
742 loopRes = mlir::failure();
743 emitStopPoint(&s);
744 },
745 /*stepBuilder=*/
746 [&](mlir::OpBuilder &b, mlir::Location loc) {
747 if (s.getInc())
748 if (emitStmt(s.getInc(), /*useCurrentScope=*/true).failed())
749 loopRes = mlir::failure();
750 builder.createYield(loc);
751 });
752 return loopRes;
753 };
754
755 mlir::LogicalResult res = mlir::success();
756 mlir::Location scopeLoc = getLoc(s.getSourceRange());
757 builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
758 [&](mlir::OpBuilder &b, mlir::Location loc) {
759 // Create a cleanup scope for the condition
760 // variable cleanups. Logical equivalent from
761 // LLVM codegn for LexicalScope
762 // ConditionScope(*this, S.getSourceRange())...
763 LexicalScope lexScope{
764 *this, loc, builder.getInsertionBlock()};
765 res = forStmtBuilder();
766 });
767
768 if (res.failed())
769 return res;
770
771 terminateBody(builder, forOp.getBody(), getLoc(s.getEndLoc()));
772 return mlir::success();
773}
774
775mlir::LogicalResult CIRGenFunction::emitForStmt(const ForStmt &s) {
776 cir::ForOp forOp;
777
778 // TODO: pass in an array of attributes.
779 auto forStmtBuilder = [&]() -> mlir::LogicalResult {
780 mlir::LogicalResult loopRes = mlir::success();
781 // Evaluate the first part before the loop.
782 if (s.getInit())
783 if (emitStmt(s.getInit(), /*useCurrentScope=*/true).failed())
784 return mlir::failure();
786 // In the classic codegen, if there are any cleanups between here and the
787 // loop-exit scope, a block is created to stage the loop exit. We probably
788 // already do the right thing because of ScopeOp, but we need more testing
789 // to be sure we handle all cases.
791
792 forOp = builder.createFor(
793 getLoc(s.getSourceRange()),
794 /*condBuilder=*/
795 [&](mlir::OpBuilder &b, mlir::Location loc) {
796 assert(!cir::MissingFeatures::createProfileWeightsForLoop());
797 assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
798 mlir::Value condVal;
799 if (s.getCond()) {
800 // If the for statement has a condition scope,
801 // emit the local variable declaration.
802 if (s.getConditionVariable())
803 emitDecl(*s.getConditionVariable());
804 // C99 6.8.5p2/p4: The first substatement is executed if the
805 // expression compares unequal to 0. The condition must be a
806 // scalar type.
807 condVal = evaluateExprAsBool(s.getCond());
808 } else {
809 condVal = b.create<cir::ConstantOp>(loc, builder.getTrueAttr());
810 }
811 builder.createCondition(condVal);
812 },
813 /*bodyBuilder=*/
814 [&](mlir::OpBuilder &b, mlir::Location loc) {
815 // The scope of the for loop body is nested within the scope of the
816 // for loop's init-statement and condition.
817 if (emitStmt(s.getBody(), /*useCurrentScope=*/false).failed())
818 loopRes = mlir::failure();
820 },
821 /*stepBuilder=*/
822 [&](mlir::OpBuilder &b, mlir::Location loc) {
823 if (s.getInc())
824 if (emitStmt(s.getInc(), /*useCurrentScope=*/true).failed())
825 loopRes = mlir::failure();
826 builder.createYield(loc);
827 });
828 return loopRes;
829 };
830
831 auto res = mlir::success();
832 auto scopeLoc = getLoc(s.getSourceRange());
833 builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
834 [&](mlir::OpBuilder &b, mlir::Location loc) {
835 LexicalScope lexScope{
836 *this, loc, builder.getInsertionBlock()};
837 res = forStmtBuilder();
838 });
839
840 if (res.failed())
841 return res;
842
843 terminateBody(builder, forOp.getBody(), getLoc(s.getEndLoc()));
844 return mlir::success();
845}
846
847mlir::LogicalResult CIRGenFunction::emitDoStmt(const DoStmt &s) {
848 cir::DoWhileOp doWhileOp;
849
850 // TODO: pass in array of attributes.
851 auto doStmtBuilder = [&]() -> mlir::LogicalResult {
852 mlir::LogicalResult loopRes = mlir::success();
854 // From LLVM: if there are any cleanups between here and the loop-exit
855 // scope, create a block to stage a loop exit along.
856 // We probably already do the right thing because of ScopeOp, but make
857 // sure we handle all cases.
859
860 doWhileOp = builder.createDoWhile(
861 getLoc(s.getSourceRange()),
862 /*condBuilder=*/
863 [&](mlir::OpBuilder &b, mlir::Location loc) {
864 assert(!cir::MissingFeatures::createProfileWeightsForLoop());
865 assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
866 // C99 6.8.5p2/p4: The first substatement is executed if the
867 // expression compares unequal to 0. The condition must be a
868 // scalar type.
869 mlir::Value condVal = evaluateExprAsBool(s.getCond());
870 builder.createCondition(condVal);
871 },
872 /*bodyBuilder=*/
873 [&](mlir::OpBuilder &b, mlir::Location loc) {
874 // The scope of the do-while loop body is a nested scope.
875 if (emitStmt(s.getBody(), /*useCurrentScope=*/false).failed())
876 loopRes = mlir::failure();
877 emitStopPoint(&s);
878 });
879 return loopRes;
880 };
881
882 mlir::LogicalResult res = mlir::success();
883 mlir::Location scopeLoc = getLoc(s.getSourceRange());
884 builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
885 [&](mlir::OpBuilder &b, mlir::Location loc) {
886 LexicalScope lexScope{
887 *this, loc, builder.getInsertionBlock()};
888 res = doStmtBuilder();
889 });
890
891 if (res.failed())
892 return res;
893
894 terminateBody(builder, doWhileOp.getBody(), getLoc(s.getEndLoc()));
895 return mlir::success();
896}
897
898mlir::LogicalResult CIRGenFunction::emitWhileStmt(const WhileStmt &s) {
899 cir::WhileOp whileOp;
900
901 // TODO: pass in array of attributes.
902 auto whileStmtBuilder = [&]() -> mlir::LogicalResult {
903 mlir::LogicalResult loopRes = mlir::success();
905 // From LLVM: if there are any cleanups between here and the loop-exit
906 // scope, create a block to stage a loop exit along.
907 // We probably already do the right thing because of ScopeOp, but make
908 // sure we handle all cases.
910
911 whileOp = builder.createWhile(
912 getLoc(s.getSourceRange()),
913 /*condBuilder=*/
914 [&](mlir::OpBuilder &b, mlir::Location loc) {
915 assert(!cir::MissingFeatures::createProfileWeightsForLoop());
916 assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
917 mlir::Value condVal;
918 // If the for statement has a condition scope,
919 // emit the local variable declaration.
920 if (s.getConditionVariable())
921 emitDecl(*s.getConditionVariable());
922 // C99 6.8.5p2/p4: The first substatement is executed if the
923 // expression compares unequal to 0. The condition must be a
924 // scalar type.
925 condVal = evaluateExprAsBool(s.getCond());
926 builder.createCondition(condVal);
927 },
928 /*bodyBuilder=*/
929 [&](mlir::OpBuilder &b, mlir::Location loc) {
930 // The scope of the while loop body is a nested scope.
931 if (emitStmt(s.getBody(), /*useCurrentScope=*/false).failed())
932 loopRes = mlir::failure();
933 emitStopPoint(&s);
934 });
935 return loopRes;
936 };
937
938 mlir::LogicalResult res = mlir::success();
939 mlir::Location scopeLoc = getLoc(s.getSourceRange());
940 builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
941 [&](mlir::OpBuilder &b, mlir::Location loc) {
942 LexicalScope lexScope{
943 *this, loc, builder.getInsertionBlock()};
944 res = whileStmtBuilder();
945 });
946
947 if (res.failed())
948 return res;
949
950 terminateBody(builder, whileOp.getBody(), getLoc(s.getEndLoc()));
951 return mlir::success();
952}
953
954mlir::LogicalResult CIRGenFunction::emitSwitchBody(const Stmt *s) {
955 // It is rare but legal if the switch body is not a compound stmt. e.g.,
956 //
957 // switch(a)
958 // while(...) {
959 // case1
960 // ...
961 // case2
962 // ...
963 // }
964 if (!isa<CompoundStmt>(s))
965 return emitStmt(s, /*useCurrentScope=*/true);
966
968
969 mlir::Block *swtichBlock = builder.getBlock();
970 for (auto *c : compoundStmt->body()) {
971 if (auto *switchCase = dyn_cast<SwitchCase>(c)) {
972 builder.setInsertionPointToEnd(swtichBlock);
973 // Reset insert point automatically, so that we can attach following
974 // random stmt to the region of previous built case op to try to make
975 // the being generated `cir.switch` to be in simple form.
976 if (mlir::failed(
977 emitSwitchCase(*switchCase, /*buildingTopLevelCase=*/true)))
978 return mlir::failure();
979
980 continue;
981 }
982
983 // Otherwise, just build the statements in the nearest case region.
984 if (mlir::failed(emitStmt(c, /*useCurrentScope=*/!isa<CompoundStmt>(c))))
985 return mlir::failure();
986 }
987
988 return mlir::success();
989}
990
992 // TODO: LLVM codegen does some early optimization to fold the condition and
993 // only emit live cases. CIR should use MLIR to achieve similar things,
994 // nothing to be done here.
995 // if (ConstantFoldsToSimpleInteger(S.getCond(), ConstantCondValue))...
997
998 SwitchOp swop;
999 auto switchStmtBuilder = [&]() -> mlir::LogicalResult {
1000 if (s.getInit())
1001 if (emitStmt(s.getInit(), /*useCurrentScope=*/true).failed())
1002 return mlir::failure();
1003
1004 if (s.getConditionVariable())
1005 emitDecl(*s.getConditionVariable(), /*evaluateConditionDecl=*/true);
1006
1007 mlir::Value condV = emitScalarExpr(s.getCond());
1008
1009 // TODO: PGO and likelihood (e.g. PGO.haveRegionCounts())
1012 // TODO: if the switch has a condition wrapped by __builtin_unpredictable?
1014
1015 mlir::LogicalResult res = mlir::success();
1016 swop = builder.create<SwitchOp>(
1017 getLoc(s.getBeginLoc()), condV,
1018 /*switchBuilder=*/
1019 [&](mlir::OpBuilder &b, mlir::Location loc, mlir::OperationState &os) {
1020 curLexScope->setAsSwitch();
1021
1022 condTypeStack.push_back(condV.getType());
1023
1024 res = emitSwitchBody(s.getBody());
1025
1026 condTypeStack.pop_back();
1027 });
1028
1029 return res;
1030 };
1031
1032 // The switch scope contains the full source range for SwitchStmt.
1033 mlir::Location scopeLoc = getLoc(s.getSourceRange());
1034 mlir::LogicalResult res = mlir::success();
1035 builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
1036 [&](mlir::OpBuilder &b, mlir::Location loc) {
1037 LexicalScope lexScope{
1038 *this, loc, builder.getInsertionBlock()};
1039 res = switchStmtBuilder();
1040 });
1041
1043 swop.collectCases(cases);
1044 for (auto caseOp : cases)
1045 terminateBody(builder, caseOp.getCaseRegion(), caseOp.getLoc());
1046 terminateBody(builder, swop.getBody(), swop.getLoc());
1047
1048 return res;
1049}
1050
1051void CIRGenFunction::emitReturnOfRValue(mlir::Location loc, RValue rv,
1052 QualType ty) {
1053 if (rv.isScalar()) {
1054 builder.createStore(loc, rv.getValue(), returnValue);
1055 } else if (rv.isAggregate()) {
1056 LValue dest = makeAddrLValue(returnValue, ty);
1059 } else {
1060 cgm.errorNYI(loc, "emitReturnOfRValue: complex return type");
1061 }
1062 mlir::Block *retBlock = curLexScope->getOrCreateRetBlock(*this, loc);
1064 builder.create<cir::BrOp>(loc, retBlock);
1065 if (ehStack.stable_begin() != currentCleanupStackDepth)
1066 cgm.errorNYI(loc, "return with cleanup stack");
1067}
static void terminateBody(CIRGenBuilderTy &builder, mlir::Region &r, mlir::Location loc)
static mlir::LogicalResult emitStmtWithResult(CIRGenFunction &cgf, const Stmt *exprResult, AggValueSlot slot, Address *lastValue)
Defines the clang::Expr interface and subclasses for C++ expressions.
This file defines OpenACC AST classes for statement-level contructs.
__device__ __2f16 b
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
BreakStmt - This represents a break.
Definition Stmt.h:3135
An aggregate value slot.
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
mlir::LogicalResult emitDoStmt(const clang::DoStmt &s)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s)
mlir::LogicalResult emitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &s)
mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s)
const clang::LangOptions & getLangOpts() const
mlir::LogicalResult emitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &s)
mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond, const clang::Stmt *thenS, const clang::Stmt *elseS)
Emit an if on a boolean condition to the specified blocks.
mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s)
mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s, llvm::ArrayRef< const Attr * > attrs)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s)
mlir::LogicalResult emitOpenACCInitConstruct(const OpenACCInitConstruct &s)
void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals, bool isInitializer)
Emits the code necessary to evaluate an arbitrary expression into the given memory location.
mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s)
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored())
Emit code to compute the specified expression which can have any type.
mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s)
mlir::LogicalResult emitCaseStmt(const clang::CaseStmt &s, mlir::Type condType, bool buildingTopLevelCase)
llvm::ScopedHashTableScope< const clang::Decl *, mlir::Value > SymTableScopeTy
mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, bool useCurrentScope)
mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s)
Definition CIRGenAsm.cpp:86
mlir::LogicalResult emitOpenACCComputeConstruct(const OpenACCComputeConstruct &s)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
mlir::LogicalResult emitSwitchBody(const clang::Stmt *s)
mlir::LogicalResult emitForStmt(const clang::ForStmt &s)
std::optional< mlir::Value > fnRetAlloca
The compiler-generated variable that holds the return value.
Address returnValue
The temporary alloca to hold the return value.
mlir::LogicalResult emitLabel(const clang::LabelDecl &d)
static bool hasAggregateEvaluationKind(clang::QualType type)
mlir::LogicalResult emitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &s)
mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s)
void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty)
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s)
llvm::SmallVector< mlir::Type, 2 > condTypeStack
The type of the condition for the emitting switch statement.
mlir::Value emitScalarExpr(const clang::Expr *e)
Emit the computation of the specified expression of scalar type.
void emitStopPoint(const Stmt *s)
Build a debug stoppoint if we are emitting debug info.
mlir::LogicalResult emitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &s)
mlir::LogicalResult emitIfStmt(const clang::IfStmt &s)
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s, bool buildingTopLevelCase)
void emitDecl(const clang::Decl &d, bool evaluateConditionDecl=false)
mlir::LogicalResult emitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &s)
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s)
mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType, mlir::ArrayAttr value, cir::CaseOpKind kind, bool buildingTopLevelCase)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s)
mlir::LogicalResult emitDefaultStmt(const clang::DefaultStmt &s, mlir::Type condType, bool buildingTopLevelCase)
mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s)
mlir::LogicalResult emitLabelStmt(const clang::LabelStmt &s)
EHScopeStack::stable_iterator currentCleanupStackDepth
clang::ASTContext & getContext() const
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap)
Emit an aggregate copy.
mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s)
mlir::LogicalResult emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
mlir::LogicalResult emitGotoStmt(const clang::GotoStmt &s)
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
mlir::LogicalResult emitCompoundStmtWithoutScope(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
mlir::LogicalResult emitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &s)
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
mlir::LogicalResult emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s)
mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
Address getAggregateAddress() const
Return the value of the address of the aggregate.
Definition CIRGenValue.h:68
bool isAggregate() const
Definition CIRGenValue.h:51
mlir::Value getValue() const
Return the value of this scalar value.
Definition CIRGenValue.h:56
bool isScalar() const
Definition CIRGenValue.h:49
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition StmtCXX.h:135
CaseStmt - Represent a case statement.
Definition Stmt.h:1920
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1720
ContinueStmt - This represents a continue.
Definition Stmt.h:3119
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1611
DoStmt - This represents a 'do/while' stmt.
Definition Stmt.h:2832
This represents one expression.
Definition Expr.h:112
QualType getType() const
Definition Expr.h:144
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2888
GotoStmt - This represents a direct goto.
Definition Stmt.h:2969
IfStmt - This represents an if/then/else.
Definition Stmt.h:2259
Represents the declaration of a label.
Definition Decl.h:524
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.h:554
LabelStmt - Represents a label, which has a substatement.
Definition Stmt.h:2146
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
A (possibly-)qualified type.
Definition TypeBase.h:937
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition Stmt.h:3160
Stmt - This represents one statement.
Definition Stmt.h:85
@ NoStmtClass
Definition Stmt.h:88
SwitchStmt - This represents a 'switch' stmt.
Definition Stmt.h:2509
bool isVoidType() const
Definition TypeBase.h:8883
WhileStmt - This represents a 'while' stmt.
Definition Stmt.h:2697
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
const internal::VariadicDynCastAllOfMatcher< Stmt, CompoundStmt > compoundStmt
Matches compound statements.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, SwitchCase > switchCase
Matches case and default statements inside switch statements.
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Other
Other implicit parameter.
Definition Decl.h:1746
static bool aggValueSlotGC()
static bool loopInfoStack()
static bool emitCondLikelihoodViaExpectIntrinsic()
static bool constantFoldSwitchStatement()
static bool insertBuiltinUnpredictable()
static bool ehstackBranches()
static bool emitBranchThroughCleanup()
static bool requiresCleanups()
static bool generateDebugInfo()
static bool incrementProfileCounter()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...