Thanks to visit codestin.com
Credit goes to clang.llvm.org

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