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::CXXForRangeStmtClass:
159 case Stmt::OpenACCComputeConstructClass:
161 case Stmt::OpenACCLoopConstructClass:
163 case Stmt::OpenACCCombinedConstructClass:
165 case Stmt::OpenACCDataConstructClass:
167 case Stmt::OpenACCEnterDataConstructClass:
169 case Stmt::OpenACCExitDataConstructClass:
171 case Stmt::OpenACCHostDataConstructClass:
173 case Stmt::OpenACCWaitConstructClass:
175 case Stmt::OpenACCInitConstructClass:
177 case Stmt::OpenACCShutdownConstructClass:
179 case Stmt::OpenACCSetConstructClass:
181 case Stmt::OpenACCUpdateConstructClass:
183 case Stmt::OpenACCCacheConstructClass:
185 case Stmt::OpenACCAtomicConstructClass:
187 case Stmt::GCCAsmStmtClass:
188 case Stmt::MSAsmStmtClass:
189 return emitAsmStmt(cast<AsmStmt>(*s));
190 case Stmt::OMPScopeDirectiveClass:
191 case Stmt::OMPErrorDirectiveClass:
192 case Stmt::LabelStmtClass:
193 case Stmt::AttributedStmtClass:
194 case Stmt::GotoStmtClass:
195 case Stmt::DefaultStmtClass:
196 case Stmt::CaseStmtClass:
197 case Stmt::SEHLeaveStmtClass:
198 case Stmt::SYCLKernelCallStmtClass:
199 case Stmt::CoroutineBodyStmtClass:
200 case Stmt::CoreturnStmtClass:
201 case Stmt::CXXTryStmtClass:
202 case Stmt::IndirectGotoStmtClass:
203 case Stmt::OMPParallelDirectiveClass:
204 case Stmt::OMPTaskwaitDirectiveClass:
205 case Stmt::OMPTaskyieldDirectiveClass:
206 case Stmt::OMPBarrierDirectiveClass:
207 case Stmt::CapturedStmtClass:
208 case Stmt::ObjCAtTryStmtClass:
209 case Stmt::ObjCAtThrowStmtClass:
210 case Stmt::ObjCAtSynchronizedStmtClass:
211 case Stmt::ObjCForCollectionStmtClass:
212 case Stmt::ObjCAutoreleasePoolStmtClass:
213 case Stmt::SEHTryStmtClass:
214 case Stmt::OMPMetaDirectiveClass:
215 case Stmt::OMPCanonicalLoopClass:
216 case Stmt::OMPSimdDirectiveClass:
217 case Stmt::OMPTileDirectiveClass:
218 case Stmt::OMPUnrollDirectiveClass:
219 case Stmt::OMPForDirectiveClass:
220 case Stmt::OMPForSimdDirectiveClass:
221 case Stmt::OMPSectionsDirectiveClass:
222 case Stmt::OMPSectionDirectiveClass:
223 case Stmt::OMPSingleDirectiveClass:
224 case Stmt::OMPMasterDirectiveClass:
225 case Stmt::OMPCriticalDirectiveClass:
226 case Stmt::OMPParallelForDirectiveClass:
227 case Stmt::OMPParallelForSimdDirectiveClass:
228 case Stmt::OMPParallelMasterDirectiveClass:
229 case Stmt::OMPParallelSectionsDirectiveClass:
230 case Stmt::OMPTaskDirectiveClass:
231 case Stmt::OMPTaskgroupDirectiveClass:
232 case Stmt::OMPFlushDirectiveClass:
233 case Stmt::OMPDepobjDirectiveClass:
234 case Stmt::OMPScanDirectiveClass:
235 case Stmt::OMPOrderedDirectiveClass:
236 case Stmt::OMPAtomicDirectiveClass:
237 case Stmt::OMPTargetDirectiveClass:
238 case Stmt::OMPTeamsDirectiveClass:
239 case Stmt::OMPCancellationPointDirectiveClass:
240 case Stmt::OMPCancelDirectiveClass:
241 case Stmt::OMPTargetDataDirectiveClass:
242 case Stmt::OMPTargetEnterDataDirectiveClass:
243 case Stmt::OMPTargetExitDataDirectiveClass:
244 case Stmt::OMPTargetParallelDirectiveClass:
245 case Stmt::OMPTargetParallelForDirectiveClass:
246 case Stmt::OMPTaskLoopDirectiveClass:
247 case Stmt::OMPTaskLoopSimdDirectiveClass:
248 case Stmt::OMPMaskedTaskLoopDirectiveClass:
249 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
250 case Stmt::OMPMasterTaskLoopDirectiveClass:
251 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
252 case Stmt::OMPParallelGenericLoopDirectiveClass:
253 case Stmt::OMPParallelMaskedDirectiveClass:
254 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
255 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
256 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
257 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
258 case Stmt::OMPDistributeDirectiveClass:
259 case Stmt::OMPDistributeParallelForDirectiveClass:
260 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
261 case Stmt::OMPDistributeSimdDirectiveClass:
262 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
263 case Stmt::OMPTargetParallelForSimdDirectiveClass:
264 case Stmt::OMPTargetSimdDirectiveClass:
265 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
266 case Stmt::OMPTargetUpdateDirectiveClass:
267 case Stmt::OMPTeamsDistributeDirectiveClass:
268 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
269 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
270 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
271 case Stmt::OMPTeamsGenericLoopDirectiveClass:
272 case Stmt::OMPTargetTeamsDirectiveClass:
273 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
274 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
275 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
276 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
277 case Stmt::OMPInteropDirectiveClass:
278 case Stmt::OMPDispatchDirectiveClass:
279 case Stmt::OMPGenericLoopDirectiveClass:
280 case Stmt::OMPReverseDirectiveClass:
281 case Stmt::OMPInterchangeDirectiveClass:
282 case Stmt::OMPAssumeDirectiveClass:
283 case Stmt::OMPMaskedDirectiveClass:
284 case Stmt::OMPStripeDirectiveClass:
285 case Stmt::ObjCAtCatchStmtClass:
286 case Stmt::ObjCAtFinallyStmtClass:
287 cgm.errorNYI(s->getSourceRange(),
288 std::string("emitStmt: ") + s->getStmtClassName());
289 return mlir::failure();
290 }
291
292 llvm_unreachable("Unexpected statement class");
293}
294
295mlir::LogicalResult CIRGenFunction::emitSimpleStmt(const Stmt *s,
296 bool useCurrentScope) {
297 switch (s->getStmtClass()) {
298 default:
299 return mlir::failure();
300 case Stmt::DeclStmtClass:
301 return emitDeclStmt(cast<DeclStmt>(*s));
302 case Stmt::CompoundStmtClass:
303 if (useCurrentScope)
306 case Stmt::GotoStmtClass:
307 return emitGotoStmt(cast<GotoStmt>(*s));
308 case Stmt::ContinueStmtClass:
310
311 // NullStmt doesn't need any handling, but we need to say we handled it.
312 case Stmt::NullStmtClass:
313 break;
314
315 case Stmt::LabelStmtClass:
317 case Stmt::CaseStmtClass:
318 case Stmt::DefaultStmtClass:
319 // If we reached here, we must not handling a switch case in the top level.
321 /*buildingTopLevelCase=*/false);
322 break;
323
324 case Stmt::BreakStmtClass:
326 case Stmt::ReturnStmtClass:
328 }
329
330 return mlir::success();
331}
332
334
335 if (emitLabel(*s.getDecl()).failed())
336 return mlir::failure();
337
338 if (getContext().getLangOpts().EHAsynch && s.isSideEntry())
339 getCIRGenModule().errorNYI(s.getSourceRange(), "IsEHa: not implemented.");
340
341 return emitStmt(s.getSubStmt(), /*useCurrentScope*/ true);
342}
343
344// Add a terminating yield on a body region if no other terminators are used.
345static void terminateBody(CIRGenBuilderTy &builder, mlir::Region &r,
346 mlir::Location loc) {
347 if (r.empty())
348 return;
349
351 unsigned numBlocks = r.getBlocks().size();
352 for (auto &block : r.getBlocks()) {
353 // Already cleanup after return operations, which might create
354 // empty blocks if emitted as last stmt.
355 if (numBlocks != 1 && block.empty() && block.hasNoPredecessors() &&
356 block.hasNoSuccessors())
357 eraseBlocks.push_back(&block);
358
359 if (block.empty() ||
360 !block.back().hasTrait<mlir::OpTrait::IsTerminator>()) {
361 mlir::OpBuilder::InsertionGuard guardCase(builder);
362 builder.setInsertionPointToEnd(&block);
363 builder.createYield(loc);
364 }
365 }
366
367 for (auto *b : eraseBlocks)
368 b->erase();
369}
370
371mlir::LogicalResult CIRGenFunction::emitIfStmt(const IfStmt &s) {
372 mlir::LogicalResult res = mlir::success();
373 // The else branch of a consteval if statement is always the only branch
374 // that can be runtime evaluated.
375 const Stmt *constevalExecuted;
376 if (s.isConsteval()) {
377 constevalExecuted = s.isNegatedConsteval() ? s.getThen() : s.getElse();
378 if (!constevalExecuted) {
379 // No runtime code execution required
380 return res;
381 }
382 }
383
384 // C99 6.8.4.1: The first substatement is executed if the expression
385 // compares unequal to 0. The condition must be a scalar type.
386 auto ifStmtBuilder = [&]() -> mlir::LogicalResult {
387 if (s.isConsteval())
388 return emitStmt(constevalExecuted, /*useCurrentScope=*/true);
389
390 if (s.getInit())
391 if (emitStmt(s.getInit(), /*useCurrentScope=*/true).failed())
392 return mlir::failure();
393
394 if (s.getConditionVariable())
395 emitDecl(*s.getConditionVariable());
396
397 // If the condition folds to a constant and this is an 'if constexpr',
398 // we simplify it early in CIRGen to avoid emitting the full 'if'.
399 bool condConstant;
400 if (constantFoldsToBool(s.getCond(), condConstant, s.isConstexpr())) {
401 if (s.isConstexpr()) {
402 // Handle "if constexpr" explicitly here to avoid generating some
403 // ill-formed code since in CIR the "if" is no longer simplified
404 // in this lambda like in Clang but postponed to other MLIR
405 // passes.
406 if (const Stmt *executed = condConstant ? s.getThen() : s.getElse())
407 return emitStmt(executed, /*useCurrentScope=*/true);
408 // There is nothing to execute at runtime.
409 // TODO(cir): there is still an empty cir.scope generated by the caller.
410 return mlir::success();
411 }
412 }
413
416 return emitIfOnBoolExpr(s.getCond(), s.getThen(), s.getElse());
417 };
418
419 // TODO: Add a new scoped symbol table.
420 // LexicalScope ConditionScope(*this, S.getCond()->getSourceRange());
421 // The if scope contains the full source range for IfStmt.
422 mlir::Location scopeLoc = getLoc(s.getSourceRange());
423 builder.create<cir::ScopeOp>(
424 scopeLoc, /*scopeBuilder=*/
425 [&](mlir::OpBuilder &b, mlir::Location loc) {
426 LexicalScope lexScope{*this, scopeLoc, builder.getInsertionBlock()};
427 res = ifStmtBuilder();
428 });
429
430 return res;
431}
432
433mlir::LogicalResult CIRGenFunction::emitDeclStmt(const DeclStmt &s) {
434 assert(builder.getInsertionBlock() && "expected valid insertion point");
435
436 for (const Decl *i : s.decls())
437 emitDecl(*i, /*evaluateConditionDecl=*/true);
438
439 return mlir::success();
440}
441
442mlir::LogicalResult CIRGenFunction::emitReturnStmt(const ReturnStmt &s) {
443 mlir::Location loc = getLoc(s.getSourceRange());
444 const Expr *rv = s.getRetValue();
445
446 if (getContext().getLangOpts().ElideConstructors && s.getNRVOCandidate() &&
447 s.getNRVOCandidate()->isNRVOVariable()) {
450 } else if (!rv) {
451 // No return expression. Do nothing.
452 } else if (rv->getType()->isVoidType()) {
453 // Make sure not to return anything, but evaluate the expression
454 // for side effects.
455 if (rv) {
456 emitAnyExpr(rv);
457 }
458 } else if (cast<FunctionDecl>(curGD.getDecl())
459 ->getReturnType()
460 ->isReferenceType()) {
461 // If this function returns a reference, take the address of the
462 // expression rather than the value.
464 builder.CIRBaseBuilderTy::createStore(loc, result.getValue(), *fnRetAlloca);
465 } else {
466 mlir::Value value = nullptr;
468 case cir::TEK_Scalar:
469 value = emitScalarExpr(rv);
470 if (value) { // Change this to an assert once emitScalarExpr is complete
471 builder.CIRBaseBuilderTy::createStore(loc, value, *fnRetAlloca);
472 }
473 break;
474 case cir::TEK_Complex:
475 getCIRGenModule().errorNYI(s.getSourceRange(),
476 "complex function return type");
477 break;
484 break;
485 }
486 }
487
488 auto *retBlock = curLexScope->getOrCreateRetBlock(*this, loc);
489 // This should emit a branch through the cleanup block if one exists.
490 builder.create<cir::BrOp>(loc, retBlock);
492 if (ehStack.stable_begin() != currentCleanupStackDepth)
493 cgm.errorNYI(s.getSourceRange(), "return with cleanup stack");
494
495 // Insert the new block to continue codegen after branch to ret block.
496 builder.createBlock(builder.getBlock()->getParent());
497
498 return mlir::success();
499}
500
501mlir::LogicalResult CIRGenFunction::emitGotoStmt(const clang::GotoStmt &s) {
502 // FIXME: LLVM codegen inserts emit a stop point here for debug info
503 // sake when the insertion point is available, but doesn't do
504 // anything special when there isn't. We haven't implemented debug
505 // info support just yet, look at this again once we have it.
507
508 cir::GotoOp::create(builder, getLoc(s.getSourceRange()),
509 s.getLabel()->getName());
510
511 // A goto marks the end of a block, create a new one for codegen after
512 // emitGotoStmt can resume building in that block.
513 // Insert the new block to continue codegen after goto.
514 builder.createBlock(builder.getBlock()->getParent());
515
516 return mlir::success();
517}
518
519mlir::LogicalResult
521 builder.createContinue(getLoc(s.getKwLoc()));
522
523 // Insert the new block to continue codegen after the continue statement.
524 builder.createBlock(builder.getBlock()->getParent());
525
526 return mlir::success();
527}
528
529mlir::LogicalResult CIRGenFunction::emitLabel(const clang::LabelDecl &d) {
530 // Create a new block to tag with a label and add a branch from
531 // the current one to it. If the block is empty just call attach it
532 // to this label.
533 mlir::Block *currBlock = builder.getBlock();
534 mlir::Block *labelBlock = currBlock;
535
536 if (!currBlock->empty()) {
537 {
538 mlir::OpBuilder::InsertionGuard guard(builder);
539 labelBlock = builder.createBlock(builder.getBlock()->getParent());
540 }
541 builder.create<cir::BrOp>(getLoc(d.getSourceRange()), labelBlock);
542 }
543
544 builder.setInsertionPointToEnd(labelBlock);
545 builder.create<cir::LabelOp>(getLoc(d.getSourceRange()), d.getName());
546 builder.setInsertionPointToEnd(labelBlock);
547
548 // FIXME: emit debug info for labels, incrementProfileCounter
552 return mlir::success();
553}
554
556 builder.createBreak(getLoc(s.getKwLoc()));
557
558 // Insert the new block to continue codegen after the break statement.
559 builder.createBlock(builder.getBlock()->getParent());
560
561 return mlir::success();
562}
563
564template <typename T>
565mlir::LogicalResult
567 mlir::ArrayAttr value, CaseOpKind kind,
568 bool buildingTopLevelCase) {
569
571 "only case or default stmt go here");
572
573 mlir::LogicalResult result = mlir::success();
574
575 mlir::Location loc = getLoc(stmt->getBeginLoc());
576
577 enum class SubStmtKind { Case, Default, Other };
578 SubStmtKind subStmtKind = SubStmtKind::Other;
579 const Stmt *sub = stmt->getSubStmt();
580
581 mlir::OpBuilder::InsertPoint insertPoint;
582 builder.create<CaseOp>(loc, value, kind, insertPoint);
583
584 {
585 mlir::OpBuilder::InsertionGuard guardSwitch(builder);
586 builder.restoreInsertionPoint(insertPoint);
587
588 if (isa<DefaultStmt>(sub) && isa<CaseStmt>(stmt)) {
589 subStmtKind = SubStmtKind::Default;
590 builder.createYield(loc);
591 } else if (isa<CaseStmt>(sub) && isa<DefaultStmt, CaseStmt>(stmt)) {
592 subStmtKind = SubStmtKind::Case;
593 builder.createYield(loc);
594 } else {
595 result = emitStmt(sub, /*useCurrentScope=*/!isa<CompoundStmt>(sub));
596 }
597
598 insertPoint = builder.saveInsertionPoint();
599 }
600
601 // If the substmt is default stmt or case stmt, try to handle the special case
602 // to make it into the simple form. e.g.
603 //
604 // swtich () {
605 // case 1:
606 // default:
607 // ...
608 // }
609 //
610 // we prefer generating
611 //
612 // cir.switch() {
613 // cir.case(equal, 1) {
614 // cir.yield
615 // }
616 // cir.case(default) {
617 // ...
618 // }
619 // }
620 //
621 // than
622 //
623 // cir.switch() {
624 // cir.case(equal, 1) {
625 // cir.case(default) {
626 // ...
627 // }
628 // }
629 // }
630 //
631 // We don't need to revert this if we find the current switch can't be in
632 // simple form later since the conversion itself should be harmless.
633 if (subStmtKind == SubStmtKind::Case) {
634 result = emitCaseStmt(*cast<CaseStmt>(sub), condType, buildingTopLevelCase);
635 } else if (subStmtKind == SubStmtKind::Default) {
636 result = emitDefaultStmt(*cast<DefaultStmt>(sub), condType,
637 buildingTopLevelCase);
638 } else if (buildingTopLevelCase) {
639 // If we're building a top level case, try to restore the insert point to
640 // the case we're building, then we can attach more random stmts to the
641 // case to make generating `cir.switch` operation to be a simple form.
642 builder.restoreInsertionPoint(insertPoint);
643 }
644
645 return result;
646}
647
648mlir::LogicalResult CIRGenFunction::emitCaseStmt(const CaseStmt &s,
649 mlir::Type condType,
650 bool buildingTopLevelCase) {
651 cir::CaseOpKind kind;
652 mlir::ArrayAttr value;
653 llvm::APSInt intVal = s.getLHS()->EvaluateKnownConstInt(getContext());
654
655 // If the case statement has an RHS value, it is representing a GNU
656 // case range statement, where LHS is the beginning of the range
657 // and RHS is the end of the range.
658 if (const Expr *rhs = s.getRHS()) {
659 llvm::APSInt endVal = rhs->EvaluateKnownConstInt(getContext());
660 value = builder.getArrayAttr({cir::IntAttr::get(condType, intVal),
661 cir::IntAttr::get(condType, endVal)});
662 kind = cir::CaseOpKind::Range;
663 } else {
664 value = builder.getArrayAttr({cir::IntAttr::get(condType, intVal)});
665 kind = cir::CaseOpKind::Equal;
666 }
667
668 return emitCaseDefaultCascade(&s, condType, value, kind,
669 buildingTopLevelCase);
670}
671
673 mlir::Type condType,
674 bool buildingTopLevelCase) {
675 return emitCaseDefaultCascade(&s, condType, builder.getArrayAttr({}),
676 cir::CaseOpKind::Default, buildingTopLevelCase);
677}
678
679mlir::LogicalResult CIRGenFunction::emitSwitchCase(const SwitchCase &s,
680 bool buildingTopLevelCase) {
681 assert(!condTypeStack.empty() &&
682 "build switch case without specifying the type of the condition");
683
684 if (s.getStmtClass() == Stmt::CaseStmtClass)
686 buildingTopLevelCase);
687
688 if (s.getStmtClass() == Stmt::DefaultStmtClass)
690 buildingTopLevelCase);
691
692 llvm_unreachable("expect case or default stmt");
693}
694
695mlir::LogicalResult
697 ArrayRef<const Attr *> forAttrs) {
698 cir::ForOp forOp;
699
700 // TODO(cir): pass in array of attributes.
701 auto forStmtBuilder = [&]() -> mlir::LogicalResult {
702 mlir::LogicalResult loopRes = mlir::success();
703 // Evaluate the first pieces before the loop.
704 if (s.getInit())
705 if (emitStmt(s.getInit(), /*useCurrentScope=*/true).failed())
706 return mlir::failure();
707 if (emitStmt(s.getRangeStmt(), /*useCurrentScope=*/true).failed())
708 return mlir::failure();
709 if (emitStmt(s.getBeginStmt(), /*useCurrentScope=*/true).failed())
710 return mlir::failure();
711 if (emitStmt(s.getEndStmt(), /*useCurrentScope=*/true).failed())
712 return mlir::failure();
713
715 // From LLVM: if there are any cleanups between here and the loop-exit
716 // scope, create a block to stage a loop exit along.
717 // We probably already do the right thing because of ScopeOp, but make
718 // sure we handle all cases.
720
721 forOp = builder.createFor(
722 getLoc(s.getSourceRange()),
723 /*condBuilder=*/
724 [&](mlir::OpBuilder &b, mlir::Location loc) {
725 assert(!cir::MissingFeatures::createProfileWeightsForLoop());
726 assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
727 mlir::Value condVal = evaluateExprAsBool(s.getCond());
728 builder.createCondition(condVal);
729 },
730 /*bodyBuilder=*/
731 [&](mlir::OpBuilder &b, mlir::Location loc) {
732 // https://en.cppreference.com/w/cpp/language/for
733 // In C++ the scope of the init-statement and the scope of
734 // statement are one and the same.
735 bool useCurrentScope = true;
736 if (emitStmt(s.getLoopVarStmt(), useCurrentScope).failed())
737 loopRes = mlir::failure();
738 if (emitStmt(s.getBody(), useCurrentScope).failed())
739 loopRes = mlir::failure();
740 emitStopPoint(&s);
741 },
742 /*stepBuilder=*/
743 [&](mlir::OpBuilder &b, mlir::Location loc) {
744 if (s.getInc())
745 if (emitStmt(s.getInc(), /*useCurrentScope=*/true).failed())
746 loopRes = mlir::failure();
747 builder.createYield(loc);
748 });
749 return loopRes;
750 };
751
752 mlir::LogicalResult res = mlir::success();
753 mlir::Location scopeLoc = getLoc(s.getSourceRange());
754 builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
755 [&](mlir::OpBuilder &b, mlir::Location loc) {
756 // Create a cleanup scope for the condition
757 // variable cleanups. Logical equivalent from
758 // LLVM codegn for LexicalScope
759 // ConditionScope(*this, S.getSourceRange())...
760 LexicalScope lexScope{
761 *this, loc, builder.getInsertionBlock()};
762 res = forStmtBuilder();
763 });
764
765 if (res.failed())
766 return res;
767
768 terminateBody(builder, forOp.getBody(), getLoc(s.getEndLoc()));
769 return mlir::success();
770}
771
772mlir::LogicalResult CIRGenFunction::emitForStmt(const ForStmt &s) {
773 cir::ForOp forOp;
774
775 // TODO: pass in an array of attributes.
776 auto forStmtBuilder = [&]() -> mlir::LogicalResult {
777 mlir::LogicalResult loopRes = mlir::success();
778 // Evaluate the first part before the loop.
779 if (s.getInit())
780 if (emitStmt(s.getInit(), /*useCurrentScope=*/true).failed())
781 return mlir::failure();
783 // In the classic codegen, if there are any cleanups between here and the
784 // loop-exit scope, a block is created to stage the loop exit. We probably
785 // already do the right thing because of ScopeOp, but we need more testing
786 // to be sure we handle all cases.
788
789 forOp = builder.createFor(
790 getLoc(s.getSourceRange()),
791 /*condBuilder=*/
792 [&](mlir::OpBuilder &b, mlir::Location loc) {
793 assert(!cir::MissingFeatures::createProfileWeightsForLoop());
794 assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
795 mlir::Value condVal;
796 if (s.getCond()) {
797 // If the for statement has a condition scope,
798 // emit the local variable declaration.
799 if (s.getConditionVariable())
800 emitDecl(*s.getConditionVariable());
801 // C99 6.8.5p2/p4: The first substatement is executed if the
802 // expression compares unequal to 0. The condition must be a
803 // scalar type.
804 condVal = evaluateExprAsBool(s.getCond());
805 } else {
806 condVal = b.create<cir::ConstantOp>(loc, builder.getTrueAttr());
807 }
808 builder.createCondition(condVal);
809 },
810 /*bodyBuilder=*/
811 [&](mlir::OpBuilder &b, mlir::Location loc) {
812 // The scope of the for loop body is nested within the scope of the
813 // for loop's init-statement and condition.
814 if (emitStmt(s.getBody(), /*useCurrentScope=*/false).failed())
815 loopRes = mlir::failure();
817 },
818 /*stepBuilder=*/
819 [&](mlir::OpBuilder &b, mlir::Location loc) {
820 if (s.getInc())
821 if (emitStmt(s.getInc(), /*useCurrentScope=*/true).failed())
822 loopRes = mlir::failure();
823 builder.createYield(loc);
824 });
825 return loopRes;
826 };
827
828 auto res = mlir::success();
829 auto scopeLoc = getLoc(s.getSourceRange());
830 builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
831 [&](mlir::OpBuilder &b, mlir::Location loc) {
832 LexicalScope lexScope{
833 *this, loc, builder.getInsertionBlock()};
834 res = forStmtBuilder();
835 });
836
837 if (res.failed())
838 return res;
839
840 terminateBody(builder, forOp.getBody(), getLoc(s.getEndLoc()));
841 return mlir::success();
842}
843
844mlir::LogicalResult CIRGenFunction::emitDoStmt(const DoStmt &s) {
845 cir::DoWhileOp doWhileOp;
846
847 // TODO: pass in array of attributes.
848 auto doStmtBuilder = [&]() -> mlir::LogicalResult {
849 mlir::LogicalResult loopRes = mlir::success();
851 // From LLVM: if there are any cleanups between here and the loop-exit
852 // scope, create a block to stage a loop exit along.
853 // We probably already do the right thing because of ScopeOp, but make
854 // sure we handle all cases.
856
857 doWhileOp = builder.createDoWhile(
858 getLoc(s.getSourceRange()),
859 /*condBuilder=*/
860 [&](mlir::OpBuilder &b, mlir::Location loc) {
861 assert(!cir::MissingFeatures::createProfileWeightsForLoop());
862 assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
863 // C99 6.8.5p2/p4: The first substatement is executed if the
864 // expression compares unequal to 0. The condition must be a
865 // scalar type.
866 mlir::Value condVal = evaluateExprAsBool(s.getCond());
867 builder.createCondition(condVal);
868 },
869 /*bodyBuilder=*/
870 [&](mlir::OpBuilder &b, mlir::Location loc) {
871 // The scope of the do-while loop body is a nested scope.
872 if (emitStmt(s.getBody(), /*useCurrentScope=*/false).failed())
873 loopRes = mlir::failure();
874 emitStopPoint(&s);
875 });
876 return loopRes;
877 };
878
879 mlir::LogicalResult res = mlir::success();
880 mlir::Location scopeLoc = getLoc(s.getSourceRange());
881 builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
882 [&](mlir::OpBuilder &b, mlir::Location loc) {
883 LexicalScope lexScope{
884 *this, loc, builder.getInsertionBlock()};
885 res = doStmtBuilder();
886 });
887
888 if (res.failed())
889 return res;
890
891 terminateBody(builder, doWhileOp.getBody(), getLoc(s.getEndLoc()));
892 return mlir::success();
893}
894
895mlir::LogicalResult CIRGenFunction::emitWhileStmt(const WhileStmt &s) {
896 cir::WhileOp whileOp;
897
898 // TODO: pass in array of attributes.
899 auto whileStmtBuilder = [&]() -> mlir::LogicalResult {
900 mlir::LogicalResult loopRes = mlir::success();
902 // From LLVM: if there are any cleanups between here and the loop-exit
903 // scope, create a block to stage a loop exit along.
904 // We probably already do the right thing because of ScopeOp, but make
905 // sure we handle all cases.
907
908 whileOp = builder.createWhile(
909 getLoc(s.getSourceRange()),
910 /*condBuilder=*/
911 [&](mlir::OpBuilder &b, mlir::Location loc) {
912 assert(!cir::MissingFeatures::createProfileWeightsForLoop());
913 assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
914 mlir::Value condVal;
915 // If the for statement has a condition scope,
916 // emit the local variable declaration.
917 if (s.getConditionVariable())
918 emitDecl(*s.getConditionVariable());
919 // C99 6.8.5p2/p4: The first substatement is executed if the
920 // expression compares unequal to 0. The condition must be a
921 // scalar type.
922 condVal = evaluateExprAsBool(s.getCond());
923 builder.createCondition(condVal);
924 },
925 /*bodyBuilder=*/
926 [&](mlir::OpBuilder &b, mlir::Location loc) {
927 // The scope of the while loop body is a nested scope.
928 if (emitStmt(s.getBody(), /*useCurrentScope=*/false).failed())
929 loopRes = mlir::failure();
930 emitStopPoint(&s);
931 });
932 return loopRes;
933 };
934
935 mlir::LogicalResult res = mlir::success();
936 mlir::Location scopeLoc = getLoc(s.getSourceRange());
937 builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
938 [&](mlir::OpBuilder &b, mlir::Location loc) {
939 LexicalScope lexScope{
940 *this, loc, builder.getInsertionBlock()};
941 res = whileStmtBuilder();
942 });
943
944 if (res.failed())
945 return res;
946
947 terminateBody(builder, whileOp.getBody(), getLoc(s.getEndLoc()));
948 return mlir::success();
949}
950
951mlir::LogicalResult CIRGenFunction::emitSwitchBody(const Stmt *s) {
952 // It is rare but legal if the switch body is not a compound stmt. e.g.,
953 //
954 // switch(a)
955 // while(...) {
956 // case1
957 // ...
958 // case2
959 // ...
960 // }
961 if (!isa<CompoundStmt>(s))
962 return emitStmt(s, /*useCurrentScope=*/true);
963
965
966 mlir::Block *swtichBlock = builder.getBlock();
967 for (auto *c : compoundStmt->body()) {
968 if (auto *switchCase = dyn_cast<SwitchCase>(c)) {
969 builder.setInsertionPointToEnd(swtichBlock);
970 // Reset insert point automatically, so that we can attach following
971 // random stmt to the region of previous built case op to try to make
972 // the being generated `cir.switch` to be in simple form.
973 if (mlir::failed(
974 emitSwitchCase(*switchCase, /*buildingTopLevelCase=*/true)))
975 return mlir::failure();
976
977 continue;
978 }
979
980 // Otherwise, just build the statements in the nearest case region.
981 if (mlir::failed(emitStmt(c, /*useCurrentScope=*/!isa<CompoundStmt>(c))))
982 return mlir::failure();
983 }
984
985 return mlir::success();
986}
987
989 // TODO: LLVM codegen does some early optimization to fold the condition and
990 // only emit live cases. CIR should use MLIR to achieve similar things,
991 // nothing to be done here.
992 // if (ConstantFoldsToSimpleInteger(S.getCond(), ConstantCondValue))...
994
995 SwitchOp swop;
996 auto switchStmtBuilder = [&]() -> mlir::LogicalResult {
997 if (s.getInit())
998 if (emitStmt(s.getInit(), /*useCurrentScope=*/true).failed())
999 return mlir::failure();
1000
1001 if (s.getConditionVariable())
1002 emitDecl(*s.getConditionVariable(), /*evaluateConditionDecl=*/true);
1003
1004 mlir::Value condV = emitScalarExpr(s.getCond());
1005
1006 // TODO: PGO and likelihood (e.g. PGO.haveRegionCounts())
1009 // TODO: if the switch has a condition wrapped by __builtin_unpredictable?
1011
1012 mlir::LogicalResult res = mlir::success();
1013 swop = builder.create<SwitchOp>(
1014 getLoc(s.getBeginLoc()), condV,
1015 /*switchBuilder=*/
1016 [&](mlir::OpBuilder &b, mlir::Location loc, mlir::OperationState &os) {
1017 curLexScope->setAsSwitch();
1018
1019 condTypeStack.push_back(condV.getType());
1020
1021 res = emitSwitchBody(s.getBody());
1022
1023 condTypeStack.pop_back();
1024 });
1025
1026 return res;
1027 };
1028
1029 // The switch scope contains the full source range for SwitchStmt.
1030 mlir::Location scopeLoc = getLoc(s.getSourceRange());
1031 mlir::LogicalResult res = mlir::success();
1032 builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
1033 [&](mlir::OpBuilder &b, mlir::Location loc) {
1034 LexicalScope lexScope{
1035 *this, loc, builder.getInsertionBlock()};
1036 res = switchStmtBuilder();
1037 });
1038
1040 swop.collectCases(cases);
1041 for (auto caseOp : cases)
1042 terminateBody(builder, caseOp.getCaseRegion(), caseOp.getLoc());
1043 terminateBody(builder, swop.getBody(), swop.getLoc());
1044
1045 return res;
1046}
1047
1048void CIRGenFunction::emitReturnOfRValue(mlir::Location loc, RValue rv,
1049 QualType ty) {
1050 if (rv.isScalar()) {
1051 builder.createStore(loc, rv.getValue(), returnValue);
1052 } else if (rv.isAggregate()) {
1053 LValue dest = makeAddrLValue(returnValue, ty);
1056 } else {
1057 cgm.errorNYI(loc, "emitReturnOfRValue: complex return type");
1058 }
1059 mlir::Block *retBlock = curLexScope->getOrCreateRetBlock(*this, loc);
1061 builder.create<cir::BrOp>(loc, retBlock);
1062 if (ehStack.stable_begin() != currentCleanupStackDepth)
1063 cgm.errorNYI(loc, "return with cleanup stack");
1064}
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 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 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:523
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.h:553
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:300
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:8878
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:1745
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...