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::OMPFuseDirectiveClass:
247 case Stmt::OMPForDirectiveClass:
250 case Stmt::OMPForSimdDirectiveClass:
253 case Stmt::OMPSectionsDirectiveClass:
256 case Stmt::OMPSectionDirectiveClass:
259 case Stmt::OMPSingleDirectiveClass:
262 case Stmt::OMPMasterDirectiveClass:
265 case Stmt::OMPCriticalDirectiveClass:
268 case Stmt::OMPParallelForDirectiveClass:
271 case Stmt::OMPParallelForSimdDirectiveClass:
274 case Stmt::OMPParallelMasterDirectiveClass:
277 case Stmt::OMPParallelSectionsDirectiveClass:
280 case Stmt::OMPTaskDirectiveClass:
283 case Stmt::OMPTaskyieldDirectiveClass:
286 case Stmt::OMPErrorDirectiveClass:
289 case Stmt::OMPBarrierDirectiveClass:
292 case Stmt::OMPTaskwaitDirectiveClass:
295 case Stmt::OMPTaskgroupDirectiveClass:
298 case Stmt::OMPFlushDirectiveClass:
301 case Stmt::OMPDepobjDirectiveClass:
304 case Stmt::OMPScanDirectiveClass:
307 case Stmt::OMPOrderedDirectiveClass:
310 case Stmt::OMPAtomicDirectiveClass:
313 case Stmt::OMPTargetDirectiveClass:
316 case Stmt::OMPTeamsDirectiveClass:
319 case Stmt::OMPCancellationPointDirectiveClass:
322 case Stmt::OMPCancelDirectiveClass:
325 case Stmt::OMPTargetDataDirectiveClass:
328 case Stmt::OMPTargetEnterDataDirectiveClass:
331 case Stmt::OMPTargetExitDataDirectiveClass:
334 case Stmt::OMPTargetParallelDirectiveClass:
337 case Stmt::OMPTargetParallelForDirectiveClass:
340 case Stmt::OMPTaskLoopDirectiveClass:
343 case Stmt::OMPTaskLoopSimdDirectiveClass:
346 case Stmt::OMPMasterTaskLoopDirectiveClass:
349 case Stmt::OMPMaskedTaskLoopDirectiveClass:
352 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
356 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
360 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
364 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
368 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
372 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
376 case Stmt::OMPDistributeDirectiveClass:
379 case Stmt::OMPTargetUpdateDirectiveClass:
382 case Stmt::OMPDistributeParallelForDirectiveClass:
386 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
390 case Stmt::OMPDistributeSimdDirectiveClass:
393 case Stmt::OMPTargetParallelForSimdDirectiveClass:
397 case Stmt::OMPTargetSimdDirectiveClass:
400 case Stmt::OMPTeamsDistributeDirectiveClass:
403 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
407 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
411 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
415 case Stmt::OMPTargetTeamsDirectiveClass:
418 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
422 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
426 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
430 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
434 case Stmt::OMPInteropDirectiveClass:
437 case Stmt::OMPDispatchDirectiveClass:
438 CGM.ErrorUnsupported(S,
"OpenMP dispatch directive");
440 case Stmt::OMPScopeDirectiveClass:
443 case Stmt::OMPMaskedDirectiveClass:
446 case Stmt::OMPGenericLoopDirectiveClass:
449 case Stmt::OMPTeamsGenericLoopDirectiveClass:
452 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
456 case Stmt::OMPParallelGenericLoopDirectiveClass:
460 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
464 case Stmt::OMPParallelMaskedDirectiveClass:
467 case Stmt::OMPAssumeDirectiveClass:
470 case Stmt::OpenACCComputeConstructClass:
473 case Stmt::OpenACCLoopConstructClass:
476 case Stmt::OpenACCCombinedConstructClass:
479 case Stmt::OpenACCDataConstructClass:
482 case Stmt::OpenACCEnterDataConstructClass:
485 case Stmt::OpenACCExitDataConstructClass:
488 case Stmt::OpenACCHostDataConstructClass:
491 case Stmt::OpenACCWaitConstructClass:
494 case Stmt::OpenACCInitConstructClass:
497 case Stmt::OpenACCShutdownConstructClass:
500 case Stmt::OpenACCSetConstructClass:
503 case Stmt::OpenACCUpdateConstructClass:
506 case Stmt::OpenACCAtomicConstructClass:
509 case Stmt::OpenACCCacheConstructClass:
520 case Stmt::NullStmtClass:
522 case Stmt::CompoundStmtClass:
525 case Stmt::DeclStmtClass:
528 case Stmt::LabelStmtClass:
531 case Stmt::AttributedStmtClass:
534 case Stmt::GotoStmtClass:
537 case Stmt::BreakStmtClass:
540 case Stmt::ContinueStmtClass:
543 case Stmt::DefaultStmtClass:
546 case Stmt::CaseStmtClass:
549 case Stmt::DeferStmtClass:
552 case Stmt::SEHLeaveStmtClass:
555 case Stmt::SYCLKernelCallStmtClass:
568 "LLVM IR generation of compound statement ('{}')");
595 if (
const auto *LS = dyn_cast<LabelStmt>(LastStmt)) {
597 LastStmt = LS->getSubStmt();
598 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(LastStmt)) {
601 LastStmt = AS->getSubStmt();
603 llvm_unreachable(
"unknown value statement");
627 llvm::UncondBrInst *BI = dyn_cast<llvm::UncondBrInst>(BB->getTerminator());
640 if (BI->getIterator() != BB->begin())
643 BB->replaceAllUsesWith(BI->getSuccessor());
644 BI->eraseFromParent();
645 BB->eraseFromParent();
649 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
654 if (IsFinished && BB->use_empty()) {
661 if (CurBB && CurBB->getParent())
662 CurFn->insert(std::next(CurBB->getIterator()), BB);
672 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
674 if (!CurBB || CurBB->hasTerminator()) {
686 bool inserted =
false;
687 for (llvm::User *u : block->users()) {
688 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
689 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
704 if (Dest.
isValid())
return Dest;
717 if (
EHStack.hasNormalCleanups() && CurLexicalScope)
718 CurLexicalScope->addLabel(D);
739 if (
CGM.getCodeGenOpts().hasReducedDebugInfo()) {
751 assert(!Labels.empty());
753 =
CGF.EHStack.getInnermostNormalCleanup();
757 assert(
CGF.LabelMap.count(Label));
766 ParentScope->Labels.append(Labels.begin(), Labels.end());
782 bool nomerge =
false;
783 bool noinline =
false;
784 bool alwaysinline =
false;
785 bool noconvergent =
false;
786 HLSLControlFlowHintAttr::Spelling flattenOrBranch =
787 HLSLControlFlowHintAttr::SpellingNotCalculated;
789 const AtomicAttr *AA =
nullptr;
791 for (
const auto *A : S.
getAttrs()) {
792 switch (A->getKind()) {
801 case attr::AlwaysInline:
804 case attr::NoConvergent:
807 case attr::MustTail: {
812 case attr::CXXAssume: {
817 Builder.CreateAssumption(AssumptionVal);
823 case attr::HLSLControlFlowHint: {
860 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
870 if (CurBB && CurBB->hasTerminator())
911 const Stmt *Skipped = Else;
913 std::swap(Executed, Skipped);
925 PGO->markStmtMaybeUsed(Skipped);
936 llvm::BasicBlock *ElseBlock =
952 CGM.getCodeGenOpts().OptimizationLevel)
961 if (!
CGM.getCodeGenOpts().MCDCCoverage) {
968 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
999 }
else if (HasSkip) {
1010 bool HasEmptyBody) {
1011 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1021 bool CondIsConstInt =
1022 !ControllingExpression ||
1026 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
1027 Result.Val.getInt().getBoolValue());
1038 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1041 if (HasEmptyBody && CondIsTrue) {
1042 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1060 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1064 const Stmt *Body = S.getBody();
1067 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
1068 return Compound->body_empty();
1079 if (
CGM.shouldEmitConvergenceTokens())
1088 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopHeader));
1111 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1112 bool EmitBoolCondBranch = !
C || !
C->isOne();
1121 if (EmitBoolCondBranch) {
1122 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1125 llvm::MDNode *Weights =
1127 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1128 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1130 auto *I =
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1136 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1140 if (ExitBlock !=
LoopExit.getBlock()) {
1146 CGM.getDiags().Report(A->getLocation(),
1147 diag::warn_attribute_has_no_effect_on_infinite_loop)
1148 << A << A->getRange();
1149 CGM.getDiags().Report(
1151 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1164 BreakContinueStack.pop_back();
1180 if (!EmitBoolCondBranch) {
1182 PGO->markStmtAsUsed(
true, &S);
1185 if (
CGM.shouldEmitConvergenceTokens())
1197 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopCond));
1204 if (
CGM.shouldEmitConvergenceTokens())
1222 BreakContinueStack.pop_back();
1226 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1227 bool EmitBoolCondBranch = !
C || !
C->isZero();
1230 LoopStack.push(LoopBody,
CGM.getContext(),
CGM.getCodeGenOpts(), DoAttrs,
1239 if (EmitBoolCondBranch) {
1241 auto *I =
Builder.CreateCondBr(
1242 BoolCondVal, LoopBody, LoopFalse,
1243 createProfileWeightsForLoop(S.
getCond(), BackedgeCount));
1250 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1257 if (LoopFalse !=
LoopExit.getBlock()) {
1267 if (!EmitBoolCondBranch)
1270 if (
CGM.shouldEmitConvergenceTokens())
1278 std::optional<LexicalScope> ForScope;
1290 llvm::BasicBlock *CondBlock = CondDest.
getBlock();
1293 if (
CGM.shouldEmitConvergenceTokens())
1297 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1314 Continue = CondDest;
1317 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1328 BreakContinueStack.back().ContinueBlock = Continue;
1331 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1334 if (
hasSkipCounter(&S) || (ForScope && ForScope->requiresCleanups()))
1346 llvm::MDNode *Weights =
1348 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1349 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1352 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1357 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1361 if (ExitBlock !=
LoopExit.getBlock()) {
1371 PGO->markStmtAsUsed(
true, &S);
1385 auto *FinalBodyBB =
Builder.GetInsertBlock();
1393 BreakContinueStack.pop_back();
1401 ForScope->ForceCleanup();
1408 if (
CGM.shouldEmitConvergenceTokens())
1438 if (
CGM.shouldEmitConvergenceTokens())
1442 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1448 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1458 llvm::MDNode *Weights =
1460 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1461 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1463 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1468 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1472 if (ExitBlock !=
LoopExit.getBlock()) {
1485 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1495 auto *FinalBodyBB =
Builder.GetInsertBlock();
1502 BreakContinueStack.pop_back();
1513 if (
CGM.shouldEmitConvergenceTokens())
1537 ContinueDest = ExpandExit;
1541 LexicalScope ExpansionScope(*
this, Inst->getSourceRange());
1542 BreakContinueStack.push_back(BreakContinue(S, ExpandExit, ContinueDest));
1544 BreakContinueStack.pop_back();
1549void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1565struct SaveRetExprRAII {
1566 SaveRetExprRAII(
const Expr *RetExpr, CodeGenFunction &CGF)
1567 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1570 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1571 const Expr *OldRetExpr;
1572 CodeGenFunction &CGF;
1580 if (calleeQualType->isFunctionPointerType() ||
1581 calleeQualType->isFunctionReferenceType() ||
1582 calleeQualType->isBlockPointerType() ||
1583 calleeQualType->isMemberFunctionPointerType()) {
1585 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1587 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1588 if (
auto methodDecl = CMCE->getMethodDecl()) {
1605 if (requiresReturnValueCheck()) {
1608 new llvm::GlobalVariable(
CGM.getModule(), SLoc->getType(),
false,
1609 llvm::GlobalVariable::PrivateLinkage, SLoc);
1610 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1611 CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
1612 assert(ReturnLocation.isValid() &&
"No valid return location");
1613 Builder.CreateStore(SLocPtr, ReturnLocation);
1619 Builder.ClearInsertionPoint();
1633 SaveRetExprRAII SaveRetExpr(RV, *
this);
1636 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1637 RV = EWC->getSubExpr();
1641 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1644 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1657 !
CGM.getOpenMPRuntime()
1676 }
else if (
FnRetTy->isReferenceType()) {
1712 ++NumSimpleReturnExprs;
1724 for (
const auto *I : S.
decls())
1729 ->
const BreakContinue * {
1730 if (!S.hasLabelTarget())
1731 return &BreakContinueStack.back();
1733 const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
1734 assert(LoopOrSwitch &&
"break/continue target not set?");
1735 for (
const BreakContinue &BC : llvm::reverse(BreakContinueStack))
1736 if (BC.LoopOrSwitch == LoopOrSwitch)
1739 llvm_unreachable(
"break/continue target not found");
1743 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1756 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1773 assert(S.
getRHS() &&
"Expected RHS value in CaseStmt");
1786 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1790 llvm::APInt Range = RHS - LHS;
1792 if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
1795 unsigned NCases = Range.getZExtValue() + 1;
1800 uint64_t Weight = Total / NCases, Rem = Total % NCases;
1801 for (
unsigned I = 0; I != NCases; ++I) {
1803 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1804 else if (SwitchLikelihood)
1805 SwitchLikelihood->push_back(LH);
1809 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1817 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1822 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1826 Builder.SetInsertPoint(CaseRangeBlock);
1830 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1834 llvm::MDNode *Weights =
nullptr;
1835 if (SwitchWeights) {
1837 uint64_t DefaultCount = (*SwitchWeights)[0];
1838 Weights = createProfileWeights(ThisCount, DefaultCount);
1843 (*SwitchWeights)[0] += ThisCount;
1844 }
else if (SwitchLikelihood)
1845 Cond = emitCondLikelihoodViaExpectIntrinsic(
Cond, LH);
1847 Builder.CreateCondBr(
Cond, CaseDest, FalseDest, Weights);
1851 Builder.SetInsertPoint(RestoreBB);
1853 Builder.ClearInsertionPoint();
1874 llvm::ConstantInt *CaseVal =
1879 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.
getLHS()))
1880 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1882 CE = dyn_cast<ConstantExpr>(S.
getLHS());
1884 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1886 if (
CGM.getCodeGenOpts().hasReducedDebugInfo())
1887 Dbg->EmitGlobalVariable(DE->getDecl(),
1888 APValue(llvm::APSInt(CaseVal->getValue())));
1891 if (SwitchLikelihood)
1897 if (!
CGM.getCodeGenOpts().hasProfileClangInstr() &&
1898 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1906 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1910 if (
Builder.GetInsertBlock()) {
1912 Builder.ClearInsertionPoint();
1922 SwitchInsn->addCase(CaseVal, CaseDest);
1941 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1943 llvm::ConstantInt *CaseVal =
1948 if (
CGM.getCodeGenOpts().hasProfileClangInstr()) {
1954 if (SwitchLikelihood)
1957 SwitchInsn->addCase(CaseVal, CaseDest);
1958 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1981 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1982 assert(DefaultBlock->empty() &&
1983 "EmitDefaultStmt: Default block already defined?");
1985 if (SwitchLikelihood)
1994struct EmitDeferredStatement final : EHScopeStack::Cleanup {
2054 llvm::Value *SavedCleanupDest =
nullptr;
2108 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
2127 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
2131 bool StartedInLiveCode = FoundCase;
2132 unsigned StartSize = ResultStmts.size();
2139 bool HadSkippedDecl =
false;
2143 for (; Case && I != E; ++I) {
2159 for (++I; I != E; ++I)
2169 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
2184 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
2189 bool AnyDecls =
false;
2190 for (; I != E; ++I) {
2203 for (++I; I != E; ++I)
2220 ResultStmts.resize(StartSize);
2221 ResultStmts.push_back(S);
2245 ResultStmts.push_back(S);
2254 const llvm::APSInt &ConstantCondValue,
2266 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2274 if (CS->
getRHS())
return false;
2299 bool FoundCase =
false;
2306static std::optional<SmallVector<uint64_t, 16>>
2309 if (Likelihoods.size() <= 1)
2310 return std::nullopt;
2312 uint64_t NumUnlikely = 0;
2313 uint64_t NumNone = 0;
2314 uint64_t NumLikely = 0;
2315 for (
const auto LH : Likelihoods) {
2330 if (NumUnlikely == 0 && NumLikely == 0)
2331 return std::nullopt;
2339 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2340 const uint64_t
None = Likely / (NumNone + 1);
2341 const uint64_t Unlikely = 0;
2344 Result.reserve(Likelihoods.size());
2345 for (
const auto LH : Likelihoods) {
2348 Result.push_back(Unlikely);
2354 Result.push_back(Likely);
2364 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2367 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2371 llvm::APSInt ConstantCondValue;
2392 SwitchInsn =
nullptr;
2399 PGO->markStmtMaybeUsed(S.
getBody());
2403 SwitchInsn = SavedSwitchInsn;
2431 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2435 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2436 llvm::ConstantInt *BranchHintConstant =
2438 HLSLControlFlowHintAttr::Spelling::Microsoft_branch
2439 ? llvm::ConstantInt::get(
CGM.Int32Ty, 1)
2440 : llvm::ConstantInt::get(
CGM.Int32Ty, 2);
2441 llvm::Metadata *Vals[] = {MDHelper.createString(
"hlsl.controlflow.hint"),
2442 MDHelper.createConstant(BranchHintConstant)};
2443 SwitchInsn->setMetadata(
"hlsl.controlflow.hint",
2444 llvm::MDNode::get(
CGM.getLLVMContext(), Vals));
2447 if (PGO->haveRegionCounts()) {
2449 uint64_t DefaultCount = 0;
2450 unsigned NumCases = 0;
2459 SwitchWeights->reserve(NumCases);
2462 SwitchWeights->push_back(DefaultCount);
2463 }
else if (
CGM.getCodeGenOpts().OptimizationLevel) {
2469 CaseRangeBlock = DefaultBlock;
2472 Builder.ClearInsertionPoint();
2477 if (!BreakContinueStack.empty())
2478 OuterContinue = BreakContinueStack.back().ContinueBlock;
2480 BreakContinueStack.push_back(BreakContinue(S, SwitchExit, OuterContinue));
2485 BreakContinueStack.pop_back();
2489 SwitchInsn->setDefaultDest(CaseRangeBlock);
2492 if (!DefaultBlock->getParent()) {
2500 DefaultBlock->replaceAllUsesWith(SwitchExit.
getBlock());
2501 delete DefaultBlock;
2515 Builder.CreateBr(SwitchInsn->getDefaultDest());
2516 SwitchInsn->setDefaultDest(ImplicitDefaultBlock);
2527 if (
Call &&
CGM.getCodeGenOpts().OptimizationLevel != 0) {
2528 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2529 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2531 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2532 MDHelper.createUnpredictable());
2536 if (SwitchWeights) {
2537 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2538 "switch weights do not match switch cases");
2540 if (SwitchWeights->size() > 1)
2541 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2542 createProfileWeights(*SwitchWeights));
2543 delete SwitchWeights;
2544 }
else if (SwitchLikelihood) {
2545 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2546 "switch likelihoods do not match switch cases");
2547 std::optional<SmallVector<uint64_t, 16>> LHW =
2550 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2551 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2552 createProfileWeights(*LHW));
2554 delete SwitchLikelihood;
2556 SwitchInsn = SavedSwitchInsn;
2557 SwitchWeights = SavedSwitchWeights;
2558 SwitchLikelihood = SavedSwitchLikelihood;
2559 CaseRangeBlock = SavedCRBlock;
2562std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2571 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2581 ConstraintStr +=
'*';
2584std::pair<llvm::Value *, llvm::Type *>
2585CodeGenFunction::EmitAsmInput(
const TargetInfo::ConstraintInfo &Info,
2586 const Expr *InputExpr,
2587 std::string &ConstraintStr) {
2592 Expr::EvalResult EVResult;
2595 llvm::APSInt IntResult;
2598 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2610 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2614 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2626 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2629 if (!StrVal.empty()) {
2632 unsigned StartToken = 0;
2633 unsigned ByteOffset = 0;
2637 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2638 if (StrVal[i] !=
'\n')
continue;
2640 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2641 Locs.push_back(llvm::ConstantAsMetadata::get(
2661 std::string AsmString;
2668 std::string Constraints;
2669 std::string InOutConstraints;
2672 std::vector<std::string> OutputConstraints;
2675 std::vector<llvm::Value *> Args;
2676 std::vector<llvm::Type *> ArgTypes;
2677 std::vector<llvm::Type *> ArgElemTypes;
2680 std::vector<LValue> ResultRegDests;
2681 std::vector<QualType> ResultRegQualTys;
2682 std::vector<llvm::Type *> ResultRegTypes;
2683 std::vector<llvm::Type *> ResultTruncRegTypes;
2685 llvm::BitVector ResultTypeRequiresCast;
2688 std::vector<llvm::Value *> InOutArgs;
2689 std::vector<llvm::Type *> InOutArgTypes;
2690 std::vector<llvm::Type *> InOutArgElemTypes;
2693 llvm::BasicBlock *DefaultDest =
nullptr;
2696 std::vector<std::optional<std::pair<unsigned, unsigned>>> ResultBounds;
2707 bool ReadOnly =
true;
2708 bool ReadNone =
true;
2710 bool GetOutputAndInputConstraints();
2711 void HandleOutputConstraints();
2712 void HandleMSStyleAsmBlob();
2713 void HandleInputConstraints();
2714 bool HandleLabels();
2715 bool HandleClobbers();
2716 void UpdateAsmCallInst(llvm::CallBase &
Result,
bool HasSideEffect,
2717 bool HasUnwindClobber,
bool NoMerge,
bool NoConvergent,
2718 std::vector<llvm::Value *> &RegResults);
2721 void EmitHipStdParUnsupportedAsm() {
2722 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2725 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2726 Asm = GCCAsm->getAsmString();
2728 auto &Ctx = getLLVMContext();
2729 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2730 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2731 {StrTy->getType()},
false);
2732 auto UBF = CGM.getModule().getOrInsertFunction(Name, FnTy);
2734 Builder.CreateCall(UBF, {StrTy});
2737 ASTContext &getContext() {
return CGF.getContext(); }
2738 llvm::LLVMContext &getLLVMContext() {
return CGF.getLLVMContext(); }
2739 const TargetInfo &getTarget()
const {
return CGF.getTarget(); }
2740 const LangOptions &getLangOpts()
const {
return CGF.getLangOpts(); }
2742 return CGM.getTargetCodeGenInfo();
2747 : CGF(CGF), CGM(CGF.CGM), S(S), Builder(CGF.Builder),
2748 AsmString(S.generateAsmString(CGF.getContext())) {}
2765 if (!GetOutputAndInputConstraints())
2766 return EmitHipStdParUnsupportedAsm();
2769 HandleOutputConstraints();
2773 HandleMSStyleAsmBlob();
2776 HandleInputConstraints();
2779 bool IsGCCAsmGoto = HandleLabels();
2782 bool HasUnwindClobber = HandleClobbers();
2783 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
2784 "unwind clobber can't be used with asm goto");
2787 std::string_view MachineClobbers = getTarget().getClobbers();
2788 if (!MachineClobbers.empty()) {
2789 if (!Constraints.empty())
2791 Constraints += MachineClobbers;
2794 llvm::Type *ResultType;
2795 if (ResultRegTypes.empty())
2796 ResultType = CGF.VoidTy;
2797 else if (ResultRegTypes.size() == 1)
2798 ResultType = ResultRegTypes[0];
2800 ResultType = llvm::StructType::get(getLLVMContext(), ResultRegTypes);
2802 llvm::FunctionType *FTy =
2803 llvm::FunctionType::get(ResultType, ArgTypes,
false);
2805 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
2807 llvm::InlineAsm::AsmDialect GnuAsmDialect =
2809 ? llvm::InlineAsm::AD_ATT
2810 : llvm::InlineAsm::AD_Intel;
2811 llvm::InlineAsm::AsmDialect AsmDialect =
2814 llvm::InlineAsm *IA = llvm::InlineAsm::get(
2815 FTy, AsmString, Constraints, HasSideEffect,
2816 false, AsmDialect, HasUnwindClobber);
2817 std::vector<llvm::Value *> RegResults;
2818 llvm::CallBrInst *CBR;
2819 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
2823 CBR = Builder.CreateCallBr(IA, DefaultDest, IndirectDests, Args);
2824 CGF.EmitBlock(DefaultDest);
2825 UpdateAsmCallInst(*CBR, HasSideEffect,
2826 false, CGF.InNoMergeAttributedStmt,
2827 CGF.InNoConvergentAttributedStmt, RegResults);
2832 if (!RegResults.empty()) {
2834 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
2835 llvm::Twine SynthName = Dest->getName() +
".split";
2836 llvm::BasicBlock *SynthBB = CGF.createBasicBlock(SynthName);
2837 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
2838 Builder.SetInsertPoint(SynthBB);
2840 if (ResultRegTypes.size() == 1) {
2841 CBRRegResults[SynthBB].push_back(CBR);
2843 for (
unsigned J = 0, E = ResultRegTypes.size(); J != E; ++J) {
2844 llvm::Value *Tmp = Builder.CreateExtractValue(CBR, J,
"asmresult");
2845 CBRRegResults[SynthBB].push_back(Tmp);
2849 CGF.EmitBranch(Dest);
2850 CGF.EmitBlock(SynthBB);
2851 CBR->setIndirectDest(I++, SynthBB);
2854 }
else if (HasUnwindClobber) {
2855 llvm::CallBase *
Result = CGF.EmitCallOrInvoke(IA, Args,
"");
2856 UpdateAsmCallInst(*
Result, HasSideEffect,
2857 true, CGF.InNoMergeAttributedStmt,
2858 CGF.InNoConvergentAttributedStmt, RegResults);
2861 Builder.CreateCall(IA, Args, CGF.getBundlesForFunclet(IA));
2862 UpdateAsmCallInst(*
Result, HasSideEffect,
2863 false, CGF.InNoMergeAttributedStmt,
2864 CGF.InNoConvergentAttributedStmt, RegResults);
2867 EmitAsmStores(RegResults);
2872 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
2873 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
2874 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
2875 Builder.SetInsertPoint(Succ, --(Succ->end()));
2876 EmitAsmStores(CBRRegResults[Succ]);
2884bool AsmConstraintsInfo::GetOutputAndInputConstraints() {
2885 bool IsValidTargetAsm =
true;
2886 bool IsHipStdPar = getLangOpts().HIPStdPar && getLangOpts().CUDAIsDevice;
2887 for (
unsigned I = 0, E = S.getNumOutputs(); I != E && IsValidTargetAsm; I++) {
2889 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2890 Name = GAS->getOutputName(I);
2894 bool IsValid = getTarget().validateOutputConstraint(Info);
2895 if (IsHipStdPar && !IsValid)
2896 IsValidTargetAsm =
false;
2898 assert(IsValid &&
"Failed to parse output constraint");
2900 OutputConstraintInfos.push_back(Info);
2903 for (
unsigned I = 0, E = S.getNumInputs(); I != E && IsValidTargetAsm; I++) {
2905 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2906 Name = GAS->getInputName(I);
2911 getTarget().validateInputConstraint(OutputConstraintInfos, Info);
2912 if (IsHipStdPar && !IsValid)
2913 IsValidTargetAsm =
false;
2915 assert(IsValid &&
"Failed to parse input constraint");
2917 InputConstraintInfos.push_back(Info);
2920 return IsValidTargetAsm;
2927void AsmConstraintsInfo::HandleOutputConstraints() {
2929 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2931 for (
unsigned I = 0, E = S.getNumOutputs(); I != E; I++) {
2932 TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[I];
2935 std::string OutputConstraint(S.getOutputConstraint(I));
2936 OutputConstraint = getTarget().simplifyConstraint(
2937 StringRef(OutputConstraint).substr(1), &OutputConstraintInfos);
2939 const Expr *OutExpr = S.getOutputExpr(I);
2943 OutputConstraint = S.addVariableConstraints(
2944 OutputConstraint, *OutExpr, getTarget(), Info.
earlyClobber(),
2945 [&](
const Stmt *UnspStmt, StringRef Msg) {
2946 CGM.ErrorUnsupported(UnspStmt, Msg);
2951 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2952 CGM.Error(S.getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2954 OutputConstraints.push_back(OutputConstraint);
2956 if (!Constraints.empty())
2961 QualType QTy = OutExpr->
getType();
2962 const bool IsScalarOrAggregate =
2967 Constraints +=
"=" + OutputConstraint;
2968 ResultRegQualTys.push_back(QTy);
2969 ResultRegDests.push_back(Dest);
2974 const bool RequiresCast =
2976 (getTargetHooks().isScalarizableAsmOperand(CGF, Ty) ||
2977 Ty->isAggregateType());
2979 ResultTruncRegTypes.push_back(Ty);
2980 ResultTypeRequiresCast.push_back(RequiresCast);
2983 if (
unsigned Size = getContext().getTypeSize(QTy))
2984 Ty = llvm::IntegerType::get(getLLVMContext(), Size);
2986 CGM.Error(OutExpr->
getExprLoc(),
"output size should not be zero");
2989 ResultRegTypes.push_back(Ty);
2996 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2997 TargetInfo::ConstraintInfo &Input = InputConstraintInfos[InputNo];
3001 assert(InputNo != S.getNumInputs() &&
"Didn't find matching input!");
3003 QualType
InputTy = S.getInputExpr(InputNo)->getType();
3004 QualType OutputType = OutExpr->
getType();
3006 uint64_t InputSize = getContext().getTypeSize(InputTy);
3007 if (getContext().getTypeSize(OutputType) < InputSize)
3012 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
3013 CGF, OutputConstraint, ResultRegTypes.back()))
3014 ResultRegTypes.back() = AdjTy;
3016 CGM.getDiags().Report(S.getAsmLoc(),
3017 diag::err_asm_invalid_type_in_input)
3018 << OutExpr->
getType() << OutputConstraint;
3021 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
3022 CGF.LargestVectorWidth =
3023 std::max((uint64_t)CGF.LargestVectorWidth,
3024 VT->getPrimitiveSizeInBits().getKnownMinValue());
3026 Address DestAddr = Dest.getAddress();
3037 ArgTypes.push_back(DestAddr.
getType());
3041 Constraints +=
"=*" + OutputConstraint;
3049 InOutConstraints +=
',';
3051 const Expr *InputExpr = S.getOutputExpr(I);
3053 llvm::Type *ArgElemType;
3054 std::tie(Arg, ArgElemType) =
3055 CGF.EmitAsmInputLValue(Info, Dest, InputExpr->
getType(),
3058 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
3059 CGF, OutputConstraint, Arg->getType()))
3060 Arg = Builder.CreateBitCast(Arg, AdjTy);
3063 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3064 CGF.LargestVectorWidth =
3065 std::max((uint64_t)CGF.LargestVectorWidth,
3066 VT->getPrimitiveSizeInBits().getKnownMinValue());
3070 InOutConstraints += llvm::utostr(I);
3072 InOutConstraints += OutputConstraint;
3074 InOutArgTypes.push_back(Arg->getType());
3075 InOutArgElemTypes.push_back(ArgElemType);
3076 InOutArgs.push_back(Arg);
3083void AsmConstraintsInfo::HandleMSStyleAsmBlob() {
3094 CGM.getTargetCodeGenInfo().addReturnRegisterOutputs(
3095 CGF, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
3096 ResultRegDests, AsmString, S.getNumOutputs());
3103void AsmConstraintsInfo::HandleInputConstraints() {
3104 ASTContext &Ctx = getContext();
3106 for (
unsigned I = 0, E = S.getNumInputs(); I != E; I++) {
3107 TargetInfo::ConstraintInfo &Info = InputConstraintInfos[I];
3108 const Expr *InputExpr = S.getInputExpr(I);
3113 if (!Constraints.empty())
3117 std::string InputConstraint(S.getInputConstraint(I));
3119 getTarget().simplifyConstraint(InputConstraint, &OutputConstraintInfos);
3121 InputConstraint = S.addVariableConstraints(
3124 [&](
const Stmt *UnspStmt, std::string_view Msg) {
3125 CGM.ErrorUnsupported(UnspStmt, Msg);
3128 std::string ReplaceConstraint(InputConstraint);
3130 llvm::Type *ArgElemType;
3131 std::tie(Arg, ArgElemType) = CGF.EmitAsmInput(Info, InputExpr, Constraints);
3140 QualType OutputType = S.getOutputExpr(Output)->getType();
3146 Arg = Builder.CreatePtrToInt(Arg, CGF.
IntPtrTy);
3148 llvm::Type *OutputTy = CGF.
ConvertType(OutputType);
3150 Arg = Builder.CreateZExt(Arg, OutputTy);
3152 Arg = Builder.CreateZExt(Arg, CGF.
IntPtrTy);
3153 else if (OutputTy->isFloatingPointTy())
3154 Arg = Builder.CreateFPExt(Arg, OutputTy);
3158 ReplaceConstraint = OutputConstraints[Output];
3161 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
3162 CGF, ReplaceConstraint, Arg->getType()))
3163 Arg = Builder.CreateBitCast(Arg, AdjTy);
3165 CGM.getDiags().Report(S.getAsmLoc(), diag::err_asm_invalid_type_in_input)
3166 << InputExpr->
getType() << InputConstraint;
3169 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3170 CGF.LargestVectorWidth =
3171 std::max((uint64_t)CGF.LargestVectorWidth,
3172 VT->getPrimitiveSizeInBits().getKnownMinValue());
3174 ArgTypes.push_back(Arg->getType());
3175 ArgElemTypes.push_back(ArgElemType);
3176 Args.push_back(Arg);
3178 Constraints += InputConstraint;
3182 for (
unsigned I = 0, E = InOutArgs.size(); I != E; I++) {
3183 ArgTypes.push_back(InOutArgTypes[I]);
3184 ArgElemTypes.push_back(InOutArgElemTypes[I]);
3185 Args.push_back(InOutArgs[I]);
3188 Constraints += InOutConstraints;
3194bool AsmConstraintsInfo::HandleLabels() {
3195 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S); GS && GS->isAsmGoto()) {
3196 for (
const auto *E : GS->labels()) {
3198 IndirectDests.push_back(Dest.
getBlock());
3200 if (!Constraints.empty())
3203 Constraints +=
"!i";
3217bool AsmConstraintsInfo::HandleClobbers() {
3218 bool HasUnwindClobber =
false;
3219 for (
unsigned I = 0, E = S.getNumClobbers(); I != E; I++) {
3220 std::string Clobber = S.getClobber(I);
3222 if (Clobber ==
"unwind") {
3223 HasUnwindClobber =
true;
3227 if (Clobber ==
"memory") {
3230 }
else if (Clobber !=
"cc") {
3231 Clobber = getTarget().getNormalizedGCCRegisterName(Clobber);
3232 if (CGM.getCodeGenOpts().StackClashProtector &&
3233 getTarget().isSPRegName(Clobber)) {
3234 CGM.getDiags().Report(S.getAsmLoc(),
3235 diag::warn_stack_clash_protection_inline_asm);
3240 if (Clobber ==
"eax" || Clobber ==
"edx") {
3241 if (Constraints.find(
"=&A") != std::string::npos)
3244 std::string::size_type position1 =
3245 Constraints.find(
"={" + Clobber +
"}");
3246 if (position1 != std::string::npos) {
3247 Constraints.insert(position1 + 1,
"&");
3251 std::string::size_type position2 = Constraints.find(
"=A");
3252 if (position2 != std::string::npos) {
3253 Constraints.insert(position2 + 1,
"&");
3259 if (!Constraints.empty())
3262 Constraints +=
"~{" + Clobber +
'}';
3265 return HasUnwindClobber;
3268void AsmConstraintsInfo::UpdateAsmCallInst(
3269 llvm::CallBase &
Result,
bool HasSideEffect,
bool HasUnwindClobber,
3270 bool NoMerge,
bool NoConvergent, std::vector<llvm::Value *> &RegResults) {
3271 if (!HasUnwindClobber)
3272 Result.addFnAttr(llvm::Attribute::NoUnwind);
3275 Result.addFnAttr(llvm::Attribute::NoMerge);
3278 if (!HasSideEffect) {
3280 Result.setDoesNotAccessMemory();
3282 Result.setOnlyReadsMemory();
3286 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
3288 auto Attr = llvm::Attribute::get(
3289 getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
3290 Result.addParamAttr(Pair.index(), Attr);
3296 const StringLiteral *SL;
3297 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S);
3299 (SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))) {
3304 llvm::Constant *Loc =
3305 llvm::ConstantInt::get(CGF.
Int64Ty, S.getAsmLoc().getRawEncoding());
3306 Result.setMetadata(
"srcloc",
3307 llvm::MDNode::get(getLLVMContext(),
3308 llvm::ConstantAsMetadata::get(Loc)));
3314 if (!NoConvergent && getLangOpts().assumeFunctionsAreConvergent())
3319 Result.addFnAttr(llvm::Attribute::Convergent);
3322 if (ResultRegTypes.size() == 1) {
3323 RegResults.push_back(&
Result);
3325 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
3326 llvm::Value *Tmp = Builder.CreateExtractValue(&
Result, i,
"asmresult");
3327 RegResults.push_back(Tmp);
3332void AsmConstraintsInfo::EmitAsmStores(
3333 const llvm::ArrayRef<llvm::Value *> RegResults) {
3334 llvm::LLVMContext &CTX = getLLVMContext();
3336 assert(RegResults.size() == ResultRegTypes.size());
3337 assert(RegResults.size() == ResultTruncRegTypes.size());
3338 assert(RegResults.size() == ResultRegDests.size());
3342 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
3343 assert(ResultBounds.size() <= ResultRegDests.size());
3345 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
3346 llvm::Value *Tmp = RegResults[i];
3347 llvm::Type *TruncTy = ResultTruncRegTypes[i];
3349 if (i < ResultBounds.size() && ResultBounds[i].has_value()) {
3350 const auto [LowerBound, UpperBound] = ResultBounds[i].value();
3353 assert(LowerBound == 0 &&
"Output operand lower bound is not zero.");
3355 llvm::Constant *UpperBoundConst =
3356 llvm::ConstantInt::get(Tmp->getType(), UpperBound);
3357 llvm::Value *IsBooleanValue =
3358 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, UpperBoundConst);
3359 llvm::Function *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume);
3361 Builder.CreateCall(FnAssume, IsBooleanValue);
3366 if (ResultRegTypes[i] != TruncTy) {
3369 if (TruncTy->isFloatingPointTy())
3370 Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
3371 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
3372 uint64_t ResSize = CGM.getDataLayout().getTypeSizeInBits(TruncTy);
3373 Tmp = Builder.CreateTrunc(
3374 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
3375 Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
3376 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
3378 CGM.getDataLayout().getTypeSizeInBits(Tmp->getType());
3379 Tmp = Builder.CreatePtrToInt(
3380 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
3381 Tmp = Builder.CreateTrunc(Tmp, TruncTy);
3382 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
3383 Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
3384 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
3385 Tmp = Builder.CreateBitCast(Tmp, TruncTy);
3390 LValue Dest = ResultRegDests[i];
3394 if (i < ResultTypeRequiresCast.size() && ResultTypeRequiresCast[i]) {
3395 unsigned Size = getContext().getTypeSize(ResultRegQualTys[i]);
3396 Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
3398 if (getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) {
3399 llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
3404 QualType Ty = getContext().getIntTypeForBitwidth(Size,
false);
3406 const Expr *OutExpr = S.getOutputExpr(i);
3408 diag::err_store_value_to_reg);
3430 I != E; ++I, ++CurField) {
3432 if (CurField->hasCapturedVLAType()) {
3449 CodeGenFunction CGF(
CGM,
true);
3469 "CapturedStmtInfo should be set when generating the captured function");
3473 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3482 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Args);
3483 llvm::FunctionType *FuncLLVMTy =
CGM.getTypes().GetFunctionType(FuncInfo);
3486 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3488 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
3489 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
3490 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3492 F->addFnAttr(llvm::Attribute::NoUnwind);
3504 for (
auto *FD : RD->
fields()) {
3505 if (FD->hasCapturedVLAType()) {
3509 auto VAT = FD->getCapturedVLAType();
3510 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3521 PGO->assignRegionCounters(
GlobalDecl(CD), F);
3531 for (
auto &I : *BB) {
3532 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3539CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3540 llvm::ConvergenceControlInst *ParentToken = ConvergenceTokenStack.back();
3541 assert(ParentToken);
3543 llvm::Value *bundleArgs[] = {ParentToken};
3544 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3545 auto *Output = llvm::CallBase::addOperandBundle(
3546 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3547 Input->replaceAllUsesWith(Output);
3548 Input->eraseFromParent();
3552llvm::ConvergenceControlInst *
3555 assert(ParentToken);
3556 return llvm::ConvergenceControlInst::CreateLoop(*BB, ParentToken);
3559llvm::ConvergenceControlInst *
3560CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3561 llvm::BasicBlock *BB = &F->getEntryBlock();
3569 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)
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 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 EmitOMPOrderedDirective(const OMPOrderedDirective &S)
void EmitForStmt(const ForStmt &S, ArrayRef< const Attr * > Attrs={})
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S)
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void 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)
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)
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
getLocationOfByte - Return a source location that points to the specified byte of this string literal...
StringRef getString() const
const SwitchCase * getNextSwitchCase() const
SwitchStmt - This represents a 'switch' stmt.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "switch" statement, if any.
SwitchCase * getSwitchCaseList()
Exposes information about the current target.
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.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
CapturedRegionKind
The different kinds of captured statement.
@ Asm
Assembly: we accept this only so that we can preprocess it.
@ Result
The result type of a method or function.
U cast(CodeGen::Address addr)
@ None
The alignment was not explicit in code.
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
void setScopeDepth(EHScopeStack::stable_iterator depth)
llvm::BasicBlock * getBlock() const
EHScopeStack::stable_iterator getScopeDepth() const
llvm::IntegerType * Int64Ty
llvm::IntegerType * IntPtrTy
llvm::PointerType * Int8PtrTy
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool hasMatchingInput() const
Return true if this output operand has a matching (tied) input operand.
unsigned getTiedOperand() const
bool allowsMemory() const
std::optional< std::pair< unsigned, unsigned > > getOutputOperandBounds() const
bool requiresImmediateConstant() const
bool hasTiedOperand() const
Return true if this input operand is a matching constraint that ties it to an output operand.
bool allowsRegister() const