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"
62 assert(S &&
"Null statement?");
63 PGO->setCurrentStmt(S);
80 PGO->markStmtMaybeUsed(S);
94 if (
const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
102 case Stmt::CXXCatchStmtClass:
103 case Stmt::SEHExceptStmtClass:
104 case Stmt::SEHFinallyStmtClass:
105 case Stmt::MSDependentExistsStmtClass:
106 llvm_unreachable(
"invalid statement class to emit generically");
107 case Stmt::NullStmtClass:
108 case Stmt::CompoundStmtClass:
109 case Stmt::DeclStmtClass:
110 case Stmt::LabelStmtClass:
111 case Stmt::AttributedStmtClass:
112 case Stmt::GotoStmtClass:
113 case Stmt::BreakStmtClass:
114 case Stmt::ContinueStmtClass:
115 case Stmt::DefaultStmtClass:
116 case Stmt::CaseStmtClass:
117 case Stmt::SEHLeaveStmtClass:
118 case Stmt::SYCLKernelCallStmtClass:
119 llvm_unreachable(
"should have emitted these statements as simple");
121#define STMT(Type, Base)
122#define ABSTRACT_STMT(Op)
123#define EXPR(Type, Base) \
124 case Stmt::Type##Class:
125#include "clang/AST/StmtNodes.inc"
128 llvm::BasicBlock *incoming =
Builder.GetInsertBlock();
129 assert(incoming &&
"expression emission must have an insertion point");
133 llvm::BasicBlock *outgoing =
Builder.GetInsertBlock();
134 assert(outgoing &&
"expression emission cleared block!");
148 if (incoming != outgoing && outgoing->use_empty()) {
149 outgoing->eraseFromParent();
155 case Stmt::IndirectGotoStmtClass:
166 case Stmt::GCCAsmStmtClass:
168 case Stmt::CoroutineBodyStmtClass:
171 case Stmt::CoreturnStmtClass:
174 case Stmt::CapturedStmtClass: {
179 case Stmt::ObjCAtTryStmtClass:
182 case Stmt::ObjCAtCatchStmtClass:
184 "@catch statements should be handled by EmitObjCAtTryStmt");
185 case Stmt::ObjCAtFinallyStmtClass:
187 "@finally statements should be handled by EmitObjCAtTryStmt");
188 case Stmt::ObjCAtThrowStmtClass:
191 case Stmt::ObjCAtSynchronizedStmtClass:
194 case Stmt::ObjCForCollectionStmtClass:
197 case Stmt::ObjCAutoreleasePoolStmtClass:
201 case Stmt::CXXTryStmtClass:
204 case Stmt::CXXForRangeStmtClass:
207 case Stmt::SEHTryStmtClass:
210 case Stmt::OMPMetaDirectiveClass:
213 case Stmt::OMPCanonicalLoopClass:
216 case Stmt::OMPParallelDirectiveClass:
219 case Stmt::OMPSimdDirectiveClass:
222 case Stmt::OMPTileDirectiveClass:
225 case Stmt::OMPStripeDirectiveClass:
228 case Stmt::OMPUnrollDirectiveClass:
231 case Stmt::OMPReverseDirectiveClass:
234 case Stmt::OMPInterchangeDirectiveClass:
237 case Stmt::OMPFuseDirectiveClass:
240 case Stmt::OMPForDirectiveClass:
243 case Stmt::OMPForSimdDirectiveClass:
246 case Stmt::OMPSectionsDirectiveClass:
249 case Stmt::OMPSectionDirectiveClass:
252 case Stmt::OMPSingleDirectiveClass:
255 case Stmt::OMPMasterDirectiveClass:
258 case Stmt::OMPCriticalDirectiveClass:
261 case Stmt::OMPParallelForDirectiveClass:
264 case Stmt::OMPParallelForSimdDirectiveClass:
267 case Stmt::OMPParallelMasterDirectiveClass:
270 case Stmt::OMPParallelSectionsDirectiveClass:
273 case Stmt::OMPTaskDirectiveClass:
276 case Stmt::OMPTaskyieldDirectiveClass:
279 case Stmt::OMPErrorDirectiveClass:
282 case Stmt::OMPBarrierDirectiveClass:
285 case Stmt::OMPTaskwaitDirectiveClass:
288 case Stmt::OMPTaskgroupDirectiveClass:
291 case Stmt::OMPFlushDirectiveClass:
294 case Stmt::OMPDepobjDirectiveClass:
297 case Stmt::OMPScanDirectiveClass:
300 case Stmt::OMPOrderedDirectiveClass:
303 case Stmt::OMPAtomicDirectiveClass:
306 case Stmt::OMPTargetDirectiveClass:
309 case Stmt::OMPTeamsDirectiveClass:
312 case Stmt::OMPCancellationPointDirectiveClass:
315 case Stmt::OMPCancelDirectiveClass:
318 case Stmt::OMPTargetDataDirectiveClass:
321 case Stmt::OMPTargetEnterDataDirectiveClass:
324 case Stmt::OMPTargetExitDataDirectiveClass:
327 case Stmt::OMPTargetParallelDirectiveClass:
330 case Stmt::OMPTargetParallelForDirectiveClass:
333 case Stmt::OMPTaskLoopDirectiveClass:
336 case Stmt::OMPTaskLoopSimdDirectiveClass:
339 case Stmt::OMPMasterTaskLoopDirectiveClass:
342 case Stmt::OMPMaskedTaskLoopDirectiveClass:
345 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
349 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
353 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
357 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
361 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
365 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
369 case Stmt::OMPDistributeDirectiveClass:
372 case Stmt::OMPTargetUpdateDirectiveClass:
375 case Stmt::OMPDistributeParallelForDirectiveClass:
379 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
383 case Stmt::OMPDistributeSimdDirectiveClass:
386 case Stmt::OMPTargetParallelForSimdDirectiveClass:
390 case Stmt::OMPTargetSimdDirectiveClass:
393 case Stmt::OMPTeamsDistributeDirectiveClass:
396 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
400 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
404 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
408 case Stmt::OMPTargetTeamsDirectiveClass:
411 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
415 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
419 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
423 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
427 case Stmt::OMPInteropDirectiveClass:
430 case Stmt::OMPDispatchDirectiveClass:
431 CGM.ErrorUnsupported(S,
"OpenMP dispatch directive");
433 case Stmt::OMPScopeDirectiveClass:
436 case Stmt::OMPMaskedDirectiveClass:
439 case Stmt::OMPGenericLoopDirectiveClass:
442 case Stmt::OMPTeamsGenericLoopDirectiveClass:
445 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
449 case Stmt::OMPParallelGenericLoopDirectiveClass:
453 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
457 case Stmt::OMPParallelMaskedDirectiveClass:
460 case Stmt::OMPAssumeDirectiveClass:
463 case Stmt::OpenACCComputeConstructClass:
466 case Stmt::OpenACCLoopConstructClass:
469 case Stmt::OpenACCCombinedConstructClass:
472 case Stmt::OpenACCDataConstructClass:
475 case Stmt::OpenACCEnterDataConstructClass:
478 case Stmt::OpenACCExitDataConstructClass:
481 case Stmt::OpenACCHostDataConstructClass:
484 case Stmt::OpenACCWaitConstructClass:
487 case Stmt::OpenACCInitConstructClass:
490 case Stmt::OpenACCShutdownConstructClass:
493 case Stmt::OpenACCSetConstructClass:
496 case Stmt::OpenACCUpdateConstructClass:
499 case Stmt::OpenACCAtomicConstructClass:
502 case Stmt::OpenACCCacheConstructClass:
513 case Stmt::NullStmtClass:
515 case Stmt::CompoundStmtClass:
518 case Stmt::DeclStmtClass:
521 case Stmt::LabelStmtClass:
524 case Stmt::AttributedStmtClass:
527 case Stmt::GotoStmtClass:
530 case Stmt::BreakStmtClass:
533 case Stmt::ContinueStmtClass:
536 case Stmt::DefaultStmtClass:
539 case Stmt::CaseStmtClass:
542 case Stmt::SEHLeaveStmtClass:
545 case Stmt::SYCLKernelCallStmtClass:
572 "LLVM IR generation of compound statement ('{}')");
586 assert((!GetLast || (GetLast &&
ExprResult)) &&
587 "If GetLast is true then the CompoundStmt must have a StmtExprResult");
591 for (
auto *CurStmt : S.
body()) {
599 if (
const auto *LS = dyn_cast<LabelStmt>(
ExprResult)) {
602 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(
ExprResult)) {
607 llvm_unreachable(
"unknown value statement");
634 llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
643 if (!BI || !BI->isUnconditional())
647 if (BI->getIterator() != BB->begin())
650 BB->replaceAllUsesWith(BI->getSuccessor(0));
651 BI->eraseFromParent();
652 BB->eraseFromParent();
656 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
661 if (IsFinished && BB->use_empty()) {
668 if (CurBB && CurBB->getParent())
669 CurFn->insert(std::next(CurBB->getIterator()), BB);
679 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
681 if (!CurBB || CurBB->getTerminator()) {
693 bool inserted =
false;
694 for (llvm::User *u : block->users()) {
695 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
696 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
711 if (Dest.
isValid())
return Dest;
724 if (
EHStack.hasNormalCleanups() && CurLexicalScope)
725 CurLexicalScope->addLabel(D);
746 if (
CGM.getCodeGenOpts().hasReducedDebugInfo()) {
758 assert(!Labels.empty());
760 =
CGF.EHStack.getInnermostNormalCleanup();
764 assert(
CGF.LabelMap.count(Label));
773 ParentScope->Labels.append(Labels.begin(), Labels.end());
789 bool nomerge =
false;
790 bool noinline =
false;
791 bool alwaysinline =
false;
792 bool noconvergent =
false;
793 HLSLControlFlowHintAttr::Spelling flattenOrBranch =
794 HLSLControlFlowHintAttr::SpellingNotCalculated;
796 const AtomicAttr *AA =
nullptr;
798 for (
const auto *A : S.
getAttrs()) {
799 switch (A->getKind()) {
808 case attr::AlwaysInline:
811 case attr::NoConvergent:
814 case attr::MustTail: {
819 case attr::CXXAssume: {
824 Builder.CreateAssumption(AssumptionVal);
830 case attr::HLSLControlFlowHint: {
867 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
877 if (CurBB && CurBB->getTerminator())
913 const Stmt *Skipped = Else;
915 std::swap(Executed, Skipped);
927 PGO->markStmtMaybeUsed(Skipped);
936 llvm::BasicBlock *ElseBlock = ContBlock;
954 CGM.getCodeGenOpts().OptimizationLevel)
963 if (!
CGM.getCodeGenOpts().MCDCCoverage) {
970 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
1016 bool HasEmptyBody) {
1017 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1027 bool CondIsConstInt =
1028 !ControllingExpression ||
1032 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
1033 Result.Val.getInt().getBoolValue());
1044 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1047 if (HasEmptyBody && CondIsTrue) {
1048 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1066 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1070 const Stmt *Body = S.getBody();
1073 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
1074 return Compound->body_empty();
1085 if (
CGM.shouldEmitConvergenceTokens())
1087 emitConvergenceLoopToken(LoopHeader.
getBlock()));
1094 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopHeader));
1117 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1118 bool EmitBoolCondBranch = !
C || !
C->isOne();
1131 if (EmitBoolCondBranch) {
1132 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1135 llvm::MDNode *Weights =
1137 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1138 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1140 auto *I =
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1146 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1150 if (ExitBlock !=
LoopExit.getBlock()) {
1155 CGM.getDiags().Report(A->getLocation(),
1156 diag::warn_attribute_has_no_effect_on_infinite_loop)
1157 << A << A->getRange();
1158 CGM.getDiags().Report(
1160 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1177 BreakContinueStack.pop_back();
1193 if (!EmitBoolCondBranch)
1201 if (
CGM.shouldEmitConvergenceTokens())
1213 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopCond));
1223 if (
CGM.shouldEmitConvergenceTokens())
1244 BreakContinueStack.pop_back();
1248 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1249 bool EmitBoolCondBranch = !
C || !
C->isZero();
1252 LoopStack.push(LoopBody,
CGM.getContext(),
CGM.getCodeGenOpts(), DoAttrs,
1258 if (EmitBoolCondBranch) {
1260 auto *I =
Builder.CreateCondBr(
1261 BoolCondVal, LoopBody,
LoopExit.getBlock(),
1262 createProfileWeightsForLoop(S.
getCond(), BackedgeCount));
1269 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1281 if (!EmitBoolCondBranch)
1289 if (
CGM.shouldEmitConvergenceTokens())
1297 std::optional<LexicalScope> ForScope;
1309 llvm::BasicBlock *CondBlock = CondDest.
getBlock();
1312 if (
CGM.shouldEmitConvergenceTokens())
1316 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1333 Continue = CondDest;
1336 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1347 BreakContinueStack.back().ContinueBlock = Continue;
1355 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1358 if (ForScope && ForScope->requiresCleanups())
1370 llvm::MDNode *Weights =
1372 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1373 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1376 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1381 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1385 if (ExitBlock !=
LoopExit.getBlock()) {
1410 auto *FinalBodyBB =
Builder.GetInsertBlock();
1420 BreakContinueStack.pop_back();
1428 ForScope->ForceCleanup();
1440 if (
CGM.shouldEmitConvergenceTokens())
1470 if (
CGM.shouldEmitConvergenceTokens())
1474 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1480 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1490 llvm::MDNode *Weights =
1492 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1493 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1495 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1500 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1504 if (ExitBlock !=
LoopExit.getBlock()) {
1519 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1529 auto *FinalBodyBB =
Builder.GetInsertBlock();
1536 BreakContinueStack.pop_back();
1552 if (
CGM.shouldEmitConvergenceTokens())
1562void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1578struct SaveRetExprRAII {
1579 SaveRetExprRAII(
const Expr *RetExpr, CodeGenFunction &CGF)
1580 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1583 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1584 const Expr *OldRetExpr;
1585 CodeGenFunction &CGF;
1593 if (calleeQualType->isFunctionPointerType() ||
1594 calleeQualType->isFunctionReferenceType() ||
1595 calleeQualType->isBlockPointerType() ||
1596 calleeQualType->isMemberFunctionPointerType()) {
1598 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1600 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1601 if (
auto methodDecl = CMCE->getMethodDecl()) {
1618 if (requiresReturnValueCheck()) {
1621 new llvm::GlobalVariable(
CGM.getModule(), SLoc->getType(),
false,
1622 llvm::GlobalVariable::PrivateLinkage, SLoc);
1623 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1624 CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
1625 assert(ReturnLocation.isValid() &&
"No valid return location");
1626 Builder.CreateStore(SLocPtr, ReturnLocation);
1632 Builder.ClearInsertionPoint();
1646 SaveRetExprRAII SaveRetExpr(RV, *
this);
1649 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1650 RV = EWC->getSubExpr();
1654 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1657 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1670 !
CGM.getOpenMPRuntime()
1689 }
else if (
FnRetTy->isReferenceType()) {
1725 ++NumSimpleReturnExprs;
1737 for (
const auto *I : S.
decls())
1742 ->
const BreakContinue * {
1743 if (!S.hasLabelTarget())
1744 return &BreakContinueStack.back();
1746 const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
1747 assert(LoopOrSwitch &&
"break/continue target not set?");
1748 for (
const BreakContinue &BC : llvm::reverse(BreakContinueStack))
1749 if (BC.LoopOrSwitch == LoopOrSwitch)
1752 llvm_unreachable(
"break/continue target not found");
1756 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1769 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1786 assert(S.
getRHS() &&
"Expected RHS value in CaseStmt");
1799 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1803 llvm::APInt Range = RHS - LHS;
1805 if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
1808 unsigned NCases = Range.getZExtValue() + 1;
1813 uint64_t Weight = Total / NCases, Rem = Total % NCases;
1814 for (
unsigned I = 0; I != NCases; ++I) {
1816 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1817 else if (SwitchLikelihood)
1818 SwitchLikelihood->push_back(LH);
1822 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1830 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1835 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1839 Builder.SetInsertPoint(CaseRangeBlock);
1843 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1847 llvm::MDNode *Weights =
nullptr;
1848 if (SwitchWeights) {
1850 uint64_t DefaultCount = (*SwitchWeights)[0];
1851 Weights = createProfileWeights(ThisCount, DefaultCount);
1856 (*SwitchWeights)[0] += ThisCount;
1857 }
else if (SwitchLikelihood)
1858 Cond = emitCondLikelihoodViaExpectIntrinsic(
Cond, LH);
1860 Builder.CreateCondBr(
Cond, CaseDest, FalseDest, Weights);
1864 Builder.SetInsertPoint(RestoreBB);
1866 Builder.ClearInsertionPoint();
1887 llvm::ConstantInt *CaseVal =
1892 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.
getLHS()))
1893 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1895 CE = dyn_cast<ConstantExpr>(S.
getLHS());
1897 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1899 if (
CGM.getCodeGenOpts().hasReducedDebugInfo())
1900 Dbg->EmitGlobalVariable(DE->getDecl(),
1901 APValue(llvm::APSInt(CaseVal->getValue())));
1904 if (SwitchLikelihood)
1910 if (!
CGM.getCodeGenOpts().hasProfileClangInstr() &&
1911 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1919 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1923 if (
Builder.GetInsertBlock()) {
1925 Builder.ClearInsertionPoint();
1935 SwitchInsn->addCase(CaseVal, CaseDest);
1954 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1956 llvm::ConstantInt *CaseVal =
1961 if (
CGM.getCodeGenOpts().hasProfileClangInstr()) {
1967 if (SwitchLikelihood)
1970 SwitchInsn->addCase(CaseVal, CaseDest);
1971 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1994 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1995 assert(DefaultBlock->empty() &&
1996 "EmitDefaultStmt: Default block already defined?");
1998 if (SwitchLikelihood)
2040 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
2059 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
2063 bool StartedInLiveCode = FoundCase;
2064 unsigned StartSize = ResultStmts.size();
2071 bool HadSkippedDecl =
false;
2075 for (; Case && I != E; ++I) {
2091 for (++I; I != E; ++I)
2101 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
2116 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
2121 bool AnyDecls =
false;
2122 for (; I != E; ++I) {
2135 for (++I; I != E; ++I)
2152 ResultStmts.resize(StartSize);
2153 ResultStmts.push_back(S);
2177 ResultStmts.push_back(S);
2186 const llvm::APSInt &ConstantCondValue,
2198 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2206 if (CS->
getRHS())
return false;
2231 bool FoundCase =
false;
2238static std::optional<SmallVector<uint64_t, 16>>
2241 if (Likelihoods.size() <= 1)
2242 return std::nullopt;
2244 uint64_t NumUnlikely = 0;
2245 uint64_t NumNone = 0;
2246 uint64_t NumLikely = 0;
2247 for (
const auto LH : Likelihoods) {
2262 if (NumUnlikely == 0 && NumLikely == 0)
2263 return std::nullopt;
2271 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2272 const uint64_t
None = Likely / (NumNone + 1);
2273 const uint64_t Unlikely = 0;
2276 Result.reserve(Likelihoods.size());
2277 for (
const auto LH : Likelihoods) {
2280 Result.push_back(Unlikely);
2283 Result.push_back(
None);
2286 Result.push_back(Likely);
2296 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2299 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2303 llvm::APSInt ConstantCondValue;
2324 SwitchInsn =
nullptr;
2331 PGO->markStmtMaybeUsed(S.
getBody());
2335 SwitchInsn = SavedSwitchInsn;
2358 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2362 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2363 llvm::ConstantInt *BranchHintConstant =
2365 HLSLControlFlowHintAttr::Spelling::Microsoft_branch
2366 ? llvm::ConstantInt::get(
CGM.Int32Ty, 1)
2367 : llvm::ConstantInt::get(
CGM.Int32Ty, 2);
2368 llvm::Metadata *Vals[] = {MDHelper.createString(
"hlsl.controlflow.hint"),
2369 MDHelper.createConstant(BranchHintConstant)};
2370 SwitchInsn->setMetadata(
"hlsl.controlflow.hint",
2371 llvm::MDNode::get(
CGM.getLLVMContext(), Vals));
2374 if (PGO->haveRegionCounts()) {
2376 uint64_t DefaultCount = 0;
2377 unsigned NumCases = 0;
2386 SwitchWeights->reserve(NumCases);
2389 SwitchWeights->push_back(DefaultCount);
2390 }
else if (
CGM.getCodeGenOpts().OptimizationLevel) {
2396 CaseRangeBlock = DefaultBlock;
2399 Builder.ClearInsertionPoint();
2404 if (!BreakContinueStack.empty())
2405 OuterContinue = BreakContinueStack.back().ContinueBlock;
2407 BreakContinueStack.push_back(BreakContinue(S, SwitchExit, OuterContinue));
2412 BreakContinueStack.pop_back();
2416 SwitchInsn->setDefaultDest(CaseRangeBlock);
2419 if (!DefaultBlock->getParent()) {
2427 DefaultBlock->replaceAllUsesWith(SwitchExit.
getBlock());
2428 delete DefaultBlock;
2442 if (
Call &&
CGM.getCodeGenOpts().OptimizationLevel != 0) {
2443 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2444 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2446 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2447 MDHelper.createUnpredictable());
2451 if (SwitchWeights) {
2452 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2453 "switch weights do not match switch cases");
2455 if (SwitchWeights->size() > 1)
2456 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2457 createProfileWeights(*SwitchWeights));
2458 delete SwitchWeights;
2459 }
else if (SwitchLikelihood) {
2460 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2461 "switch likelihoods do not match switch cases");
2462 std::optional<SmallVector<uint64_t, 16>> LHW =
2465 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2466 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2467 createProfileWeights(*LHW));
2469 delete SwitchLikelihood;
2471 SwitchInsn = SavedSwitchInsn;
2472 SwitchWeights = SavedSwitchWeights;
2473 SwitchLikelihood = SavedSwitchLikelihood;
2474 CaseRangeBlock = SavedCRBlock;
2484 std::string *GCCReg =
nullptr) {
2485 const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
2494 AsmLabelAttr *
Attr = Variable->getAttr<AsmLabelAttr>();
2497 StringRef Register =
Attr->getLabel();
2498 assert(
Target.isValidGCCRegisterName(Register));
2502 if (
Target.validateOutputConstraint(Info) &&
2508 Register =
Target.getNormalizedGCCRegisterName(Register);
2509 if (GCCReg !=
nullptr)
2510 *GCCReg = Register.str();
2511 return (EarlyClobber ?
"&{" :
"{") + Register.str() +
"}";
2514std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2515 const TargetInfo::ConstraintInfo &Info, LValue InputValue,
2516 QualType InputType, std::string &ConstraintStr, SourceLocation Loc) {
2523 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2527 return {
Builder.CreateLoad(InputValue.getAddress().withElementType(Ty)),
2532 Address
Addr = InputValue.getAddress();
2533 ConstraintStr +=
'*';
2534 return {InputValue.getPointer(*
this),
Addr.getElementType()};
2537std::pair<llvm::Value *, llvm::Type *>
2538CodeGenFunction::EmitAsmInput(
const TargetInfo::ConstraintInfo &Info,
2539 const Expr *InputExpr,
2540 std::string &ConstraintStr) {
2545 Expr::EvalResult EVResult;
2548 llvm::APSInt IntResult;
2551 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2563 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2567 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2579 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2582 if (!StrVal.empty()) {
2585 unsigned StartToken = 0;
2586 unsigned ByteOffset = 0;
2590 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2591 if (StrVal[i] !=
'\n')
continue;
2593 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2594 Locs.push_back(llvm::ConstantAsMetadata::get(
2603 bool HasUnwindClobber,
bool ReadOnly,
2604 bool ReadNone,
bool NoMerge,
bool NoConvergent,
2606 const std::vector<llvm::Type *> &ResultRegTypes,
2607 const std::vector<llvm::Type *> &ArgElemTypes,
2609 std::vector<llvm::Value *> &RegResults) {
2610 if (!HasUnwindClobber)
2611 Result.addFnAttr(llvm::Attribute::NoUnwind);
2614 Result.addFnAttr(llvm::Attribute::NoMerge);
2616 if (!HasSideEffect) {
2618 Result.setDoesNotAccessMemory();
2620 Result.setOnlyReadsMemory();
2624 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
2626 auto Attr = llvm::Attribute::get(
2627 CGF.
getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2628 Result.addParamAttr(Pair.index(),
Attr);
2635 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S);
2637 (SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))) {
2642 llvm::Constant *Loc =
2644 Result.setMetadata(
"srcloc",
2646 llvm::ConstantAsMetadata::get(Loc)));
2657 Result.addFnAttr(llvm::Attribute::Convergent);
2659 if (ResultRegTypes.size() == 1) {
2660 RegResults.push_back(&Result);
2662 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2663 llvm::Value *Tmp = CGF.
Builder.CreateExtractValue(&Result, i,
"asmresult");
2664 RegResults.push_back(Tmp);
2676 const llvm::BitVector &ResultTypeRequiresCast,
2677 const llvm::BitVector &ResultRegIsFlagReg) {
2682 assert(RegResults.size() == ResultRegTypes.size());
2683 assert(RegResults.size() == ResultTruncRegTypes.size());
2684 assert(RegResults.size() == ResultRegDests.size());
2687 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2688 assert(ResultRegIsFlagReg.size() <= ResultRegDests.size());
2690 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2691 llvm::Value *Tmp = RegResults[i];
2692 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2694 if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
2697 llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2);
2698 llvm::Value *IsBooleanValue =
2699 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two);
2701 Builder.CreateCall(FnAssume, IsBooleanValue);
2706 if (ResultRegTypes[i] != TruncTy) {
2710 if (TruncTy->isFloatingPointTy())
2711 Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
2712 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2714 Tmp = Builder.CreateTrunc(
2715 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
2716 Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
2717 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2720 Tmp = Builder.CreatePtrToInt(
2721 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
2722 Tmp = Builder.CreateTrunc(Tmp, TruncTy);
2723 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2724 Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2725 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2726 Tmp = Builder.CreateBitCast(Tmp, TruncTy);
2731 LValue Dest = ResultRegDests[i];
2734 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2736 Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
2738 llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
2748 diag::err_store_value_to_reg);
2759 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2762 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2763 Asm = GCCAsm->getAsmString();
2767 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2768 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2769 {StrTy->getType()},
false);
2770 auto UBF = CGF->
CGM.
getModule().getOrInsertFunction(Name, FnTy);
2772 CGF->
Builder.CreateCall(UBF, {StrTy});
2787 bool IsValidTargetAsm =
true;
2788 for (
unsigned i = 0, e = S.
getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2790 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2791 Name = GAS->getOutputName(i);
2794 if (IsHipStdPar && !IsValid)
2795 IsValidTargetAsm =
false;
2797 assert(IsValid &&
"Failed to parse output constraint");
2798 OutputConstraintInfos.push_back(Info);
2801 for (
unsigned i = 0, e = S.
getNumInputs(); i != e && IsValidTargetAsm; i++) {
2803 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2804 Name = GAS->getInputName(i);
2808 if (IsHipStdPar && !IsValid)
2809 IsValidTargetAsm =
false;
2811 assert(IsValid &&
"Failed to parse input constraint");
2812 InputConstraintInfos.push_back(Info);
2815 if (!IsValidTargetAsm)
2818 std::string Constraints;
2820 std::vector<LValue> ResultRegDests;
2821 std::vector<QualType> ResultRegQualTys;
2822 std::vector<llvm::Type *> ResultRegTypes;
2823 std::vector<llvm::Type *> ResultTruncRegTypes;
2824 std::vector<llvm::Type *> ArgTypes;
2825 std::vector<llvm::Type *> ArgElemTypes;
2826 std::vector<llvm::Value*> Args;
2827 llvm::BitVector ResultTypeRequiresCast;
2828 llvm::BitVector ResultRegIsFlagReg;
2831 std::string InOutConstraints;
2832 std::vector<llvm::Value*> InOutArgs;
2833 std::vector<llvm::Type*> InOutArgTypes;
2834 std::vector<llvm::Type*> InOutArgElemTypes;
2837 std::vector<std::string> OutputConstraints;
2840 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2848 bool ReadOnly =
true, ReadNone =
true;
2856 StringRef(OutputConstraint).substr(1), &OutputConstraintInfos);
2867 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2868 CGM.Error(S.
getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2870 OutputConstraints.push_back(OutputConstraint);
2872 if (!Constraints.empty())
2882 Constraints +=
"=" + OutputConstraint;
2883 ResultRegQualTys.push_back(QTy);
2884 ResultRegDests.push_back(Dest);
2886 bool IsFlagReg = llvm::StringRef(OutputConstraint).starts_with(
"{@cc");
2887 ResultRegIsFlagReg.push_back(IsFlagReg);
2892 Ty->isAggregateType());
2894 ResultTruncRegTypes.push_back(Ty);
2895 ResultTypeRequiresCast.push_back(RequiresCast);
2902 CGM.Error(OutExpr->
getExprLoc(),
"output size should not be zero");
2904 ResultRegTypes.push_back(Ty);
2910 for (InputNo = 0; InputNo != S.
getNumInputs(); ++InputNo) {
2915 assert(InputNo != S.
getNumInputs() &&
"Didn't find matching input!");
2926 if (llvm::Type* AdjTy =
2928 ResultRegTypes.back()))
2929 ResultRegTypes.back() = AdjTy;
2932 diag::err_asm_invalid_type_in_input)
2933 << OutExpr->
getType() << OutputConstraint;
2937 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
2938 LargestVectorWidth =
2939 std::max((uint64_t)LargestVectorWidth,
2940 VT->getPrimitiveSizeInBits().getKnownMinValue());
2951 ArgTypes.push_back(DestAddr.
getType());
2954 Constraints +=
"=*";
2955 Constraints += OutputConstraint;
2956 ReadOnly = ReadNone =
false;
2960 InOutConstraints +=
',';
2964 llvm::Type *ArgElemType;
2965 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
2966 Info, Dest, InputExpr->
getType(), InOutConstraints,
2969 if (llvm::Type* AdjTy =
2972 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2975 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2976 LargestVectorWidth =
2977 std::max((uint64_t)LargestVectorWidth,
2978 VT->getPrimitiveSizeInBits().getKnownMinValue());
2981 InOutConstraints += llvm::utostr(i);
2983 InOutConstraints += OutputConstraint;
2985 InOutArgTypes.push_back(Arg->getType());
2986 InOutArgElemTypes.push_back(ArgElemType);
2987 InOutArgs.push_back(Arg);
2998 CGM.getTargetCodeGenInfo().addReturnRegisterOutputs(
2999 *
this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
3005 for (
unsigned i = 0, e = S.
getNumInputs(); i != e; i++) {
3013 if (!Constraints.empty())
3025 std::string ReplaceConstraint (InputConstraint);
3027 llvm::Type *ArgElemType;
3028 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
3047 Arg =
Builder.CreateZExt(Arg, OutputTy);
3050 else if (OutputTy->isFloatingPointTy())
3051 Arg =
Builder.CreateFPExt(Arg, OutputTy);
3054 ReplaceConstraint = OutputConstraints[Output];
3056 if (llvm::Type* AdjTy =
3059 Arg =
Builder.CreateBitCast(Arg, AdjTy);
3061 CGM.getDiags().Report(S.
getAsmLoc(), diag::err_asm_invalid_type_in_input)
3062 << InputExpr->
getType() << InputConstraint;
3065 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3066 LargestVectorWidth =
3067 std::max((uint64_t)LargestVectorWidth,
3068 VT->getPrimitiveSizeInBits().getKnownMinValue());
3070 ArgTypes.push_back(Arg->getType());
3071 ArgElemTypes.push_back(ArgElemType);
3072 Args.push_back(Arg);
3073 Constraints += InputConstraint;
3077 for (
unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
3078 ArgTypes.push_back(InOutArgTypes[i]);
3079 ArgElemTypes.push_back(InOutArgElemTypes[i]);
3080 Args.push_back(InOutArgs[i]);
3082 Constraints += InOutConstraints;
3086 llvm::BasicBlock *Fallthrough =
nullptr;
3087 bool IsGCCAsmGoto =
false;
3088 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S)) {
3089 IsGCCAsmGoto = GS->isAsmGoto();
3091 for (
const auto *E : GS->labels()) {
3093 Transfer.push_back(Dest.
getBlock());
3094 if (!Constraints.empty())
3096 Constraints +=
"!i";
3102 bool HasUnwindClobber =
false;
3108 if (Clobber ==
"memory")
3109 ReadOnly = ReadNone =
false;
3110 else if (Clobber ==
"unwind") {
3111 HasUnwindClobber =
true;
3113 }
else if (Clobber !=
"cc") {
3115 if (
CGM.getCodeGenOpts().StackClashProtector &&
3118 diag::warn_stack_clash_protection_inline_asm);
3123 if (Clobber ==
"eax" || Clobber ==
"edx") {
3124 if (Constraints.find(
"=&A") != std::string::npos)
3126 std::string::size_type position1 =
3127 Constraints.find(
"={" + Clobber +
"}");
3128 if (position1 != std::string::npos) {
3129 Constraints.insert(position1 + 1,
"&");
3132 std::string::size_type position2 = Constraints.find(
"=A");
3133 if (position2 != std::string::npos) {
3134 Constraints.insert(position2 + 1,
"&");
3139 if (!Constraints.empty())
3142 Constraints +=
"~{";
3143 Constraints += Clobber;
3147 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
3148 "unwind clobber can't be used with asm goto");
3152 if (!MachineClobbers.empty()) {
3153 if (!Constraints.empty())
3155 Constraints += MachineClobbers;
3158 llvm::Type *ResultType;
3159 if (ResultRegTypes.empty())
3161 else if (ResultRegTypes.size() == 1)
3162 ResultType = ResultRegTypes[0];
3164 ResultType = llvm::StructType::get(
getLLVMContext(), ResultRegTypes);
3166 llvm::FunctionType *FTy =
3167 llvm::FunctionType::get(ResultType, ArgTypes,
false);
3171 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3173 ? llvm::InlineAsm::AD_ATT
3174 : llvm::InlineAsm::AD_Intel;
3176 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3178 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3179 FTy, AsmString, Constraints, HasSideEffect,
3180 false, AsmDialect, HasUnwindClobber);
3181 std::vector<llvm::Value*> RegResults;
3182 llvm::CallBrInst *CBR;
3183 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3186 CBR =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3191 ArgElemTypes, *
this, RegResults);
3195 if (!RegResults.empty()) {
3197 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3198 llvm::Twine SynthName = Dest->getName() +
".split";
3200 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3201 Builder.SetInsertPoint(SynthBB);
3203 if (ResultRegTypes.size() == 1) {
3204 CBRRegResults[SynthBB].push_back(CBR);
3206 for (
unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3207 llvm::Value *Tmp =
Builder.CreateExtractValue(CBR, j,
"asmresult");
3208 CBRRegResults[SynthBB].push_back(Tmp);
3214 CBR->setIndirectDest(i++, SynthBB);
3217 }
else if (HasUnwindClobber) {
3222 ArgElemTypes, *
this, RegResults);
3229 ArgElemTypes, *
this, RegResults);
3232 EmitAsmStores(*
this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3233 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3234 ResultRegIsFlagReg);
3239 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3240 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3241 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3242 Builder.SetInsertPoint(Succ, --(Succ->end()));
3243 EmitAsmStores(*
this, S, CBRRegResults[Succ], ResultRegTypes,
3244 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3245 ResultTypeRequiresCast, ResultRegIsFlagReg);
3261 I != E; ++I, ++CurField) {
3263 if (CurField->hasCapturedVLAType()) {
3280 CodeGenFunction CGF(
CGM,
true);
3300 "CapturedStmtInfo should be set when generating the captured function");
3304 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3313 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Args);
3314 llvm::FunctionType *FuncLLVMTy =
CGM.getTypes().GetFunctionType(FuncInfo);
3317 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3319 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
3321 F->addFnAttr(llvm::Attribute::NoUnwind);
3333 for (
auto *FD : RD->
fields()) {
3334 if (FD->hasCapturedVLAType()) {
3338 auto VAT = FD->getCapturedVLAType();
3339 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3350 PGO->assignRegionCounters(
GlobalDecl(CD), F);
3360 for (
auto &I : *BB) {
3361 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3368CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3370 assert(ParentToken);
3372 llvm::Value *bundleArgs[] = {ParentToken};
3373 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3374 auto *Output = llvm::CallBase::addOperandBundle(
3375 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3376 Input->replaceAllUsesWith(Output);
3377 Input->eraseFromParent();
3381llvm::ConvergenceControlInst *
3382CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
3384 assert(ParentToken);
3385 return llvm::ConvergenceControlInst::CreateLoop(*BB, ParentToken);
3388llvm::ConvergenceControlInst *
3389CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3390 llvm::BasicBlock *BB = &F->getEntryBlock();
3398 return llvm::ConvergenceControlInst::CreateEntry(*BB);
Defines enum values for all the target-independent builtin functions.
static std::string AddVariableConstraints(const std::string &Constraint, const Expr &AsmExpr, const TargetInfo &Target, CodeGenModule &CGM, const AsmStmt &Stmt, const bool EarlyClobber, std::string *GCCReg=nullptr)
AddVariableConstraints - Look at AsmExpr and if it is a variable declared as using a particular regis...
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 llvm::BitVector &ResultRegIsFlagReg)
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)
llvm::MachO::Target Target
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
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.
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...
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)
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 incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
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 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)
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 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
void ErrorUnsupported(const Stmt *S, const char *Type)
Print out an error that codegen doesn't support the specified stmt yet.
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
Stmt * getStmtExprResult()
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
ContinueStmt - This represents a continue.
A reference to a declared variable, function, enum, etc.
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
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()
Exposes information about the current target.
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.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
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)
ActionResult< Expr * > ExprResult
Diagnostic wrappers for TextAPI types for error reporting.
cl::opt< bool > EnableSingleByteCoverage
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
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