29#include "llvm/ADT/ArrayRef.h"
30#include "llvm/ADT/DenseMap.h"
31#include "llvm/ADT/SmallSet.h"
32#include "llvm/ADT/StringExtras.h"
33#include "llvm/IR/Assumptions.h"
34#include "llvm/IR/DataLayout.h"
35#include "llvm/IR/InlineAsm.h"
36#include "llvm/IR/Intrinsics.h"
37#include "llvm/IR/MDBuilder.h"
38#include "llvm/Support/SaveAndRestore.h"
59 assert(S &&
"Null statement?");
60 PGO->setCurrentStmt(S);
77 PGO->markStmtMaybeUsed(S);
91 if (
const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
99 case Stmt::CXXCatchStmtClass:
100 case Stmt::SEHExceptStmtClass:
101 case Stmt::SEHFinallyStmtClass:
102 case Stmt::MSDependentExistsStmtClass:
103 case Stmt::UnresolvedSYCLKernelCallStmtClass:
104 llvm_unreachable(
"invalid statement class to emit generically");
105 case Stmt::NullStmtClass:
106 case Stmt::CompoundStmtClass:
107 case Stmt::DeclStmtClass:
108 case Stmt::LabelStmtClass:
109 case Stmt::AttributedStmtClass:
110 case Stmt::GotoStmtClass:
111 case Stmt::BreakStmtClass:
112 case Stmt::ContinueStmtClass:
113 case Stmt::DefaultStmtClass:
114 case Stmt::CaseStmtClass:
115 case Stmt::DeferStmtClass:
116 case Stmt::SEHLeaveStmtClass:
117 case Stmt::SYCLKernelCallStmtClass:
118 llvm_unreachable(
"should have emitted these statements as simple");
120#define STMT(Type, Base)
121#define ABSTRACT_STMT(Op)
122#define EXPR(Type, Base) \
123 case Stmt::Type##Class:
124#include "clang/AST/StmtNodes.inc"
127 llvm::BasicBlock *incoming =
Builder.GetInsertBlock();
128 assert(incoming &&
"expression emission must have an insertion point");
132 llvm::BasicBlock *outgoing =
Builder.GetInsertBlock();
133 assert(outgoing &&
"expression emission cleared block!");
147 if (incoming != outgoing && outgoing->use_empty()) {
148 outgoing->eraseFromParent();
154 case Stmt::IndirectGotoStmtClass:
165 case Stmt::GCCAsmStmtClass:
167 case Stmt::CoroutineBodyStmtClass:
170 case Stmt::CoreturnStmtClass:
173 case Stmt::CapturedStmtClass: {
178 case Stmt::ObjCAtTryStmtClass:
181 case Stmt::ObjCAtCatchStmtClass:
183 "@catch statements should be handled by EmitObjCAtTryStmt");
184 case Stmt::ObjCAtFinallyStmtClass:
186 "@finally statements should be handled by EmitObjCAtTryStmt");
187 case Stmt::ObjCAtThrowStmtClass:
190 case Stmt::ObjCAtSynchronizedStmtClass:
193 case Stmt::ObjCForCollectionStmtClass:
196 case Stmt::ObjCAutoreleasePoolStmtClass:
200 case Stmt::CXXTryStmtClass:
203 case Stmt::CXXForRangeStmtClass:
206 case Stmt::SEHTryStmtClass:
209 case Stmt::OMPMetaDirectiveClass:
212 case Stmt::OMPCanonicalLoopClass:
215 case Stmt::OMPParallelDirectiveClass:
218 case Stmt::OMPSimdDirectiveClass:
221 case Stmt::OMPTileDirectiveClass:
224 case Stmt::OMPStripeDirectiveClass:
227 case Stmt::OMPUnrollDirectiveClass:
230 case Stmt::OMPReverseDirectiveClass:
233 case Stmt::OMPInterchangeDirectiveClass:
236 case Stmt::OMPFuseDirectiveClass:
239 case Stmt::OMPForDirectiveClass:
242 case Stmt::OMPForSimdDirectiveClass:
245 case Stmt::OMPSectionsDirectiveClass:
248 case Stmt::OMPSectionDirectiveClass:
251 case Stmt::OMPSingleDirectiveClass:
254 case Stmt::OMPMasterDirectiveClass:
257 case Stmt::OMPCriticalDirectiveClass:
260 case Stmt::OMPParallelForDirectiveClass:
263 case Stmt::OMPParallelForSimdDirectiveClass:
266 case Stmt::OMPParallelMasterDirectiveClass:
269 case Stmt::OMPParallelSectionsDirectiveClass:
272 case Stmt::OMPTaskDirectiveClass:
275 case Stmt::OMPTaskyieldDirectiveClass:
278 case Stmt::OMPErrorDirectiveClass:
281 case Stmt::OMPBarrierDirectiveClass:
284 case Stmt::OMPTaskwaitDirectiveClass:
287 case Stmt::OMPTaskgroupDirectiveClass:
290 case Stmt::OMPFlushDirectiveClass:
293 case Stmt::OMPDepobjDirectiveClass:
296 case Stmt::OMPScanDirectiveClass:
299 case Stmt::OMPOrderedDirectiveClass:
302 case Stmt::OMPAtomicDirectiveClass:
305 case Stmt::OMPTargetDirectiveClass:
308 case Stmt::OMPTeamsDirectiveClass:
311 case Stmt::OMPCancellationPointDirectiveClass:
314 case Stmt::OMPCancelDirectiveClass:
317 case Stmt::OMPTargetDataDirectiveClass:
320 case Stmt::OMPTargetEnterDataDirectiveClass:
323 case Stmt::OMPTargetExitDataDirectiveClass:
326 case Stmt::OMPTargetParallelDirectiveClass:
329 case Stmt::OMPTargetParallelForDirectiveClass:
332 case Stmt::OMPTaskLoopDirectiveClass:
335 case Stmt::OMPTaskLoopSimdDirectiveClass:
338 case Stmt::OMPMasterTaskLoopDirectiveClass:
341 case Stmt::OMPMaskedTaskLoopDirectiveClass:
344 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
348 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
352 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
356 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
360 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
364 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
368 case Stmt::OMPDistributeDirectiveClass:
371 case Stmt::OMPTargetUpdateDirectiveClass:
374 case Stmt::OMPDistributeParallelForDirectiveClass:
378 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
382 case Stmt::OMPDistributeSimdDirectiveClass:
385 case Stmt::OMPTargetParallelForSimdDirectiveClass:
389 case Stmt::OMPTargetSimdDirectiveClass:
392 case Stmt::OMPTeamsDistributeDirectiveClass:
395 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
399 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
403 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
407 case Stmt::OMPTargetTeamsDirectiveClass:
410 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
414 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
418 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
422 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
426 case Stmt::OMPInteropDirectiveClass:
429 case Stmt::OMPDispatchDirectiveClass:
430 CGM.ErrorUnsupported(S,
"OpenMP dispatch directive");
432 case Stmt::OMPScopeDirectiveClass:
435 case Stmt::OMPMaskedDirectiveClass:
438 case Stmt::OMPGenericLoopDirectiveClass:
441 case Stmt::OMPTeamsGenericLoopDirectiveClass:
444 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
448 case Stmt::OMPParallelGenericLoopDirectiveClass:
452 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
456 case Stmt::OMPParallelMaskedDirectiveClass:
459 case Stmt::OMPAssumeDirectiveClass:
462 case Stmt::OpenACCComputeConstructClass:
465 case Stmt::OpenACCLoopConstructClass:
468 case Stmt::OpenACCCombinedConstructClass:
471 case Stmt::OpenACCDataConstructClass:
474 case Stmt::OpenACCEnterDataConstructClass:
477 case Stmt::OpenACCExitDataConstructClass:
480 case Stmt::OpenACCHostDataConstructClass:
483 case Stmt::OpenACCWaitConstructClass:
486 case Stmt::OpenACCInitConstructClass:
489 case Stmt::OpenACCShutdownConstructClass:
492 case Stmt::OpenACCSetConstructClass:
495 case Stmt::OpenACCUpdateConstructClass:
498 case Stmt::OpenACCAtomicConstructClass:
501 case Stmt::OpenACCCacheConstructClass:
512 case Stmt::NullStmtClass:
514 case Stmt::CompoundStmtClass:
517 case Stmt::DeclStmtClass:
520 case Stmt::LabelStmtClass:
523 case Stmt::AttributedStmtClass:
526 case Stmt::GotoStmtClass:
529 case Stmt::BreakStmtClass:
532 case Stmt::ContinueStmtClass:
535 case Stmt::DefaultStmtClass:
538 case Stmt::CaseStmtClass:
541 case Stmt::DeferStmtClass:
544 case Stmt::SEHLeaveStmtClass:
547 case Stmt::SYCLKernelCallStmtClass:
560 "LLVM IR generation of compound statement ('{}')");
587 if (
const auto *LS = dyn_cast<LabelStmt>(LastStmt)) {
589 LastStmt = LS->getSubStmt();
590 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(LastStmt)) {
593 LastStmt = AS->getSubStmt();
595 llvm_unreachable(
"unknown value statement");
619 llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
628 if (!BI || !BI->isUnconditional())
632 if (BI->getIterator() != BB->begin())
635 BB->replaceAllUsesWith(BI->getSuccessor(0));
636 BI->eraseFromParent();
637 BB->eraseFromParent();
641 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
646 if (IsFinished && BB->use_empty()) {
653 if (CurBB && CurBB->getParent())
654 CurFn->insert(std::next(CurBB->getIterator()), BB);
664 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
666 if (!CurBB || CurBB->getTerminator()) {
678 bool inserted =
false;
679 for (llvm::User *u : block->users()) {
680 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
681 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
696 if (Dest.
isValid())
return Dest;
709 if (
EHStack.hasNormalCleanups() && CurLexicalScope)
710 CurLexicalScope->addLabel(D);
731 if (
CGM.getCodeGenOpts().hasReducedDebugInfo()) {
743 assert(!Labels.empty());
745 =
CGF.EHStack.getInnermostNormalCleanup();
749 assert(
CGF.LabelMap.count(Label));
758 ParentScope->Labels.append(Labels.begin(), Labels.end());
774 bool nomerge =
false;
775 bool noinline =
false;
776 bool alwaysinline =
false;
777 bool noconvergent =
false;
778 HLSLControlFlowHintAttr::Spelling flattenOrBranch =
779 HLSLControlFlowHintAttr::SpellingNotCalculated;
781 const AtomicAttr *AA =
nullptr;
783 for (
const auto *A : S.
getAttrs()) {
784 switch (A->getKind()) {
793 case attr::AlwaysInline:
796 case attr::NoConvergent:
799 case attr::MustTail: {
804 case attr::CXXAssume: {
809 Builder.CreateAssumption(AssumptionVal);
815 case attr::HLSLControlFlowHint: {
852 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
862 if (CurBB && CurBB->getTerminator())
898 const Stmt *Skipped = Else;
900 std::swap(Executed, Skipped);
912 PGO->markStmtMaybeUsed(Skipped);
923 llvm::BasicBlock *ElseBlock =
939 CGM.getCodeGenOpts().OptimizationLevel)
948 if (!
CGM.getCodeGenOpts().MCDCCoverage) {
955 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
986 }
else if (HasSkip) {
998 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1008 bool CondIsConstInt =
1009 !ControllingExpression ||
1013 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
1014 Result.Val.getInt().getBoolValue());
1025 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1028 if (HasEmptyBody && CondIsTrue) {
1029 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1047 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1051 const Stmt *Body = S.getBody();
1054 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
1055 return Compound->body_empty();
1066 if (
CGM.shouldEmitConvergenceTokens())
1068 emitConvergenceLoopToken(LoopHeader.
getBlock()));
1075 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopHeader));
1098 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1099 bool EmitBoolCondBranch = !
C || !
C->isOne();
1108 if (EmitBoolCondBranch) {
1109 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1112 llvm::MDNode *Weights =
1114 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1115 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1117 auto *I =
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1123 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1127 if (ExitBlock !=
LoopExit.getBlock()) {
1133 CGM.getDiags().Report(A->getLocation(),
1134 diag::warn_attribute_has_no_effect_on_infinite_loop)
1135 << A << A->getRange();
1136 CGM.getDiags().Report(
1138 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1151 BreakContinueStack.pop_back();
1167 if (!EmitBoolCondBranch) {
1169 PGO->markStmtAsUsed(
true, &S);
1172 if (
CGM.shouldEmitConvergenceTokens())
1184 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopCond));
1191 if (
CGM.shouldEmitConvergenceTokens())
1209 BreakContinueStack.pop_back();
1213 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1214 bool EmitBoolCondBranch = !
C || !
C->isZero();
1217 LoopStack.push(LoopBody,
CGM.getContext(),
CGM.getCodeGenOpts(), DoAttrs,
1226 if (EmitBoolCondBranch) {
1228 auto *I =
Builder.CreateCondBr(
1229 BoolCondVal, LoopBody, LoopFalse,
1230 createProfileWeightsForLoop(S.
getCond(), BackedgeCount));
1237 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1244 if (LoopFalse !=
LoopExit.getBlock()) {
1254 if (!EmitBoolCondBranch)
1257 if (
CGM.shouldEmitConvergenceTokens())
1265 std::optional<LexicalScope> ForScope;
1277 llvm::BasicBlock *CondBlock = CondDest.
getBlock();
1280 if (
CGM.shouldEmitConvergenceTokens())
1284 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1301 Continue = CondDest;
1304 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1315 BreakContinueStack.back().ContinueBlock = Continue;
1318 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1321 if (
hasSkipCounter(&S) || (ForScope && ForScope->requiresCleanups()))
1333 llvm::MDNode *Weights =
1335 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1336 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1339 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1344 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1348 if (ExitBlock !=
LoopExit.getBlock()) {
1358 PGO->markStmtAsUsed(
true, &S);
1372 auto *FinalBodyBB =
Builder.GetInsertBlock();
1380 BreakContinueStack.pop_back();
1388 ForScope->ForceCleanup();
1395 if (
CGM.shouldEmitConvergenceTokens())
1425 if (
CGM.shouldEmitConvergenceTokens())
1429 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1435 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1445 llvm::MDNode *Weights =
1447 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1448 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1450 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1455 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1459 if (ExitBlock !=
LoopExit.getBlock()) {
1472 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1482 auto *FinalBodyBB =
Builder.GetInsertBlock();
1489 BreakContinueStack.pop_back();
1500 if (
CGM.shouldEmitConvergenceTokens())
1510void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1526struct SaveRetExprRAII {
1527 SaveRetExprRAII(
const Expr *RetExpr, CodeGenFunction &CGF)
1528 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1531 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1532 const Expr *OldRetExpr;
1533 CodeGenFunction &CGF;
1541 if (calleeQualType->isFunctionPointerType() ||
1542 calleeQualType->isFunctionReferenceType() ||
1543 calleeQualType->isBlockPointerType() ||
1544 calleeQualType->isMemberFunctionPointerType()) {
1546 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1548 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1549 if (
auto methodDecl = CMCE->getMethodDecl()) {
1566 if (requiresReturnValueCheck()) {
1569 new llvm::GlobalVariable(
CGM.getModule(), SLoc->getType(),
false,
1570 llvm::GlobalVariable::PrivateLinkage, SLoc);
1571 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1572 CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
1573 assert(ReturnLocation.isValid() &&
"No valid return location");
1574 Builder.CreateStore(SLocPtr, ReturnLocation);
1580 Builder.ClearInsertionPoint();
1594 SaveRetExprRAII SaveRetExpr(RV, *
this);
1597 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1598 RV = EWC->getSubExpr();
1602 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1605 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1618 !
CGM.getOpenMPRuntime()
1637 }
else if (
FnRetTy->isReferenceType()) {
1673 ++NumSimpleReturnExprs;
1685 for (
const auto *I : S.
decls())
1690 ->
const BreakContinue * {
1691 if (!S.hasLabelTarget())
1692 return &BreakContinueStack.back();
1694 const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
1695 assert(LoopOrSwitch &&
"break/continue target not set?");
1696 for (
const BreakContinue &BC : llvm::reverse(BreakContinueStack))
1697 if (BC.LoopOrSwitch == LoopOrSwitch)
1700 llvm_unreachable(
"break/continue target not found");
1704 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1717 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1734 assert(S.
getRHS() &&
"Expected RHS value in CaseStmt");
1747 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1751 llvm::APInt Range = RHS - LHS;
1753 if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
1756 unsigned NCases = Range.getZExtValue() + 1;
1761 uint64_t Weight = Total / NCases, Rem = Total % NCases;
1762 for (
unsigned I = 0; I != NCases; ++I) {
1764 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1765 else if (SwitchLikelihood)
1766 SwitchLikelihood->push_back(LH);
1770 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1778 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1783 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1787 Builder.SetInsertPoint(CaseRangeBlock);
1791 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1795 llvm::MDNode *Weights =
nullptr;
1796 if (SwitchWeights) {
1798 uint64_t DefaultCount = (*SwitchWeights)[0];
1799 Weights = createProfileWeights(ThisCount, DefaultCount);
1804 (*SwitchWeights)[0] += ThisCount;
1805 }
else if (SwitchLikelihood)
1806 Cond = emitCondLikelihoodViaExpectIntrinsic(
Cond, LH);
1808 Builder.CreateCondBr(
Cond, CaseDest, FalseDest, Weights);
1812 Builder.SetInsertPoint(RestoreBB);
1814 Builder.ClearInsertionPoint();
1835 llvm::ConstantInt *CaseVal =
1840 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.
getLHS()))
1841 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1843 CE = dyn_cast<ConstantExpr>(S.
getLHS());
1845 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1847 if (
CGM.getCodeGenOpts().hasReducedDebugInfo())
1848 Dbg->EmitGlobalVariable(DE->getDecl(),
1849 APValue(llvm::APSInt(CaseVal->getValue())));
1852 if (SwitchLikelihood)
1858 if (!
CGM.getCodeGenOpts().hasProfileClangInstr() &&
1859 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1867 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1871 if (
Builder.GetInsertBlock()) {
1873 Builder.ClearInsertionPoint();
1883 SwitchInsn->addCase(CaseVal, CaseDest);
1902 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1904 llvm::ConstantInt *CaseVal =
1909 if (
CGM.getCodeGenOpts().hasProfileClangInstr()) {
1915 if (SwitchLikelihood)
1918 SwitchInsn->addCase(CaseVal, CaseDest);
1919 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1942 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1943 assert(DefaultBlock->empty() &&
1944 "EmitDefaultStmt: Default block already defined?");
1946 if (SwitchLikelihood)
1955struct EmitDeferredStatement final : EHScopeStack::Cleanup {
2015 llvm::Value *SavedCleanupDest =
nullptr;
2069 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
2088 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
2092 bool StartedInLiveCode = FoundCase;
2093 unsigned StartSize = ResultStmts.size();
2100 bool HadSkippedDecl =
false;
2104 for (; Case && I != E; ++I) {
2120 for (++I; I != E; ++I)
2130 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
2145 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
2150 bool AnyDecls =
false;
2151 for (; I != E; ++I) {
2164 for (++I; I != E; ++I)
2181 ResultStmts.resize(StartSize);
2182 ResultStmts.push_back(S);
2206 ResultStmts.push_back(S);
2215 const llvm::APSInt &ConstantCondValue,
2227 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2235 if (CS->
getRHS())
return false;
2260 bool FoundCase =
false;
2267static std::optional<SmallVector<uint64_t, 16>>
2270 if (Likelihoods.size() <= 1)
2271 return std::nullopt;
2273 uint64_t NumUnlikely = 0;
2274 uint64_t NumNone = 0;
2275 uint64_t NumLikely = 0;
2276 for (
const auto LH : Likelihoods) {
2291 if (NumUnlikely == 0 && NumLikely == 0)
2292 return std::nullopt;
2300 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2301 const uint64_t
None = Likely / (NumNone + 1);
2302 const uint64_t Unlikely = 0;
2305 Result.reserve(Likelihoods.size());
2306 for (
const auto LH : Likelihoods) {
2309 Result.push_back(Unlikely);
2312 Result.push_back(
None);
2315 Result.push_back(Likely);
2325 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2328 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2332 llvm::APSInt ConstantCondValue;
2353 SwitchInsn =
nullptr;
2360 PGO->markStmtMaybeUsed(S.
getBody());
2364 SwitchInsn = SavedSwitchInsn;
2387 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2391 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2392 llvm::ConstantInt *BranchHintConstant =
2394 HLSLControlFlowHintAttr::Spelling::Microsoft_branch
2395 ? llvm::ConstantInt::get(
CGM.Int32Ty, 1)
2396 : llvm::ConstantInt::get(
CGM.Int32Ty, 2);
2397 llvm::Metadata *Vals[] = {MDHelper.createString(
"hlsl.controlflow.hint"),
2398 MDHelper.createConstant(BranchHintConstant)};
2399 SwitchInsn->setMetadata(
"hlsl.controlflow.hint",
2400 llvm::MDNode::get(
CGM.getLLVMContext(), Vals));
2403 if (PGO->haveRegionCounts()) {
2405 uint64_t DefaultCount = 0;
2406 unsigned NumCases = 0;
2415 SwitchWeights->reserve(NumCases);
2418 SwitchWeights->push_back(DefaultCount);
2419 }
else if (
CGM.getCodeGenOpts().OptimizationLevel) {
2425 CaseRangeBlock = DefaultBlock;
2428 Builder.ClearInsertionPoint();
2433 if (!BreakContinueStack.empty())
2434 OuterContinue = BreakContinueStack.back().ContinueBlock;
2436 BreakContinueStack.push_back(BreakContinue(S, SwitchExit, OuterContinue));
2441 BreakContinueStack.pop_back();
2445 SwitchInsn->setDefaultDest(CaseRangeBlock);
2448 if (!DefaultBlock->getParent()) {
2456 DefaultBlock->replaceAllUsesWith(SwitchExit.
getBlock());
2457 delete DefaultBlock;
2471 Builder.CreateBr(SwitchInsn->getDefaultDest());
2472 SwitchInsn->setDefaultDest(ImplicitDefaultBlock);
2483 if (
Call &&
CGM.getCodeGenOpts().OptimizationLevel != 0) {
2484 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2485 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2487 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2488 MDHelper.createUnpredictable());
2492 if (SwitchWeights) {
2493 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2494 "switch weights do not match switch cases");
2496 if (SwitchWeights->size() > 1)
2497 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2498 createProfileWeights(*SwitchWeights));
2499 delete SwitchWeights;
2500 }
else if (SwitchLikelihood) {
2501 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2502 "switch likelihoods do not match switch cases");
2503 std::optional<SmallVector<uint64_t, 16>> LHW =
2506 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2507 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2508 createProfileWeights(*LHW));
2510 delete SwitchLikelihood;
2512 SwitchInsn = SavedSwitchInsn;
2513 SwitchWeights = SavedSwitchWeights;
2514 SwitchLikelihood = SavedSwitchLikelihood;
2515 CaseRangeBlock = SavedCRBlock;
2518std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2527 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2537 ConstraintStr +=
'*';
2540std::pair<llvm::Value *, llvm::Type *>
2541CodeGenFunction::EmitAsmInput(
const TargetInfo::ConstraintInfo &Info,
2542 const Expr *InputExpr,
2543 std::string &ConstraintStr) {
2548 Expr::EvalResult EVResult;
2551 llvm::APSInt IntResult;
2554 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2566 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2570 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2582 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2585 if (!StrVal.empty()) {
2588 unsigned StartToken = 0;
2589 unsigned ByteOffset = 0;
2593 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2594 if (StrVal[i] !=
'\n')
continue;
2596 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2597 Locs.push_back(llvm::ConstantAsMetadata::get(
2606 bool HasUnwindClobber,
bool ReadOnly,
2607 bool ReadNone,
bool NoMerge,
bool NoConvergent,
2609 const std::vector<llvm::Type *> &ResultRegTypes,
2610 const std::vector<llvm::Type *> &ArgElemTypes,
2612 std::vector<llvm::Value *> &RegResults) {
2613 if (!HasUnwindClobber)
2614 Result.addFnAttr(llvm::Attribute::NoUnwind);
2617 Result.addFnAttr(llvm::Attribute::NoMerge);
2619 if (!HasSideEffect) {
2621 Result.setDoesNotAccessMemory();
2623 Result.setOnlyReadsMemory();
2627 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
2629 auto Attr = llvm::Attribute::get(
2630 CGF.
getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2631 Result.addParamAttr(Pair.index(),
Attr);
2638 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S);
2640 (SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))) {
2645 llvm::Constant *Loc =
2647 Result.setMetadata(
"srcloc",
2649 llvm::ConstantAsMetadata::get(Loc)));
2660 Result.addFnAttr(llvm::Attribute::Convergent);
2662 if (ResultRegTypes.size() == 1) {
2663 RegResults.push_back(&Result);
2665 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2666 llvm::Value *Tmp = CGF.
Builder.CreateExtractValue(&Result, i,
"asmresult");
2667 RegResults.push_back(Tmp);
2679 const llvm::BitVector &ResultTypeRequiresCast,
2680 const std::vector<std::optional<std::pair<unsigned, unsigned>>>
2686 assert(RegResults.size() == ResultRegTypes.size());
2687 assert(RegResults.size() == ResultTruncRegTypes.size());
2688 assert(RegResults.size() == ResultRegDests.size());
2691 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2692 assert(ResultBounds.size() <= ResultRegDests.size());
2694 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2695 llvm::Value *Tmp = RegResults[i];
2696 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2698 if ((i < ResultBounds.size()) && ResultBounds[i].has_value()) {
2699 const auto [LowerBound, UpperBound] = ResultBounds[i].value();
2701 assert(LowerBound == 0 &&
"Output operand lower bound is not zero.");
2702 llvm::Constant *UpperBoundConst =
2703 llvm::ConstantInt::get(Tmp->getType(), UpperBound);
2704 llvm::Value *IsBooleanValue =
2705 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, UpperBoundConst);
2707 Builder.CreateCall(FnAssume, IsBooleanValue);
2712 if (ResultRegTypes[i] != TruncTy) {
2716 if (TruncTy->isFloatingPointTy())
2717 Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
2718 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2720 Tmp = Builder.CreateTrunc(
2721 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
2722 Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
2723 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2726 Tmp = Builder.CreatePtrToInt(
2727 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
2728 Tmp = Builder.CreateTrunc(Tmp, TruncTy);
2729 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2730 Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2731 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2732 Tmp = Builder.CreateBitCast(Tmp, TruncTy);
2737 LValue Dest = ResultRegDests[i];
2740 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2742 Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
2744 llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
2754 diag::err_store_value_to_reg);
2765 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2768 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2769 Asm = GCCAsm->getAsmString();
2773 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2774 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2775 {StrTy->getType()},
false);
2776 auto UBF = CGF->
CGM.
getModule().getOrInsertFunction(Name, FnTy);
2778 CGF->
Builder.CreateCall(UBF, {StrTy});
2793 bool IsValidTargetAsm =
true;
2794 for (
unsigned i = 0, e = S.
getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2796 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2797 Name = GAS->getOutputName(i);
2800 if (IsHipStdPar && !IsValid)
2801 IsValidTargetAsm =
false;
2803 assert(IsValid &&
"Failed to parse output constraint");
2804 OutputConstraintInfos.push_back(Info);
2807 for (
unsigned i = 0, e = S.
getNumInputs(); i != e && IsValidTargetAsm; i++) {
2809 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2810 Name = GAS->getInputName(i);
2814 if (IsHipStdPar && !IsValid)
2815 IsValidTargetAsm =
false;
2817 assert(IsValid &&
"Failed to parse input constraint");
2818 InputConstraintInfos.push_back(Info);
2821 if (!IsValidTargetAsm)
2824 std::string Constraints;
2826 std::vector<LValue> ResultRegDests;
2827 std::vector<QualType> ResultRegQualTys;
2828 std::vector<llvm::Type *> ResultRegTypes;
2829 std::vector<llvm::Type *> ResultTruncRegTypes;
2830 std::vector<llvm::Type *> ArgTypes;
2831 std::vector<llvm::Type *> ArgElemTypes;
2832 std::vector<llvm::Value*> Args;
2833 llvm::BitVector ResultTypeRequiresCast;
2834 std::vector<std::optional<std::pair<unsigned, unsigned>>> ResultBounds;
2837 std::string InOutConstraints;
2838 std::vector<llvm::Value*> InOutArgs;
2839 std::vector<llvm::Type*> InOutArgTypes;
2840 std::vector<llvm::Type*> InOutArgElemTypes;
2843 std::vector<std::string> OutputConstraints;
2846 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2854 bool ReadOnly =
true, ReadNone =
true;
2862 StringRef(OutputConstraint).substr(1), &OutputConstraintInfos);
2870 [&](
const Stmt *UnspStmt, StringRef Msg) {
2871 CGM.ErrorUnsupported(UnspStmt, Msg);
2875 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2876 CGM.Error(S.
getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2878 OutputConstraints.push_back(OutputConstraint);
2880 if (!Constraints.empty())
2890 Constraints +=
"=" + OutputConstraint;
2891 ResultRegQualTys.push_back(QTy);
2892 ResultRegDests.push_back(Dest);
2899 Ty->isAggregateType());
2901 ResultTruncRegTypes.push_back(Ty);
2902 ResultTypeRequiresCast.push_back(RequiresCast);
2909 CGM.Error(OutExpr->
getExprLoc(),
"output size should not be zero");
2911 ResultRegTypes.push_back(Ty);
2917 for (InputNo = 0; InputNo != S.
getNumInputs(); ++InputNo) {
2922 assert(InputNo != S.
getNumInputs() &&
"Didn't find matching input!");
2933 if (llvm::Type* AdjTy =
2935 ResultRegTypes.back()))
2936 ResultRegTypes.back() = AdjTy;
2939 diag::err_asm_invalid_type_in_input)
2940 << OutExpr->
getType() << OutputConstraint;
2944 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
2945 LargestVectorWidth =
2946 std::max((uint64_t)LargestVectorWidth,
2947 VT->getPrimitiveSizeInBits().getKnownMinValue());
2958 ArgTypes.push_back(DestAddr.
getType());
2961 Constraints +=
"=*";
2962 Constraints += OutputConstraint;
2963 ReadOnly = ReadNone =
false;
2967 InOutConstraints +=
',';
2971 llvm::Type *ArgElemType;
2972 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
2973 Info, Dest, InputExpr->
getType(), InOutConstraints,
2976 if (llvm::Type* AdjTy =
2979 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2982 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2983 LargestVectorWidth =
2984 std::max((uint64_t)LargestVectorWidth,
2985 VT->getPrimitiveSizeInBits().getKnownMinValue());
2988 InOutConstraints += llvm::utostr(i);
2990 InOutConstraints += OutputConstraint;
2992 InOutArgTypes.push_back(Arg->getType());
2993 InOutArgElemTypes.push_back(ArgElemType);
2994 InOutArgs.push_back(Arg);
3005 CGM.getTargetCodeGenInfo().addReturnRegisterOutputs(
3006 *
this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
3012 for (
unsigned i = 0, e = S.
getNumInputs(); i != e; i++) {
3020 if (!Constraints.empty())
3031 [&](
const Stmt *UnspStmt, std::string_view Msg) {
3032 CGM.ErrorUnsupported(UnspStmt, Msg);
3035 std::string ReplaceConstraint (InputConstraint);
3037 llvm::Type *ArgElemType;
3038 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
3057 Arg =
Builder.CreateZExt(Arg, OutputTy);
3060 else if (OutputTy->isFloatingPointTy())
3061 Arg =
Builder.CreateFPExt(Arg, OutputTy);
3064 ReplaceConstraint = OutputConstraints[Output];
3066 if (llvm::Type* AdjTy =
3069 Arg =
Builder.CreateBitCast(Arg, AdjTy);
3071 CGM.getDiags().Report(S.
getAsmLoc(), diag::err_asm_invalid_type_in_input)
3072 << InputExpr->
getType() << InputConstraint;
3075 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3076 LargestVectorWidth =
3077 std::max((uint64_t)LargestVectorWidth,
3078 VT->getPrimitiveSizeInBits().getKnownMinValue());
3080 ArgTypes.push_back(Arg->getType());
3081 ArgElemTypes.push_back(ArgElemType);
3082 Args.push_back(Arg);
3083 Constraints += InputConstraint;
3087 for (
unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
3088 ArgTypes.push_back(InOutArgTypes[i]);
3089 ArgElemTypes.push_back(InOutArgElemTypes[i]);
3090 Args.push_back(InOutArgs[i]);
3092 Constraints += InOutConstraints;
3096 llvm::BasicBlock *Fallthrough =
nullptr;
3097 bool IsGCCAsmGoto =
false;
3098 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S)) {
3099 IsGCCAsmGoto = GS->isAsmGoto();
3101 for (
const auto *E : GS->labels()) {
3103 Transfer.push_back(Dest.
getBlock());
3104 if (!Constraints.empty())
3106 Constraints +=
"!i";
3112 bool HasUnwindClobber =
false;
3118 if (Clobber ==
"memory")
3119 ReadOnly = ReadNone =
false;
3120 else if (Clobber ==
"unwind") {
3121 HasUnwindClobber =
true;
3123 }
else if (Clobber !=
"cc") {
3125 if (
CGM.getCodeGenOpts().StackClashProtector &&
3128 diag::warn_stack_clash_protection_inline_asm);
3133 if (Clobber ==
"eax" || Clobber ==
"edx") {
3134 if (Constraints.find(
"=&A") != std::string::npos)
3136 std::string::size_type position1 =
3137 Constraints.find(
"={" + Clobber +
"}");
3138 if (position1 != std::string::npos) {
3139 Constraints.insert(position1 + 1,
"&");
3142 std::string::size_type position2 = Constraints.find(
"=A");
3143 if (position2 != std::string::npos) {
3144 Constraints.insert(position2 + 1,
"&");
3149 if (!Constraints.empty())
3152 Constraints +=
"~{";
3153 Constraints += Clobber;
3157 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
3158 "unwind clobber can't be used with asm goto");
3162 if (!MachineClobbers.empty()) {
3163 if (!Constraints.empty())
3165 Constraints += MachineClobbers;
3168 llvm::Type *ResultType;
3169 if (ResultRegTypes.empty())
3171 else if (ResultRegTypes.size() == 1)
3172 ResultType = ResultRegTypes[0];
3174 ResultType = llvm::StructType::get(
getLLVMContext(), ResultRegTypes);
3176 llvm::FunctionType *FTy =
3177 llvm::FunctionType::get(ResultType, ArgTypes,
false);
3181 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3183 ? llvm::InlineAsm::AD_ATT
3184 : llvm::InlineAsm::AD_Intel;
3186 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3188 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3189 FTy, AsmString, Constraints, HasSideEffect,
3190 false, AsmDialect, HasUnwindClobber);
3191 std::vector<llvm::Value*> RegResults;
3192 llvm::CallBrInst *CBR;
3193 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3196 CBR =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3201 ArgElemTypes, *
this, RegResults);
3205 if (!RegResults.empty()) {
3207 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3208 llvm::Twine SynthName = Dest->getName() +
".split";
3210 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3211 Builder.SetInsertPoint(SynthBB);
3213 if (ResultRegTypes.size() == 1) {
3214 CBRRegResults[SynthBB].push_back(CBR);
3216 for (
unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3217 llvm::Value *Tmp =
Builder.CreateExtractValue(CBR, j,
"asmresult");
3218 CBRRegResults[SynthBB].push_back(Tmp);
3224 CBR->setIndirectDest(i++, SynthBB);
3227 }
else if (HasUnwindClobber) {
3232 ArgElemTypes, *
this, RegResults);
3239 ArgElemTypes, *
this, RegResults);
3242 EmitAsmStores(*
this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3243 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3249 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3250 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3251 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3252 Builder.SetInsertPoint(Succ, --(Succ->end()));
3253 EmitAsmStores(*
this, S, CBRRegResults[Succ], ResultRegTypes,
3254 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3255 ResultTypeRequiresCast, ResultBounds);
3271 I != E; ++I, ++CurField) {
3273 if (CurField->hasCapturedVLAType()) {
3290 CodeGenFunction CGF(
CGM,
true);
3310 "CapturedStmtInfo should be set when generating the captured function");
3314 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3323 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Args);
3324 llvm::FunctionType *FuncLLVMTy =
CGM.getTypes().GetFunctionType(FuncInfo);
3327 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3329 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
3330 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
3331 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3333 F->addFnAttr(llvm::Attribute::NoUnwind);
3345 for (
auto *FD : RD->
fields()) {
3346 if (FD->hasCapturedVLAType()) {
3350 auto VAT = FD->getCapturedVLAType();
3351 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3362 PGO->assignRegionCounters(
GlobalDecl(CD), F);
3372 for (
auto &I : *BB) {
3373 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3380CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3382 assert(ParentToken);
3384 llvm::Value *bundleArgs[] = {ParentToken};
3385 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3386 auto *Output = llvm::CallBase::addOperandBundle(
3387 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3388 Input->replaceAllUsesWith(Output);
3389 Input->eraseFromParent();
3393llvm::ConvergenceControlInst *
3394CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
3396 assert(ParentToken);
3397 return llvm::ConvergenceControlInst::CreateLoop(*BB, ParentToken);
3400llvm::ConvergenceControlInst *
3401CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3402 llvm::BasicBlock *BB = &F->getEntryBlock();
3410 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.
This file defines SYCL AST classes used to represent calls to SYCL kernels.
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 EmitSYCLKernelCallStmt(const SYCLKernelCallStmt &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