30#include "llvm/ADT/ArrayRef.h"
31#include "llvm/ADT/DenseMap.h"
32#include "llvm/ADT/SmallSet.h"
33#include "llvm/ADT/StringExtras.h"
34#include "llvm/IR/Assumptions.h"
35#include "llvm/IR/DataLayout.h"
36#include "llvm/IR/InlineAsm.h"
37#include "llvm/IR/Intrinsics.h"
38#include "llvm/IR/MDBuilder.h"
39#include "llvm/Support/SaveAndRestore.h"
60 assert(S &&
"Null statement?");
61 PGO->setCurrentStmt(S);
78 PGO->markStmtMaybeUsed(S);
92 if (
const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
100 case Stmt::CXXCatchStmtClass:
101 case Stmt::SEHExceptStmtClass:
102 case Stmt::SEHFinallyStmtClass:
103 case Stmt::MSDependentExistsStmtClass:
104 case Stmt::UnresolvedSYCLKernelCallStmtClass:
105 llvm_unreachable(
"invalid statement class to emit generically");
106 case Stmt::NullStmtClass:
107 case Stmt::CompoundStmtClass:
108 case Stmt::DeclStmtClass:
109 case Stmt::LabelStmtClass:
110 case Stmt::AttributedStmtClass:
111 case Stmt::GotoStmtClass:
112 case Stmt::BreakStmtClass:
113 case Stmt::ContinueStmtClass:
114 case Stmt::DefaultStmtClass:
115 case Stmt::CaseStmtClass:
116 case Stmt::DeferStmtClass:
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::CXXExpansionStmtPatternClass:
208 llvm_unreachable(
"unexpanded expansion statements should not be emitted");
209 case Stmt::CXXExpansionStmtInstantiationClass:
212 case Stmt::SEHTryStmtClass:
215 case Stmt::OMPMetaDirectiveClass:
218 case Stmt::OMPCanonicalLoopClass:
221 case Stmt::OMPParallelDirectiveClass:
224 case Stmt::OMPSimdDirectiveClass:
227 case Stmt::OMPTileDirectiveClass:
230 case Stmt::OMPStripeDirectiveClass:
233 case Stmt::OMPUnrollDirectiveClass:
236 case Stmt::OMPReverseDirectiveClass:
239 case Stmt::OMPSplitDirectiveClass:
242 case Stmt::OMPInterchangeDirectiveClass:
245 case Stmt::OMPFlattenDirectiveClass:
248 case Stmt::OMPFuseDirectiveClass:
251 case Stmt::OMPForDirectiveClass:
254 case Stmt::OMPForSimdDirectiveClass:
257 case Stmt::OMPSectionsDirectiveClass:
260 case Stmt::OMPSectionDirectiveClass:
263 case Stmt::OMPSingleDirectiveClass:
266 case Stmt::OMPMasterDirectiveClass:
269 case Stmt::OMPCriticalDirectiveClass:
272 case Stmt::OMPParallelForDirectiveClass:
275 case Stmt::OMPParallelForSimdDirectiveClass:
278 case Stmt::OMPParallelMasterDirectiveClass:
281 case Stmt::OMPParallelSectionsDirectiveClass:
284 case Stmt::OMPTaskDirectiveClass:
287 case Stmt::OMPTaskyieldDirectiveClass:
290 case Stmt::OMPErrorDirectiveClass:
293 case Stmt::OMPBarrierDirectiveClass:
296 case Stmt::OMPTaskwaitDirectiveClass:
299 case Stmt::OMPTaskgroupDirectiveClass:
302 case Stmt::OMPFlushDirectiveClass:
305 case Stmt::OMPDepobjDirectiveClass:
308 case Stmt::OMPScanDirectiveClass:
311 case Stmt::OMPOrderedStandaloneDirectiveClass:
314 case Stmt::OMPOrderedBlockAssocDirectiveClass:
317 case Stmt::OMPAtomicDirectiveClass:
320 case Stmt::OMPTargetDirectiveClass:
323 case Stmt::OMPTeamsDirectiveClass:
326 case Stmt::OMPCancellationPointDirectiveClass:
329 case Stmt::OMPCancelDirectiveClass:
332 case Stmt::OMPTargetDataDirectiveClass:
335 case Stmt::OMPTargetEnterDataDirectiveClass:
338 case Stmt::OMPTargetExitDataDirectiveClass:
341 case Stmt::OMPTargetParallelDirectiveClass:
344 case Stmt::OMPTargetParallelForDirectiveClass:
347 case Stmt::OMPTaskLoopDirectiveClass:
350 case Stmt::OMPTaskLoopSimdDirectiveClass:
353 case Stmt::OMPMasterTaskLoopDirectiveClass:
356 case Stmt::OMPMaskedTaskLoopDirectiveClass:
359 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
363 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
367 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
371 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
375 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
379 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
383 case Stmt::OMPDistributeDirectiveClass:
386 case Stmt::OMPTargetUpdateDirectiveClass:
389 case Stmt::OMPDistributeParallelForDirectiveClass:
393 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
397 case Stmt::OMPDistributeSimdDirectiveClass:
400 case Stmt::OMPTargetParallelForSimdDirectiveClass:
404 case Stmt::OMPTargetSimdDirectiveClass:
407 case Stmt::OMPTeamsDistributeDirectiveClass:
410 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
414 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
418 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
422 case Stmt::OMPTargetTeamsDirectiveClass:
425 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
429 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
433 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
437 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
441 case Stmt::OMPInteropDirectiveClass:
444 case Stmt::OMPDispatchDirectiveClass:
445 CGM.ErrorUnsupported(S,
"OpenMP dispatch directive");
447 case Stmt::OMPScopeDirectiveClass:
450 case Stmt::OMPMaskedDirectiveClass:
453 case Stmt::OMPGenericLoopDirectiveClass:
456 case Stmt::OMPTeamsGenericLoopDirectiveClass:
459 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
463 case Stmt::OMPParallelGenericLoopDirectiveClass:
467 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
471 case Stmt::OMPParallelMaskedDirectiveClass:
474 case Stmt::OMPAssumeDirectiveClass:
477 case Stmt::OpenACCComputeConstructClass:
480 case Stmt::OpenACCLoopConstructClass:
483 case Stmt::OpenACCCombinedConstructClass:
486 case Stmt::OpenACCDataConstructClass:
489 case Stmt::OpenACCEnterDataConstructClass:
492 case Stmt::OpenACCExitDataConstructClass:
495 case Stmt::OpenACCHostDataConstructClass:
498 case Stmt::OpenACCWaitConstructClass:
501 case Stmt::OpenACCInitConstructClass:
504 case Stmt::OpenACCShutdownConstructClass:
507 case Stmt::OpenACCSetConstructClass:
510 case Stmt::OpenACCUpdateConstructClass:
513 case Stmt::OpenACCAtomicConstructClass:
516 case Stmt::OpenACCCacheConstructClass:
527 case Stmt::NullStmtClass:
529 case Stmt::CompoundStmtClass:
532 case Stmt::DeclStmtClass:
535 case Stmt::LabelStmtClass:
538 case Stmt::AttributedStmtClass:
541 case Stmt::GotoStmtClass:
544 case Stmt::BreakStmtClass:
547 case Stmt::ContinueStmtClass:
550 case Stmt::DefaultStmtClass:
553 case Stmt::CaseStmtClass:
556 case Stmt::DeferStmtClass:
559 case Stmt::SEHLeaveStmtClass:
562 case Stmt::SYCLKernelCallStmtClass:
575 "LLVM IR generation of compound statement ('{}')");
602 if (
const auto *LS = dyn_cast<LabelStmt>(LastStmt)) {
604 LastStmt = LS->getSubStmt();
605 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(LastStmt)) {
608 LastStmt = AS->getSubStmt();
610 llvm_unreachable(
"unknown value statement");
634 llvm::UncondBrInst *BI = dyn_cast<llvm::UncondBrInst>(BB->getTerminator());
647 if (BI->getIterator() != BB->begin())
650 BB->replaceAllUsesWith(BI->getSuccessor());
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->hasTerminator()) {
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());
796 const AtomicAttr *AA =
nullptr;
798 for (
const auto *A : S.
getAttrs()) {
799 switch (A->getKind()) {
807 alwaysinline =
false;
809 case attr::AlwaysInline:
813 case attr::NoConvergent:
816 case attr::MustTail: {
821 case attr::CXXAssume: {
826 Builder.CreateAssumption(AssumptionVal);
832 case attr::AMDGPUAvailableVisible:
835 case attr::HLSLControlFlowHint: {
841 assert(!(alwaysinline && noinline) &&
842 "alwaysinline and noinline are mutually exclusive");
887 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
897 if (CurBB && CurBB->hasTerminator())
938 const Stmt *Skipped = Else;
940 std::swap(Executed, Skipped);
952 PGO->markStmtMaybeUsed(Skipped);
963 llvm::BasicBlock *ElseBlock =
979 CGM.getCodeGenOpts().OptimizationLevel)
988 if (!
CGM.getCodeGenOpts().MCDCCoverage) {
995 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
1026 }
else if (HasSkip) {
1037 bool HasEmptyBody) {
1041 [
this] {
CurFn->removeFnAttr(llvm::Attribute::MustProgress); });
1051 if (
CGM.shouldEmitConvergenceTokens())
1060 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopHeader));
1083 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1084 bool EmitBoolCondBranch = !
C || !
C->isOne();
1087 LoopHeader.
getBlock(),
CGM.getContext(),
CGM.getCodeGenOpts(), WhileAttrs,
1093 if (EmitBoolCondBranch) {
1094 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1097 llvm::MDNode *Weights =
1099 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1100 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1102 auto *I =
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1108 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1112 if (ExitBlock !=
LoopExit.getBlock()) {
1118 CGM.getDiags().Report(A->getLocation(),
1119 diag::warn_attribute_has_no_effect_on_infinite_loop)
1120 << A << A->getRange();
1121 CGM.getDiags().Report(
1123 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1136 BreakContinueStack.pop_back();
1152 if (!EmitBoolCondBranch) {
1154 PGO->markStmtAsUsed(
true, &S);
1157 if (
CGM.shouldEmitConvergenceTokens())
1169 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopCond));
1176 if (
CGM.shouldEmitConvergenceTokens())
1194 BreakContinueStack.pop_back();
1198 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1199 bool EmitBoolCondBranch = !
C || !
C->isZero();
1203 LoopBody,
CGM.getContext(),
CGM.getCodeGenOpts(), DoAttrs,
1211 if (EmitBoolCondBranch) {
1213 auto *I =
Builder.CreateCondBr(
1214 BoolCondVal, LoopBody, LoopFalse,
1215 createProfileWeightsForLoop(S.
getCond(), BackedgeCount));
1222 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1229 if (LoopFalse !=
LoopExit.getBlock()) {
1239 if (!EmitBoolCondBranch)
1242 if (
CGM.shouldEmitConvergenceTokens())
1248 std::optional<LexicalScope> ForScope;
1269 llvm::BasicBlock *CondBlock = CondDest.
getBlock();
1272 if (
CGM.shouldEmitConvergenceTokens())
1277 CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1293 Continue = CondDest;
1296 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1307 BreakContinueStack.back().ContinueBlock = Continue;
1310 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1313 if (
hasSkipCounter(&S) || (ForScope && ForScope->requiresCleanups()))
1325 llvm::MDNode *Weights =
1327 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1328 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1331 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1336 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1340 if (ExitBlock !=
LoopExit.getBlock()) {
1350 PGO->markStmtAsUsed(
true, &S);
1364 auto *FinalBodyBB =
Builder.GetInsertBlock();
1372 BreakContinueStack.pop_back();
1380 ForScope->ForceCleanup();
1387 if (
CGM.shouldEmitConvergenceTokens())
1417 if (
CGM.shouldEmitConvergenceTokens())
1421 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1427 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1437 llvm::MDNode *Weights =
1439 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1440 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1442 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1447 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1451 if (ExitBlock !=
LoopExit.getBlock()) {
1464 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1474 auto *FinalBodyBB =
Builder.GetInsertBlock();
1481 BreakContinueStack.pop_back();
1492 if (
CGM.shouldEmitConvergenceTokens())
1516 ContinueDest = ExpandExit;
1520 LexicalScope ExpansionScope(*
this, Inst->getSourceRange());
1521 BreakContinueStack.push_back(BreakContinue(S, ExpandExit, ContinueDest));
1523 BreakContinueStack.pop_back();
1528void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1544struct SaveRetExprRAII {
1545 SaveRetExprRAII(
const Expr *RetExpr, CodeGenFunction &CGF)
1546 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1549 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1550 const Expr *OldRetExpr;
1551 CodeGenFunction &CGF;
1559 if (calleeQualType->isFunctionPointerType() ||
1560 calleeQualType->isFunctionReferenceType() ||
1561 calleeQualType->isBlockPointerType() ||
1562 calleeQualType->isMemberFunctionPointerType()) {
1564 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1566 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1567 if (
auto methodDecl = CMCE->getMethodDecl()) {
1584 if (requiresReturnValueCheck()) {
1587 new llvm::GlobalVariable(
CGM.getModule(), SLoc->getType(),
false,
1588 llvm::GlobalVariable::PrivateLinkage, SLoc);
1589 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1590 CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
1591 assert(ReturnLocation.isValid() &&
"No valid return location");
1592 Builder.CreateStore(SLocPtr, ReturnLocation);
1598 Builder.ClearInsertionPoint();
1612 SaveRetExprRAII SaveRetExpr(RV, *
this);
1615 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1616 RV = EWC->getSubExpr();
1620 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1623 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1636 !
CGM.getOpenMPRuntime()
1655 }
else if (
FnRetTy->isReferenceType()) {
1691 ++NumSimpleReturnExprs;
1703 for (
const auto *I : S.
decls())
1708 ->
const BreakContinue * {
1710 return &BreakContinueStack.back();
1712 const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
1713 assert(LoopOrSwitch &&
"break/continue target label not available?");
1714 for (
const BreakContinue &BC : llvm::reverse(BreakContinueStack))
1715 if (BC.LoopOrSwitch == LoopOrSwitch)
1718 llvm_unreachable(
"break/continue target not found");
1722 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1735 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1752 assert(S.
getRHS() &&
"Expected RHS value in CaseStmt");
1765 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1769 llvm::APInt Range = RHS - LHS;
1771 if (Range.getBitWidth() < 7 ||
1772 Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
1775 unsigned NCases = Range.getZExtValue() + 1;
1780 uint64_t Weight = Total / NCases, Rem = Total % NCases;
1781 for (
unsigned I = 0; I != NCases; ++I) {
1783 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1784 else if (SwitchLikelihood)
1785 SwitchLikelihood->push_back(LH);
1789 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1797 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1802 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1806 Builder.SetInsertPoint(CaseRangeBlock);
1810 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1814 llvm::MDNode *Weights =
nullptr;
1815 if (SwitchWeights) {
1817 uint64_t DefaultCount = (*SwitchWeights)[0];
1818 Weights = createProfileWeights(ThisCount, DefaultCount);
1823 (*SwitchWeights)[0] += ThisCount;
1824 }
else if (SwitchLikelihood)
1825 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
1827 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
1831 Builder.SetInsertPoint(RestoreBB);
1833 Builder.ClearInsertionPoint();
1854 llvm::ConstantInt *CaseVal =
1861 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SubExpr))
1863 if (
CGM.getCodeGenOpts().hasReducedDebugInfo())
1864 Dbg->EmitGlobalVariable(DRE->getDecl(),
1865 APValue(llvm::APSInt(CaseVal->getValue())));
1867 if (SwitchLikelihood)
1873 if (!
CGM.getCodeGenOpts().hasProfileClangInstr() &&
1874 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1882 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1886 if (
Builder.GetInsertBlock()) {
1888 Builder.ClearInsertionPoint();
1898 SwitchInsn->addCase(CaseVal, CaseDest);
1917 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1919 llvm::ConstantInt *CaseVal =
1924 if (
CGM.getCodeGenOpts().hasProfileClangInstr()) {
1930 if (SwitchLikelihood)
1933 SwitchInsn->addCase(CaseVal, CaseDest);
1934 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1957 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1958 assert(DefaultBlock->empty() &&
1959 "EmitDefaultStmt: Default block already defined?");
1961 if (SwitchLikelihood)
1970struct EmitDeferredStatement final : EHScopeStack::Cleanup {
2030 llvm::Value *SavedCleanupDest =
nullptr;
2084 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
2103 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
2107 bool StartedInLiveCode = FoundCase;
2108 unsigned StartSize = ResultStmts.size();
2115 bool HadSkippedDecl =
false;
2119 for (; Case && I != E; ++I) {
2135 for (++I; I != E; ++I)
2145 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
2160 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
2165 bool AnyDecls =
false;
2166 for (; I != E; ++I) {
2179 for (++I; I != E; ++I)
2196 ResultStmts.resize(StartSize);
2197 ResultStmts.push_back(S);
2221 ResultStmts.push_back(S);
2230 const llvm::APSInt &ConstantCondValue,
2242 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2250 if (CS->
getRHS())
return false;
2275 bool FoundCase =
false;
2282static std::optional<SmallVector<uint64_t, 16>>
2285 if (Likelihoods.size() <= 1)
2286 return std::nullopt;
2288 uint64_t NumUnlikely = 0;
2289 uint64_t NumNone = 0;
2290 uint64_t NumLikely = 0;
2291 for (
const auto LH : Likelihoods) {
2306 if (NumUnlikely == 0 && NumLikely == 0)
2307 return std::nullopt;
2315 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2316 const uint64_t
None = Likely / (NumNone + 1);
2317 const uint64_t Unlikely = 0;
2320 Result.reserve(Likelihoods.size());
2321 for (
const auto LH : Likelihoods) {
2324 Result.push_back(Unlikely);
2330 Result.push_back(Likely);
2340 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2343 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2347 llvm::APSInt ConstantCondValue;
2368 SwitchInsn =
nullptr;
2375 PGO->markStmtMaybeUsed(S.
getBody());
2379 SwitchInsn = SavedSwitchInsn;
2418 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2422 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2423 llvm::ConstantInt *BranchHintConstant =
2425 HLSLControlFlowHintAttr::Spelling::Microsoft_branch
2426 ? llvm::ConstantInt::get(
CGM.Int32Ty, 1)
2427 : llvm::ConstantInt::get(
CGM.Int32Ty, 2);
2428 llvm::Metadata *Vals[] = {MDHelper.createString(
"hlsl.controlflow.hint"),
2429 MDHelper.createConstant(BranchHintConstant)};
2430 SwitchInsn->setMetadata(
"hlsl.controlflow.hint",
2431 llvm::MDNode::get(
CGM.getLLVMContext(), Vals));
2434 if (PGO->haveRegionCounts()) {
2436 uint64_t DefaultCount = 0;
2437 unsigned NumCases = 0;
2446 SwitchWeights->reserve(NumCases);
2449 SwitchWeights->push_back(DefaultCount);
2450 }
else if (
CGM.getCodeGenOpts().OptimizationLevel) {
2456 CaseRangeBlock = DefaultBlock;
2459 Builder.ClearInsertionPoint();
2464 if (!BreakContinueStack.empty())
2465 OuterContinue = BreakContinueStack.back().ContinueBlock;
2467 BreakContinueStack.push_back(BreakContinue(S, SwitchExit, OuterContinue));
2472 BreakContinueStack.pop_back();
2476 SwitchInsn->setDefaultDest(CaseRangeBlock);
2479 if (!DefaultBlock->getParent()) {
2487 DefaultBlock->replaceAllUsesWith(SwitchExit.
getBlock());
2488 delete DefaultBlock;
2502 Builder.CreateBr(SwitchInsn->getDefaultDest());
2503 SwitchInsn->setDefaultDest(ImplicitDefaultBlock);
2514 if (
Call &&
CGM.getCodeGenOpts().OptimizationLevel != 0) {
2515 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2516 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2518 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2519 MDHelper.createUnpredictable());
2523 if (SwitchWeights) {
2524 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2525 "switch weights do not match switch cases");
2527 if (SwitchWeights->size() > 1)
2528 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2529 createProfileWeights(*SwitchWeights));
2530 delete SwitchWeights;
2531 }
else if (SwitchLikelihood) {
2532 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2533 "switch likelihoods do not match switch cases");
2534 std::optional<SmallVector<uint64_t, 16>> LHW =
2537 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2538 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2539 createProfileWeights(*LHW));
2541 delete SwitchLikelihood;
2543 SwitchInsn = SavedSwitchInsn;
2544 SwitchWeights = SavedSwitchWeights;
2545 SwitchLikelihood = SavedSwitchLikelihood;
2546 CaseRangeBlock = SavedCRBlock;
2549std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2558 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2568 ConstraintStr +=
'*';
2571std::pair<llvm::Value *, llvm::Type *>
2572CodeGenFunction::EmitAsmInput(
const TargetInfo::ConstraintInfo &Info,
2573 const Expr *InputExpr,
2574 std::string &ConstraintStr) {
2579 Expr::EvalResult EVResult;
2582 llvm::APSInt IntResult;
2585 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2597 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2601 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2613 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2616 if (!StrVal.empty()) {
2619 unsigned StartToken = 0;
2620 unsigned ByteOffset = 0;
2624 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2625 if (StrVal[i] !=
'\n')
continue;
2627 i + 1, SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2628 Locs.push_back(llvm::ConstantAsMetadata::get(
2648 std::string AsmString;
2655 std::string Constraints;
2656 std::string InOutConstraints;
2659 std::vector<std::string> OutputConstraints;
2662 std::vector<llvm::Value *> Args;
2663 std::vector<llvm::Type *> ArgTypes;
2664 std::vector<llvm::Type *> ArgElemTypes;
2667 std::vector<LValue> ResultRegDests;
2668 std::vector<QualType> ResultRegQualTys;
2669 std::vector<llvm::Type *> ResultRegTypes;
2670 std::vector<llvm::Type *> ResultTruncRegTypes;
2672 llvm::BitVector ResultTypeRequiresCast;
2675 std::vector<llvm::Value *> InOutArgs;
2676 std::vector<llvm::Type *> InOutArgTypes;
2677 std::vector<llvm::Type *> InOutArgElemTypes;
2680 llvm::BasicBlock *DefaultDest =
nullptr;
2683 std::vector<std::optional<std::pair<unsigned, unsigned>>> ResultBounds;
2694 bool ReadOnly =
true;
2695 bool ReadNone =
true;
2697 bool GetOutputAndInputConstraints();
2698 void HandleOutputConstraints();
2699 void HandleMSStyleAsmBlob();
2700 void HandleInputConstraints();
2701 bool HandleLabels();
2702 bool HandleClobbers();
2703 void UpdateAsmCallInst(llvm::CallBase &
Result,
bool HasSideEffect,
2704 bool HasUnwindClobber,
bool NoMerge,
bool NoConvergent,
2705 std::vector<llvm::Value *> &RegResults);
2708 void EmitHipStdParUnsupportedAsm() {
2709 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2712 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2713 Asm = GCCAsm->getAsmString();
2715 auto &Ctx = getLLVMContext();
2716 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2717 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2718 {StrTy->getType()},
false);
2719 auto UBF = CGM.getModule().getOrInsertFunction(Name, FnTy);
2721 Builder.CreateCall(UBF, {StrTy});
2724 ASTContext &getContext() {
return CGF.getContext(); }
2725 llvm::LLVMContext &getLLVMContext() {
return CGF.getLLVMContext(); }
2726 const TargetInfo &getTarget()
const {
return CGF.getTarget(); }
2727 const LangOptions &getLangOpts()
const {
return CGF.getLangOpts(); }
2729 return CGM.getTargetCodeGenInfo();
2734 : CGF(CGF), CGM(CGF.CGM), S(S), Builder(CGF.Builder),
2735 AsmString(S.generateAsmString(CGF.getContext())) {}
2752 if (!GetOutputAndInputConstraints())
2753 return EmitHipStdParUnsupportedAsm();
2756 HandleOutputConstraints();
2760 HandleMSStyleAsmBlob();
2763 HandleInputConstraints();
2766 bool IsGCCAsmGoto = HandleLabels();
2769 bool HasUnwindClobber = HandleClobbers();
2770 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
2771 "unwind clobber can't be used with asm goto");
2774 std::string_view MachineClobbers = getTarget().getClobbers();
2775 if (!MachineClobbers.empty()) {
2776 if (!Constraints.empty())
2778 Constraints += MachineClobbers;
2781 llvm::Type *ResultType;
2782 if (ResultRegTypes.empty())
2783 ResultType = CGF.VoidTy;
2784 else if (ResultRegTypes.size() == 1)
2785 ResultType = ResultRegTypes[0];
2787 ResultType = llvm::StructType::get(getLLVMContext(), ResultRegTypes);
2789 llvm::FunctionType *FTy =
2790 llvm::FunctionType::get(ResultType, ArgTypes,
false);
2792 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
2794 llvm::InlineAsm::AsmDialect GnuAsmDialect =
2796 ? llvm::InlineAsm::AD_ATT
2797 : llvm::InlineAsm::AD_Intel;
2798 llvm::InlineAsm::AsmDialect AsmDialect =
2801 llvm::InlineAsm *IA = llvm::InlineAsm::get(
2802 FTy, AsmString, Constraints, HasSideEffect,
2803 false, AsmDialect, HasUnwindClobber);
2804 std::vector<llvm::Value *> RegResults;
2805 llvm::CallBrInst *CBR;
2806 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
2810 if (CGF.HaveInsertPoint() && !CGF.Bypasses.isAlwaysBypassed()) {
2811 CGF.emitBypassedVarInitsForSource(&S);
2812 CGF.BypassingForwardJumps.push_back({Builder.GetInsertBlock(), &S});
2814 CBR = Builder.CreateCallBr(IA, DefaultDest, IndirectDests, Args);
2815 CGF.EmitBlock(DefaultDest);
2816 UpdateAsmCallInst(*CBR, HasSideEffect,
2817 false, CGF.InNoMergeAttributedStmt,
2818 CGF.InNoConvergentAttributedStmt, RegResults);
2823 if (!RegResults.empty()) {
2825 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
2826 llvm::Twine SynthName = Dest->getName() +
".split";
2827 llvm::BasicBlock *SynthBB = CGF.createBasicBlock(SynthName);
2828 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
2829 Builder.SetInsertPoint(SynthBB);
2831 if (ResultRegTypes.size() == 1) {
2832 CBRRegResults[SynthBB].push_back(CBR);
2834 for (
unsigned J = 0, E = ResultRegTypes.size(); J != E; ++J) {
2835 llvm::Value *Tmp = Builder.CreateExtractValue(CBR, J,
"asmresult");
2836 CBRRegResults[SynthBB].push_back(Tmp);
2840 CGF.EmitBranch(Dest);
2841 CGF.EmitBlock(SynthBB);
2842 CBR->setIndirectDest(I++, SynthBB);
2845 }
else if (HasUnwindClobber) {
2846 llvm::CallBase *
Result = CGF.EmitCallOrInvoke(IA, Args,
"");
2847 UpdateAsmCallInst(*
Result, HasSideEffect,
2848 true, CGF.InNoMergeAttributedStmt,
2849 CGF.InNoConvergentAttributedStmt, RegResults);
2852 Builder.CreateCall(IA, Args, CGF.getBundlesForFunclet(IA));
2853 UpdateAsmCallInst(*
Result, HasSideEffect,
2854 false, CGF.InNoMergeAttributedStmt,
2855 CGF.InNoConvergentAttributedStmt, RegResults);
2858 EmitAsmStores(RegResults);
2863 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
2864 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
2865 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
2866 Builder.SetInsertPoint(--(Succ->end()));
2867 EmitAsmStores(CBRRegResults[Succ]);
2875bool AsmConstraintsInfo::GetOutputAndInputConstraints() {
2876 bool IsValidTargetAsm =
true;
2877 bool IsHipStdPar = getLangOpts().HIPStdPar && getLangOpts().CUDAIsDevice;
2878 for (
unsigned I = 0, E = S.getNumOutputs(); I != E && IsValidTargetAsm; I++) {
2880 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2881 Name = GAS->getOutputName(I);
2885 bool IsValid = getTarget().validateOutputConstraint(Info);
2886 if (IsHipStdPar && !IsValid)
2887 IsValidTargetAsm =
false;
2889 assert(IsValid &&
"Failed to parse output constraint");
2891 OutputConstraintInfos.push_back(Info);
2894 for (
unsigned I = 0, E = S.getNumInputs(); I != E && IsValidTargetAsm; I++) {
2896 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2897 Name = GAS->getInputName(I);
2902 getTarget().validateInputConstraint(OutputConstraintInfos, Info);
2903 if (IsHipStdPar && !IsValid)
2904 IsValidTargetAsm =
false;
2906 assert(IsValid &&
"Failed to parse input constraint");
2908 InputConstraintInfos.push_back(Info);
2911 return IsValidTargetAsm;
2918void AsmConstraintsInfo::HandleOutputConstraints() {
2920 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2922 for (
unsigned I = 0, E = S.getNumOutputs(); I != E; I++) {
2923 TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[I];
2926 std::string OutputConstraint(S.getOutputConstraint(I));
2927 OutputConstraint = getTarget().simplifyConstraint(
2928 StringRef(OutputConstraint).substr(1), &OutputConstraintInfos);
2930 const Expr *OutExpr = S.getOutputExpr(I);
2934 OutputConstraint = S.addVariableConstraints(
2935 OutputConstraint, *OutExpr, getTarget(), Info.
earlyClobber(),
2936 [&](
const Stmt *UnspStmt, StringRef Msg) {
2937 CGM.ErrorUnsupported(UnspStmt, Msg);
2942 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2943 CGM.Error(S.getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2945 OutputConstraints.push_back(OutputConstraint);
2947 if (!Constraints.empty())
2952 QualType QTy = OutExpr->
getType();
2953 const bool IsScalarOrAggregate =
2958 Constraints +=
"=" + OutputConstraint;
2959 ResultRegQualTys.push_back(QTy);
2960 ResultRegDests.push_back(Dest);
2965 const bool RequiresCast =
2967 (getTargetHooks().isScalarizableAsmOperand(CGF, Ty) ||
2968 Ty->isAggregateType());
2970 ResultTruncRegTypes.push_back(Ty);
2971 ResultTypeRequiresCast.push_back(RequiresCast);
2974 if (
unsigned Size = getContext().getTypeSize(QTy))
2975 Ty = llvm::IntegerType::get(getLLVMContext(), Size);
2977 CGM.Error(OutExpr->
getExprLoc(),
"output size should not be zero");
2980 ResultRegTypes.push_back(Ty);
2987 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2988 TargetInfo::ConstraintInfo &Input = InputConstraintInfos[InputNo];
2992 assert(InputNo != S.getNumInputs() &&
"Didn't find matching input!");
2994 QualType
InputTy = S.getInputExpr(InputNo)->getType();
2995 QualType OutputType = OutExpr->
getType();
2997 uint64_t InputSize = getContext().getTypeSize(InputTy);
2998 if (getContext().getTypeSize(OutputType) < InputSize)
3003 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
3004 CGF, OutputConstraint, ResultRegTypes.back()))
3005 ResultRegTypes.back() = AdjTy;
3007 CGM.getDiags().Report(S.getAsmLoc(),
3008 diag::err_asm_invalid_type_in_input)
3009 << OutExpr->
getType() << OutputConstraint;
3012 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
3013 CGF.LargestVectorWidth =
3014 std::max((uint64_t)CGF.LargestVectorWidth,
3015 VT->getPrimitiveSizeInBits().getKnownMinValue());
3017 Address DestAddr = Dest.getAddress();
3028 ArgTypes.push_back(DestAddr.
getType());
3032 Constraints +=
"=*" + OutputConstraint;
3040 InOutConstraints +=
',';
3042 const Expr *InputExpr = S.getOutputExpr(I);
3044 llvm::Type *ArgElemType;
3045 std::tie(Arg, ArgElemType) =
3046 CGF.EmitAsmInputLValue(Info, Dest, InputExpr->
getType(),
3049 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
3050 CGF, OutputConstraint, Arg->getType()))
3051 Arg = Builder.CreateBitCast(Arg, AdjTy);
3054 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3055 CGF.LargestVectorWidth =
3056 std::max((uint64_t)CGF.LargestVectorWidth,
3057 VT->getPrimitiveSizeInBits().getKnownMinValue());
3061 InOutConstraints += llvm::utostr(I);
3063 InOutConstraints += OutputConstraint;
3065 InOutArgTypes.push_back(Arg->getType());
3066 InOutArgElemTypes.push_back(ArgElemType);
3067 InOutArgs.push_back(Arg);
3074void AsmConstraintsInfo::HandleMSStyleAsmBlob() {
3085 CGM.getTargetCodeGenInfo().addReturnRegisterOutputs(
3086 CGF, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
3087 ResultRegDests, AsmString, S.getNumOutputs());
3094void AsmConstraintsInfo::HandleInputConstraints() {
3095 ASTContext &Ctx = getContext();
3097 for (
unsigned I = 0, E = S.getNumInputs(); I != E; I++) {
3098 TargetInfo::ConstraintInfo &Info = InputConstraintInfos[I];
3099 const Expr *InputExpr = S.getInputExpr(I);
3104 if (!Constraints.empty())
3108 std::string InputConstraint(S.getInputConstraint(I));
3110 getTarget().simplifyConstraint(InputConstraint, &OutputConstraintInfos);
3112 InputConstraint = S.addVariableConstraints(
3115 [&](
const Stmt *UnspStmt, std::string_view Msg) {
3116 CGM.ErrorUnsupported(UnspStmt, Msg);
3119 std::string ReplaceConstraint(InputConstraint);
3121 llvm::Type *ArgElemType;
3122 std::tie(Arg, ArgElemType) = CGF.EmitAsmInput(Info, InputExpr, Constraints);
3131 QualType OutputType = S.getOutputExpr(Output)->getType();
3137 Arg = Builder.CreatePtrToInt(Arg, CGF.
IntPtrTy);
3139 llvm::Type *OutputTy = CGF.
ConvertType(OutputType);
3141 Arg = Builder.CreateZExt(Arg, OutputTy);
3143 Arg = Builder.CreateZExt(Arg, CGF.
IntPtrTy);
3144 else if (OutputTy->isFloatingPointTy())
3145 Arg = Builder.CreateFPExt(Arg, OutputTy);
3149 ReplaceConstraint = OutputConstraints[Output];
3152 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
3153 CGF, ReplaceConstraint, Arg->getType()))
3154 Arg = Builder.CreateBitCast(Arg, AdjTy);
3156 CGM.getDiags().Report(S.getAsmLoc(), diag::err_asm_invalid_type_in_input)
3157 << InputExpr->
getType() << InputConstraint;
3160 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3161 CGF.LargestVectorWidth =
3162 std::max((uint64_t)CGF.LargestVectorWidth,
3163 VT->getPrimitiveSizeInBits().getKnownMinValue());
3165 ArgTypes.push_back(Arg->getType());
3166 ArgElemTypes.push_back(ArgElemType);
3167 Args.push_back(Arg);
3169 Constraints += InputConstraint;
3173 for (
unsigned I = 0, E = InOutArgs.size(); I != E; I++) {
3174 ArgTypes.push_back(InOutArgTypes[I]);
3175 ArgElemTypes.push_back(InOutArgElemTypes[I]);
3176 Args.push_back(InOutArgs[I]);
3179 Constraints += InOutConstraints;
3185bool AsmConstraintsInfo::HandleLabels() {
3186 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S); GS && GS->isAsmGoto()) {
3187 for (
const auto *E : GS->labels()) {
3189 IndirectDests.push_back(Dest.
getBlock());
3191 if (!Constraints.empty())
3194 Constraints +=
"!i";
3208bool AsmConstraintsInfo::HandleClobbers() {
3209 bool HasUnwindClobber =
false;
3210 for (
unsigned I = 0, E = S.getNumClobbers(); I != E; I++) {
3211 std::string Clobber = S.getClobber(I);
3213 if (Clobber ==
"unwind") {
3214 HasUnwindClobber =
true;
3218 if (Clobber ==
"memory") {
3221 }
else if (Clobber !=
"cc") {
3222 Clobber = getTarget().getNormalizedGCCRegisterName(Clobber);
3223 if (CGM.getCodeGenOpts().StackClashProtector &&
3224 getTarget().isSPRegName(Clobber)) {
3225 CGM.getDiags().Report(S.getAsmLoc(),
3226 diag::warn_stack_clash_protection_inline_asm);
3231 if (Clobber ==
"eax" || Clobber ==
"edx") {
3232 if (Constraints.find(
"=&A") != std::string::npos)
3235 std::string::size_type position1 =
3236 Constraints.find(
"={" + Clobber +
"}");
3237 if (position1 != std::string::npos) {
3238 Constraints.insert(position1 + 1,
"&");
3242 std::string::size_type position2 = Constraints.find(
"=A");
3243 if (position2 != std::string::npos) {
3244 Constraints.insert(position2 + 1,
"&");
3250 if (!Constraints.empty())
3253 Constraints +=
"~{" + Clobber +
'}';
3256 return HasUnwindClobber;
3259void AsmConstraintsInfo::UpdateAsmCallInst(
3260 llvm::CallBase &
Result,
bool HasSideEffect,
bool HasUnwindClobber,
3261 bool NoMerge,
bool NoConvergent, std::vector<llvm::Value *> &RegResults) {
3262 if (!HasUnwindClobber)
3263 Result.addFnAttr(llvm::Attribute::NoUnwind);
3266 Result.addFnAttr(llvm::Attribute::NoMerge);
3269 if (!HasSideEffect) {
3271 Result.setDoesNotAccessMemory();
3273 Result.setOnlyReadsMemory();
3277 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
3279 auto Attr = llvm::Attribute::get(
3280 getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
3281 Result.addParamAttr(Pair.index(), Attr);
3287 const StringLiteral *SL;
3288 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S);
3290 (SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))) {
3295 llvm::Constant *Loc =
3296 llvm::ConstantInt::get(CGF.
Int64Ty, S.getAsmLoc().getRawEncoding());
3297 Result.setMetadata(
"srcloc",
3298 llvm::MDNode::get(getLLVMContext(),
3299 llvm::ConstantAsMetadata::get(Loc)));
3305 if (!NoConvergent && getLangOpts().assumeFunctionsAreConvergent())
3310 Result.addFnAttr(llvm::Attribute::Convergent);
3313 if (ResultRegTypes.size() == 1) {
3314 RegResults.push_back(&
Result);
3316 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
3317 llvm::Value *Tmp = Builder.CreateExtractValue(&
Result, i,
"asmresult");
3318 RegResults.push_back(Tmp);
3323void AsmConstraintsInfo::EmitAsmStores(
3324 const llvm::ArrayRef<llvm::Value *> RegResults) {
3325 llvm::LLVMContext &CTX = getLLVMContext();
3327 assert(RegResults.size() == ResultRegTypes.size());
3328 assert(RegResults.size() == ResultTruncRegTypes.size());
3329 assert(RegResults.size() == ResultRegDests.size());
3333 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
3334 assert(ResultBounds.size() <= ResultRegDests.size());
3336 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
3337 llvm::Value *Tmp = RegResults[i];
3338 llvm::Type *TruncTy = ResultTruncRegTypes[i];
3340 if (i < ResultBounds.size() && ResultBounds[i].has_value()) {
3341 const auto [LowerBound, UpperBound] = ResultBounds[i].value();
3344 assert(LowerBound == 0 &&
"Output operand lower bound is not zero.");
3346 llvm::Constant *UpperBoundConst =
3347 llvm::ConstantInt::get(Tmp->getType(), UpperBound);
3348 llvm::Value *IsBooleanValue =
3349 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, UpperBoundConst);
3350 llvm::Function *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume);
3352 Builder.CreateCall(FnAssume, IsBooleanValue);
3357 const bool RequiresCast =
3358 i < ResultTypeRequiresCast.size() && ResultTypeRequiresCast[i];
3363 if (ResultRegTypes[i] != TruncTy && !RequiresCast) {
3366 if (TruncTy->isFloatingPointTy())
3367 Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
3368 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
3369 uint64_t ResSize = CGM.getDataLayout().getTypeSizeInBits(TruncTy);
3370 Tmp = Builder.CreateTrunc(
3371 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
3372 Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
3373 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
3375 CGM.getDataLayout().getTypeSizeInBits(Tmp->getType());
3376 Tmp = Builder.CreatePtrToInt(
3377 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
3378 Tmp = Builder.CreateTrunc(Tmp, TruncTy);
3379 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
3380 Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
3381 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
3382 Tmp = Builder.CreateBitCast(Tmp, TruncTy);
3387 LValue Dest = ResultRegDests[i];
3390 unsigned Size = getContext().getTypeSize(ResultRegQualTys[i]);
3391 Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
3393 if (getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) {
3394 llvm::StoreInst *S =
3395 Builder.CreateStore(Tmp, A, Dest.isVolatileQualified());
3400 QualType Ty = getContext().getIntTypeForBitwidth(Size,
false);
3402 const Expr *OutExpr = S.getOutputExpr(i);
3404 diag::err_store_value_to_reg);
3412 llvm::Type *IntTy = llvm::IntegerType::get(CTX, Size);
3413 uint64_t TmpSize = CGM.getDataLayout().getTypeSizeInBits(Tmp->getType());
3414 Tmp = Builder.CreateBitOrPointerCast(
3415 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
3416 Tmp = Builder.CreateTrunc(Tmp, IntTy);
3423 Dest.getAddress().withElementType(IntTy),
3424 getContext().getQualifiedType(Ty, Dest.getQuals()),
3443 I != E; ++I, ++CurField) {
3445 if (CurField->hasCapturedVLAType()) {
3462 CodeGenFunction CGF(
CGM,
true);
3482 "CapturedStmtInfo should be set when generating the captured function");
3486 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3495 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Args);
3496 llvm::FunctionType *FuncLLVMTy =
CGM.getTypes().GetFunctionType(FuncInfo);
3499 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3501 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
3502 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
3503 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3505 F->addFnAttr(llvm::Attribute::NoUnwind);
3517 for (
auto *FD : RD->
fields()) {
3518 if (FD->hasCapturedVLAType()) {
3522 auto VAT = FD->getCapturedVLAType();
3523 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3534 PGO->assignRegionCounters(
GlobalDecl(CD), F);
3544 for (
auto &I : *BB) {
3545 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3551void CodeGenFunction::addConvergenceControlBundle(
3552 SmallVectorImpl<llvm::OperandBundleDef> &Bundles) {
3553 if (!CGM.shouldEmitConvergenceTokens())
3556 llvm::ConvergenceControlInst *ParentToken = ConvergenceTokenStack.back();
3557 assert(ParentToken);
3558 Bundles.emplace_back(
"convergencectrl", ParentToken);
3561void CodeGenFunction::setConvergentCallSite(llvm::CallBase *
Call,
3562 bool IsConvergent) {
3563 if (IsConvergent && !
Call->isConvergent())
3564 Call->setConvergent();
3566 assert((IsConvergent || !
Call->isConvergent() ||
3567 !CGM.shouldEmitConvergenceTokens()) &&
3568 "convergent call is missing a convergence control token");
3571llvm::ConvergenceControlInst *
3574 assert(ParentToken);
3575 return llvm::ConvergenceControlInst::CreateLoop(*BB, ParentToken);
3578llvm::ConvergenceControlInst *
3579CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3580 llvm::BasicBlock *BB = &F->getEntryBlock();
3588 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 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)
CSFC_Result
CollectStatementsForCase - Given the body of a 'switch' statement and a constant value that is being ...
Result
Implement __builtin_bit_cast and related operations.
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()
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType getCanonicalTagType(const TagDecl *TD) const
AsmConstraintsInfo(CodeGenFunction &CGF, const AsmStmt &S)
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
Attr - This represents one attribute.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
BreakStmt - This represents a break.
Represents the code generated for an expanded expansion statement.
ArrayRef< Stmt * > getInstantiations() const
ArrayRef< Stmt * > getPreambleStmts() const
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.
@ 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.
ABIArgInfo & getReturnInfo()
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)
StringRef AMDGPUAvailableVisibleMode
The mode string from the amdgpu_av attribute on the current statement, or empty if the attribute is n...
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)
friend class clang::AsmConstraintsInfo
LValue InitCapturedStruct(const CapturedStmt &S)
void EmitOMPFlattenDirective(const OMPFlattenDirective &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...
llvm::SmallVector< BypassingForwardJump, 4 > BypassingForwardJumps
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 EmitOMPSplitDirective(const OMPSplitDirective &S)
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)
llvm::ConvergenceControlInst * emitConvergenceLoopToken(llvm::BasicBlock *BB)
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 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 EmitCXXExpansionStmtInstantiation(const CXXExpansionStmtInstantiation &S)
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)
void EmitOMPOrderedBlockAssocDirective(const OMPOrderedBlockAssocDirective &S)
CGDebugInfo * getDebugInfo()
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPReverseDirective(const OMPReverseDirective &S)
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)
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
bool InNoInlineAttributedStmt
True if the current statement has noinline attribute.
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 emitBypassedVarInitsForSource(const Stmt *Source)
Re-emit trivial-auto-var-init stores for variables bypassed by the jump Source.
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)
void EmitOMPOrderedStandaloneDirective(const OMPOrderedStandaloneDirective &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.
VarBypassDetector Bypasses
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.
const LangOptions & getLangOpts() const
const llvm::DataLayout & getDataLayout() const
ASTContext & getContext() const
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.
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
CompoundStmt - This represents a group of statements like { stmt stmt }.
Stmt *const * const_body_iterator
SourceLocation getLBracLoc() const
body_iterator body_begin()
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.
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.
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...
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
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.
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...
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.
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
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.
Token - This structure provides full information about a lexed token.
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.
bool checkIfLoopMustProgress(const LangOptions &LangOpts, const CodeGenOptions &CGOpts, ASTContext &Ctx, const Expr *ControllingExpression, bool HasEmptyBody, llvm::function_ref< void()> RemoveMustProgress)
Returns true if a loop must make progress, which means the mustprogress attribute can be added to it.
bool hasEmptyLoopBody(const LoopStmt &S)
std::pair< types::ID, const llvm::opt::Arg * > InputTy
A list of inputs and their types for the given arguments.
@ Address
A pointer to a ValueDecl.
Top level wrappers for InstallAPI frontend operations.
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)
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
static TBAAAccessInfo getMayAliasInfo()
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