29#include "llvm/ADT/ArrayRef.h"
30#include "llvm/ADT/DenseMap.h"
31#include "llvm/ADT/SmallSet.h"
32#include "llvm/ADT/StringExtras.h"
33#include "llvm/IR/Assumptions.h"
34#include "llvm/IR/DataLayout.h"
35#include "llvm/IR/InlineAsm.h"
36#include "llvm/IR/Intrinsics.h"
37#include "llvm/IR/MDBuilder.h"
38#include "llvm/Support/SaveAndRestore.h"
59 assert(S &&
"Null statement?");
60 PGO->setCurrentStmt(S);
77 PGO->markStmtMaybeUsed(S);
91 if (
const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
99 case Stmt::CXXCatchStmtClass:
100 case Stmt::SEHExceptStmtClass:
101 case Stmt::SEHFinallyStmtClass:
102 case Stmt::MSDependentExistsStmtClass:
103 case Stmt::UnresolvedSYCLKernelCallStmtClass:
104 llvm_unreachable(
"invalid statement class to emit generically");
105 case Stmt::NullStmtClass:
106 case Stmt::CompoundStmtClass:
107 case Stmt::DeclStmtClass:
108 case Stmt::LabelStmtClass:
109 case Stmt::AttributedStmtClass:
110 case Stmt::GotoStmtClass:
111 case Stmt::BreakStmtClass:
112 case Stmt::ContinueStmtClass:
113 case Stmt::DefaultStmtClass:
114 case Stmt::CaseStmtClass:
115 case Stmt::DeferStmtClass:
116 case Stmt::SEHLeaveStmtClass:
117 case Stmt::SYCLKernelCallStmtClass:
118 llvm_unreachable(
"should have emitted these statements as simple");
120#define STMT(Type, Base)
121#define ABSTRACT_STMT(Op)
122#define EXPR(Type, Base) \
123 case Stmt::Type##Class:
124#include "clang/AST/StmtNodes.inc"
127 llvm::BasicBlock *incoming =
Builder.GetInsertBlock();
128 assert(incoming &&
"expression emission must have an insertion point");
132 llvm::BasicBlock *outgoing =
Builder.GetInsertBlock();
133 assert(outgoing &&
"expression emission cleared block!");
147 if (incoming != outgoing && outgoing->use_empty()) {
148 outgoing->eraseFromParent();
154 case Stmt::IndirectGotoStmtClass:
165 case Stmt::GCCAsmStmtClass:
167 case Stmt::CoroutineBodyStmtClass:
170 case Stmt::CoreturnStmtClass:
173 case Stmt::CapturedStmtClass: {
178 case Stmt::ObjCAtTryStmtClass:
181 case Stmt::ObjCAtCatchStmtClass:
183 "@catch statements should be handled by EmitObjCAtTryStmt");
184 case Stmt::ObjCAtFinallyStmtClass:
186 "@finally statements should be handled by EmitObjCAtTryStmt");
187 case Stmt::ObjCAtThrowStmtClass:
190 case Stmt::ObjCAtSynchronizedStmtClass:
193 case Stmt::ObjCForCollectionStmtClass:
196 case Stmt::ObjCAutoreleasePoolStmtClass:
200 case Stmt::CXXTryStmtClass:
203 case Stmt::CXXForRangeStmtClass:
206 case Stmt::SEHTryStmtClass:
209 case Stmt::OMPMetaDirectiveClass:
212 case Stmt::OMPCanonicalLoopClass:
215 case Stmt::OMPParallelDirectiveClass:
218 case Stmt::OMPSimdDirectiveClass:
221 case Stmt::OMPTileDirectiveClass:
224 case Stmt::OMPStripeDirectiveClass:
227 case Stmt::OMPUnrollDirectiveClass:
230 case Stmt::OMPReverseDirectiveClass:
233 case Stmt::OMPSplitDirectiveClass:
236 case Stmt::OMPInterchangeDirectiveClass:
239 case Stmt::OMPFuseDirectiveClass:
242 case Stmt::OMPForDirectiveClass:
245 case Stmt::OMPForSimdDirectiveClass:
248 case Stmt::OMPSectionsDirectiveClass:
251 case Stmt::OMPSectionDirectiveClass:
254 case Stmt::OMPSingleDirectiveClass:
257 case Stmt::OMPMasterDirectiveClass:
260 case Stmt::OMPCriticalDirectiveClass:
263 case Stmt::OMPParallelForDirectiveClass:
266 case Stmt::OMPParallelForSimdDirectiveClass:
269 case Stmt::OMPParallelMasterDirectiveClass:
272 case Stmt::OMPParallelSectionsDirectiveClass:
275 case Stmt::OMPTaskDirectiveClass:
278 case Stmt::OMPTaskyieldDirectiveClass:
281 case Stmt::OMPErrorDirectiveClass:
284 case Stmt::OMPBarrierDirectiveClass:
287 case Stmt::OMPTaskwaitDirectiveClass:
290 case Stmt::OMPTaskgroupDirectiveClass:
293 case Stmt::OMPFlushDirectiveClass:
296 case Stmt::OMPDepobjDirectiveClass:
299 case Stmt::OMPScanDirectiveClass:
302 case Stmt::OMPOrderedDirectiveClass:
305 case Stmt::OMPAtomicDirectiveClass:
308 case Stmt::OMPTargetDirectiveClass:
311 case Stmt::OMPTeamsDirectiveClass:
314 case Stmt::OMPCancellationPointDirectiveClass:
317 case Stmt::OMPCancelDirectiveClass:
320 case Stmt::OMPTargetDataDirectiveClass:
323 case Stmt::OMPTargetEnterDataDirectiveClass:
326 case Stmt::OMPTargetExitDataDirectiveClass:
329 case Stmt::OMPTargetParallelDirectiveClass:
332 case Stmt::OMPTargetParallelForDirectiveClass:
335 case Stmt::OMPTaskLoopDirectiveClass:
338 case Stmt::OMPTaskLoopSimdDirectiveClass:
341 case Stmt::OMPMasterTaskLoopDirectiveClass:
344 case Stmt::OMPMaskedTaskLoopDirectiveClass:
347 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
351 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
355 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
359 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
363 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
367 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
371 case Stmt::OMPDistributeDirectiveClass:
374 case Stmt::OMPTargetUpdateDirectiveClass:
377 case Stmt::OMPDistributeParallelForDirectiveClass:
381 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
385 case Stmt::OMPDistributeSimdDirectiveClass:
388 case Stmt::OMPTargetParallelForSimdDirectiveClass:
392 case Stmt::OMPTargetSimdDirectiveClass:
395 case Stmt::OMPTeamsDistributeDirectiveClass:
398 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
402 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
406 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
410 case Stmt::OMPTargetTeamsDirectiveClass:
413 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
417 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
421 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
425 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
429 case Stmt::OMPInteropDirectiveClass:
432 case Stmt::OMPDispatchDirectiveClass:
433 CGM.ErrorUnsupported(S,
"OpenMP dispatch directive");
435 case Stmt::OMPScopeDirectiveClass:
438 case Stmt::OMPMaskedDirectiveClass:
441 case Stmt::OMPGenericLoopDirectiveClass:
444 case Stmt::OMPTeamsGenericLoopDirectiveClass:
447 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
451 case Stmt::OMPParallelGenericLoopDirectiveClass:
455 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
459 case Stmt::OMPParallelMaskedDirectiveClass:
462 case Stmt::OMPAssumeDirectiveClass:
465 case Stmt::OpenACCComputeConstructClass:
468 case Stmt::OpenACCLoopConstructClass:
471 case Stmt::OpenACCCombinedConstructClass:
474 case Stmt::OpenACCDataConstructClass:
477 case Stmt::OpenACCEnterDataConstructClass:
480 case Stmt::OpenACCExitDataConstructClass:
483 case Stmt::OpenACCHostDataConstructClass:
486 case Stmt::OpenACCWaitConstructClass:
489 case Stmt::OpenACCInitConstructClass:
492 case Stmt::OpenACCShutdownConstructClass:
495 case Stmt::OpenACCSetConstructClass:
498 case Stmt::OpenACCUpdateConstructClass:
501 case Stmt::OpenACCAtomicConstructClass:
504 case Stmt::OpenACCCacheConstructClass:
515 case Stmt::NullStmtClass:
517 case Stmt::CompoundStmtClass:
520 case Stmt::DeclStmtClass:
523 case Stmt::LabelStmtClass:
526 case Stmt::AttributedStmtClass:
529 case Stmt::GotoStmtClass:
532 case Stmt::BreakStmtClass:
535 case Stmt::ContinueStmtClass:
538 case Stmt::DefaultStmtClass:
541 case Stmt::CaseStmtClass:
544 case Stmt::DeferStmtClass:
547 case Stmt::SEHLeaveStmtClass:
550 case Stmt::SYCLKernelCallStmtClass:
563 "LLVM IR generation of compound statement ('{}')");
590 if (
const auto *LS = dyn_cast<LabelStmt>(LastStmt)) {
592 LastStmt = LS->getSubStmt();
593 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(LastStmt)) {
596 LastStmt = AS->getSubStmt();
598 llvm_unreachable(
"unknown value statement");
622 llvm::UncondBrInst *BI = dyn_cast<llvm::UncondBrInst>(BB->getTerminator());
635 if (BI->getIterator() != BB->begin())
638 BB->replaceAllUsesWith(BI->getSuccessor());
639 BI->eraseFromParent();
640 BB->eraseFromParent();
644 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
649 if (IsFinished && BB->use_empty()) {
656 if (CurBB && CurBB->getParent())
657 CurFn->insert(std::next(CurBB->getIterator()), BB);
667 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
669 if (!CurBB || CurBB->hasTerminator()) {
681 bool inserted =
false;
682 for (llvm::User *u : block->users()) {
683 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
684 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
699 if (Dest.
isValid())
return Dest;
712 if (
EHStack.hasNormalCleanups() && CurLexicalScope)
713 CurLexicalScope->addLabel(D);
734 if (
CGM.getCodeGenOpts().hasReducedDebugInfo()) {
746 assert(!Labels.empty());
748 =
CGF.EHStack.getInnermostNormalCleanup();
752 assert(
CGF.LabelMap.count(Label));
761 ParentScope->Labels.append(Labels.begin(), Labels.end());
777 bool nomerge =
false;
778 bool noinline =
false;
779 bool alwaysinline =
false;
780 bool noconvergent =
false;
781 HLSLControlFlowHintAttr::Spelling flattenOrBranch =
782 HLSLControlFlowHintAttr::SpellingNotCalculated;
784 const AtomicAttr *AA =
nullptr;
786 for (
const auto *A : S.
getAttrs()) {
787 switch (A->getKind()) {
796 case attr::AlwaysInline:
799 case attr::NoConvergent:
802 case attr::MustTail: {
807 case attr::CXXAssume: {
812 Builder.CreateAssumption(AssumptionVal);
818 case attr::HLSLControlFlowHint: {
855 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
865 if (CurBB && CurBB->hasTerminator())
906 const Stmt *Skipped = Else;
908 std::swap(Executed, Skipped);
920 PGO->markStmtMaybeUsed(Skipped);
931 llvm::BasicBlock *ElseBlock =
947 CGM.getCodeGenOpts().OptimizationLevel)
956 if (!
CGM.getCodeGenOpts().MCDCCoverage) {
963 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
994 }
else if (HasSkip) {
1005 bool HasEmptyBody) {
1006 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1016 bool CondIsConstInt =
1017 !ControllingExpression ||
1021 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
1022 Result.Val.getInt().getBoolValue());
1033 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1036 if (HasEmptyBody && CondIsTrue) {
1037 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1055 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1059 const Stmt *Body = S.getBody();
1062 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
1063 return Compound->body_empty();
1074 if (
CGM.shouldEmitConvergenceTokens())
1083 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopHeader));
1106 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1107 bool EmitBoolCondBranch = !
C || !
C->isOne();
1116 if (EmitBoolCondBranch) {
1117 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1120 llvm::MDNode *Weights =
1122 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1123 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1125 auto *I =
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1131 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1135 if (ExitBlock !=
LoopExit.getBlock()) {
1141 CGM.getDiags().Report(A->getLocation(),
1142 diag::warn_attribute_has_no_effect_on_infinite_loop)
1143 << A << A->getRange();
1144 CGM.getDiags().Report(
1146 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1159 BreakContinueStack.pop_back();
1175 if (!EmitBoolCondBranch) {
1177 PGO->markStmtAsUsed(
true, &S);
1180 if (
CGM.shouldEmitConvergenceTokens())
1192 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopCond));
1199 if (
CGM.shouldEmitConvergenceTokens())
1217 BreakContinueStack.pop_back();
1221 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1222 bool EmitBoolCondBranch = !
C || !
C->isZero();
1225 LoopStack.push(LoopBody,
CGM.getContext(),
CGM.getCodeGenOpts(), DoAttrs,
1234 if (EmitBoolCondBranch) {
1236 auto *I =
Builder.CreateCondBr(
1237 BoolCondVal, LoopBody, LoopFalse,
1238 createProfileWeightsForLoop(S.
getCond(), BackedgeCount));
1245 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1252 if (LoopFalse !=
LoopExit.getBlock()) {
1262 if (!EmitBoolCondBranch)
1265 if (
CGM.shouldEmitConvergenceTokens())
1273 std::optional<LexicalScope> ForScope;
1285 llvm::BasicBlock *CondBlock = CondDest.
getBlock();
1288 if (
CGM.shouldEmitConvergenceTokens())
1292 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1309 Continue = CondDest;
1312 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1323 BreakContinueStack.back().ContinueBlock = Continue;
1326 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1329 if (
hasSkipCounter(&S) || (ForScope && ForScope->requiresCleanups()))
1341 llvm::MDNode *Weights =
1343 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1344 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1347 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1352 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1356 if (ExitBlock !=
LoopExit.getBlock()) {
1366 PGO->markStmtAsUsed(
true, &S);
1380 auto *FinalBodyBB =
Builder.GetInsertBlock();
1388 BreakContinueStack.pop_back();
1396 ForScope->ForceCleanup();
1403 if (
CGM.shouldEmitConvergenceTokens())
1433 if (
CGM.shouldEmitConvergenceTokens())
1437 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1443 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1453 llvm::MDNode *Weights =
1455 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1456 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1458 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1463 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1467 if (ExitBlock !=
LoopExit.getBlock()) {
1480 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1490 auto *FinalBodyBB =
Builder.GetInsertBlock();
1497 BreakContinueStack.pop_back();
1508 if (
CGM.shouldEmitConvergenceTokens())
1518void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1534struct SaveRetExprRAII {
1535 SaveRetExprRAII(
const Expr *RetExpr, CodeGenFunction &CGF)
1536 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1539 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1540 const Expr *OldRetExpr;
1541 CodeGenFunction &CGF;
1549 if (calleeQualType->isFunctionPointerType() ||
1550 calleeQualType->isFunctionReferenceType() ||
1551 calleeQualType->isBlockPointerType() ||
1552 calleeQualType->isMemberFunctionPointerType()) {
1554 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1556 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1557 if (
auto methodDecl = CMCE->getMethodDecl()) {
1574 if (requiresReturnValueCheck()) {
1577 new llvm::GlobalVariable(
CGM.getModule(), SLoc->getType(),
false,
1578 llvm::GlobalVariable::PrivateLinkage, SLoc);
1579 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1580 CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
1581 assert(ReturnLocation.isValid() &&
"No valid return location");
1582 Builder.CreateStore(SLocPtr, ReturnLocation);
1588 Builder.ClearInsertionPoint();
1602 SaveRetExprRAII SaveRetExpr(RV, *
this);
1605 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1606 RV = EWC->getSubExpr();
1610 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1613 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1626 !
CGM.getOpenMPRuntime()
1645 }
else if (
FnRetTy->isReferenceType()) {
1681 ++NumSimpleReturnExprs;
1693 for (
const auto *I : S.
decls())
1698 ->
const BreakContinue * {
1699 if (!S.hasLabelTarget())
1700 return &BreakContinueStack.back();
1702 const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
1703 assert(LoopOrSwitch &&
"break/continue target not set?");
1704 for (
const BreakContinue &BC : llvm::reverse(BreakContinueStack))
1705 if (BC.LoopOrSwitch == LoopOrSwitch)
1708 llvm_unreachable(
"break/continue target not found");
1712 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1725 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1742 assert(S.
getRHS() &&
"Expected RHS value in CaseStmt");
1755 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1759 llvm::APInt Range = RHS - LHS;
1761 if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
1764 unsigned NCases = Range.getZExtValue() + 1;
1769 uint64_t Weight = Total / NCases, Rem = Total % NCases;
1770 for (
unsigned I = 0; I != NCases; ++I) {
1772 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1773 else if (SwitchLikelihood)
1774 SwitchLikelihood->push_back(LH);
1778 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1786 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1791 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1795 Builder.SetInsertPoint(CaseRangeBlock);
1799 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1803 llvm::MDNode *Weights =
nullptr;
1804 if (SwitchWeights) {
1806 uint64_t DefaultCount = (*SwitchWeights)[0];
1807 Weights = createProfileWeights(ThisCount, DefaultCount);
1812 (*SwitchWeights)[0] += ThisCount;
1813 }
else if (SwitchLikelihood)
1814 Cond = emitCondLikelihoodViaExpectIntrinsic(
Cond, LH);
1816 Builder.CreateCondBr(
Cond, CaseDest, FalseDest, Weights);
1820 Builder.SetInsertPoint(RestoreBB);
1822 Builder.ClearInsertionPoint();
1843 llvm::ConstantInt *CaseVal =
1848 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.
getLHS()))
1849 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1851 CE = dyn_cast<ConstantExpr>(S.
getLHS());
1853 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1855 if (
CGM.getCodeGenOpts().hasReducedDebugInfo())
1856 Dbg->EmitGlobalVariable(DE->getDecl(),
1857 APValue(llvm::APSInt(CaseVal->getValue())));
1860 if (SwitchLikelihood)
1866 if (!
CGM.getCodeGenOpts().hasProfileClangInstr() &&
1867 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1875 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1879 if (
Builder.GetInsertBlock()) {
1881 Builder.ClearInsertionPoint();
1891 SwitchInsn->addCase(CaseVal, CaseDest);
1910 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1912 llvm::ConstantInt *CaseVal =
1917 if (
CGM.getCodeGenOpts().hasProfileClangInstr()) {
1923 if (SwitchLikelihood)
1926 SwitchInsn->addCase(CaseVal, CaseDest);
1927 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1950 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1951 assert(DefaultBlock->empty() &&
1952 "EmitDefaultStmt: Default block already defined?");
1954 if (SwitchLikelihood)
1963struct EmitDeferredStatement final : EHScopeStack::Cleanup {
2023 llvm::Value *SavedCleanupDest =
nullptr;
2077 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
2096 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
2100 bool StartedInLiveCode = FoundCase;
2101 unsigned StartSize = ResultStmts.size();
2108 bool HadSkippedDecl =
false;
2112 for (; Case && I != E; ++I) {
2128 for (++I; I != E; ++I)
2138 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
2153 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
2158 bool AnyDecls =
false;
2159 for (; I != E; ++I) {
2172 for (++I; I != E; ++I)
2189 ResultStmts.resize(StartSize);
2190 ResultStmts.push_back(S);
2214 ResultStmts.push_back(S);
2223 const llvm::APSInt &ConstantCondValue,
2235 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2243 if (CS->
getRHS())
return false;
2268 bool FoundCase =
false;
2275static std::optional<SmallVector<uint64_t, 16>>
2278 if (Likelihoods.size() <= 1)
2279 return std::nullopt;
2281 uint64_t NumUnlikely = 0;
2282 uint64_t NumNone = 0;
2283 uint64_t NumLikely = 0;
2284 for (
const auto LH : Likelihoods) {
2299 if (NumUnlikely == 0 && NumLikely == 0)
2300 return std::nullopt;
2308 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2309 const uint64_t
None = Likely / (NumNone + 1);
2310 const uint64_t Unlikely = 0;
2313 Result.reserve(Likelihoods.size());
2314 for (
const auto LH : Likelihoods) {
2317 Result.push_back(Unlikely);
2323 Result.push_back(Likely);
2333 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2336 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2340 llvm::APSInt ConstantCondValue;
2361 SwitchInsn =
nullptr;
2368 PGO->markStmtMaybeUsed(S.
getBody());
2372 SwitchInsn = SavedSwitchInsn;
2400 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2404 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2405 llvm::ConstantInt *BranchHintConstant =
2407 HLSLControlFlowHintAttr::Spelling::Microsoft_branch
2408 ? llvm::ConstantInt::get(
CGM.Int32Ty, 1)
2409 : llvm::ConstantInt::get(
CGM.Int32Ty, 2);
2410 llvm::Metadata *Vals[] = {MDHelper.createString(
"hlsl.controlflow.hint"),
2411 MDHelper.createConstant(BranchHintConstant)};
2412 SwitchInsn->setMetadata(
"hlsl.controlflow.hint",
2413 llvm::MDNode::get(
CGM.getLLVMContext(), Vals));
2416 if (PGO->haveRegionCounts()) {
2418 uint64_t DefaultCount = 0;
2419 unsigned NumCases = 0;
2428 SwitchWeights->reserve(NumCases);
2431 SwitchWeights->push_back(DefaultCount);
2432 }
else if (
CGM.getCodeGenOpts().OptimizationLevel) {
2438 CaseRangeBlock = DefaultBlock;
2441 Builder.ClearInsertionPoint();
2446 if (!BreakContinueStack.empty())
2447 OuterContinue = BreakContinueStack.back().ContinueBlock;
2449 BreakContinueStack.push_back(BreakContinue(S, SwitchExit, OuterContinue));
2454 BreakContinueStack.pop_back();
2458 SwitchInsn->setDefaultDest(CaseRangeBlock);
2461 if (!DefaultBlock->getParent()) {
2469 DefaultBlock->replaceAllUsesWith(SwitchExit.
getBlock());
2470 delete DefaultBlock;
2484 Builder.CreateBr(SwitchInsn->getDefaultDest());
2485 SwitchInsn->setDefaultDest(ImplicitDefaultBlock);
2496 if (
Call &&
CGM.getCodeGenOpts().OptimizationLevel != 0) {
2497 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2498 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2500 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2501 MDHelper.createUnpredictable());
2505 if (SwitchWeights) {
2506 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2507 "switch weights do not match switch cases");
2509 if (SwitchWeights->size() > 1)
2510 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2511 createProfileWeights(*SwitchWeights));
2512 delete SwitchWeights;
2513 }
else if (SwitchLikelihood) {
2514 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2515 "switch likelihoods do not match switch cases");
2516 std::optional<SmallVector<uint64_t, 16>> LHW =
2519 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2520 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2521 createProfileWeights(*LHW));
2523 delete SwitchLikelihood;
2525 SwitchInsn = SavedSwitchInsn;
2526 SwitchWeights = SavedSwitchWeights;
2527 SwitchLikelihood = SavedSwitchLikelihood;
2528 CaseRangeBlock = SavedCRBlock;
2531std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2540 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2550 ConstraintStr +=
'*';
2553std::pair<llvm::Value *, llvm::Type *>
2554CodeGenFunction::EmitAsmInput(
const TargetInfo::ConstraintInfo &Info,
2555 const Expr *InputExpr,
2556 std::string &ConstraintStr) {
2561 Expr::EvalResult EVResult;
2564 llvm::APSInt IntResult;
2567 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2579 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2583 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2595 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2598 if (!StrVal.empty()) {
2601 unsigned StartToken = 0;
2602 unsigned ByteOffset = 0;
2606 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2607 if (StrVal[i] !=
'\n')
continue;
2609 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2610 Locs.push_back(llvm::ConstantAsMetadata::get(
2630 std::string AsmString;
2637 std::string Constraints;
2638 std::string InOutConstraints;
2641 std::vector<std::string> OutputConstraints;
2644 std::vector<llvm::Value *> Args;
2645 std::vector<llvm::Type *> ArgTypes;
2646 std::vector<llvm::Type *> ArgElemTypes;
2649 std::vector<LValue> ResultRegDests;
2650 std::vector<QualType> ResultRegQualTys;
2651 std::vector<llvm::Type *> ResultRegTypes;
2652 std::vector<llvm::Type *> ResultTruncRegTypes;
2654 llvm::BitVector ResultTypeRequiresCast;
2657 std::vector<llvm::Value *> InOutArgs;
2658 std::vector<llvm::Type *> InOutArgTypes;
2659 std::vector<llvm::Type *> InOutArgElemTypes;
2662 llvm::BasicBlock *DefaultDest =
nullptr;
2665 std::vector<std::optional<std::pair<unsigned, unsigned>>> ResultBounds;
2676 bool ReadOnly =
true;
2677 bool ReadNone =
true;
2679 bool GetOutputAndInputConstraints();
2680 void HandleOutputConstraints();
2681 void HandleMSStyleAsmBlob();
2682 void HandleInputConstraints();
2683 bool HandleLabels();
2684 bool HandleClobbers();
2685 void UpdateAsmCallInst(llvm::CallBase &
Result,
bool HasSideEffect,
2686 bool HasUnwindClobber,
bool NoMerge,
bool NoConvergent,
2687 std::vector<llvm::Value *> &RegResults);
2690 void EmitHipStdParUnsupportedAsm() {
2691 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2694 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2695 Asm = GCCAsm->getAsmString();
2697 auto &Ctx = getLLVMContext();
2698 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2699 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2700 {StrTy->getType()},
false);
2701 auto UBF = CGM.getModule().getOrInsertFunction(Name, FnTy);
2703 Builder.CreateCall(UBF, {StrTy});
2706 ASTContext &getContext() {
return CGF.getContext(); }
2707 llvm::LLVMContext &getLLVMContext() {
return CGF.getLLVMContext(); }
2708 const TargetInfo &getTarget()
const {
return CGF.getTarget(); }
2709 const LangOptions &getLangOpts()
const {
return CGF.getLangOpts(); }
2711 return CGM.getTargetCodeGenInfo();
2716 : CGF(CGF), CGM(CGF.CGM), S(S), Builder(CGF.Builder),
2717 AsmString(S.generateAsmString(CGF.getContext())) {}
2734 if (!GetOutputAndInputConstraints())
2735 return EmitHipStdParUnsupportedAsm();
2738 HandleOutputConstraints();
2742 HandleMSStyleAsmBlob();
2745 HandleInputConstraints();
2748 bool IsGCCAsmGoto = HandleLabels();
2751 bool HasUnwindClobber = HandleClobbers();
2752 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
2753 "unwind clobber can't be used with asm goto");
2756 std::string_view MachineClobbers = getTarget().getClobbers();
2757 if (!MachineClobbers.empty()) {
2758 if (!Constraints.empty())
2760 Constraints += MachineClobbers;
2763 llvm::Type *ResultType;
2764 if (ResultRegTypes.empty())
2765 ResultType = CGF.VoidTy;
2766 else if (ResultRegTypes.size() == 1)
2767 ResultType = ResultRegTypes[0];
2769 ResultType = llvm::StructType::get(getLLVMContext(), ResultRegTypes);
2771 llvm::FunctionType *FTy =
2772 llvm::FunctionType::get(ResultType, ArgTypes,
false);
2774 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
2776 llvm::InlineAsm::AsmDialect GnuAsmDialect =
2778 ? llvm::InlineAsm::AD_ATT
2779 : llvm::InlineAsm::AD_Intel;
2780 llvm::InlineAsm::AsmDialect AsmDialect =
2783 llvm::InlineAsm *IA = llvm::InlineAsm::get(
2784 FTy, AsmString, Constraints, HasSideEffect,
2785 false, AsmDialect, HasUnwindClobber);
2786 std::vector<llvm::Value *> RegResults;
2787 llvm::CallBrInst *CBR;
2788 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
2792 CBR = Builder.CreateCallBr(IA, DefaultDest, IndirectDests, Args);
2793 CGF.EmitBlock(DefaultDest);
2794 UpdateAsmCallInst(*CBR, HasSideEffect,
2795 false, CGF.InNoMergeAttributedStmt,
2796 CGF.InNoConvergentAttributedStmt, RegResults);
2801 if (!RegResults.empty()) {
2803 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
2804 llvm::Twine SynthName = Dest->getName() +
".split";
2805 llvm::BasicBlock *SynthBB = CGF.createBasicBlock(SynthName);
2806 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
2807 Builder.SetInsertPoint(SynthBB);
2809 if (ResultRegTypes.size() == 1) {
2810 CBRRegResults[SynthBB].push_back(CBR);
2812 for (
unsigned J = 0, E = ResultRegTypes.size(); J != E; ++J) {
2813 llvm::Value *Tmp = Builder.CreateExtractValue(CBR, J,
"asmresult");
2814 CBRRegResults[SynthBB].push_back(Tmp);
2818 CGF.EmitBranch(Dest);
2819 CGF.EmitBlock(SynthBB);
2820 CBR->setIndirectDest(I++, SynthBB);
2823 }
else if (HasUnwindClobber) {
2824 llvm::CallBase *
Result = CGF.EmitCallOrInvoke(IA, Args,
"");
2825 UpdateAsmCallInst(*
Result, HasSideEffect,
2826 true, CGF.InNoMergeAttributedStmt,
2827 CGF.InNoConvergentAttributedStmt, RegResults);
2830 Builder.CreateCall(IA, Args, CGF.getBundlesForFunclet(IA));
2831 UpdateAsmCallInst(*
Result, HasSideEffect,
2832 false, CGF.InNoMergeAttributedStmt,
2833 CGF.InNoConvergentAttributedStmt, RegResults);
2836 EmitAsmStores(RegResults);
2841 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
2842 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
2843 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
2844 Builder.SetInsertPoint(Succ, --(Succ->end()));
2845 EmitAsmStores(CBRRegResults[Succ]);
2853bool AsmConstraintsInfo::GetOutputAndInputConstraints() {
2854 bool IsValidTargetAsm =
true;
2855 bool IsHipStdPar = getLangOpts().HIPStdPar && getLangOpts().CUDAIsDevice;
2856 for (
unsigned I = 0, E = S.getNumOutputs(); I != E && IsValidTargetAsm; I++) {
2858 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2859 Name = GAS->getOutputName(I);
2863 bool IsValid = getTarget().validateOutputConstraint(Info);
2864 if (IsHipStdPar && !IsValid)
2865 IsValidTargetAsm =
false;
2867 assert(IsValid &&
"Failed to parse output constraint");
2869 OutputConstraintInfos.push_back(Info);
2872 for (
unsigned I = 0, E = S.getNumInputs(); I != E && IsValidTargetAsm; I++) {
2874 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2875 Name = GAS->getInputName(I);
2880 getTarget().validateInputConstraint(OutputConstraintInfos, Info);
2881 if (IsHipStdPar && !IsValid)
2882 IsValidTargetAsm =
false;
2884 assert(IsValid &&
"Failed to parse input constraint");
2886 InputConstraintInfos.push_back(Info);
2889 return IsValidTargetAsm;
2896void AsmConstraintsInfo::HandleOutputConstraints() {
2898 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2900 for (
unsigned I = 0, E = S.getNumOutputs(); I != E; I++) {
2901 TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[I];
2904 std::string OutputConstraint(S.getOutputConstraint(I));
2905 OutputConstraint = getTarget().simplifyConstraint(
2906 StringRef(OutputConstraint).substr(1), &OutputConstraintInfos);
2908 const Expr *OutExpr = S.getOutputExpr(I);
2912 OutputConstraint = S.addVariableConstraints(
2913 OutputConstraint, *OutExpr, getTarget(), Info.
earlyClobber(),
2914 [&](
const Stmt *UnspStmt, StringRef Msg) {
2915 CGM.ErrorUnsupported(UnspStmt, Msg);
2920 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2921 CGM.Error(S.getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2923 OutputConstraints.push_back(OutputConstraint);
2925 if (!Constraints.empty())
2930 QualType QTy = OutExpr->
getType();
2931 const bool IsScalarOrAggregate =
2936 Constraints +=
"=" + OutputConstraint;
2937 ResultRegQualTys.push_back(QTy);
2938 ResultRegDests.push_back(Dest);
2943 const bool RequiresCast =
2945 (getTargetHooks().isScalarizableAsmOperand(CGF, Ty) ||
2946 Ty->isAggregateType());
2948 ResultTruncRegTypes.push_back(Ty);
2949 ResultTypeRequiresCast.push_back(RequiresCast);
2952 if (
unsigned Size = getContext().getTypeSize(QTy))
2953 Ty = llvm::IntegerType::get(getLLVMContext(), Size);
2955 CGM.Error(OutExpr->
getExprLoc(),
"output size should not be zero");
2958 ResultRegTypes.push_back(Ty);
2965 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2966 TargetInfo::ConstraintInfo &Input = InputConstraintInfos[InputNo];
2970 assert(InputNo != S.getNumInputs() &&
"Didn't find matching input!");
2972 QualType
InputTy = S.getInputExpr(InputNo)->getType();
2973 QualType OutputType = OutExpr->
getType();
2975 uint64_t InputSize = getContext().getTypeSize(InputTy);
2976 if (getContext().getTypeSize(OutputType) < InputSize)
2981 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
2982 CGF, OutputConstraint, ResultRegTypes.back()))
2983 ResultRegTypes.back() = AdjTy;
2985 CGM.getDiags().Report(S.getAsmLoc(),
2986 diag::err_asm_invalid_type_in_input)
2987 << OutExpr->
getType() << OutputConstraint;
2990 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
2991 CGF.LargestVectorWidth =
2992 std::max((uint64_t)CGF.LargestVectorWidth,
2993 VT->getPrimitiveSizeInBits().getKnownMinValue());
2995 Address DestAddr = Dest.getAddress();
3006 ArgTypes.push_back(DestAddr.
getType());
3010 Constraints +=
"=*" + OutputConstraint;
3018 InOutConstraints +=
',';
3020 const Expr *InputExpr = S.getOutputExpr(I);
3022 llvm::Type *ArgElemType;
3023 std::tie(Arg, ArgElemType) =
3024 CGF.EmitAsmInputLValue(Info, Dest, InputExpr->
getType(),
3027 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
3028 CGF, OutputConstraint, Arg->getType()))
3029 Arg = Builder.CreateBitCast(Arg, AdjTy);
3032 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3033 CGF.LargestVectorWidth =
3034 std::max((uint64_t)CGF.LargestVectorWidth,
3035 VT->getPrimitiveSizeInBits().getKnownMinValue());
3039 InOutConstraints += llvm::utostr(I);
3041 InOutConstraints += OutputConstraint;
3043 InOutArgTypes.push_back(Arg->getType());
3044 InOutArgElemTypes.push_back(ArgElemType);
3045 InOutArgs.push_back(Arg);
3052void AsmConstraintsInfo::HandleMSStyleAsmBlob() {
3063 CGM.getTargetCodeGenInfo().addReturnRegisterOutputs(
3064 CGF, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
3065 ResultRegDests, AsmString, S.getNumOutputs());
3072void AsmConstraintsInfo::HandleInputConstraints() {
3073 ASTContext &Ctx = getContext();
3075 for (
unsigned I = 0, E = S.getNumInputs(); I != E; I++) {
3076 TargetInfo::ConstraintInfo &Info = InputConstraintInfos[I];
3077 const Expr *InputExpr = S.getInputExpr(I);
3082 if (!Constraints.empty())
3086 std::string InputConstraint(S.getInputConstraint(I));
3088 getTarget().simplifyConstraint(InputConstraint, &OutputConstraintInfos);
3090 InputConstraint = S.addVariableConstraints(
3093 [&](
const Stmt *UnspStmt, std::string_view Msg) {
3094 CGM.ErrorUnsupported(UnspStmt, Msg);
3097 std::string ReplaceConstraint(InputConstraint);
3099 llvm::Type *ArgElemType;
3100 std::tie(Arg, ArgElemType) = CGF.EmitAsmInput(Info, InputExpr, Constraints);
3109 QualType OutputType = S.getOutputExpr(Output)->getType();
3115 Arg = Builder.CreatePtrToInt(Arg, CGF.
IntPtrTy);
3117 llvm::Type *OutputTy = CGF.
ConvertType(OutputType);
3119 Arg = Builder.CreateZExt(Arg, OutputTy);
3121 Arg = Builder.CreateZExt(Arg, CGF.
IntPtrTy);
3122 else if (OutputTy->isFloatingPointTy())
3123 Arg = Builder.CreateFPExt(Arg, OutputTy);
3127 ReplaceConstraint = OutputConstraints[Output];
3130 if (llvm::Type *AdjTy = getTargetHooks().adjustInlineAsmType(
3131 CGF, ReplaceConstraint, Arg->getType()))
3132 Arg = Builder.CreateBitCast(Arg, AdjTy);
3134 CGM.getDiags().Report(S.getAsmLoc(), diag::err_asm_invalid_type_in_input)
3135 << InputExpr->
getType() << InputConstraint;
3138 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3139 CGF.LargestVectorWidth =
3140 std::max((uint64_t)CGF.LargestVectorWidth,
3141 VT->getPrimitiveSizeInBits().getKnownMinValue());
3143 ArgTypes.push_back(Arg->getType());
3144 ArgElemTypes.push_back(ArgElemType);
3145 Args.push_back(Arg);
3147 Constraints += InputConstraint;
3151 for (
unsigned I = 0, E = InOutArgs.size(); I != E; I++) {
3152 ArgTypes.push_back(InOutArgTypes[I]);
3153 ArgElemTypes.push_back(InOutArgElemTypes[I]);
3154 Args.push_back(InOutArgs[I]);
3157 Constraints += InOutConstraints;
3163bool AsmConstraintsInfo::HandleLabels() {
3164 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S); GS && GS->isAsmGoto()) {
3165 for (
const auto *E : GS->labels()) {
3167 IndirectDests.push_back(Dest.
getBlock());
3169 if (!Constraints.empty())
3172 Constraints +=
"!i";
3186bool AsmConstraintsInfo::HandleClobbers() {
3187 bool HasUnwindClobber =
false;
3188 for (
unsigned I = 0, E = S.getNumClobbers(); I != E; I++) {
3189 std::string Clobber = S.getClobber(I);
3191 if (Clobber ==
"unwind") {
3192 HasUnwindClobber =
true;
3196 if (Clobber ==
"memory") {
3199 }
else if (Clobber !=
"cc") {
3200 Clobber = getTarget().getNormalizedGCCRegisterName(Clobber);
3201 if (CGM.getCodeGenOpts().StackClashProtector &&
3202 getTarget().isSPRegName(Clobber)) {
3203 CGM.getDiags().Report(S.getAsmLoc(),
3204 diag::warn_stack_clash_protection_inline_asm);
3209 if (Clobber ==
"eax" || Clobber ==
"edx") {
3210 if (Constraints.find(
"=&A") != std::string::npos)
3213 std::string::size_type position1 =
3214 Constraints.find(
"={" + Clobber +
"}");
3215 if (position1 != std::string::npos) {
3216 Constraints.insert(position1 + 1,
"&");
3220 std::string::size_type position2 = Constraints.find(
"=A");
3221 if (position2 != std::string::npos) {
3222 Constraints.insert(position2 + 1,
"&");
3228 if (!Constraints.empty())
3231 Constraints +=
"~{" + Clobber +
'}';
3234 return HasUnwindClobber;
3237void AsmConstraintsInfo::UpdateAsmCallInst(
3238 llvm::CallBase &
Result,
bool HasSideEffect,
bool HasUnwindClobber,
3239 bool NoMerge,
bool NoConvergent, std::vector<llvm::Value *> &RegResults) {
3240 if (!HasUnwindClobber)
3241 Result.addFnAttr(llvm::Attribute::NoUnwind);
3244 Result.addFnAttr(llvm::Attribute::NoMerge);
3247 if (!HasSideEffect) {
3249 Result.setDoesNotAccessMemory();
3251 Result.setOnlyReadsMemory();
3255 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
3257 auto Attr = llvm::Attribute::get(
3258 getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
3259 Result.addParamAttr(Pair.index(), Attr);
3265 const StringLiteral *SL;
3266 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S);
3268 (SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))) {
3273 llvm::Constant *Loc =
3274 llvm::ConstantInt::get(CGF.
Int64Ty, S.getAsmLoc().getRawEncoding());
3275 Result.setMetadata(
"srcloc",
3276 llvm::MDNode::get(getLLVMContext(),
3277 llvm::ConstantAsMetadata::get(Loc)));
3283 if (!NoConvergent && getLangOpts().assumeFunctionsAreConvergent())
3288 Result.addFnAttr(llvm::Attribute::Convergent);
3291 if (ResultRegTypes.size() == 1) {
3292 RegResults.push_back(&
Result);
3294 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
3295 llvm::Value *Tmp = Builder.CreateExtractValue(&
Result, i,
"asmresult");
3296 RegResults.push_back(Tmp);
3301void AsmConstraintsInfo::EmitAsmStores(
3302 const llvm::ArrayRef<llvm::Value *> RegResults) {
3303 llvm::LLVMContext &CTX = getLLVMContext();
3305 assert(RegResults.size() == ResultRegTypes.size());
3306 assert(RegResults.size() == ResultTruncRegTypes.size());
3307 assert(RegResults.size() == ResultRegDests.size());
3311 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
3312 assert(ResultBounds.size() <= ResultRegDests.size());
3314 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
3315 llvm::Value *Tmp = RegResults[i];
3316 llvm::Type *TruncTy = ResultTruncRegTypes[i];
3318 if (i < ResultBounds.size() && ResultBounds[i].has_value()) {
3319 const auto [LowerBound, UpperBound] = ResultBounds[i].value();
3322 assert(LowerBound == 0 &&
"Output operand lower bound is not zero.");
3324 llvm::Constant *UpperBoundConst =
3325 llvm::ConstantInt::get(Tmp->getType(), UpperBound);
3326 llvm::Value *IsBooleanValue =
3327 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, UpperBoundConst);
3328 llvm::Function *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume);
3330 Builder.CreateCall(FnAssume, IsBooleanValue);
3335 if (ResultRegTypes[i] != TruncTy) {
3338 if (TruncTy->isFloatingPointTy())
3339 Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
3340 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
3341 uint64_t ResSize = CGM.getDataLayout().getTypeSizeInBits(TruncTy);
3342 Tmp = Builder.CreateTrunc(
3343 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
3344 Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
3345 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
3347 CGM.getDataLayout().getTypeSizeInBits(Tmp->getType());
3348 Tmp = Builder.CreatePtrToInt(
3349 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
3350 Tmp = Builder.CreateTrunc(Tmp, TruncTy);
3351 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
3352 Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
3353 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
3354 Tmp = Builder.CreateBitCast(Tmp, TruncTy);
3359 LValue Dest = ResultRegDests[i];
3363 if (i < ResultTypeRequiresCast.size() && ResultTypeRequiresCast[i]) {
3364 unsigned Size = getContext().getTypeSize(ResultRegQualTys[i]);
3365 Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
3367 if (getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) {
3368 llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
3373 QualType Ty = getContext().getIntTypeForBitwidth(Size,
false);
3375 const Expr *OutExpr = S.getOutputExpr(i);
3377 diag::err_store_value_to_reg);
3399 I != E; ++I, ++CurField) {
3401 if (CurField->hasCapturedVLAType()) {
3418 CodeGenFunction CGF(
CGM,
true);
3438 "CapturedStmtInfo should be set when generating the captured function");
3442 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3451 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Args);
3452 llvm::FunctionType *FuncLLVMTy =
CGM.getTypes().GetFunctionType(FuncInfo);
3455 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3457 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
3458 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
3459 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3461 F->addFnAttr(llvm::Attribute::NoUnwind);
3473 for (
auto *FD : RD->
fields()) {
3474 if (FD->hasCapturedVLAType()) {
3478 auto VAT = FD->getCapturedVLAType();
3479 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3490 PGO->assignRegionCounters(
GlobalDecl(CD), F);
3500 for (
auto &I : *BB) {
3501 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3508CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3509 llvm::ConvergenceControlInst *ParentToken = ConvergenceTokenStack.back();
3510 assert(ParentToken);
3512 llvm::Value *bundleArgs[] = {ParentToken};
3513 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3514 auto *Output = llvm::CallBase::addOperandBundle(
3515 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3516 Input->replaceAllUsesWith(Output);
3517 Input->eraseFromParent();
3521llvm::ConvergenceControlInst *
3524 assert(ParentToken);
3525 return llvm::ConvergenceControlInst::CreateLoop(*BB, ParentToken);
3528llvm::ConvergenceControlInst *
3529CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3530 llvm::BasicBlock *BB = &F->getEntryBlock();
3538 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.
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 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