29#include "llvm/ADT/ArrayRef.h"
30#include "llvm/ADT/DenseMap.h"
31#include "llvm/ADT/SmallSet.h"
32#include "llvm/ADT/StringExtras.h"
33#include "llvm/IR/Assumptions.h"
34#include "llvm/IR/DataLayout.h"
35#include "llvm/IR/InlineAsm.h"
36#include "llvm/IR/Intrinsics.h"
37#include "llvm/IR/MDBuilder.h"
38#include "llvm/Support/SaveAndRestore.h"
59 assert(S &&
"Null statement?");
60 PGO->setCurrentStmt(S);
77 PGO->markStmtMaybeUsed(S);
91 if (
const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
99 case Stmt::CXXCatchStmtClass:
100 case Stmt::SEHExceptStmtClass:
101 case Stmt::SEHFinallyStmtClass:
102 case Stmt::MSDependentExistsStmtClass:
103 case Stmt::UnresolvedSYCLKernelCallStmtClass:
104 llvm_unreachable(
"invalid statement class to emit generically");
105 case Stmt::NullStmtClass:
106 case Stmt::CompoundStmtClass:
107 case Stmt::DeclStmtClass:
108 case Stmt::LabelStmtClass:
109 case Stmt::AttributedStmtClass:
110 case Stmt::GotoStmtClass:
111 case Stmt::BreakStmtClass:
112 case Stmt::ContinueStmtClass:
113 case Stmt::DefaultStmtClass:
114 case Stmt::CaseStmtClass:
115 case Stmt::DeferStmtClass:
116 case Stmt::SEHLeaveStmtClass:
117 case Stmt::SYCLKernelCallStmtClass:
118 llvm_unreachable(
"should have emitted these statements as simple");
120#define STMT(Type, Base)
121#define ABSTRACT_STMT(Op)
122#define EXPR(Type, Base) \
123 case Stmt::Type##Class:
124#include "clang/AST/StmtNodes.inc"
127 llvm::BasicBlock *incoming =
Builder.GetInsertBlock();
128 assert(incoming &&
"expression emission must have an insertion point");
132 llvm::BasicBlock *outgoing =
Builder.GetInsertBlock();
133 assert(outgoing &&
"expression emission cleared block!");
147 if (incoming != outgoing && outgoing->use_empty()) {
148 outgoing->eraseFromParent();
154 case Stmt::IndirectGotoStmtClass:
165 case Stmt::GCCAsmStmtClass:
167 case Stmt::CoroutineBodyStmtClass:
170 case Stmt::CoreturnStmtClass:
173 case Stmt::CapturedStmtClass: {
178 case Stmt::ObjCAtTryStmtClass:
181 case Stmt::ObjCAtCatchStmtClass:
183 "@catch statements should be handled by EmitObjCAtTryStmt");
184 case Stmt::ObjCAtFinallyStmtClass:
186 "@finally statements should be handled by EmitObjCAtTryStmt");
187 case Stmt::ObjCAtThrowStmtClass:
190 case Stmt::ObjCAtSynchronizedStmtClass:
193 case Stmt::ObjCForCollectionStmtClass:
196 case Stmt::ObjCAutoreleasePoolStmtClass:
200 case Stmt::CXXTryStmtClass:
203 case Stmt::CXXForRangeStmtClass:
206 case Stmt::CXXExpansionStmtPatternClass:
207 llvm_unreachable(
"unexpanded expansion statements should not be emitted");
208 case Stmt::CXXExpansionStmtInstantiationClass:
211 case Stmt::SEHTryStmtClass:
214 case Stmt::OMPMetaDirectiveClass:
217 case Stmt::OMPCanonicalLoopClass:
220 case Stmt::OMPParallelDirectiveClass:
223 case Stmt::OMPSimdDirectiveClass:
226 case Stmt::OMPTileDirectiveClass:
229 case Stmt::OMPStripeDirectiveClass:
232 case Stmt::OMPUnrollDirectiveClass:
235 case Stmt::OMPReverseDirectiveClass:
238 case Stmt::OMPSplitDirectiveClass:
241 case Stmt::OMPInterchangeDirectiveClass:
244 case Stmt::OMPFlattenDirectiveClass:
247 case Stmt::OMPFuseDirectiveClass:
250 case Stmt::OMPForDirectiveClass:
253 case Stmt::OMPForSimdDirectiveClass:
256 case Stmt::OMPSectionsDirectiveClass:
259 case Stmt::OMPSectionDirectiveClass:
262 case Stmt::OMPSingleDirectiveClass:
265 case Stmt::OMPMasterDirectiveClass:
268 case Stmt::OMPCriticalDirectiveClass:
271 case Stmt::OMPParallelForDirectiveClass:
274 case Stmt::OMPParallelForSimdDirectiveClass:
277 case Stmt::OMPParallelMasterDirectiveClass:
280 case Stmt::OMPParallelSectionsDirectiveClass:
283 case Stmt::OMPTaskDirectiveClass:
286 case Stmt::OMPTaskyieldDirectiveClass:
289 case Stmt::OMPErrorDirectiveClass:
292 case Stmt::OMPBarrierDirectiveClass:
295 case Stmt::OMPTaskwaitDirectiveClass:
298 case Stmt::OMPTaskgroupDirectiveClass:
301 case Stmt::OMPFlushDirectiveClass:
304 case Stmt::OMPDepobjDirectiveClass:
307 case Stmt::OMPScanDirectiveClass:
310 case Stmt::OMPOrderedStandaloneDirectiveClass:
313 case Stmt::OMPOrderedBlockAssocDirectiveClass:
316 case Stmt::OMPAtomicDirectiveClass:
319 case Stmt::OMPTargetDirectiveClass:
322 case Stmt::OMPTeamsDirectiveClass:
325 case Stmt::OMPCancellationPointDirectiveClass:
328 case Stmt::OMPCancelDirectiveClass:
331 case Stmt::OMPTargetDataDirectiveClass:
334 case Stmt::OMPTargetEnterDataDirectiveClass:
337 case Stmt::OMPTargetExitDataDirectiveClass:
340 case Stmt::OMPTargetParallelDirectiveClass:
343 case Stmt::OMPTargetParallelForDirectiveClass:
346 case Stmt::OMPTaskLoopDirectiveClass:
349 case Stmt::OMPTaskLoopSimdDirectiveClass:
352 case Stmt::OMPMasterTaskLoopDirectiveClass:
355 case Stmt::OMPMaskedTaskLoopDirectiveClass:
358 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
362 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
366 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
370 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
374 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
378 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
382 case Stmt::OMPDistributeDirectiveClass:
385 case Stmt::OMPTargetUpdateDirectiveClass:
388 case Stmt::OMPDistributeParallelForDirectiveClass:
392 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
396 case Stmt::OMPDistributeSimdDirectiveClass:
399 case Stmt::OMPTargetParallelForSimdDirectiveClass:
403 case Stmt::OMPTargetSimdDirectiveClass:
406 case Stmt::OMPTeamsDistributeDirectiveClass:
409 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
413 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
417 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
421 case Stmt::OMPTargetTeamsDirectiveClass:
424 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
428 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
432 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
436 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
440 case Stmt::OMPInteropDirectiveClass:
443 case Stmt::OMPDispatchDirectiveClass:
444 CGM.ErrorUnsupported(S,
"OpenMP dispatch directive");
446 case Stmt::OMPScopeDirectiveClass:
449 case Stmt::OMPMaskedDirectiveClass:
452 case Stmt::OMPGenericLoopDirectiveClass:
455 case Stmt::OMPTeamsGenericLoopDirectiveClass:
458 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
462 case Stmt::OMPParallelGenericLoopDirectiveClass:
466 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
470 case Stmt::OMPParallelMaskedDirectiveClass:
473 case Stmt::OMPAssumeDirectiveClass:
476 case Stmt::OpenACCComputeConstructClass:
479 case Stmt::OpenACCLoopConstructClass:
482 case Stmt::OpenACCCombinedConstructClass:
485 case Stmt::OpenACCDataConstructClass:
488 case Stmt::OpenACCEnterDataConstructClass:
491 case Stmt::OpenACCExitDataConstructClass:
494 case Stmt::OpenACCHostDataConstructClass:
497 case Stmt::OpenACCWaitConstructClass:
500 case Stmt::OpenACCInitConstructClass:
503 case Stmt::OpenACCShutdownConstructClass:
506 case Stmt::OpenACCSetConstructClass:
509 case Stmt::OpenACCUpdateConstructClass:
512 case Stmt::OpenACCAtomicConstructClass:
515 case Stmt::OpenACCCacheConstructClass:
526 case Stmt::NullStmtClass:
528 case Stmt::CompoundStmtClass:
531 case Stmt::DeclStmtClass:
534 case Stmt::LabelStmtClass:
537 case Stmt::AttributedStmtClass:
540 case Stmt::GotoStmtClass:
543 case Stmt::BreakStmtClass:
546 case Stmt::ContinueStmtClass:
549 case Stmt::DefaultStmtClass:
552 case Stmt::CaseStmtClass:
555 case Stmt::DeferStmtClass:
558 case Stmt::SEHLeaveStmtClass:
561 case Stmt::SYCLKernelCallStmtClass:
574 "LLVM IR generation of compound statement ('{}')");
601 if (
const auto *LS = dyn_cast<LabelStmt>(LastStmt)) {
603 LastStmt = LS->getSubStmt();
604 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(LastStmt)) {
607 LastStmt = AS->getSubStmt();
609 llvm_unreachable(
"unknown value statement");
633 llvm::UncondBrInst *BI = dyn_cast<llvm::UncondBrInst>(BB->getTerminator());
646 if (BI->getIterator() != BB->begin())
649 BB->replaceAllUsesWith(BI->getSuccessor());
650 BI->eraseFromParent();
651 BB->eraseFromParent();
655 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
660 if (IsFinished && BB->use_empty()) {
667 if (CurBB && CurBB->getParent())
668 CurFn->insert(std::next(CurBB->getIterator()), BB);
678 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
680 if (!CurBB || CurBB->hasTerminator()) {
692 bool inserted =
false;
693 for (llvm::User *u : block->users()) {
694 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
695 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
710 if (Dest.
isValid())
return Dest;
723 if (
EHStack.hasNormalCleanups() && CurLexicalScope)
724 CurLexicalScope->addLabel(D);
745 if (
CGM.getCodeGenOpts().hasReducedDebugInfo()) {
757 assert(!Labels.empty());
759 =
CGF.EHStack.getInnermostNormalCleanup();
763 assert(
CGF.LabelMap.count(Label));
772 ParentScope->Labels.append(Labels.begin(), Labels.end());
795 const AtomicAttr *AA =
nullptr;
797 for (
const auto *A : S.
getAttrs()) {
798 switch (A->getKind()) {
806 alwaysinline =
false;
808 case attr::AlwaysInline:
812 case attr::NoConvergent:
815 case attr::MustTail: {
820 case attr::CXXAssume: {
825 Builder.CreateAssumption(AssumptionVal);
831 case attr::AMDGPUAvailableVisible:
834 case attr::HLSLControlFlowHint: {
840 assert(!(alwaysinline && noinline) &&
841 "alwaysinline and noinline are mutually exclusive");
876 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
886 if (CurBB && CurBB->hasTerminator())
927 const Stmt *Skipped = Else;
929 std::swap(Executed, Skipped);
941 PGO->markStmtMaybeUsed(Skipped);
952 llvm::BasicBlock *ElseBlock =
968 CGM.getCodeGenOpts().OptimizationLevel)
977 if (!
CGM.getCodeGenOpts().MCDCCoverage) {
984 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
1015 }
else if (HasSkip) {
1026 bool HasEmptyBody) {
1027 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1037 bool CondIsConstInt =
1038 !ControllingExpression ||
1042 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
1043 Result.Val.getInt().getBoolValue());
1054 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1057 if (HasEmptyBody && CondIsTrue) {
1058 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1076 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1080 const Stmt *Body = S.getBody();
1083 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
1084 return Compound->body_empty();
1095 if (
CGM.shouldEmitConvergenceTokens())
1104 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopHeader));
1127 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1128 bool EmitBoolCondBranch = !
C || !
C->isOne();
1137 if (EmitBoolCondBranch) {
1138 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1141 llvm::MDNode *Weights =
1143 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1144 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1146 auto *I =
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1152 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1156 if (ExitBlock !=
LoopExit.getBlock()) {
1162 CGM.getDiags().Report(A->getLocation(),
1163 diag::warn_attribute_has_no_effect_on_infinite_loop)
1164 << A << A->getRange();
1165 CGM.getDiags().Report(
1167 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1180 BreakContinueStack.pop_back();
1196 if (!EmitBoolCondBranch) {
1198 PGO->markStmtAsUsed(
true, &S);
1201 if (
CGM.shouldEmitConvergenceTokens())
1213 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopCond));
1220 if (
CGM.shouldEmitConvergenceTokens())
1238 BreakContinueStack.pop_back();
1242 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1243 bool EmitBoolCondBranch = !
C || !
C->isZero();
1246 LoopStack.push(LoopBody,
CGM.getContext(),
CGM.getCodeGenOpts(), DoAttrs,
1255 if (EmitBoolCondBranch) {
1257 auto *I =
Builder.CreateCondBr(
1258 BoolCondVal, LoopBody, LoopFalse,
1259 createProfileWeightsForLoop(S.
getCond(), BackedgeCount));
1266 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1273 if (LoopFalse !=
LoopExit.getBlock()) {
1283 if (!EmitBoolCondBranch)
1286 if (
CGM.shouldEmitConvergenceTokens())
1294 std::optional<LexicalScope> ForScope;
1306 llvm::BasicBlock *CondBlock = CondDest.
getBlock();
1309 if (
CGM.shouldEmitConvergenceTokens())
1313 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1330 Continue = CondDest;
1333 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1344 BreakContinueStack.back().ContinueBlock = Continue;
1347 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1350 if (
hasSkipCounter(&S) || (ForScope && ForScope->requiresCleanups()))
1362 llvm::MDNode *Weights =
1364 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1365 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1368 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1373 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1377 if (ExitBlock !=
LoopExit.getBlock()) {
1387 PGO->markStmtAsUsed(
true, &S);
1401 auto *FinalBodyBB =
Builder.GetInsertBlock();
1409 BreakContinueStack.pop_back();
1417 ForScope->ForceCleanup();
1424 if (
CGM.shouldEmitConvergenceTokens())
1454 if (
CGM.shouldEmitConvergenceTokens())
1458 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1464 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1474 llvm::MDNode *Weights =
1476 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1477 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1479 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1484 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1488 if (ExitBlock !=
LoopExit.getBlock()) {
1501 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1511 auto *FinalBodyBB =
Builder.GetInsertBlock();
1518 BreakContinueStack.pop_back();
1529 if (
CGM.shouldEmitConvergenceTokens())
1553 ContinueDest = ExpandExit;
1557 LexicalScope ExpansionScope(*
this, Inst->getSourceRange());
1558 BreakContinueStack.push_back(BreakContinue(S, ExpandExit, ContinueDest));
1560 BreakContinueStack.pop_back();
1565void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1581struct SaveRetExprRAII {
1582 SaveRetExprRAII(
const Expr *RetExpr, CodeGenFunction &CGF)
1583 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1586 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1587 const Expr *OldRetExpr;
1588 CodeGenFunction &CGF;
1596 if (calleeQualType->isFunctionPointerType() ||
1597 calleeQualType->isFunctionReferenceType() ||
1598 calleeQualType->isBlockPointerType() ||
1599 calleeQualType->isMemberFunctionPointerType()) {
1601 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1603 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1604 if (
auto methodDecl = CMCE->getMethodDecl()) {
1621 if (requiresReturnValueCheck()) {
1624 new llvm::GlobalVariable(
CGM.getModule(), SLoc->getType(),
false,
1625 llvm::GlobalVariable::PrivateLinkage, SLoc);
1626 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1627 CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
1628 assert(ReturnLocation.isValid() &&
"No valid return location");
1629 Builder.CreateStore(SLocPtr, ReturnLocation);
1635 Builder.ClearInsertionPoint();
1649 SaveRetExprRAII SaveRetExpr(RV, *
this);
1652 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1653 RV = EWC->getSubExpr();
1657 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1660 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1673 !
CGM.getOpenMPRuntime()
1692 }
else if (
FnRetTy->isReferenceType()) {
1728 ++NumSimpleReturnExprs;
1740 for (
const auto *I : S.
decls())
1745 ->
const BreakContinue * {
1746 if (!S.hasLabelTarget())
1747 return &BreakContinueStack.back();
1749 const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
1750 assert(LoopOrSwitch &&
"break/continue target not set?");
1751 for (
const BreakContinue &BC : llvm::reverse(BreakContinueStack))
1752 if (BC.LoopOrSwitch == LoopOrSwitch)
1755 llvm_unreachable(
"break/continue target not found");
1759 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1772 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1789 assert(S.
getRHS() &&
"Expected RHS value in CaseStmt");
1802 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1806 llvm::APInt Range = RHS - LHS;
1808 if (Range.getBitWidth() < 7 ||
1809 Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
1812 unsigned NCases = Range.getZExtValue() + 1;
1817 uint64_t Weight = Total / NCases, Rem = Total % NCases;
1818 for (
unsigned I = 0; I != NCases; ++I) {
1820 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1821 else if (SwitchLikelihood)
1822 SwitchLikelihood->push_back(LH);
1826 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1834 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1839 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1843 Builder.SetInsertPoint(CaseRangeBlock);
1847 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1851 llvm::MDNode *Weights =
nullptr;
1852 if (SwitchWeights) {
1854 uint64_t DefaultCount = (*SwitchWeights)[0];
1855 Weights = createProfileWeights(ThisCount, DefaultCount);
1860 (*SwitchWeights)[0] += ThisCount;
1861 }
else if (SwitchLikelihood)
1862 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
1864 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
1868 Builder.SetInsertPoint(RestoreBB);
1870 Builder.ClearInsertionPoint();
1891 llvm::ConstantInt *CaseVal =
1896 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.
getLHS()))
1897 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1899 CE = dyn_cast<ConstantExpr>(S.
getLHS());
1901 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1903 if (
CGM.getCodeGenOpts().hasReducedDebugInfo())
1904 Dbg->EmitGlobalVariable(DE->getDecl(),
1905 APValue(llvm::APSInt(CaseVal->getValue())));
1908 if (SwitchLikelihood)
1914 if (!
CGM.getCodeGenOpts().hasProfileClangInstr() &&
1915 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1923 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1927 if (
Builder.GetInsertBlock()) {
1929 Builder.ClearInsertionPoint();
1939 SwitchInsn->addCase(CaseVal, CaseDest);
1958 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1960 llvm::ConstantInt *CaseVal =
1965 if (
CGM.getCodeGenOpts().hasProfileClangInstr()) {
1971 if (SwitchLikelihood)
1974 SwitchInsn->addCase(CaseVal, CaseDest);
1975 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1998 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1999 assert(DefaultBlock->empty() &&
2000 "EmitDefaultStmt: Default block already defined?");
2002 if (SwitchLikelihood)
2011struct EmitDeferredStatement final : EHScopeStack::Cleanup {
2071 llvm::Value *SavedCleanupDest =
nullptr;
2125 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
2144 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
2148 bool StartedInLiveCode = FoundCase;
2149 unsigned StartSize = ResultStmts.size();
2156 bool HadSkippedDecl =
false;
2160 for (; Case && I != E; ++I) {
2176 for (++I; I != E; ++I)
2186 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
2201 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
2206 bool AnyDecls =
false;
2207 for (; I != E; ++I) {
2220 for (++I; I != E; ++I)
2237 ResultStmts.resize(StartSize);
2238 ResultStmts.push_back(S);
2262 ResultStmts.push_back(S);
2271 const llvm::APSInt &ConstantCondValue,
2283 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2291 if (CS->
getRHS())
return false;
2316 bool FoundCase =
false;
2323static std::optional<SmallVector<uint64_t, 16>>
2326 if (Likelihoods.size() <= 1)
2327 return std::nullopt;
2329 uint64_t NumUnlikely = 0;
2330 uint64_t NumNone = 0;
2331 uint64_t NumLikely = 0;
2332 for (
const auto LH : Likelihoods) {
2347 if (NumUnlikely == 0 && NumLikely == 0)
2348 return std::nullopt;
2356 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2357 const uint64_t
None = Likely / (NumNone + 1);
2358 const uint64_t Unlikely = 0;
2361 Result.reserve(Likelihoods.size());
2362 for (
const auto LH : Likelihoods) {
2365 Result.push_back(Unlikely);
2371 Result.push_back(Likely);
2381 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2384 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2388 llvm::APSInt ConstantCondValue;
2409 SwitchInsn =
nullptr;
2416 PGO->markStmtMaybeUsed(S.
getBody());
2420 SwitchInsn = SavedSwitchInsn;
2448 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2452 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2453 llvm::ConstantInt *BranchHintConstant =
2455 HLSLControlFlowHintAttr::Spelling::Microsoft_branch
2456 ? llvm::ConstantInt::get(
CGM.Int32Ty, 1)
2457 : llvm::ConstantInt::get(
CGM.Int32Ty, 2);
2458 llvm::Metadata *Vals[] = {MDHelper.createString(
"hlsl.controlflow.hint"),
2459 MDHelper.createConstant(BranchHintConstant)};
2460 SwitchInsn->setMetadata(
"hlsl.controlflow.hint",
2461 llvm::MDNode::get(
CGM.getLLVMContext(), Vals));
2464 if (PGO->haveRegionCounts()) {
2466 uint64_t DefaultCount = 0;
2467 unsigned NumCases = 0;
2476 SwitchWeights->reserve(NumCases);
2479 SwitchWeights->push_back(DefaultCount);
2480 }
else if (
CGM.getCodeGenOpts().OptimizationLevel) {
2486 CaseRangeBlock = DefaultBlock;
2489 Builder.ClearInsertionPoint();
2494 if (!BreakContinueStack.empty())
2495 OuterContinue = BreakContinueStack.back().ContinueBlock;
2497 BreakContinueStack.push_back(BreakContinue(S, SwitchExit, OuterContinue));
2502 BreakContinueStack.pop_back();
2506 SwitchInsn->setDefaultDest(CaseRangeBlock);
2509 if (!DefaultBlock->getParent()) {
2517 DefaultBlock->replaceAllUsesWith(SwitchExit.
getBlock());
2518 delete DefaultBlock;
2532 Builder.CreateBr(SwitchInsn->getDefaultDest());
2533 SwitchInsn->setDefaultDest(ImplicitDefaultBlock);
2544 if (
Call &&
CGM.getCodeGenOpts().OptimizationLevel != 0) {
2545 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2546 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2548 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2549 MDHelper.createUnpredictable());
2553 if (SwitchWeights) {
2554 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2555 "switch weights do not match switch cases");
2557 if (SwitchWeights->size() > 1)
2558 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2559 createProfileWeights(*SwitchWeights));
2560 delete SwitchWeights;
2561 }
else if (SwitchLikelihood) {
2562 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2563 "switch likelihoods do not match switch cases");
2564 std::optional<SmallVector<uint64_t, 16>> LHW =
2567 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2568 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2569 createProfileWeights(*LHW));
2571 delete SwitchLikelihood;
2573 SwitchInsn = SavedSwitchInsn;
2574 SwitchWeights = SavedSwitchWeights;
2575 SwitchLikelihood = SavedSwitchLikelihood;
2576 CaseRangeBlock = SavedCRBlock;
2579std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2588 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2598 ConstraintStr +=
'*';
2601std::pair<llvm::Value *, llvm::Type *>
2602CodeGenFunction::EmitAsmInput(
const TargetInfo::ConstraintInfo &Info,
2603 const Expr *InputExpr,
2604 std::string &ConstraintStr) {
2609 Expr::EvalResult EVResult;
2612 llvm::APSInt IntResult;
2615 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2627 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2631 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2643 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2646 if (!StrVal.empty()) {
2649 unsigned StartToken = 0;
2650 unsigned ByteOffset = 0;
2654 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2655 if (StrVal[i] !=
'\n')
continue;
2657 i + 1, SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2658 Locs.push_back(llvm::ConstantAsMetadata::get(
2678 std::string AsmString;
2685 std::string Constraints;
2686 std::string InOutConstraints;
2689 std::vector<std::string> OutputConstraints;
2692 std::vector<llvm::Value *> Args;
2693 std::vector<llvm::Type *> ArgTypes;
2694 std::vector<llvm::Type *> ArgElemTypes;
2697 std::vector<LValue> ResultRegDests;
2698 std::vector<QualType> ResultRegQualTys;
2699 std::vector<llvm::Type *> ResultRegTypes;
2700 std::vector<llvm::Type *> ResultTruncRegTypes;
2702 llvm::BitVector ResultTypeRequiresCast;
2705 std::vector<llvm::Value *> InOutArgs;
2706 std::vector<llvm::Type *> InOutArgTypes;
2707 std::vector<llvm::Type *> InOutArgElemTypes;
2710 llvm::BasicBlock *DefaultDest =
nullptr;
2713 std::vector<std::optional<std::pair<unsigned, unsigned>>> ResultBounds;
2724 bool ReadOnly =
true;
2725 bool ReadNone =
true;
2727 bool GetOutputAndInputConstraints();
2728 void HandleOutputConstraints();
2729 void HandleMSStyleAsmBlob();
2730 void HandleInputConstraints();
2731 bool HandleLabels();
2732 bool HandleClobbers();
2733 void UpdateAsmCallInst(llvm::CallBase &
Result,
bool HasSideEffect,
2734 bool HasUnwindClobber,
bool NoMerge,
bool NoConvergent,
2735 std::vector<llvm::Value *> &RegResults);
2738 void EmitHipStdParUnsupportedAsm() {
2739 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2742 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2743 Asm = GCCAsm->getAsmString();
2745 auto &Ctx = getLLVMContext();
2746 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2747 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2748 {StrTy->getType()},
false);
2749 auto UBF = CGM.getModule().getOrInsertFunction(Name, FnTy);
2751 Builder.CreateCall(UBF, {StrTy});
2754 ASTContext &getContext() {
return CGF.getContext(); }
2755 llvm::LLVMContext &getLLVMContext() {
return CGF.getLLVMContext(); }
2756 const TargetInfo &getTarget()
const {
return CGF.getTarget(); }
2757 const LangOptions &getLangOpts()
const {
return CGF.getLangOpts(); }
2759 return CGM.getTargetCodeGenInfo();
2764 : CGF(CGF), CGM(CGF.CGM), S(S), Builder(CGF.Builder),
2765 AsmString(S.generateAsmString(CGF.getContext())) {}
2782 if (!GetOutputAndInputConstraints())
2783 return EmitHipStdParUnsupportedAsm();
2786 HandleOutputConstraints();
2790 HandleMSStyleAsmBlob();
2793 HandleInputConstraints();
2796 bool IsGCCAsmGoto = HandleLabels();
2799 bool HasUnwindClobber = HandleClobbers();
2800 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
2801 "unwind clobber can't be used with asm goto");
2804 std::string_view MachineClobbers = getTarget().getClobbers();
2805 if (!MachineClobbers.empty()) {
2806 if (!Constraints.empty())
2808 Constraints += MachineClobbers;
2811 llvm::Type *ResultType;
2812 if (ResultRegTypes.empty())
2813 ResultType = CGF.VoidTy;
2814 else if (ResultRegTypes.size() == 1)
2815 ResultType = ResultRegTypes[0];
2817 ResultType = llvm::StructType::get(getLLVMContext(), ResultRegTypes);
2819 llvm::FunctionType *FTy =
2820 llvm::FunctionType::get(ResultType, ArgTypes,
false);
2822 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
2824 llvm::InlineAsm::AsmDialect GnuAsmDialect =
2826 ? llvm::InlineAsm::AD_ATT
2827 : llvm::InlineAsm::AD_Intel;
2828 llvm::InlineAsm::AsmDialect AsmDialect =
2831 llvm::InlineAsm *IA = llvm::InlineAsm::get(
2832 FTy, AsmString, Constraints, HasSideEffect,
2833 false, AsmDialect, HasUnwindClobber);
2834 std::vector<llvm::Value *> RegResults;
2835 llvm::CallBrInst *CBR;
2836 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
2840 CBR = Builder.CreateCallBr(IA, DefaultDest, IndirectDests, Args);
2841 CGF.EmitBlock(DefaultDest);
2842 UpdateAsmCallInst(*CBR, HasSideEffect,
2843 false, CGF.InNoMergeAttributedStmt,
2844 CGF.InNoConvergentAttributedStmt, RegResults);
2849 if (!RegResults.empty()) {
2851 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
2852 llvm::Twine SynthName = Dest->getName() +
".split";
2853 llvm::BasicBlock *SynthBB = CGF.createBasicBlock(SynthName);
2854 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
2855 Builder.SetInsertPoint(SynthBB);
2857 if (ResultRegTypes.size() == 1) {
2858 CBRRegResults[SynthBB].push_back(CBR);
2860 for (
unsigned J = 0, E = ResultRegTypes.size(); J != E; ++J) {
2861 llvm::Value *Tmp = Builder.CreateExtractValue(CBR, J,
"asmresult");
2862 CBRRegResults[SynthBB].push_back(Tmp);
2866 CGF.EmitBranch(Dest);
2867 CGF.EmitBlock(SynthBB);
2868 CBR->setIndirectDest(I++, SynthBB);
2871 }
else if (HasUnwindClobber) {
2872 llvm::CallBase *
Result = CGF.EmitCallOrInvoke(IA, Args,
"");
2873 UpdateAsmCallInst(*
Result, HasSideEffect,
2874 true, CGF.InNoMergeAttributedStmt,
2875 CGF.InNoConvergentAttributedStmt, RegResults);
2878 Builder.CreateCall(IA, Args, CGF.getBundlesForFunclet(IA));
2879 UpdateAsmCallInst(*
Result, HasSideEffect,
2880 false, CGF.InNoMergeAttributedStmt,
2881 CGF.InNoConvergentAttributedStmt, RegResults);
2884 EmitAsmStores(RegResults);
2889 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
2890 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
2891 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
2892 Builder.SetInsertPoint(Succ, --(Succ->end()));
2893 EmitAsmStores(CBRRegResults[Succ]);
2901bool AsmConstraintsInfo::GetOutputAndInputConstraints() {
2902 bool IsValidTargetAsm =
true;
2903 bool IsHipStdPar = getLangOpts().HIPStdPar && getLangOpts().CUDAIsDevice;
2904 for (
unsigned I = 0, E = S.getNumOutputs(); I != E && IsValidTargetAsm; I++) {
2906 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2907 Name = GAS->getOutputName(I);
2911 bool IsValid = getTarget().validateOutputConstraint(Info);
2912 if (IsHipStdPar && !IsValid)
2913 IsValidTargetAsm =
false;
2915 assert(IsValid &&
"Failed to parse output constraint");
2917 OutputConstraintInfos.push_back(Info);
2920 for (
unsigned I = 0, E = S.getNumInputs(); I != E && IsValidTargetAsm; I++) {
2922 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2923 Name = GAS->getInputName(I);
2928 getTarget().validateInputConstraint(OutputConstraintInfos, Info);
2929 if (IsHipStdPar && !IsValid)
2930 IsValidTargetAsm =
false;
2932 assert(IsValid &&
"Failed to parse input constraint");
2934 InputConstraintInfos.push_back(Info);
2937 return IsValidTargetAsm;
2944void AsmConstraintsInfo::HandleOutputConstraints() {
2946 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2948 for (
unsigned I = 0, E = S.getNumOutputs(); I != E; I++) {
2949 TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[I];
2952 std::string OutputConstraint(S.getOutputConstraint(I));
2953 OutputConstraint = getTarget().simplifyConstraint(
2954 StringRef(OutputConstraint).substr(1), &OutputConstraintInfos);
2956 const Expr *OutExpr = S.getOutputExpr(I);
2960 OutputConstraint = S.addVariableConstraints(
2961 OutputConstraint, *OutExpr, getTarget(), Info.
earlyClobber(),
2962 [&](
const Stmt *UnspStmt, StringRef Msg) {
2963 CGM.ErrorUnsupported(UnspStmt, Msg);
2968 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2969 CGM.Error(S.getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2971 OutputConstraints.push_back(OutputConstraint);
2973 if (!Constraints.empty())
2978 QualType QTy = OutExpr->
getType();
2979 const bool IsScalarOrAggregate =
2984 Constraints +=
"=" + OutputConstraint;
2985 ResultRegQualTys.push_back(QTy);
2986 ResultRegDests.push_back(Dest);
2991 const bool RequiresCast =
2993 (getTargetHooks().isScalarizableAsmOperand(CGF, Ty) ||
2994 Ty->isAggregateType());
2996 ResultTruncRegTypes.push_back(Ty);
2997 ResultTypeRequiresCast.push_back(RequiresCast);
3000 if (
unsigned Size = getContext().getTypeSize(QTy))
3001 Ty = llvm::IntegerType::get(getLLVMContext(), Size);
3003 CGM.Error(OutExpr->
getExprLoc(),
"output size should not be zero");
3006 ResultRegTypes.push_back(Ty);
3013 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
3014 TargetInfo::ConstraintInfo &Input = InputConstraintInfos[InputNo];
3018 assert(InputNo != S.getNumInputs() &&
"Didn't find matching input!");
3020 QualType
InputTy = S.getInputExpr(InputNo)->getType();
3021 QualType OutputType = OutExpr->
getType();
3023 uint64_t InputSize = getContext().getTypeSize(InputTy);
3024 if (getContext().getTypeSize(OutputType) < InputSize)
3029 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
3030 CGF, OutputConstraint, ResultRegTypes.back()))
3031 ResultRegTypes.back() = AdjTy;
3033 CGM.getDiags().Report(S.getAsmLoc(),
3034 diag::err_asm_invalid_type_in_input)
3035 << OutExpr->
getType() << OutputConstraint;
3038 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
3039 CGF.LargestVectorWidth =
3040 std::max((uint64_t)CGF.LargestVectorWidth,
3041 VT->getPrimitiveSizeInBits().getKnownMinValue());
3043 Address DestAddr = Dest.getAddress();
3054 ArgTypes.push_back(DestAddr.
getType());
3058 Constraints +=
"=*" + OutputConstraint;
3066 InOutConstraints +=
',';
3068 const Expr *InputExpr = S.getOutputExpr(I);
3070 llvm::Type *ArgElemType;
3071 std::tie(Arg, ArgElemType) =
3072 CGF.EmitAsmInputLValue(Info, Dest, InputExpr->
getType(),
3075 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
3076 CGF, OutputConstraint, Arg->getType()))
3077 Arg = Builder.CreateBitCast(Arg, AdjTy);
3080 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3081 CGF.LargestVectorWidth =
3082 std::max((uint64_t)CGF.LargestVectorWidth,
3083 VT->getPrimitiveSizeInBits().getKnownMinValue());
3087 InOutConstraints += llvm::utostr(I);
3089 InOutConstraints += OutputConstraint;
3091 InOutArgTypes.push_back(Arg->getType());
3092 InOutArgElemTypes.push_back(ArgElemType);
3093 InOutArgs.push_back(Arg);
3100void AsmConstraintsInfo::HandleMSStyleAsmBlob() {
3111 CGM.getTargetCodeGenInfo().addReturnRegisterOutputs(
3112 CGF, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
3113 ResultRegDests, AsmString, S.getNumOutputs());
3120void AsmConstraintsInfo::HandleInputConstraints() {
3121 ASTContext &Ctx = getContext();
3123 for (
unsigned I = 0, E = S.getNumInputs(); I != E; I++) {
3124 TargetInfo::ConstraintInfo &Info = InputConstraintInfos[I];
3125 const Expr *InputExpr = S.getInputExpr(I);
3130 if (!Constraints.empty())
3134 std::string InputConstraint(S.getInputConstraint(I));
3136 getTarget().simplifyConstraint(InputConstraint, &OutputConstraintInfos);
3138 InputConstraint = S.addVariableConstraints(
3141 [&](
const Stmt *UnspStmt, std::string_view Msg) {
3142 CGM.ErrorUnsupported(UnspStmt, Msg);
3145 std::string ReplaceConstraint(InputConstraint);
3147 llvm::Type *ArgElemType;
3148 std::tie(Arg, ArgElemType) = CGF.EmitAsmInput(Info, InputExpr, Constraints);
3157 QualType OutputType = S.getOutputExpr(Output)->getType();
3163 Arg = Builder.CreatePtrToInt(Arg, CGF.
IntPtrTy);
3165 llvm::Type *OutputTy = CGF.
ConvertType(OutputType);
3167 Arg = Builder.CreateZExt(Arg, OutputTy);
3169 Arg = Builder.CreateZExt(Arg, CGF.
IntPtrTy);
3170 else if (OutputTy->isFloatingPointTy())
3171 Arg = Builder.CreateFPExt(Arg, OutputTy);
3175 ReplaceConstraint = OutputConstraints[Output];
3178 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
3179 CGF, ReplaceConstraint, Arg->getType()))
3180 Arg = Builder.CreateBitCast(Arg, AdjTy);
3182 CGM.getDiags().Report(S.getAsmLoc(), diag::err_asm_invalid_type_in_input)
3183 << InputExpr->
getType() << InputConstraint;
3186 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3187 CGF.LargestVectorWidth =
3188 std::max((uint64_t)CGF.LargestVectorWidth,
3189 VT->getPrimitiveSizeInBits().getKnownMinValue());
3191 ArgTypes.push_back(Arg->getType());
3192 ArgElemTypes.push_back(ArgElemType);
3193 Args.push_back(Arg);
3195 Constraints += InputConstraint;
3199 for (
unsigned I = 0, E = InOutArgs.size(); I != E; I++) {
3200 ArgTypes.push_back(InOutArgTypes[I]);
3201 ArgElemTypes.push_back(InOutArgElemTypes[I]);
3202 Args.push_back(InOutArgs[I]);
3205 Constraints += InOutConstraints;
3211bool AsmConstraintsInfo::HandleLabels() {
3212 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S); GS && GS->isAsmGoto()) {
3213 for (
const auto *E : GS->labels()) {
3215 IndirectDests.push_back(Dest.
getBlock());
3217 if (!Constraints.empty())
3220 Constraints +=
"!i";
3234bool AsmConstraintsInfo::HandleClobbers() {
3235 bool HasUnwindClobber =
false;
3236 for (
unsigned I = 0, E = S.getNumClobbers(); I != E; I++) {
3237 std::string Clobber = S.getClobber(I);
3239 if (Clobber ==
"unwind") {
3240 HasUnwindClobber =
true;
3244 if (Clobber ==
"memory") {
3247 }
else if (Clobber !=
"cc") {
3248 Clobber = getTarget().getNormalizedGCCRegisterName(Clobber);
3249 if (CGM.getCodeGenOpts().StackClashProtector &&
3250 getTarget().isSPRegName(Clobber)) {
3251 CGM.getDiags().Report(S.getAsmLoc(),
3252 diag::warn_stack_clash_protection_inline_asm);
3257 if (Clobber ==
"eax" || Clobber ==
"edx") {
3258 if (Constraints.find(
"=&A") != std::string::npos)
3261 std::string::size_type position1 =
3262 Constraints.find(
"={" + Clobber +
"}");
3263 if (position1 != std::string::npos) {
3264 Constraints.insert(position1 + 1,
"&");
3268 std::string::size_type position2 = Constraints.find(
"=A");
3269 if (position2 != std::string::npos) {
3270 Constraints.insert(position2 + 1,
"&");
3276 if (!Constraints.empty())
3279 Constraints +=
"~{" + Clobber +
'}';
3282 return HasUnwindClobber;
3285void AsmConstraintsInfo::UpdateAsmCallInst(
3286 llvm::CallBase &
Result,
bool HasSideEffect,
bool HasUnwindClobber,
3287 bool NoMerge,
bool NoConvergent, std::vector<llvm::Value *> &RegResults) {
3288 if (!HasUnwindClobber)
3289 Result.addFnAttr(llvm::Attribute::NoUnwind);
3292 Result.addFnAttr(llvm::Attribute::NoMerge);
3295 if (!HasSideEffect) {
3297 Result.setDoesNotAccessMemory();
3299 Result.setOnlyReadsMemory();
3303 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
3305 auto Attr = llvm::Attribute::get(
3306 getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
3307 Result.addParamAttr(Pair.index(), Attr);
3313 const StringLiteral *SL;
3314 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S);
3316 (SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))) {
3321 llvm::Constant *Loc =
3322 llvm::ConstantInt::get(CGF.
Int64Ty, S.getAsmLoc().getRawEncoding());
3323 Result.setMetadata(
"srcloc",
3324 llvm::MDNode::get(getLLVMContext(),
3325 llvm::ConstantAsMetadata::get(Loc)));
3331 if (!NoConvergent && getLangOpts().assumeFunctionsAreConvergent())
3336 Result.addFnAttr(llvm::Attribute::Convergent);
3339 if (ResultRegTypes.size() == 1) {
3340 RegResults.push_back(&
Result);
3342 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
3343 llvm::Value *Tmp = Builder.CreateExtractValue(&
Result, i,
"asmresult");
3344 RegResults.push_back(Tmp);
3349void AsmConstraintsInfo::EmitAsmStores(
3350 const llvm::ArrayRef<llvm::Value *> RegResults) {
3351 llvm::LLVMContext &CTX = getLLVMContext();
3353 assert(RegResults.size() == ResultRegTypes.size());
3354 assert(RegResults.size() == ResultTruncRegTypes.size());
3355 assert(RegResults.size() == ResultRegDests.size());
3359 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
3360 assert(ResultBounds.size() <= ResultRegDests.size());
3362 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
3363 llvm::Value *Tmp = RegResults[i];
3364 llvm::Type *TruncTy = ResultTruncRegTypes[i];
3366 if (i < ResultBounds.size() && ResultBounds[i].has_value()) {
3367 const auto [LowerBound, UpperBound] = ResultBounds[i].value();
3370 assert(LowerBound == 0 &&
"Output operand lower bound is not zero.");
3372 llvm::Constant *UpperBoundConst =
3373 llvm::ConstantInt::get(Tmp->getType(), UpperBound);
3374 llvm::Value *IsBooleanValue =
3375 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, UpperBoundConst);
3376 llvm::Function *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume);
3378 Builder.CreateCall(FnAssume, IsBooleanValue);
3383 if (ResultRegTypes[i] != TruncTy) {
3386 if (TruncTy->isFloatingPointTy())
3387 Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
3388 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
3389 uint64_t ResSize = CGM.getDataLayout().getTypeSizeInBits(TruncTy);
3390 Tmp = Builder.CreateTrunc(
3391 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
3392 Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
3393 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
3395 CGM.getDataLayout().getTypeSizeInBits(Tmp->getType());
3396 Tmp = Builder.CreatePtrToInt(
3397 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
3398 Tmp = Builder.CreateTrunc(Tmp, TruncTy);
3399 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
3400 Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
3401 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
3402 Tmp = Builder.CreateBitCast(Tmp, TruncTy);
3407 LValue Dest = ResultRegDests[i];
3411 if (i < ResultTypeRequiresCast.size() && ResultTypeRequiresCast[i]) {
3412 unsigned Size = getContext().getTypeSize(ResultRegQualTys[i]);
3413 Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
3415 if (getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) {
3416 llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
3421 QualType Ty = getContext().getIntTypeForBitwidth(Size,
false);
3423 const Expr *OutExpr = S.getOutputExpr(i);
3425 diag::err_store_value_to_reg);
3447 I != E; ++I, ++CurField) {
3449 if (CurField->hasCapturedVLAType()) {
3466 CodeGenFunction CGF(
CGM,
true);
3486 "CapturedStmtInfo should be set when generating the captured function");
3490 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3499 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Args);
3500 llvm::FunctionType *FuncLLVMTy =
CGM.getTypes().GetFunctionType(FuncInfo);
3503 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3505 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
3506 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
3507 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3509 F->addFnAttr(llvm::Attribute::NoUnwind);
3521 for (
auto *FD : RD->
fields()) {
3522 if (FD->hasCapturedVLAType()) {
3526 auto VAT = FD->getCapturedVLAType();
3527 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3538 PGO->assignRegionCounters(
GlobalDecl(CD), F);
3548 for (
auto &I : *BB) {
3549 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3556CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3557 llvm::ConvergenceControlInst *ParentToken = ConvergenceTokenStack.back();
3558 assert(ParentToken);
3560 llvm::Value *bundleArgs[] = {ParentToken};
3561 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3562 auto *Output = llvm::CallBase::addOperandBundle(
3563 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3564 Input->replaceAllUsesWith(Output);
3565 Input->eraseFromParent();
3569llvm::ConvergenceControlInst *
3572 assert(ParentToken);
3573 return llvm::ConvergenceControlInst::CreateLoop(*BB, ParentToken);
3576llvm::ConvergenceControlInst *
3577CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3578 llvm::BasicBlock *BB = &F->getEntryBlock();
3586 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)
static bool hasEmptyLoopBody(const LoopStmt &S)
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...
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 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.
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()
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
ContinueStmt - This represents a continue.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
DeferStmt - This represents a deferred statement.
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...
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...
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.
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)
@ None
The alignment was not explicit in code.
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
void setScopeDepth(EHScopeStack::stable_iterator depth)
llvm::BasicBlock * getBlock() const
EHScopeStack::stable_iterator getScopeDepth() const
llvm::IntegerType * Int64Ty
llvm::IntegerType * IntPtrTy
llvm::PointerType * Int8PtrTy
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool hasMatchingInput() const
Return true if this output operand has a matching (tied) input operand.
unsigned getTiedOperand() const
bool allowsMemory() const
std::optional< std::pair< unsigned, unsigned > > getOutputOperandBounds() const
bool requiresImmediateConstant() const
bool hasTiedOperand() const
Return true if this input operand is a matching constraint that ties it to an output operand.
bool allowsRegister() const