28#include "llvm/ADT/ArrayRef.h"
29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/SmallSet.h"
31#include "llvm/ADT/StringExtras.h"
32#include "llvm/IR/Assumptions.h"
33#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/InlineAsm.h"
35#include "llvm/IR/Intrinsics.h"
36#include "llvm/IR/MDBuilder.h"
37#include "llvm/Support/SaveAndRestore.h"
58 assert(S &&
"Null statement?");
59 PGO->setCurrentStmt(S);
76 PGO->markStmtMaybeUsed(S);
90 if (
const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
98 case Stmt::CXXCatchStmtClass:
99 case Stmt::SEHExceptStmtClass:
100 case Stmt::SEHFinallyStmtClass:
101 case Stmt::MSDependentExistsStmtClass:
102 llvm_unreachable(
"invalid statement class to emit generically");
103 case Stmt::NullStmtClass:
104 case Stmt::CompoundStmtClass:
105 case Stmt::DeclStmtClass:
106 case Stmt::LabelStmtClass:
107 case Stmt::AttributedStmtClass:
108 case Stmt::GotoStmtClass:
109 case Stmt::BreakStmtClass:
110 case Stmt::ContinueStmtClass:
111 case Stmt::DefaultStmtClass:
112 case Stmt::CaseStmtClass:
113 case Stmt::DeferStmtClass:
114 case Stmt::SEHLeaveStmtClass:
115 case Stmt::SYCLKernelCallStmtClass:
116 llvm_unreachable(
"should have emitted these statements as simple");
118#define STMT(Type, Base)
119#define ABSTRACT_STMT(Op)
120#define EXPR(Type, Base) \
121 case Stmt::Type##Class:
122#include "clang/AST/StmtNodes.inc"
125 llvm::BasicBlock *incoming =
Builder.GetInsertBlock();
126 assert(incoming &&
"expression emission must have an insertion point");
130 llvm::BasicBlock *outgoing =
Builder.GetInsertBlock();
131 assert(outgoing &&
"expression emission cleared block!");
145 if (incoming != outgoing && outgoing->use_empty()) {
146 outgoing->eraseFromParent();
152 case Stmt::IndirectGotoStmtClass:
163 case Stmt::GCCAsmStmtClass:
165 case Stmt::CoroutineBodyStmtClass:
168 case Stmt::CoreturnStmtClass:
171 case Stmt::CapturedStmtClass: {
176 case Stmt::ObjCAtTryStmtClass:
179 case Stmt::ObjCAtCatchStmtClass:
181 "@catch statements should be handled by EmitObjCAtTryStmt");
182 case Stmt::ObjCAtFinallyStmtClass:
184 "@finally statements should be handled by EmitObjCAtTryStmt");
185 case Stmt::ObjCAtThrowStmtClass:
188 case Stmt::ObjCAtSynchronizedStmtClass:
191 case Stmt::ObjCForCollectionStmtClass:
194 case Stmt::ObjCAutoreleasePoolStmtClass:
198 case Stmt::CXXTryStmtClass:
201 case Stmt::CXXForRangeStmtClass:
204 case Stmt::SEHTryStmtClass:
207 case Stmt::OMPMetaDirectiveClass:
210 case Stmt::OMPCanonicalLoopClass:
213 case Stmt::OMPParallelDirectiveClass:
216 case Stmt::OMPSimdDirectiveClass:
219 case Stmt::OMPTileDirectiveClass:
222 case Stmt::OMPStripeDirectiveClass:
225 case Stmt::OMPUnrollDirectiveClass:
228 case Stmt::OMPReverseDirectiveClass:
231 case Stmt::OMPInterchangeDirectiveClass:
234 case Stmt::OMPFuseDirectiveClass:
237 case Stmt::OMPForDirectiveClass:
240 case Stmt::OMPForSimdDirectiveClass:
243 case Stmt::OMPSectionsDirectiveClass:
246 case Stmt::OMPSectionDirectiveClass:
249 case Stmt::OMPSingleDirectiveClass:
252 case Stmt::OMPMasterDirectiveClass:
255 case Stmt::OMPCriticalDirectiveClass:
258 case Stmt::OMPParallelForDirectiveClass:
261 case Stmt::OMPParallelForSimdDirectiveClass:
264 case Stmt::OMPParallelMasterDirectiveClass:
267 case Stmt::OMPParallelSectionsDirectiveClass:
270 case Stmt::OMPTaskDirectiveClass:
273 case Stmt::OMPTaskyieldDirectiveClass:
276 case Stmt::OMPErrorDirectiveClass:
279 case Stmt::OMPBarrierDirectiveClass:
282 case Stmt::OMPTaskwaitDirectiveClass:
285 case Stmt::OMPTaskgroupDirectiveClass:
288 case Stmt::OMPFlushDirectiveClass:
291 case Stmt::OMPDepobjDirectiveClass:
294 case Stmt::OMPScanDirectiveClass:
297 case Stmt::OMPOrderedDirectiveClass:
300 case Stmt::OMPAtomicDirectiveClass:
303 case Stmt::OMPTargetDirectiveClass:
306 case Stmt::OMPTeamsDirectiveClass:
309 case Stmt::OMPCancellationPointDirectiveClass:
312 case Stmt::OMPCancelDirectiveClass:
315 case Stmt::OMPTargetDataDirectiveClass:
318 case Stmt::OMPTargetEnterDataDirectiveClass:
321 case Stmt::OMPTargetExitDataDirectiveClass:
324 case Stmt::OMPTargetParallelDirectiveClass:
327 case Stmt::OMPTargetParallelForDirectiveClass:
330 case Stmt::OMPTaskLoopDirectiveClass:
333 case Stmt::OMPTaskLoopSimdDirectiveClass:
336 case Stmt::OMPMasterTaskLoopDirectiveClass:
339 case Stmt::OMPMaskedTaskLoopDirectiveClass:
342 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
346 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
350 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
354 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
358 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
362 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
366 case Stmt::OMPDistributeDirectiveClass:
369 case Stmt::OMPTargetUpdateDirectiveClass:
372 case Stmt::OMPDistributeParallelForDirectiveClass:
376 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
380 case Stmt::OMPDistributeSimdDirectiveClass:
383 case Stmt::OMPTargetParallelForSimdDirectiveClass:
387 case Stmt::OMPTargetSimdDirectiveClass:
390 case Stmt::OMPTeamsDistributeDirectiveClass:
393 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
397 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
401 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
405 case Stmt::OMPTargetTeamsDirectiveClass:
408 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
412 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
416 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
420 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
424 case Stmt::OMPInteropDirectiveClass:
427 case Stmt::OMPDispatchDirectiveClass:
428 CGM.ErrorUnsupported(S,
"OpenMP dispatch directive");
430 case Stmt::OMPScopeDirectiveClass:
433 case Stmt::OMPMaskedDirectiveClass:
436 case Stmt::OMPGenericLoopDirectiveClass:
439 case Stmt::OMPTeamsGenericLoopDirectiveClass:
442 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
446 case Stmt::OMPParallelGenericLoopDirectiveClass:
450 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
454 case Stmt::OMPParallelMaskedDirectiveClass:
457 case Stmt::OMPAssumeDirectiveClass:
460 case Stmt::OpenACCComputeConstructClass:
463 case Stmt::OpenACCLoopConstructClass:
466 case Stmt::OpenACCCombinedConstructClass:
469 case Stmt::OpenACCDataConstructClass:
472 case Stmt::OpenACCEnterDataConstructClass:
475 case Stmt::OpenACCExitDataConstructClass:
478 case Stmt::OpenACCHostDataConstructClass:
481 case Stmt::OpenACCWaitConstructClass:
484 case Stmt::OpenACCInitConstructClass:
487 case Stmt::OpenACCShutdownConstructClass:
490 case Stmt::OpenACCSetConstructClass:
493 case Stmt::OpenACCUpdateConstructClass:
496 case Stmt::OpenACCAtomicConstructClass:
499 case Stmt::OpenACCCacheConstructClass:
510 case Stmt::NullStmtClass:
512 case Stmt::CompoundStmtClass:
515 case Stmt::DeclStmtClass:
518 case Stmt::LabelStmtClass:
521 case Stmt::AttributedStmtClass:
524 case Stmt::GotoStmtClass:
527 case Stmt::BreakStmtClass:
530 case Stmt::ContinueStmtClass:
533 case Stmt::DefaultStmtClass:
536 case Stmt::CaseStmtClass:
539 case Stmt::DeferStmtClass:
542 case Stmt::SEHLeaveStmtClass:
545 case Stmt::SYCLKernelCallStmtClass:
572 "LLVM IR generation of compound statement ('{}')");
599 if (
const auto *LS = dyn_cast<LabelStmt>(LastStmt)) {
601 LastStmt = LS->getSubStmt();
602 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(LastStmt)) {
605 LastStmt = AS->getSubStmt();
607 llvm_unreachable(
"unknown value statement");
631 llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
640 if (!BI || !BI->isUnconditional())
644 if (BI->getIterator() != BB->begin())
647 BB->replaceAllUsesWith(BI->getSuccessor(0));
648 BI->eraseFromParent();
649 BB->eraseFromParent();
653 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
658 if (IsFinished && BB->use_empty()) {
665 if (CurBB && CurBB->getParent())
666 CurFn->insert(std::next(CurBB->getIterator()), BB);
676 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
678 if (!CurBB || CurBB->getTerminator()) {
690 bool inserted =
false;
691 for (llvm::User *u : block->users()) {
692 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
693 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
708 if (Dest.
isValid())
return Dest;
721 if (
EHStack.hasNormalCleanups() && CurLexicalScope)
722 CurLexicalScope->addLabel(D);
743 if (
CGM.getCodeGenOpts().hasReducedDebugInfo()) {
755 assert(!Labels.empty());
757 =
CGF.EHStack.getInnermostNormalCleanup();
761 assert(
CGF.LabelMap.count(Label));
770 ParentScope->Labels.append(Labels.begin(), Labels.end());
786 bool nomerge =
false;
787 bool noinline =
false;
788 bool alwaysinline =
false;
789 bool noconvergent =
false;
790 HLSLControlFlowHintAttr::Spelling flattenOrBranch =
791 HLSLControlFlowHintAttr::SpellingNotCalculated;
793 const AtomicAttr *AA =
nullptr;
795 for (
const auto *A : S.
getAttrs()) {
796 switch (A->getKind()) {
805 case attr::AlwaysInline:
808 case attr::NoConvergent:
811 case attr::MustTail: {
816 case attr::CXXAssume: {
821 Builder.CreateAssumption(AssumptionVal);
827 case attr::HLSLControlFlowHint: {
864 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
874 if (CurBB && CurBB->getTerminator())
910 const Stmt *Skipped = Else;
912 std::swap(Executed, Skipped);
924 PGO->markStmtMaybeUsed(Skipped);
935 llvm::BasicBlock *ElseBlock =
951 CGM.getCodeGenOpts().OptimizationLevel)
960 if (!
CGM.getCodeGenOpts().MCDCCoverage) {
967 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
998 }
else if (HasSkip) {
1009 bool HasEmptyBody) {
1010 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1020 bool CondIsConstInt =
1021 !ControllingExpression ||
1025 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
1026 Result.Val.getInt().getBoolValue());
1037 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1040 if (HasEmptyBody && CondIsTrue) {
1041 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1059 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1063 const Stmt *Body = S.getBody();
1066 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
1067 return Compound->body_empty();
1078 if (
CGM.shouldEmitConvergenceTokens())
1080 emitConvergenceLoopToken(LoopHeader.
getBlock()));
1087 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopHeader));
1110 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1111 bool EmitBoolCondBranch = !
C || !
C->isOne();
1120 if (EmitBoolCondBranch) {
1121 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1124 llvm::MDNode *Weights =
1126 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1127 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1129 auto *I =
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1135 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1139 if (ExitBlock !=
LoopExit.getBlock()) {
1145 CGM.getDiags().Report(A->getLocation(),
1146 diag::warn_attribute_has_no_effect_on_infinite_loop)
1147 << A << A->getRange();
1148 CGM.getDiags().Report(
1150 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1163 BreakContinueStack.pop_back();
1179 if (!EmitBoolCondBranch) {
1181 PGO->markStmtAsUsed(
true, &S);
1184 if (
CGM.shouldEmitConvergenceTokens())
1196 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopCond));
1203 if (
CGM.shouldEmitConvergenceTokens())
1221 BreakContinueStack.pop_back();
1225 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1226 bool EmitBoolCondBranch = !
C || !
C->isZero();
1229 LoopStack.push(LoopBody,
CGM.getContext(),
CGM.getCodeGenOpts(), DoAttrs,
1238 if (EmitBoolCondBranch) {
1240 auto *I =
Builder.CreateCondBr(
1241 BoolCondVal, LoopBody, LoopFalse,
1242 createProfileWeightsForLoop(S.
getCond(), BackedgeCount));
1249 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1256 if (LoopFalse !=
LoopExit.getBlock()) {
1266 if (!EmitBoolCondBranch)
1269 if (
CGM.shouldEmitConvergenceTokens())
1277 std::optional<LexicalScope> ForScope;
1289 llvm::BasicBlock *CondBlock = CondDest.
getBlock();
1292 if (
CGM.shouldEmitConvergenceTokens())
1296 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1313 Continue = CondDest;
1316 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1327 BreakContinueStack.back().ContinueBlock = Continue;
1330 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1333 if (
hasSkipCounter(&S) || (ForScope && ForScope->requiresCleanups()))
1345 llvm::MDNode *Weights =
1347 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1348 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1351 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1356 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1360 if (ExitBlock !=
LoopExit.getBlock()) {
1370 PGO->markStmtAsUsed(
true, &S);
1384 auto *FinalBodyBB =
Builder.GetInsertBlock();
1392 BreakContinueStack.pop_back();
1400 ForScope->ForceCleanup();
1407 if (
CGM.shouldEmitConvergenceTokens())
1437 if (
CGM.shouldEmitConvergenceTokens())
1441 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1447 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1457 llvm::MDNode *Weights =
1459 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1460 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1462 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1467 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1471 if (ExitBlock !=
LoopExit.getBlock()) {
1484 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1494 auto *FinalBodyBB =
Builder.GetInsertBlock();
1501 BreakContinueStack.pop_back();
1512 if (
CGM.shouldEmitConvergenceTokens())
1522void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1538struct SaveRetExprRAII {
1539 SaveRetExprRAII(
const Expr *RetExpr, CodeGenFunction &CGF)
1540 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1543 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1544 const Expr *OldRetExpr;
1545 CodeGenFunction &CGF;
1553 if (calleeQualType->isFunctionPointerType() ||
1554 calleeQualType->isFunctionReferenceType() ||
1555 calleeQualType->isBlockPointerType() ||
1556 calleeQualType->isMemberFunctionPointerType()) {
1558 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1560 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1561 if (
auto methodDecl = CMCE->getMethodDecl()) {
1578 if (requiresReturnValueCheck()) {
1581 new llvm::GlobalVariable(
CGM.getModule(), SLoc->getType(),
false,
1582 llvm::GlobalVariable::PrivateLinkage, SLoc);
1583 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1584 CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
1585 assert(ReturnLocation.isValid() &&
"No valid return location");
1586 Builder.CreateStore(SLocPtr, ReturnLocation);
1592 Builder.ClearInsertionPoint();
1606 SaveRetExprRAII SaveRetExpr(RV, *
this);
1609 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1610 RV = EWC->getSubExpr();
1614 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1617 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1630 !
CGM.getOpenMPRuntime()
1649 }
else if (
FnRetTy->isReferenceType()) {
1685 ++NumSimpleReturnExprs;
1697 for (
const auto *I : S.
decls())
1702 ->
const BreakContinue * {
1703 if (!S.hasLabelTarget())
1704 return &BreakContinueStack.back();
1706 const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
1707 assert(LoopOrSwitch &&
"break/continue target not set?");
1708 for (
const BreakContinue &BC : llvm::reverse(BreakContinueStack))
1709 if (BC.LoopOrSwitch == LoopOrSwitch)
1712 llvm_unreachable(
"break/continue target not found");
1716 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1729 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1746 assert(S.
getRHS() &&
"Expected RHS value in CaseStmt");
1759 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1763 llvm::APInt Range = RHS - LHS;
1765 if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
1768 unsigned NCases = Range.getZExtValue() + 1;
1773 uint64_t Weight = Total / NCases, Rem = Total % NCases;
1774 for (
unsigned I = 0; I != NCases; ++I) {
1776 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1777 else if (SwitchLikelihood)
1778 SwitchLikelihood->push_back(LH);
1782 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1790 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1795 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1799 Builder.SetInsertPoint(CaseRangeBlock);
1803 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1807 llvm::MDNode *Weights =
nullptr;
1808 if (SwitchWeights) {
1810 uint64_t DefaultCount = (*SwitchWeights)[0];
1811 Weights = createProfileWeights(ThisCount, DefaultCount);
1816 (*SwitchWeights)[0] += ThisCount;
1817 }
else if (SwitchLikelihood)
1818 Cond = emitCondLikelihoodViaExpectIntrinsic(
Cond, LH);
1820 Builder.CreateCondBr(
Cond, CaseDest, FalseDest, Weights);
1824 Builder.SetInsertPoint(RestoreBB);
1826 Builder.ClearInsertionPoint();
1847 llvm::ConstantInt *CaseVal =
1852 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.
getLHS()))
1853 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1855 CE = dyn_cast<ConstantExpr>(S.
getLHS());
1857 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1859 if (
CGM.getCodeGenOpts().hasReducedDebugInfo())
1860 Dbg->EmitGlobalVariable(DE->getDecl(),
1861 APValue(llvm::APSInt(CaseVal->getValue())));
1864 if (SwitchLikelihood)
1870 if (!
CGM.getCodeGenOpts().hasProfileClangInstr() &&
1871 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1879 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1883 if (
Builder.GetInsertBlock()) {
1885 Builder.ClearInsertionPoint();
1895 SwitchInsn->addCase(CaseVal, CaseDest);
1914 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1916 llvm::ConstantInt *CaseVal =
1921 if (
CGM.getCodeGenOpts().hasProfileClangInstr()) {
1927 if (SwitchLikelihood)
1930 SwitchInsn->addCase(CaseVal, CaseDest);
1931 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1954 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1955 assert(DefaultBlock->empty() &&
1956 "EmitDefaultStmt: Default block already defined?");
1958 if (SwitchLikelihood)
1967struct EmitDeferredStatement final : EHScopeStack::Cleanup {
2027 llvm::Value *SavedCleanupDest =
nullptr;
2081 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
2100 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
2104 bool StartedInLiveCode = FoundCase;
2105 unsigned StartSize = ResultStmts.size();
2112 bool HadSkippedDecl =
false;
2116 for (; Case && I != E; ++I) {
2132 for (++I; I != E; ++I)
2142 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
2157 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
2162 bool AnyDecls =
false;
2163 for (; I != E; ++I) {
2176 for (++I; I != E; ++I)
2193 ResultStmts.resize(StartSize);
2194 ResultStmts.push_back(S);
2218 ResultStmts.push_back(S);
2227 const llvm::APSInt &ConstantCondValue,
2239 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2247 if (CS->
getRHS())
return false;
2272 bool FoundCase =
false;
2279static std::optional<SmallVector<uint64_t, 16>>
2282 if (Likelihoods.size() <= 1)
2283 return std::nullopt;
2285 uint64_t NumUnlikely = 0;
2286 uint64_t NumNone = 0;
2287 uint64_t NumLikely = 0;
2288 for (
const auto LH : Likelihoods) {
2303 if (NumUnlikely == 0 && NumLikely == 0)
2304 return std::nullopt;
2312 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2313 const uint64_t
None = Likely / (NumNone + 1);
2314 const uint64_t Unlikely = 0;
2317 Result.reserve(Likelihoods.size());
2318 for (
const auto LH : Likelihoods) {
2321 Result.push_back(Unlikely);
2324 Result.push_back(
None);
2327 Result.push_back(Likely);
2337 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2340 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2344 llvm::APSInt ConstantCondValue;
2365 SwitchInsn =
nullptr;
2372 PGO->markStmtMaybeUsed(S.
getBody());
2376 SwitchInsn = SavedSwitchInsn;
2399 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2403 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2404 llvm::ConstantInt *BranchHintConstant =
2406 HLSLControlFlowHintAttr::Spelling::Microsoft_branch
2407 ? llvm::ConstantInt::get(
CGM.Int32Ty, 1)
2408 : llvm::ConstantInt::get(
CGM.Int32Ty, 2);
2409 llvm::Metadata *Vals[] = {MDHelper.createString(
"hlsl.controlflow.hint"),
2410 MDHelper.createConstant(BranchHintConstant)};
2411 SwitchInsn->setMetadata(
"hlsl.controlflow.hint",
2412 llvm::MDNode::get(
CGM.getLLVMContext(), Vals));
2415 if (PGO->haveRegionCounts()) {
2417 uint64_t DefaultCount = 0;
2418 unsigned NumCases = 0;
2427 SwitchWeights->reserve(NumCases);
2430 SwitchWeights->push_back(DefaultCount);
2431 }
else if (
CGM.getCodeGenOpts().OptimizationLevel) {
2437 CaseRangeBlock = DefaultBlock;
2440 Builder.ClearInsertionPoint();
2445 if (!BreakContinueStack.empty())
2446 OuterContinue = BreakContinueStack.back().ContinueBlock;
2448 BreakContinueStack.push_back(BreakContinue(S, SwitchExit, OuterContinue));
2453 BreakContinueStack.pop_back();
2457 SwitchInsn->setDefaultDest(CaseRangeBlock);
2460 if (!DefaultBlock->getParent()) {
2468 DefaultBlock->replaceAllUsesWith(SwitchExit.
getBlock());
2469 delete DefaultBlock;
2483 Builder.CreateBr(SwitchInsn->getDefaultDest());
2484 SwitchInsn->setDefaultDest(ImplicitDefaultBlock);
2495 if (
Call &&
CGM.getCodeGenOpts().OptimizationLevel != 0) {
2496 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2497 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2499 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2500 MDHelper.createUnpredictable());
2504 if (SwitchWeights) {
2505 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2506 "switch weights do not match switch cases");
2508 if (SwitchWeights->size() > 1)
2509 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2510 createProfileWeights(*SwitchWeights));
2511 delete SwitchWeights;
2512 }
else if (SwitchLikelihood) {
2513 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2514 "switch likelihoods do not match switch cases");
2515 std::optional<SmallVector<uint64_t, 16>> LHW =
2518 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2519 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2520 createProfileWeights(*LHW));
2522 delete SwitchLikelihood;
2524 SwitchInsn = SavedSwitchInsn;
2525 SwitchWeights = SavedSwitchWeights;
2526 SwitchLikelihood = SavedSwitchLikelihood;
2527 CaseRangeBlock = SavedCRBlock;
2530std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2539 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2549 ConstraintStr +=
'*';
2552std::pair<llvm::Value *, llvm::Type *>
2553CodeGenFunction::EmitAsmInput(
const TargetInfo::ConstraintInfo &Info,
2554 const Expr *InputExpr,
2555 std::string &ConstraintStr) {
2560 Expr::EvalResult EVResult;
2563 llvm::APSInt IntResult;
2566 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2578 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2582 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2594 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2597 if (!StrVal.empty()) {
2600 unsigned StartToken = 0;
2601 unsigned ByteOffset = 0;
2605 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2606 if (StrVal[i] !=
'\n')
continue;
2608 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2609 Locs.push_back(llvm::ConstantAsMetadata::get(
2618 bool HasUnwindClobber,
bool ReadOnly,
2619 bool ReadNone,
bool NoMerge,
bool NoConvergent,
2621 const std::vector<llvm::Type *> &ResultRegTypes,
2622 const std::vector<llvm::Type *> &ArgElemTypes,
2624 std::vector<llvm::Value *> &RegResults) {
2625 if (!HasUnwindClobber)
2626 Result.addFnAttr(llvm::Attribute::NoUnwind);
2629 Result.addFnAttr(llvm::Attribute::NoMerge);
2631 if (!HasSideEffect) {
2633 Result.setDoesNotAccessMemory();
2635 Result.setOnlyReadsMemory();
2639 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
2641 auto Attr = llvm::Attribute::get(
2642 CGF.
getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2643 Result.addParamAttr(Pair.index(),
Attr);
2650 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S);
2652 (SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))) {
2657 llvm::Constant *Loc =
2659 Result.setMetadata(
"srcloc",
2661 llvm::ConstantAsMetadata::get(Loc)));
2672 Result.addFnAttr(llvm::Attribute::Convergent);
2674 if (ResultRegTypes.size() == 1) {
2675 RegResults.push_back(&Result);
2677 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2678 llvm::Value *Tmp = CGF.
Builder.CreateExtractValue(&Result, i,
"asmresult");
2679 RegResults.push_back(Tmp);
2691 const llvm::BitVector &ResultTypeRequiresCast,
2692 const std::vector<std::optional<std::pair<unsigned, unsigned>>>
2698 assert(RegResults.size() == ResultRegTypes.size());
2699 assert(RegResults.size() == ResultTruncRegTypes.size());
2700 assert(RegResults.size() == ResultRegDests.size());
2703 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2704 assert(ResultBounds.size() <= ResultRegDests.size());
2706 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2707 llvm::Value *Tmp = RegResults[i];
2708 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2710 if ((i < ResultBounds.size()) && ResultBounds[i].has_value()) {
2711 const auto [LowerBound, UpperBound] = ResultBounds[i].value();
2713 assert(LowerBound == 0 &&
"Output operand lower bound is not zero.");
2714 llvm::Constant *UpperBoundConst =
2715 llvm::ConstantInt::get(Tmp->getType(), UpperBound);
2716 llvm::Value *IsBooleanValue =
2717 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, UpperBoundConst);
2719 Builder.CreateCall(FnAssume, IsBooleanValue);
2724 if (ResultRegTypes[i] != TruncTy) {
2728 if (TruncTy->isFloatingPointTy())
2729 Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
2730 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2732 Tmp = Builder.CreateTrunc(
2733 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
2734 Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
2735 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2738 Tmp = Builder.CreatePtrToInt(
2739 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
2740 Tmp = Builder.CreateTrunc(Tmp, TruncTy);
2741 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2742 Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2743 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2744 Tmp = Builder.CreateBitCast(Tmp, TruncTy);
2749 LValue Dest = ResultRegDests[i];
2752 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2754 Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
2756 llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
2766 diag::err_store_value_to_reg);
2777 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2780 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2781 Asm = GCCAsm->getAsmString();
2785 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2786 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2787 {StrTy->getType()},
false);
2788 auto UBF = CGF->
CGM.
getModule().getOrInsertFunction(Name, FnTy);
2790 CGF->
Builder.CreateCall(UBF, {StrTy});
2805 bool IsValidTargetAsm =
true;
2806 for (
unsigned i = 0, e = S.
getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2808 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2809 Name = GAS->getOutputName(i);
2812 if (IsHipStdPar && !IsValid)
2813 IsValidTargetAsm =
false;
2815 assert(IsValid &&
"Failed to parse output constraint");
2816 OutputConstraintInfos.push_back(Info);
2819 for (
unsigned i = 0, e = S.
getNumInputs(); i != e && IsValidTargetAsm; i++) {
2821 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2822 Name = GAS->getInputName(i);
2826 if (IsHipStdPar && !IsValid)
2827 IsValidTargetAsm =
false;
2829 assert(IsValid &&
"Failed to parse input constraint");
2830 InputConstraintInfos.push_back(Info);
2833 if (!IsValidTargetAsm)
2836 std::string Constraints;
2838 std::vector<LValue> ResultRegDests;
2839 std::vector<QualType> ResultRegQualTys;
2840 std::vector<llvm::Type *> ResultRegTypes;
2841 std::vector<llvm::Type *> ResultTruncRegTypes;
2842 std::vector<llvm::Type *> ArgTypes;
2843 std::vector<llvm::Type *> ArgElemTypes;
2844 std::vector<llvm::Value*> Args;
2845 llvm::BitVector ResultTypeRequiresCast;
2846 std::vector<std::optional<std::pair<unsigned, unsigned>>> ResultBounds;
2849 std::string InOutConstraints;
2850 std::vector<llvm::Value*> InOutArgs;
2851 std::vector<llvm::Type*> InOutArgTypes;
2852 std::vector<llvm::Type*> InOutArgElemTypes;
2855 std::vector<std::string> OutputConstraints;
2858 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2866 bool ReadOnly =
true, ReadNone =
true;
2874 StringRef(OutputConstraint).substr(1), &OutputConstraintInfos);
2882 [&](
const Stmt *UnspStmt, StringRef Msg) {
2883 CGM.ErrorUnsupported(UnspStmt, Msg);
2887 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2888 CGM.Error(S.
getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2890 OutputConstraints.push_back(OutputConstraint);
2892 if (!Constraints.empty())
2902 Constraints +=
"=" + OutputConstraint;
2903 ResultRegQualTys.push_back(QTy);
2904 ResultRegDests.push_back(Dest);
2911 Ty->isAggregateType());
2913 ResultTruncRegTypes.push_back(Ty);
2914 ResultTypeRequiresCast.push_back(RequiresCast);
2921 CGM.Error(OutExpr->
getExprLoc(),
"output size should not be zero");
2923 ResultRegTypes.push_back(Ty);
2929 for (InputNo = 0; InputNo != S.
getNumInputs(); ++InputNo) {
2934 assert(InputNo != S.
getNumInputs() &&
"Didn't find matching input!");
2945 if (llvm::Type* AdjTy =
2947 ResultRegTypes.back()))
2948 ResultRegTypes.back() = AdjTy;
2951 diag::err_asm_invalid_type_in_input)
2952 << OutExpr->
getType() << OutputConstraint;
2956 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
2957 LargestVectorWidth =
2958 std::max((uint64_t)LargestVectorWidth,
2959 VT->getPrimitiveSizeInBits().getKnownMinValue());
2970 ArgTypes.push_back(DestAddr.
getType());
2973 Constraints +=
"=*";
2974 Constraints += OutputConstraint;
2975 ReadOnly = ReadNone =
false;
2979 InOutConstraints +=
',';
2983 llvm::Type *ArgElemType;
2984 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
2985 Info, Dest, InputExpr->
getType(), InOutConstraints,
2988 if (llvm::Type* AdjTy =
2991 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2994 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2995 LargestVectorWidth =
2996 std::max((uint64_t)LargestVectorWidth,
2997 VT->getPrimitiveSizeInBits().getKnownMinValue());
3000 InOutConstraints += llvm::utostr(i);
3002 InOutConstraints += OutputConstraint;
3004 InOutArgTypes.push_back(Arg->getType());
3005 InOutArgElemTypes.push_back(ArgElemType);
3006 InOutArgs.push_back(Arg);
3017 CGM.getTargetCodeGenInfo().addReturnRegisterOutputs(
3018 *
this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
3024 for (
unsigned i = 0, e = S.
getNumInputs(); i != e; i++) {
3032 if (!Constraints.empty())
3043 [&](
const Stmt *UnspStmt, std::string_view Msg) {
3044 CGM.ErrorUnsupported(UnspStmt, Msg);
3047 std::string ReplaceConstraint (InputConstraint);
3049 llvm::Type *ArgElemType;
3050 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
3069 Arg =
Builder.CreateZExt(Arg, OutputTy);
3072 else if (OutputTy->isFloatingPointTy())
3073 Arg =
Builder.CreateFPExt(Arg, OutputTy);
3076 ReplaceConstraint = OutputConstraints[Output];
3078 if (llvm::Type* AdjTy =
3081 Arg =
Builder.CreateBitCast(Arg, AdjTy);
3083 CGM.getDiags().Report(S.
getAsmLoc(), diag::err_asm_invalid_type_in_input)
3084 << InputExpr->
getType() << InputConstraint;
3087 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3088 LargestVectorWidth =
3089 std::max((uint64_t)LargestVectorWidth,
3090 VT->getPrimitiveSizeInBits().getKnownMinValue());
3092 ArgTypes.push_back(Arg->getType());
3093 ArgElemTypes.push_back(ArgElemType);
3094 Args.push_back(Arg);
3095 Constraints += InputConstraint;
3099 for (
unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
3100 ArgTypes.push_back(InOutArgTypes[i]);
3101 ArgElemTypes.push_back(InOutArgElemTypes[i]);
3102 Args.push_back(InOutArgs[i]);
3104 Constraints += InOutConstraints;
3108 llvm::BasicBlock *Fallthrough =
nullptr;
3109 bool IsGCCAsmGoto =
false;
3110 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S)) {
3111 IsGCCAsmGoto = GS->isAsmGoto();
3113 for (
const auto *E : GS->labels()) {
3115 Transfer.push_back(Dest.
getBlock());
3116 if (!Constraints.empty())
3118 Constraints +=
"!i";
3124 bool HasUnwindClobber =
false;
3130 if (Clobber ==
"memory")
3131 ReadOnly = ReadNone =
false;
3132 else if (Clobber ==
"unwind") {
3133 HasUnwindClobber =
true;
3135 }
else if (Clobber !=
"cc") {
3137 if (
CGM.getCodeGenOpts().StackClashProtector &&
3140 diag::warn_stack_clash_protection_inline_asm);
3145 if (Clobber ==
"eax" || Clobber ==
"edx") {
3146 if (Constraints.find(
"=&A") != std::string::npos)
3148 std::string::size_type position1 =
3149 Constraints.find(
"={" + Clobber +
"}");
3150 if (position1 != std::string::npos) {
3151 Constraints.insert(position1 + 1,
"&");
3154 std::string::size_type position2 = Constraints.find(
"=A");
3155 if (position2 != std::string::npos) {
3156 Constraints.insert(position2 + 1,
"&");
3161 if (!Constraints.empty())
3164 Constraints +=
"~{";
3165 Constraints += Clobber;
3169 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
3170 "unwind clobber can't be used with asm goto");
3174 if (!MachineClobbers.empty()) {
3175 if (!Constraints.empty())
3177 Constraints += MachineClobbers;
3180 llvm::Type *ResultType;
3181 if (ResultRegTypes.empty())
3183 else if (ResultRegTypes.size() == 1)
3184 ResultType = ResultRegTypes[0];
3186 ResultType = llvm::StructType::get(
getLLVMContext(), ResultRegTypes);
3188 llvm::FunctionType *FTy =
3189 llvm::FunctionType::get(ResultType, ArgTypes,
false);
3193 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3195 ? llvm::InlineAsm::AD_ATT
3196 : llvm::InlineAsm::AD_Intel;
3198 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3200 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3201 FTy, AsmString, Constraints, HasSideEffect,
3202 false, AsmDialect, HasUnwindClobber);
3203 std::vector<llvm::Value*> RegResults;
3204 llvm::CallBrInst *CBR;
3205 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3208 CBR =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3213 ArgElemTypes, *
this, RegResults);
3217 if (!RegResults.empty()) {
3219 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3220 llvm::Twine SynthName = Dest->getName() +
".split";
3222 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3223 Builder.SetInsertPoint(SynthBB);
3225 if (ResultRegTypes.size() == 1) {
3226 CBRRegResults[SynthBB].push_back(CBR);
3228 for (
unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3229 llvm::Value *Tmp =
Builder.CreateExtractValue(CBR, j,
"asmresult");
3230 CBRRegResults[SynthBB].push_back(Tmp);
3236 CBR->setIndirectDest(i++, SynthBB);
3239 }
else if (HasUnwindClobber) {
3244 ArgElemTypes, *
this, RegResults);
3251 ArgElemTypes, *
this, RegResults);
3254 EmitAsmStores(*
this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3255 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3261 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3262 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3263 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3264 Builder.SetInsertPoint(Succ, --(Succ->end()));
3265 EmitAsmStores(*
this, S, CBRRegResults[Succ], ResultRegTypes,
3266 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3267 ResultTypeRequiresCast, ResultBounds);
3283 I != E; ++I, ++CurField) {
3285 if (CurField->hasCapturedVLAType()) {
3302 CodeGenFunction CGF(
CGM,
true);
3322 "CapturedStmtInfo should be set when generating the captured function");
3326 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3335 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Args);
3336 llvm::FunctionType *FuncLLVMTy =
CGM.getTypes().GetFunctionType(FuncInfo);
3339 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3341 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
3342 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
3343 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3345 F->addFnAttr(llvm::Attribute::NoUnwind);
3357 for (
auto *FD : RD->
fields()) {
3358 if (FD->hasCapturedVLAType()) {
3362 auto VAT = FD->getCapturedVLAType();
3363 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3374 PGO->assignRegionCounters(
GlobalDecl(CD), F);
3384 for (
auto &I : *BB) {
3385 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3392CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3394 assert(ParentToken);
3396 llvm::Value *bundleArgs[] = {ParentToken};
3397 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3398 auto *Output = llvm::CallBase::addOperandBundle(
3399 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3400 Input->replaceAllUsesWith(Output);
3401 Input->eraseFromParent();
3405llvm::ConvergenceControlInst *
3406CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
3408 assert(ParentToken);
3409 return llvm::ConvergenceControlInst::CreateLoop(*BB, ParentToken);
3412llvm::ConvergenceControlInst *
3413CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3414 llvm::BasicBlock *BB = &F->getEntryBlock();
3422 return llvm::ConvergenceControlInst::CreateEntry(*BB);
Defines enum values for all the target-independent builtin functions.
static bool FindCaseStatementsForValue(const SwitchStmt &S, const llvm::APSInt &ConstantCondValue, SmallVectorImpl< const Stmt * > &ResultStmts, ASTContext &C, const SwitchCase *&ResultCase)
FindCaseStatementsForValue - Find the case statement being jumped to and then invoke CollectStatement...
static llvm::ConvergenceControlInst * getConvergenceToken(llvm::BasicBlock *BB)
static void EmitHipStdParUnsupportedAsm(CodeGenFunction *CGF, const AsmStmt &S)
static std::optional< SmallVector< uint64_t, 16 > > getLikelihoodWeights(ArrayRef< Stmt::Likelihood > Likelihoods)
static llvm::MDNode * getAsmSrcLocInfo(const StringLiteral *Str, CodeGenFunction &CGF)
getAsmSrcLocInfo - Return the !srcloc metadata node to attach to an inline asm call instruction.
static bool isSwiftAsyncCallee(const CallExpr *CE)
Determine if the given call uses the swiftasync calling convention.
static CSFC_Result CollectStatementsForCase(const Stmt *S, const SwitchCase *Case, bool &FoundCase, SmallVectorImpl< const Stmt * > &ResultStmts)
static void EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S, const llvm::ArrayRef< llvm::Value * > RegResults, const llvm::ArrayRef< llvm::Type * > ResultRegTypes, const llvm::ArrayRef< llvm::Type * > ResultTruncRegTypes, const llvm::ArrayRef< LValue > ResultRegDests, const llvm::ArrayRef< QualType > ResultRegQualTys, const llvm::BitVector &ResultTypeRequiresCast, const std::vector< std::optional< std::pair< unsigned, unsigned > > > &ResultBounds)
static bool hasEmptyLoopBody(const LoopStmt &S)
CSFC_Result
CollectStatementsForCase - Given the body of a 'switch' statement and a constant value that is being ...
static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, bool HasUnwindClobber, bool ReadOnly, bool ReadNone, bool NoMerge, bool NoConvergent, const AsmStmt &S, const std::vector< llvm::Type * > &ResultRegTypes, const std::vector< llvm::Type * > &ArgElemTypes, CodeGenFunction &CGF, std::vector< llvm::Value * > &RegResults)
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Defines the SourceManager interface.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
bool toIntegralConstant(APSInt &Result, QualType SrcTy, const ASTContext &Ctx) const
Try to convert this value to an integral constant.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType getCanonicalTagType(const TagDecl *TD) const
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
std::string getInputConstraint(unsigned i) const
getInputConstraint - Return the specified input constraint.
std::string getOutputConstraint(unsigned i) const
getOutputConstraint - Return the constraint string for the specified output operand.
SourceLocation getAsmLoc() const
const Expr * getInputExpr(unsigned i) const
std::string addVariableConstraints(StringRef Constraint, const Expr &AsmExpr, const TargetInfo &Target, bool EarlyClobber, UnsupportedConstraintCallbackTy UnsupportedCB, std::string *GCCReg=nullptr) const
Look at AsmExpr and if it is a variable declared as using a particular register add that as a constra...
unsigned getNumClobbers() const
const Expr * getOutputExpr(unsigned i) const
unsigned getNumOutputs() const
std::string generateAsmString(const ASTContext &C) const
Assemble final IR asm string.
unsigned getNumInputs() const
std::string getClobber(unsigned i) const
Attr - This represents one attribute.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
BreakStmt - This represents a break.
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
DeclStmt * getBeginStmt()
DeclStmt * getLoopVarStmt()
DeclStmt * getRangeStmt()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Represents the body of a CapturedStmt, and serves as its DeclContext.
ImplicitParamDecl * getContextParam() const
Retrieve the parameter containing captured variables.
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
This captures a statement into a function.
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument.
SourceLocation getBeginLoc() const LLVM_READONLY
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument.
Expr *const * const_capture_init_iterator
Const iterator that walks over the capture initialization arguments.
CapturedRegionKind getCapturedRegionKind() const
Retrieve the captured region kind.
CaseStmt - Represent a case statement.
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::PointerType * getType() const
Return the type of the pointer value.
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
A scoped helper to set the current source atom group for CGDebugInfo::addInstToCurrentSourceAtom.
A scoped helper to set the current debug location to the specified location or preferred location of ...
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
CGFunctionInfo - Class to encapsulate the information about a function definition.
API for captured statement code generation.
RAII for correct setting/restoring of CapturedStmtInfo.
void rescopeLabels()
Change the cleanup scope of the labels in this lexical scope to match the scope of the enclosing cont...
void ForceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
bool requiresCleanups() const
Determine whether this scope requires any cleanups.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitCXXTryStmt(const CXXTryStmt &S)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void EmitSehCppScopeBegin()
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
@ UseSkipPath
Skip (false)
llvm::DenseMap< const VarDecl *, llvm::Value * > NRVOFlags
A mapping from NRVO variables to the flags used to indicate when the NRVO has been applied to this va...
bool IsOutlinedSEHHelper
True if the current function is an outlined SEH helper.
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
static bool ContainsLabel(const Stmt *S, bool IgnoreCaseStmts=false)
ContainsLabel - Return true if the statement contains a label in it.
void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef< const Attr * > Attrs={})
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit)
EmitComplexExprIntoLValue - Emit the given expression of complex type and place its result into the s...
static bool hasScalarEvaluationKind(QualType T)
llvm::Type * ConvertType(QualType T)
void EmitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &S)
LValue InitCapturedStruct(const CapturedStmt &S)
void addInstToNewSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)
Add KeyInstruction and an optional Backup instruction to a new atom group (See ApplyAtomGroup for mor...
CGCapturedStmtInfo * CapturedStmtInfo
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
void EmitOMPParallelForDirective(const OMPParallelForDirective &S)
llvm::CallBase * EmitCallOrInvoke(llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const Twine &Name="")
Emits a call or invoke instruction to the given function, depending on the current state of the EH st...
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOpenACCInitConstruct(const OpenACCInitConstruct &S)
void EmitOMPFlushDirective(const OMPFlushDirective &S)
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
JumpDest getJumpDestForLabel(const LabelDecl *S)
getBasicBlockForLabel - Return the LLVM basicblock that the specified label maps to.
void EmitCoreturnStmt(const CoreturnStmt &S)
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
SmallVector< llvm::ConvergenceControlInst *, 4 > ConvergenceTokenStack
Stack to track the controlled convergence tokens.
void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S)
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)
Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...
bool EmitSimpleStmt(const Stmt *S, ArrayRef< const Attr * > Attrs)
EmitSimpleStmt - Try to emit a "simple" statement which does not necessarily require an insertion poi...
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)
See CGDebugInfo::addInstToCurrentSourceAtom.
const LangOptions & getLangOpts() const
RValue EmitReferenceBindingToExpr(const Expr *E)
Emits a reference binding to the passed in expression.
void EmitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &S)
bool InNoConvergentAttributedStmt
True if the current statement has noconvergent attribute.
void EmitOpenACCWaitConstruct(const OpenACCWaitConstruct &S)
void EmitBlockAfterUses(llvm::BasicBlock *BB)
EmitBlockAfterUses - Emit the given block somewhere hopefully near its uses, and leave the insertion ...
void SimplifyForwardingBlocks(llvm::BasicBlock *BB)
SimplifyForwardingBlocks - If the given basic block is only a branch to another basic block,...
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
bool InNoMergeAttributedStmt
True if the current statement has nomerge attribute.
void EmitOMPScopeDirective(const OMPScopeDirective &S)
LValue MakeAddrLValueWithoutTBAA(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
bool hasSkipCounter(const Stmt *S) const
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
const TargetInfo & getTarget() const
Address EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
void EmitGotoStmt(const GotoStmt &S)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPCancelDirective(const OMPCancelDirective &S)
const Expr * RetExpr
If a return statement is being visited, this holds the return statment's result expression.
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
void EmitForStmt(const ForStmt &S, ArrayRef< const Attr * > Attrs={})
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S)
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPInteropDirective(const OMPInteropDirective &S)
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
void EmitWhileStmt(const WhileStmt &S, ArrayRef< const Attr * > Attrs={})
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
Emit combined directive 'target parallel loop' as if its constituent constructs are 'target',...
void EmitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &S)
void ResolveBranchFixups(llvm::BasicBlock *Target)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
bool checkIfLoopMustProgress(const Expr *, bool HasEmptyBody)
Returns true if a loop must make progress, which means the mustprogress attribute can be added.
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
CGDebugInfo * getDebugInfo()
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPReverseDirective(const OMPReverseDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EmitOpenACCDataConstruct(const OpenACCDataConstruct &S)
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)
void EmitObjCAtTryStmt(const ObjCAtTryStmt &S)
const TargetCodeGenInfo & getTargetHooks() const
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void EmitSEHLeaveStmt(const SEHLeaveStmt &S)
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
bool InNoInlineAttributedStmt
True if the current statement has noinline attribute.
SmallVector< llvm::OperandBundleDef, 1 > getBundlesForFunclet(llvm::Value *Callee)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
void EmitCoroutineBody(const CoroutineBodyStmt &S)
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
ASTContext & getContext() const
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitIfStmt(const IfStmt &S)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
void EmitDeferStmt(const DeferStmt &S)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
void EmitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &S)
void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S)
Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
EmitCompoundStmt - Emit a compound statement {..} node.
void EmitOpenACCCacheConstruct(const OpenACCCacheConstruct &S)
void EmitOpenACCLoopConstruct(const OpenACCLoopConstruct &S)
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
void EmitOMPFuseDirective(const OMPFuseDirective &S)
void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init)
void EmitAsmStmt(const AsmStmt &S)
void EmitDefaultStmt(const DefaultStmt &S, ArrayRef< const Attr * > Attrs)
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitSwitchStmt(const SwitchStmt &S)
static bool mightAddDeclToScope(const Stmt *S)
Determine if the given statement might introduce a declaration into the current scope,...
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
uint64_t getCurrentProfileCount()
Get the profiler's current count.
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
void EmitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &S)
llvm::Function * EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K)
Generate an outlined function for the body of a CapturedStmt, store any captured variables into the c...
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
static bool containsBreak(const Stmt *S)
containsBreak - Return true if the statement contains a break out of it.
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
HLSLControlFlowHintAttr::Spelling HLSLControlFlowAttr
HLSL Branch attribute.
bool InAlwaysInlineAttributedStmt
True if the current statement has always_inline attribute.
void EmitCaseStmt(const CaseStmt &S, ArrayRef< const Attr * > Attrs)
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitBreakStmt(const BreakStmt &S)
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void EmitOpenACCComputeConstruct(const OpenACCComputeConstruct &S)
void EmitDoStmt(const DoStmt &S, ArrayRef< const Attr * > Attrs={})
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
const TargetInfo & Target
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
void EmitOMPSimdDirective(const OMPSimdDirective &S)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
RawAddress NormalCleanupDest
i32s containing the indexes of the cleanup destinations.
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
unsigned NextCleanupDestIndex
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
const BreakContinue * GetDestForLoopControlStmt(const LoopControlStmt &S)
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
llvm::BasicBlock * GetIndirectGotoBlock()
void EmitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &S)
void EmitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &S)
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
static bool hasAggregateEvaluationKind(QualType T)
void EmitCaseStmtRange(const CaseStmt &S, ArrayRef< const Attr * > Attrs)
EmitCaseStmtRange - If case statement range is not too big then add multiple cases to switch instruct...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void EmitReturnStmt(const ReturnStmt &S)
EmitReturnStmt - Note that due to GCC extensions, this can have an operand if the function returns vo...
void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::Value * EmitCheckedArgForAssume(const Expr *E)
Emits an argument for a call to a __builtin_assume.
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
const CallExpr * MustTailCall
const CGFunctionInfo * CurFnInfo
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
void EmitDeclStmt(const DeclStmt &S)
void EmitLabelStmt(const LabelStmt &S)
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
void EmitOMPTileDirective(const OMPTileDirective &S)
void EmitDecl(const Decl &D, bool EvaluateConditionDecl=false)
EmitDecl - Emit a declaration.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
void EmitOpenACCSetConstruct(const OpenACCSetConstruct &S)
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitAttributedStmt(const AttributedStmt &S)
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
llvm::LLVMContext & getLLVMContext()
bool SawAsmBlock
Whether we processed a Microsoft-style asm block during CodeGen.
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)
void EmitIndirectGotoStmt(const IndirectGotoStmt &S)
void MaybeEmitDeferredVarDeclInit(const VarDecl *var)
bool isObviouslyBranchWithoutCleanups(JumpDest Dest) const
isObviouslyBranchWithoutCleanups - Return true if a branch to the specified destination obviously has...
void EmitSEHTryStmt(const SEHTryStmt &S)
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S)
When instrumenting to collect profile data, the counts for some blocks such as switch cases need to n...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitOMPForDirective(const OMPForDirective &S)
void EmitLabel(const LabelDecl *D)
EmitLabel - Emit the block for the given label.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
void EmitContinueStmt(const ContinueStmt &S)
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
const llvm::DataLayout & getDataLayout() const
ASTContext & getContext() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
A saved depth on the scope stack.
bool encloses(stable_iterator I) const
Returns true if this scope encloses I.
static stable_iterator invalid()
static stable_iterator stable_end()
Create a stable reference to the bottom of the EH stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
llvm::Value * getPointer(CodeGenFunction &CGF) const
Address getAddress() const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
virtual bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, llvm::Type *Ty) const
Target hook to decide whether an inline asm operand can be passed by value.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Stmt *const * const_body_iterator
SourceLocation getLBracLoc() const
body_iterator body_begin()
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
ContinueStmt - This represents a continue.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
DeferStmt - This represents a deferred statement.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
DoStmt - This represents a 'do/while' stmt.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
ForStmt - This represents a 'for (init;cond;inc)' stmt.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
const Expr * getSubExpr() const
FunctionType - C99 6.7.5.3 - Function Declarators.
CallingConv getCallConv() const
This represents a GCC inline-assembly statement extension.
GlobalDecl - represents a global declaration.
GotoStmt - This represents a direct goto.
LabelDecl * getLabel() const
IfStmt - This represents an if/then/else.
bool isNegatedConsteval() const
VarDecl * getConditionVariable()
Retrieve the variable declared in this "if" statement, if any.
IndirectGotoStmt - This represents an indirect goto.
LabelDecl * getConstantTarget()
getConstantTarget - Returns the fixed target of this indirect goto, if one exists.
Represents the declaration of a label.
LabelStmt * getStmt() const
LabelStmt - Represents a label, which has a substatement.
LabelDecl * getDecl() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool assumeFunctionsAreConvergent() const
Base class for BreakStmt and ContinueStmt.
Represents a point when we exit a loop.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType getCanonicalType() const
The collection of all-type qualifiers we support.
Represents a struct/union/class.
field_range fields() const
specific_decl_iterator< FieldDecl > field_iterator
field_iterator field_begin() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
SourceLocation getBeginLoc() const
const VarDecl * getNRVOCandidate() const
Retrieve the variable that might be used for the named return value optimization.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Likelihood
The likelihood of a branch being taken.
@ LH_Unlikely
Branch has the [[unlikely]] attribute.
@ LH_None
No attribute set or branches of the IfStmt have the same attribute.
@ LH_Likely
Branch has the [[likely]] attribute.
static const Attr * getLikelihoodAttr(const Stmt *S)
SourceLocation getBeginLoc() const LLVM_READONLY
static Likelihood getLikelihood(ArrayRef< const Attr * > Attrs)
StringLiteral - This represents a string literal expression, e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target, unsigned *StartToken=nullptr, unsigned *StartTokenByteOffset=nullptr) const
getLocationOfByte - Return a source location that points to the specified byte of this string literal...
StringRef getString() const
const SwitchCase * getNextSwitchCase() const
SwitchStmt - This represents a 'switch' stmt.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "switch" statement, if any.
SwitchCase * getSwitchCaseList()
bool validateInputConstraint(MutableArrayRef< ConstraintInfo > OutputConstraints, ConstraintInfo &info) const
std::string simplifyConstraint(StringRef Constraint, SmallVectorImpl< ConstraintInfo > *OutCons=nullptr) const
StringRef getNormalizedGCCRegisterName(StringRef Name, bool ReturnCanonical=false) const
Returns the "normalized" GCC register name.
bool validateOutputConstraint(ConstraintInfo &Info) const
virtual std::string_view getClobbers() const =0
Returns a string of target-specific clobbers, in LLVM format.
const T * castAs() const
Member-template castAs<specific type>.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isNRVOVariable() const
Determine whether this local variable can be used with the named return value optimization (NRVO).
WhileStmt - This represents a 'while' stmt.
SourceLocation getWhileLoc() const
SourceLocation getRParenLoc() const
VarDecl * getConditionVariable()
Retrieve the variable declared in this "while" statement, if any.
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
CapturedRegionKind
The different kinds of captured statement.
@ Asm
Assembly: we accept this only so that we can preprocess it.
@ Result
The result type of a method or function.
U cast(CodeGen::Address addr)
@ None
The alignment was not explicit in code.
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
void setScopeDepth(EHScopeStack::stable_iterator depth)
llvm::BasicBlock * getBlock() const
EHScopeStack::stable_iterator getScopeDepth() const
llvm::IntegerType * Int64Ty
llvm::IntegerType * IntPtrTy
llvm::PointerType * Int8PtrTy
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool hasMatchingInput() const
Return true if this output operand has a matching (tied) input operand.
unsigned getTiedOperand() const
bool allowsMemory() const
std::optional< std::pair< unsigned, unsigned > > getOutputOperandBounds() const
bool requiresImmediateConstant() const
bool hasTiedOperand() const
Return true if this input operand is a matching constraint that ties it to an output operand.
bool allowsRegister() const