28#include "llvm/ADT/ArrayRef.h"
29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/SmallSet.h"
31#include "llvm/ADT/StringExtras.h"
32#include "llvm/IR/Assumptions.h"
33#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/InlineAsm.h"
35#include "llvm/IR/Intrinsics.h"
36#include "llvm/IR/MDBuilder.h"
37#include "llvm/Support/SaveAndRestore.h"
62 assert(S &&
"Null statement?");
63 PGO->setCurrentStmt(S);
80 PGO->markStmtMaybeUsed(S);
94 if (
const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
102 case Stmt::CXXCatchStmtClass:
103 case Stmt::SEHExceptStmtClass:
104 case Stmt::SEHFinallyStmtClass:
105 case Stmt::MSDependentExistsStmtClass:
106 llvm_unreachable(
"invalid statement class to emit generically");
107 case Stmt::NullStmtClass:
108 case Stmt::CompoundStmtClass:
109 case Stmt::DeclStmtClass:
110 case Stmt::LabelStmtClass:
111 case Stmt::AttributedStmtClass:
112 case Stmt::GotoStmtClass:
113 case Stmt::BreakStmtClass:
114 case Stmt::ContinueStmtClass:
115 case Stmt::DefaultStmtClass:
116 case Stmt::CaseStmtClass:
117 case Stmt::DeferStmtClass:
118 case Stmt::SEHLeaveStmtClass:
119 case Stmt::SYCLKernelCallStmtClass:
120 llvm_unreachable(
"should have emitted these statements as simple");
122#define STMT(Type, Base)
123#define ABSTRACT_STMT(Op)
124#define EXPR(Type, Base) \
125 case Stmt::Type##Class:
126#include "clang/AST/StmtNodes.inc"
129 llvm::BasicBlock *incoming =
Builder.GetInsertBlock();
130 assert(incoming &&
"expression emission must have an insertion point");
134 llvm::BasicBlock *outgoing =
Builder.GetInsertBlock();
135 assert(outgoing &&
"expression emission cleared block!");
149 if (incoming != outgoing && outgoing->use_empty()) {
150 outgoing->eraseFromParent();
156 case Stmt::IndirectGotoStmtClass:
167 case Stmt::GCCAsmStmtClass:
169 case Stmt::CoroutineBodyStmtClass:
172 case Stmt::CoreturnStmtClass:
175 case Stmt::CapturedStmtClass: {
180 case Stmt::ObjCAtTryStmtClass:
183 case Stmt::ObjCAtCatchStmtClass:
185 "@catch statements should be handled by EmitObjCAtTryStmt");
186 case Stmt::ObjCAtFinallyStmtClass:
188 "@finally statements should be handled by EmitObjCAtTryStmt");
189 case Stmt::ObjCAtThrowStmtClass:
192 case Stmt::ObjCAtSynchronizedStmtClass:
195 case Stmt::ObjCForCollectionStmtClass:
198 case Stmt::ObjCAutoreleasePoolStmtClass:
202 case Stmt::CXXTryStmtClass:
205 case Stmt::CXXForRangeStmtClass:
208 case Stmt::SEHTryStmtClass:
211 case Stmt::OMPMetaDirectiveClass:
214 case Stmt::OMPCanonicalLoopClass:
217 case Stmt::OMPParallelDirectiveClass:
220 case Stmt::OMPSimdDirectiveClass:
223 case Stmt::OMPTileDirectiveClass:
226 case Stmt::OMPStripeDirectiveClass:
229 case Stmt::OMPUnrollDirectiveClass:
232 case Stmt::OMPReverseDirectiveClass:
235 case Stmt::OMPInterchangeDirectiveClass:
238 case Stmt::OMPFuseDirectiveClass:
241 case Stmt::OMPForDirectiveClass:
244 case Stmt::OMPForSimdDirectiveClass:
247 case Stmt::OMPSectionsDirectiveClass:
250 case Stmt::OMPSectionDirectiveClass:
253 case Stmt::OMPSingleDirectiveClass:
256 case Stmt::OMPMasterDirectiveClass:
259 case Stmt::OMPCriticalDirectiveClass:
262 case Stmt::OMPParallelForDirectiveClass:
265 case Stmt::OMPParallelForSimdDirectiveClass:
268 case Stmt::OMPParallelMasterDirectiveClass:
271 case Stmt::OMPParallelSectionsDirectiveClass:
274 case Stmt::OMPTaskDirectiveClass:
277 case Stmt::OMPTaskyieldDirectiveClass:
280 case Stmt::OMPErrorDirectiveClass:
283 case Stmt::OMPBarrierDirectiveClass:
286 case Stmt::OMPTaskwaitDirectiveClass:
289 case Stmt::OMPTaskgroupDirectiveClass:
292 case Stmt::OMPFlushDirectiveClass:
295 case Stmt::OMPDepobjDirectiveClass:
298 case Stmt::OMPScanDirectiveClass:
301 case Stmt::OMPOrderedDirectiveClass:
304 case Stmt::OMPAtomicDirectiveClass:
307 case Stmt::OMPTargetDirectiveClass:
310 case Stmt::OMPTeamsDirectiveClass:
313 case Stmt::OMPCancellationPointDirectiveClass:
316 case Stmt::OMPCancelDirectiveClass:
319 case Stmt::OMPTargetDataDirectiveClass:
322 case Stmt::OMPTargetEnterDataDirectiveClass:
325 case Stmt::OMPTargetExitDataDirectiveClass:
328 case Stmt::OMPTargetParallelDirectiveClass:
331 case Stmt::OMPTargetParallelForDirectiveClass:
334 case Stmt::OMPTaskLoopDirectiveClass:
337 case Stmt::OMPTaskLoopSimdDirectiveClass:
340 case Stmt::OMPMasterTaskLoopDirectiveClass:
343 case Stmt::OMPMaskedTaskLoopDirectiveClass:
346 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
350 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
354 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
358 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
362 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
366 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
370 case Stmt::OMPDistributeDirectiveClass:
373 case Stmt::OMPTargetUpdateDirectiveClass:
376 case Stmt::OMPDistributeParallelForDirectiveClass:
380 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
384 case Stmt::OMPDistributeSimdDirectiveClass:
387 case Stmt::OMPTargetParallelForSimdDirectiveClass:
391 case Stmt::OMPTargetSimdDirectiveClass:
394 case Stmt::OMPTeamsDistributeDirectiveClass:
397 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
401 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
405 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
409 case Stmt::OMPTargetTeamsDirectiveClass:
412 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
416 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
420 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
424 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
428 case Stmt::OMPInteropDirectiveClass:
431 case Stmt::OMPDispatchDirectiveClass:
432 CGM.ErrorUnsupported(S,
"OpenMP dispatch directive");
434 case Stmt::OMPScopeDirectiveClass:
437 case Stmt::OMPMaskedDirectiveClass:
440 case Stmt::OMPGenericLoopDirectiveClass:
443 case Stmt::OMPTeamsGenericLoopDirectiveClass:
446 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
450 case Stmt::OMPParallelGenericLoopDirectiveClass:
454 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
458 case Stmt::OMPParallelMaskedDirectiveClass:
461 case Stmt::OMPAssumeDirectiveClass:
464 case Stmt::OpenACCComputeConstructClass:
467 case Stmt::OpenACCLoopConstructClass:
470 case Stmt::OpenACCCombinedConstructClass:
473 case Stmt::OpenACCDataConstructClass:
476 case Stmt::OpenACCEnterDataConstructClass:
479 case Stmt::OpenACCExitDataConstructClass:
482 case Stmt::OpenACCHostDataConstructClass:
485 case Stmt::OpenACCWaitConstructClass:
488 case Stmt::OpenACCInitConstructClass:
491 case Stmt::OpenACCShutdownConstructClass:
494 case Stmt::OpenACCSetConstructClass:
497 case Stmt::OpenACCUpdateConstructClass:
500 case Stmt::OpenACCAtomicConstructClass:
503 case Stmt::OpenACCCacheConstructClass:
514 case Stmt::NullStmtClass:
516 case Stmt::CompoundStmtClass:
519 case Stmt::DeclStmtClass:
522 case Stmt::LabelStmtClass:
525 case Stmt::AttributedStmtClass:
528 case Stmt::GotoStmtClass:
531 case Stmt::BreakStmtClass:
534 case Stmt::ContinueStmtClass:
537 case Stmt::DefaultStmtClass:
540 case Stmt::CaseStmtClass:
543 case Stmt::DeferStmtClass:
546 case Stmt::SEHLeaveStmtClass:
549 case Stmt::SYCLKernelCallStmtClass:
576 "LLVM IR generation of compound statement ('{}')");
603 if (
const auto *LS = dyn_cast<LabelStmt>(LastStmt)) {
605 LastStmt = LS->getSubStmt();
606 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(LastStmt)) {
609 LastStmt = AS->getSubStmt();
611 llvm_unreachable(
"unknown value statement");
635 llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
644 if (!BI || !BI->isUnconditional())
648 if (BI->getIterator() != BB->begin())
651 BB->replaceAllUsesWith(BI->getSuccessor(0));
652 BI->eraseFromParent();
653 BB->eraseFromParent();
657 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
662 if (IsFinished && BB->use_empty()) {
669 if (CurBB && CurBB->getParent())
670 CurFn->insert(std::next(CurBB->getIterator()), BB);
680 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
682 if (!CurBB || CurBB->getTerminator()) {
694 bool inserted =
false;
695 for (llvm::User *u : block->users()) {
696 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
697 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
712 if (Dest.
isValid())
return Dest;
725 if (
EHStack.hasNormalCleanups() && CurLexicalScope)
726 CurLexicalScope->addLabel(D);
747 if (
CGM.getCodeGenOpts().hasReducedDebugInfo()) {
759 assert(!Labels.empty());
761 =
CGF.EHStack.getInnermostNormalCleanup();
765 assert(
CGF.LabelMap.count(Label));
774 ParentScope->Labels.append(Labels.begin(), Labels.end());
790 bool nomerge =
false;
791 bool noinline =
false;
792 bool alwaysinline =
false;
793 bool noconvergent =
false;
794 HLSLControlFlowHintAttr::Spelling flattenOrBranch =
795 HLSLControlFlowHintAttr::SpellingNotCalculated;
797 const AtomicAttr *AA =
nullptr;
799 for (
const auto *A : S.
getAttrs()) {
800 switch (A->getKind()) {
809 case attr::AlwaysInline:
812 case attr::NoConvergent:
815 case attr::MustTail: {
820 case attr::CXXAssume: {
825 Builder.CreateAssumption(AssumptionVal);
831 case attr::HLSLControlFlowHint: {
868 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
878 if (CurBB && CurBB->getTerminator())
914 const Stmt *Skipped = Else;
916 std::swap(Executed, Skipped);
928 PGO->markStmtMaybeUsed(Skipped);
937 llvm::BasicBlock *ElseBlock = ContBlock;
955 CGM.getCodeGenOpts().OptimizationLevel)
964 if (!
CGM.getCodeGenOpts().MCDCCoverage) {
971 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
1017 bool HasEmptyBody) {
1018 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1028 bool CondIsConstInt =
1029 !ControllingExpression ||
1033 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
1034 Result.Val.getInt().getBoolValue());
1045 if (
CGM.getCodeGenOpts().getFiniteLoops() ==
1048 if (HasEmptyBody && CondIsTrue) {
1049 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1067 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1071 const Stmt *Body = S.getBody();
1074 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
1075 return Compound->body_empty();
1086 if (
CGM.shouldEmitConvergenceTokens())
1088 emitConvergenceLoopToken(LoopHeader.
getBlock()));
1095 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopHeader));
1118 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1119 bool EmitBoolCondBranch = !
C || !
C->isOne();
1132 if (EmitBoolCondBranch) {
1133 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1136 llvm::MDNode *Weights =
1138 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1139 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1141 auto *I =
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1147 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1151 if (ExitBlock !=
LoopExit.getBlock()) {
1156 CGM.getDiags().Report(A->getLocation(),
1157 diag::warn_attribute_has_no_effect_on_infinite_loop)
1158 << A << A->getRange();
1159 CGM.getDiags().Report(
1161 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1178 BreakContinueStack.pop_back();
1194 if (!EmitBoolCondBranch)
1202 if (
CGM.shouldEmitConvergenceTokens())
1214 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopCond));
1224 if (
CGM.shouldEmitConvergenceTokens())
1245 BreakContinueStack.pop_back();
1249 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1250 bool EmitBoolCondBranch = !
C || !
C->isZero();
1253 LoopStack.push(LoopBody,
CGM.getContext(),
CGM.getCodeGenOpts(), DoAttrs,
1259 if (EmitBoolCondBranch) {
1261 auto *I =
Builder.CreateCondBr(
1262 BoolCondVal, LoopBody,
LoopExit.getBlock(),
1263 createProfileWeightsForLoop(S.
getCond(), BackedgeCount));
1270 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1282 if (!EmitBoolCondBranch)
1290 if (
CGM.shouldEmitConvergenceTokens())
1298 std::optional<LexicalScope> ForScope;
1310 llvm::BasicBlock *CondBlock = CondDest.
getBlock();
1313 if (
CGM.shouldEmitConvergenceTokens())
1317 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1334 Continue = CondDest;
1337 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1348 BreakContinueStack.back().ContinueBlock = Continue;
1356 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1359 if (ForScope && ForScope->requiresCleanups())
1371 llvm::MDNode *Weights =
1373 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1374 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1377 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1382 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1386 if (ExitBlock !=
LoopExit.getBlock()) {
1411 auto *FinalBodyBB =
Builder.GetInsertBlock();
1421 BreakContinueStack.pop_back();
1429 ForScope->ForceCleanup();
1441 if (
CGM.shouldEmitConvergenceTokens())
1471 if (
CGM.shouldEmitConvergenceTokens())
1475 LoopStack.push(CondBlock,
CGM.getContext(),
CGM.getCodeGenOpts(), ForAttrs,
1481 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1491 llvm::MDNode *Weights =
1493 if (!Weights &&
CGM.getCodeGenOpts().OptimizationLevel)
1494 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1496 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1501 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1505 if (ExitBlock !=
LoopExit.getBlock()) {
1520 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1530 auto *FinalBodyBB =
Builder.GetInsertBlock();
1537 BreakContinueStack.pop_back();
1553 if (
CGM.shouldEmitConvergenceTokens())
1563void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1579struct SaveRetExprRAII {
1580 SaveRetExprRAII(
const Expr *RetExpr, CodeGenFunction &CGF)
1581 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1584 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1585 const Expr *OldRetExpr;
1586 CodeGenFunction &CGF;
1594 if (calleeQualType->isFunctionPointerType() ||
1595 calleeQualType->isFunctionReferenceType() ||
1596 calleeQualType->isBlockPointerType() ||
1597 calleeQualType->isMemberFunctionPointerType()) {
1599 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1601 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1602 if (
auto methodDecl = CMCE->getMethodDecl()) {
1619 if (requiresReturnValueCheck()) {
1622 new llvm::GlobalVariable(
CGM.getModule(), SLoc->getType(),
false,
1623 llvm::GlobalVariable::PrivateLinkage, SLoc);
1624 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1625 CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
1626 assert(ReturnLocation.isValid() &&
"No valid return location");
1627 Builder.CreateStore(SLocPtr, ReturnLocation);
1633 Builder.ClearInsertionPoint();
1647 SaveRetExprRAII SaveRetExpr(RV, *
this);
1650 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1651 RV = EWC->getSubExpr();
1655 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1658 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1671 !
CGM.getOpenMPRuntime()
1690 }
else if (
FnRetTy->isReferenceType()) {
1726 ++NumSimpleReturnExprs;
1738 for (
const auto *I : S.
decls())
1743 ->
const BreakContinue * {
1744 if (!S.hasLabelTarget())
1745 return &BreakContinueStack.back();
1747 const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
1748 assert(LoopOrSwitch &&
"break/continue target not set?");
1749 for (
const BreakContinue &BC : llvm::reverse(BreakContinueStack))
1750 if (BC.LoopOrSwitch == LoopOrSwitch)
1753 llvm_unreachable(
"break/continue target not found");
1757 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1770 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1787 assert(S.
getRHS() &&
"Expected RHS value in CaseStmt");
1800 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1804 llvm::APInt Range = RHS - LHS;
1806 if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
1809 unsigned NCases = Range.getZExtValue() + 1;
1814 uint64_t Weight = Total / NCases, Rem = Total % NCases;
1815 for (
unsigned I = 0; I != NCases; ++I) {
1817 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1818 else if (SwitchLikelihood)
1819 SwitchLikelihood->push_back(LH);
1823 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1831 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1836 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1840 Builder.SetInsertPoint(CaseRangeBlock);
1844 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1848 llvm::MDNode *Weights =
nullptr;
1849 if (SwitchWeights) {
1851 uint64_t DefaultCount = (*SwitchWeights)[0];
1852 Weights = createProfileWeights(ThisCount, DefaultCount);
1857 (*SwitchWeights)[0] += ThisCount;
1858 }
else if (SwitchLikelihood)
1859 Cond = emitCondLikelihoodViaExpectIntrinsic(
Cond, LH);
1861 Builder.CreateCondBr(
Cond, CaseDest, FalseDest, Weights);
1865 Builder.SetInsertPoint(RestoreBB);
1867 Builder.ClearInsertionPoint();
1888 llvm::ConstantInt *CaseVal =
1893 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.
getLHS()))
1894 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1896 CE = dyn_cast<ConstantExpr>(S.
getLHS());
1898 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1900 if (
CGM.getCodeGenOpts().hasReducedDebugInfo())
1901 Dbg->EmitGlobalVariable(DE->getDecl(),
1902 APValue(llvm::APSInt(CaseVal->getValue())));
1905 if (SwitchLikelihood)
1911 if (!
CGM.getCodeGenOpts().hasProfileClangInstr() &&
1912 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1920 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1924 if (
Builder.GetInsertBlock()) {
1926 Builder.ClearInsertionPoint();
1936 SwitchInsn->addCase(CaseVal, CaseDest);
1955 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1957 llvm::ConstantInt *CaseVal =
1962 if (
CGM.getCodeGenOpts().hasProfileClangInstr()) {
1968 if (SwitchLikelihood)
1971 SwitchInsn->addCase(CaseVal, CaseDest);
1972 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1995 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1996 assert(DefaultBlock->empty() &&
1997 "EmitDefaultStmt: Default block already defined?");
1999 if (SwitchLikelihood)
2008struct EmitDeferredStatement final : EHScopeStack::Cleanup {
2068 llvm::Value *SavedCleanupDest =
nullptr;
2122 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
2141 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
2145 bool StartedInLiveCode = FoundCase;
2146 unsigned StartSize = ResultStmts.size();
2153 bool HadSkippedDecl =
false;
2157 for (; Case && I != E; ++I) {
2173 for (++I; I != E; ++I)
2183 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
2198 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
2203 bool AnyDecls =
false;
2204 for (; I != E; ++I) {
2217 for (++I; I != E; ++I)
2234 ResultStmts.resize(StartSize);
2235 ResultStmts.push_back(S);
2259 ResultStmts.push_back(S);
2268 const llvm::APSInt &ConstantCondValue,
2280 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2288 if (CS->
getRHS())
return false;
2313 bool FoundCase =
false;
2320static std::optional<SmallVector<uint64_t, 16>>
2323 if (Likelihoods.size() <= 1)
2324 return std::nullopt;
2326 uint64_t NumUnlikely = 0;
2327 uint64_t NumNone = 0;
2328 uint64_t NumLikely = 0;
2329 for (
const auto LH : Likelihoods) {
2344 if (NumUnlikely == 0 && NumLikely == 0)
2345 return std::nullopt;
2353 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2354 const uint64_t
None = Likely / (NumNone + 1);
2355 const uint64_t Unlikely = 0;
2358 Result.reserve(Likelihoods.size());
2359 for (
const auto LH : Likelihoods) {
2362 Result.push_back(Unlikely);
2365 Result.push_back(
None);
2368 Result.push_back(Likely);
2378 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2381 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2385 llvm::APSInt ConstantCondValue;
2406 SwitchInsn =
nullptr;
2413 PGO->markStmtMaybeUsed(S.
getBody());
2417 SwitchInsn = SavedSwitchInsn;
2440 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2444 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2445 llvm::ConstantInt *BranchHintConstant =
2447 HLSLControlFlowHintAttr::Spelling::Microsoft_branch
2448 ? llvm::ConstantInt::get(
CGM.Int32Ty, 1)
2449 : llvm::ConstantInt::get(
CGM.Int32Ty, 2);
2450 llvm::Metadata *Vals[] = {MDHelper.createString(
"hlsl.controlflow.hint"),
2451 MDHelper.createConstant(BranchHintConstant)};
2452 SwitchInsn->setMetadata(
"hlsl.controlflow.hint",
2453 llvm::MDNode::get(
CGM.getLLVMContext(), Vals));
2456 if (PGO->haveRegionCounts()) {
2458 uint64_t DefaultCount = 0;
2459 unsigned NumCases = 0;
2468 SwitchWeights->reserve(NumCases);
2471 SwitchWeights->push_back(DefaultCount);
2472 }
else if (
CGM.getCodeGenOpts().OptimizationLevel) {
2478 CaseRangeBlock = DefaultBlock;
2481 Builder.ClearInsertionPoint();
2486 if (!BreakContinueStack.empty())
2487 OuterContinue = BreakContinueStack.back().ContinueBlock;
2489 BreakContinueStack.push_back(BreakContinue(S, SwitchExit, OuterContinue));
2494 BreakContinueStack.pop_back();
2498 SwitchInsn->setDefaultDest(CaseRangeBlock);
2501 if (!DefaultBlock->getParent()) {
2509 DefaultBlock->replaceAllUsesWith(SwitchExit.
getBlock());
2510 delete DefaultBlock;
2524 if (
Call &&
CGM.getCodeGenOpts().OptimizationLevel != 0) {
2525 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2526 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2528 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2529 MDHelper.createUnpredictable());
2533 if (SwitchWeights) {
2534 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2535 "switch weights do not match switch cases");
2537 if (SwitchWeights->size() > 1)
2538 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2539 createProfileWeights(*SwitchWeights));
2540 delete SwitchWeights;
2541 }
else if (SwitchLikelihood) {
2542 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2543 "switch likelihoods do not match switch cases");
2544 std::optional<SmallVector<uint64_t, 16>> LHW =
2547 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
2548 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2549 createProfileWeights(*LHW));
2551 delete SwitchLikelihood;
2553 SwitchInsn = SavedSwitchInsn;
2554 SwitchWeights = SavedSwitchWeights;
2555 SwitchLikelihood = SavedSwitchLikelihood;
2556 CaseRangeBlock = SavedCRBlock;
2566 std::string *GCCReg =
nullptr) {
2567 const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
2576 AsmLabelAttr *
Attr = Variable->getAttr<AsmLabelAttr>();
2579 StringRef Register =
Attr->getLabel();
2580 assert(
Target.isValidGCCRegisterName(Register));
2584 if (
Target.validateOutputConstraint(Info) &&
2590 Register =
Target.getNormalizedGCCRegisterName(Register);
2591 if (GCCReg !=
nullptr)
2592 *GCCReg = Register.str();
2593 return (EarlyClobber ?
"&{" :
"{") + Register.str() +
"}";
2596std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2597 const TargetInfo::ConstraintInfo &Info, LValue InputValue,
2598 QualType InputType, std::string &ConstraintStr, SourceLocation Loc) {
2605 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2609 return {
Builder.CreateLoad(InputValue.getAddress().withElementType(Ty)),
2614 Address
Addr = InputValue.getAddress();
2615 ConstraintStr +=
'*';
2616 return {InputValue.getPointer(*
this),
Addr.getElementType()};
2619std::pair<llvm::Value *, llvm::Type *>
2620CodeGenFunction::EmitAsmInput(
const TargetInfo::ConstraintInfo &Info,
2621 const Expr *InputExpr,
2622 std::string &ConstraintStr) {
2627 Expr::EvalResult EVResult;
2630 llvm::APSInt IntResult;
2633 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2645 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2649 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2661 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2664 if (!StrVal.empty()) {
2667 unsigned StartToken = 0;
2668 unsigned ByteOffset = 0;
2672 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2673 if (StrVal[i] !=
'\n')
continue;
2675 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2676 Locs.push_back(llvm::ConstantAsMetadata::get(
2685 bool HasUnwindClobber,
bool ReadOnly,
2686 bool ReadNone,
bool NoMerge,
bool NoConvergent,
2688 const std::vector<llvm::Type *> &ResultRegTypes,
2689 const std::vector<llvm::Type *> &ArgElemTypes,
2691 std::vector<llvm::Value *> &RegResults) {
2692 if (!HasUnwindClobber)
2693 Result.addFnAttr(llvm::Attribute::NoUnwind);
2696 Result.addFnAttr(llvm::Attribute::NoMerge);
2698 if (!HasSideEffect) {
2700 Result.setDoesNotAccessMemory();
2702 Result.setOnlyReadsMemory();
2706 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
2708 auto Attr = llvm::Attribute::get(
2709 CGF.
getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2710 Result.addParamAttr(Pair.index(),
Attr);
2717 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S);
2719 (SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))) {
2724 llvm::Constant *Loc =
2726 Result.setMetadata(
"srcloc",
2728 llvm::ConstantAsMetadata::get(Loc)));
2739 Result.addFnAttr(llvm::Attribute::Convergent);
2741 if (ResultRegTypes.size() == 1) {
2742 RegResults.push_back(&Result);
2744 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2745 llvm::Value *Tmp = CGF.
Builder.CreateExtractValue(&Result, i,
"asmresult");
2746 RegResults.push_back(Tmp);
2758 const llvm::BitVector &ResultTypeRequiresCast,
2759 const std::vector<std::optional<std::pair<unsigned, unsigned>>>
2765 assert(RegResults.size() == ResultRegTypes.size());
2766 assert(RegResults.size() == ResultTruncRegTypes.size());
2767 assert(RegResults.size() == ResultRegDests.size());
2770 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2771 assert(ResultBounds.size() <= ResultRegDests.size());
2773 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2774 llvm::Value *Tmp = RegResults[i];
2775 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2777 if ((i < ResultBounds.size()) && ResultBounds[i].has_value()) {
2778 const auto [LowerBound, UpperBound] = ResultBounds[i].value();
2780 assert(LowerBound == 0 &&
"Output operand lower bound is not zero.");
2781 llvm::Constant *UpperBoundConst =
2782 llvm::ConstantInt::get(Tmp->getType(), UpperBound);
2783 llvm::Value *IsBooleanValue =
2784 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, UpperBoundConst);
2786 Builder.CreateCall(FnAssume, IsBooleanValue);
2791 if (ResultRegTypes[i] != TruncTy) {
2795 if (TruncTy->isFloatingPointTy())
2796 Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
2797 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2799 Tmp = Builder.CreateTrunc(
2800 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
2801 Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
2802 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2805 Tmp = Builder.CreatePtrToInt(
2806 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
2807 Tmp = Builder.CreateTrunc(Tmp, TruncTy);
2808 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2809 Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2810 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2811 Tmp = Builder.CreateBitCast(Tmp, TruncTy);
2816 LValue Dest = ResultRegDests[i];
2819 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2821 Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
2823 llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
2833 diag::err_store_value_to_reg);
2844 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2847 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2848 Asm = GCCAsm->getAsmString();
2852 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2853 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2854 {StrTy->getType()},
false);
2855 auto UBF = CGF->
CGM.
getModule().getOrInsertFunction(Name, FnTy);
2857 CGF->
Builder.CreateCall(UBF, {StrTy});
2872 bool IsValidTargetAsm =
true;
2873 for (
unsigned i = 0, e = S.
getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2875 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2876 Name = GAS->getOutputName(i);
2879 if (IsHipStdPar && !IsValid)
2880 IsValidTargetAsm =
false;
2882 assert(IsValid &&
"Failed to parse output constraint");
2883 OutputConstraintInfos.push_back(Info);
2886 for (
unsigned i = 0, e = S.
getNumInputs(); i != e && IsValidTargetAsm; i++) {
2888 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2889 Name = GAS->getInputName(i);
2893 if (IsHipStdPar && !IsValid)
2894 IsValidTargetAsm =
false;
2896 assert(IsValid &&
"Failed to parse input constraint");
2897 InputConstraintInfos.push_back(Info);
2900 if (!IsValidTargetAsm)
2903 std::string Constraints;
2905 std::vector<LValue> ResultRegDests;
2906 std::vector<QualType> ResultRegQualTys;
2907 std::vector<llvm::Type *> ResultRegTypes;
2908 std::vector<llvm::Type *> ResultTruncRegTypes;
2909 std::vector<llvm::Type *> ArgTypes;
2910 std::vector<llvm::Type *> ArgElemTypes;
2911 std::vector<llvm::Value*> Args;
2912 llvm::BitVector ResultTypeRequiresCast;
2913 std::vector<std::optional<std::pair<unsigned, unsigned>>> ResultBounds;
2916 std::string InOutConstraints;
2917 std::vector<llvm::Value*> InOutArgs;
2918 std::vector<llvm::Type*> InOutArgTypes;
2919 std::vector<llvm::Type*> InOutArgElemTypes;
2922 std::vector<std::string> OutputConstraints;
2925 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2933 bool ReadOnly =
true, ReadNone =
true;
2941 StringRef(OutputConstraint).substr(1), &OutputConstraintInfos);
2952 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2953 CGM.Error(S.
getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2955 OutputConstraints.push_back(OutputConstraint);
2957 if (!Constraints.empty())
2967 Constraints +=
"=" + OutputConstraint;
2968 ResultRegQualTys.push_back(QTy);
2969 ResultRegDests.push_back(Dest);
2976 Ty->isAggregateType());
2978 ResultTruncRegTypes.push_back(Ty);
2979 ResultTypeRequiresCast.push_back(RequiresCast);
2986 CGM.Error(OutExpr->
getExprLoc(),
"output size should not be zero");
2988 ResultRegTypes.push_back(Ty);
2994 for (InputNo = 0; InputNo != S.
getNumInputs(); ++InputNo) {
2999 assert(InputNo != S.
getNumInputs() &&
"Didn't find matching input!");
3010 if (llvm::Type* AdjTy =
3012 ResultRegTypes.back()))
3013 ResultRegTypes.back() = AdjTy;
3016 diag::err_asm_invalid_type_in_input)
3017 << OutExpr->
getType() << OutputConstraint;
3021 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
3022 LargestVectorWidth =
3023 std::max((uint64_t)LargestVectorWidth,
3024 VT->getPrimitiveSizeInBits().getKnownMinValue());
3035 ArgTypes.push_back(DestAddr.
getType());
3038 Constraints +=
"=*";
3039 Constraints += OutputConstraint;
3040 ReadOnly = ReadNone =
false;
3044 InOutConstraints +=
',';
3048 llvm::Type *ArgElemType;
3049 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
3050 Info, Dest, InputExpr->
getType(), InOutConstraints,
3053 if (llvm::Type* AdjTy =
3056 Arg =
Builder.CreateBitCast(Arg, AdjTy);
3059 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3060 LargestVectorWidth =
3061 std::max((uint64_t)LargestVectorWidth,
3062 VT->getPrimitiveSizeInBits().getKnownMinValue());
3065 InOutConstraints += llvm::utostr(i);
3067 InOutConstraints += OutputConstraint;
3069 InOutArgTypes.push_back(Arg->getType());
3070 InOutArgElemTypes.push_back(ArgElemType);
3071 InOutArgs.push_back(Arg);
3082 CGM.getTargetCodeGenInfo().addReturnRegisterOutputs(
3083 *
this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
3089 for (
unsigned i = 0, e = S.
getNumInputs(); i != e; i++) {
3097 if (!Constraints.empty())
3109 std::string ReplaceConstraint (InputConstraint);
3111 llvm::Type *ArgElemType;
3112 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
3131 Arg =
Builder.CreateZExt(Arg, OutputTy);
3134 else if (OutputTy->isFloatingPointTy())
3135 Arg =
Builder.CreateFPExt(Arg, OutputTy);
3138 ReplaceConstraint = OutputConstraints[Output];
3140 if (llvm::Type* AdjTy =
3143 Arg =
Builder.CreateBitCast(Arg, AdjTy);
3145 CGM.getDiags().Report(S.
getAsmLoc(), diag::err_asm_invalid_type_in_input)
3146 << InputExpr->
getType() << InputConstraint;
3149 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3150 LargestVectorWidth =
3151 std::max((uint64_t)LargestVectorWidth,
3152 VT->getPrimitiveSizeInBits().getKnownMinValue());
3154 ArgTypes.push_back(Arg->getType());
3155 ArgElemTypes.push_back(ArgElemType);
3156 Args.push_back(Arg);
3157 Constraints += InputConstraint;
3161 for (
unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
3162 ArgTypes.push_back(InOutArgTypes[i]);
3163 ArgElemTypes.push_back(InOutArgElemTypes[i]);
3164 Args.push_back(InOutArgs[i]);
3166 Constraints += InOutConstraints;
3170 llvm::BasicBlock *Fallthrough =
nullptr;
3171 bool IsGCCAsmGoto =
false;
3172 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S)) {
3173 IsGCCAsmGoto = GS->isAsmGoto();
3175 for (
const auto *E : GS->labels()) {
3177 Transfer.push_back(Dest.
getBlock());
3178 if (!Constraints.empty())
3180 Constraints +=
"!i";
3186 bool HasUnwindClobber =
false;
3192 if (Clobber ==
"memory")
3193 ReadOnly = ReadNone =
false;
3194 else if (Clobber ==
"unwind") {
3195 HasUnwindClobber =
true;
3197 }
else if (Clobber !=
"cc") {
3199 if (
CGM.getCodeGenOpts().StackClashProtector &&
3202 diag::warn_stack_clash_protection_inline_asm);
3207 if (Clobber ==
"eax" || Clobber ==
"edx") {
3208 if (Constraints.find(
"=&A") != std::string::npos)
3210 std::string::size_type position1 =
3211 Constraints.find(
"={" + Clobber +
"}");
3212 if (position1 != std::string::npos) {
3213 Constraints.insert(position1 + 1,
"&");
3216 std::string::size_type position2 = Constraints.find(
"=A");
3217 if (position2 != std::string::npos) {
3218 Constraints.insert(position2 + 1,
"&");
3223 if (!Constraints.empty())
3226 Constraints +=
"~{";
3227 Constraints += Clobber;
3231 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
3232 "unwind clobber can't be used with asm goto");
3236 if (!MachineClobbers.empty()) {
3237 if (!Constraints.empty())
3239 Constraints += MachineClobbers;
3242 llvm::Type *ResultType;
3243 if (ResultRegTypes.empty())
3245 else if (ResultRegTypes.size() == 1)
3246 ResultType = ResultRegTypes[0];
3248 ResultType = llvm::StructType::get(
getLLVMContext(), ResultRegTypes);
3250 llvm::FunctionType *FTy =
3251 llvm::FunctionType::get(ResultType, ArgTypes,
false);
3255 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3257 ? llvm::InlineAsm::AD_ATT
3258 : llvm::InlineAsm::AD_Intel;
3260 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3262 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3263 FTy, AsmString, Constraints, HasSideEffect,
3264 false, AsmDialect, HasUnwindClobber);
3265 std::vector<llvm::Value*> RegResults;
3266 llvm::CallBrInst *CBR;
3267 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3270 CBR =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3275 ArgElemTypes, *
this, RegResults);
3279 if (!RegResults.empty()) {
3281 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3282 llvm::Twine SynthName = Dest->getName() +
".split";
3284 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3285 Builder.SetInsertPoint(SynthBB);
3287 if (ResultRegTypes.size() == 1) {
3288 CBRRegResults[SynthBB].push_back(CBR);
3290 for (
unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3291 llvm::Value *Tmp =
Builder.CreateExtractValue(CBR, j,
"asmresult");
3292 CBRRegResults[SynthBB].push_back(Tmp);
3298 CBR->setIndirectDest(i++, SynthBB);
3301 }
else if (HasUnwindClobber) {
3306 ArgElemTypes, *
this, RegResults);
3313 ArgElemTypes, *
this, RegResults);
3316 EmitAsmStores(*
this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3317 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3323 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3324 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3325 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3326 Builder.SetInsertPoint(Succ, --(Succ->end()));
3327 EmitAsmStores(*
this, S, CBRRegResults[Succ], ResultRegTypes,
3328 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3329 ResultTypeRequiresCast, ResultBounds);
3345 I != E; ++I, ++CurField) {
3347 if (CurField->hasCapturedVLAType()) {
3364 CodeGenFunction CGF(
CGM,
true);
3384 "CapturedStmtInfo should be set when generating the captured function");
3388 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3397 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Args);
3398 llvm::FunctionType *FuncLLVMTy =
CGM.getTypes().GetFunctionType(FuncInfo);
3401 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3403 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
3405 F->addFnAttr(llvm::Attribute::NoUnwind);
3417 for (
auto *FD : RD->
fields()) {
3418 if (FD->hasCapturedVLAType()) {
3422 auto VAT = FD->getCapturedVLAType();
3423 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3434 PGO->assignRegionCounters(
GlobalDecl(CD), F);
3444 for (
auto &I : *BB) {
3445 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3452CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3454 assert(ParentToken);
3456 llvm::Value *bundleArgs[] = {ParentToken};
3457 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3458 auto *Output = llvm::CallBase::addOperandBundle(
3459 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3460 Input->replaceAllUsesWith(Output);
3461 Input->eraseFromParent();
3465llvm::ConvergenceControlInst *
3466CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
3468 assert(ParentToken);
3469 return llvm::ConvergenceControlInst::CreateLoop(*BB, ParentToken);
3472llvm::ConvergenceControlInst *
3473CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3474 llvm::BasicBlock *BB = &F->getEntryBlock();
3482 return llvm::ConvergenceControlInst::CreateEntry(*BB);
Defines enum values for all the target-independent builtin functions.
static std::string AddVariableConstraints(const std::string &Constraint, const Expr &AsmExpr, const TargetInfo &Target, CodeGenModule &CGM, const AsmStmt &Stmt, const bool EarlyClobber, std::string *GCCReg=nullptr)
AddVariableConstraints - Look at AsmExpr and if it is a variable declared as using a particular regis...
static bool FindCaseStatementsForValue(const SwitchStmt &S, const llvm::APSInt &ConstantCondValue, SmallVectorImpl< const Stmt * > &ResultStmts, ASTContext &C, const SwitchCase *&ResultCase)
FindCaseStatementsForValue - Find the case statement being jumped to and then invoke CollectStatement...
static llvm::ConvergenceControlInst * getConvergenceToken(llvm::BasicBlock *BB)
static void EmitHipStdParUnsupportedAsm(CodeGenFunction *CGF, const AsmStmt &S)
static std::optional< SmallVector< uint64_t, 16 > > getLikelihoodWeights(ArrayRef< Stmt::Likelihood > Likelihoods)
static llvm::MDNode * getAsmSrcLocInfo(const StringLiteral *Str, CodeGenFunction &CGF)
getAsmSrcLocInfo - Return the !srcloc metadata node to attach to an inline asm call instruction.
static bool isSwiftAsyncCallee(const CallExpr *CE)
Determine if the given call uses the swiftasync calling convention.
static CSFC_Result CollectStatementsForCase(const Stmt *S, const SwitchCase *Case, bool &FoundCase, SmallVectorImpl< const Stmt * > &ResultStmts)
static void EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S, const llvm::ArrayRef< llvm::Value * > RegResults, const llvm::ArrayRef< llvm::Type * > ResultRegTypes, const llvm::ArrayRef< llvm::Type * > ResultTruncRegTypes, const llvm::ArrayRef< LValue > ResultRegDests, const llvm::ArrayRef< QualType > ResultRegQualTys, const llvm::BitVector &ResultTypeRequiresCast, const std::vector< std::optional< std::pair< unsigned, unsigned > > > &ResultBounds)
static bool hasEmptyLoopBody(const LoopStmt &S)
CSFC_Result
CollectStatementsForCase - Given the body of a 'switch' statement and a constant value that is being ...
static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, bool HasUnwindClobber, bool ReadOnly, bool ReadNone, bool NoMerge, bool NoConvergent, const AsmStmt &S, const std::vector< llvm::Type * > &ResultRegTypes, const std::vector< llvm::Type * > &ArgElemTypes, CodeGenFunction &CGF, std::vector< llvm::Value * > &RegResults)
llvm::MachO::Target Target
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Defines the SourceManager interface.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
bool toIntegralConstant(APSInt &Result, QualType SrcTy, const ASTContext &Ctx) const
Try to convert this value to an integral constant.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType getCanonicalTagType(const TagDecl *TD) const
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
std::string getInputConstraint(unsigned i) const
getInputConstraint - Return the specified input constraint.
std::string getOutputConstraint(unsigned i) const
getOutputConstraint - Return the constraint string for the specified output operand.
SourceLocation getAsmLoc() const
const Expr * getInputExpr(unsigned i) const
unsigned getNumClobbers() const
const Expr * getOutputExpr(unsigned i) const
unsigned getNumOutputs() const
std::string generateAsmString(const ASTContext &C) const
Assemble final IR asm string.
unsigned getNumInputs() const
std::string getClobber(unsigned i) const
Attr - This represents one attribute.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
BreakStmt - This represents a break.
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
DeclStmt * getBeginStmt()
DeclStmt * getLoopVarStmt()
DeclStmt * getRangeStmt()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Represents the body of a CapturedStmt, and serves as its DeclContext.
ImplicitParamDecl * getContextParam() const
Retrieve the parameter containing captured variables.
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
This captures a statement into a function.
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument.
SourceLocation getBeginLoc() const LLVM_READONLY
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument.
Expr *const * const_capture_init_iterator
Const iterator that walks over the capture initialization arguments.
CapturedRegionKind getCapturedRegionKind() const
Retrieve the captured region kind.
CaseStmt - Represent a case statement.
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::PointerType * getType() const
Return the type of the pointer value.
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
A scoped helper to set the current source atom group for CGDebugInfo::addInstToCurrentSourceAtom.
A scoped helper to set the current debug location to the specified location or preferred location of ...
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
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.
API for captured statement code generation.
RAII for correct setting/restoring of CapturedStmtInfo.
void rescopeLabels()
Change the cleanup scope of the labels in this lexical scope to match the scope of the enclosing cont...
void ForceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
bool requiresCleanups() const
Determine whether this scope requires any cleanups.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitCXXTryStmt(const CXXTryStmt &S)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void EmitSehCppScopeBegin()
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
llvm::DenseMap< const VarDecl *, llvm::Value * > NRVOFlags
A mapping from NRVO variables to the flags used to indicate when the NRVO has been applied to this va...
bool IsOutlinedSEHHelper
True if the current function is an outlined SEH helper.
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
static bool ContainsLabel(const Stmt *S, bool IgnoreCaseStmts=false)
ContainsLabel - Return true if the statement contains a label in it.
void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef< const Attr * > Attrs={})
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit)
EmitComplexExprIntoLValue - Emit the given expression of complex type and place its result into the s...
static bool hasScalarEvaluationKind(QualType T)
llvm::Type * ConvertType(QualType T)
void EmitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &S)
LValue InitCapturedStruct(const CapturedStmt &S)
void addInstToNewSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)
Add KeyInstruction and an optional Backup instruction to a new atom group (See ApplyAtomGroup for mor...
CGCapturedStmtInfo * CapturedStmtInfo
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
void EmitOMPParallelForDirective(const OMPParallelForDirective &S)
llvm::CallBase * EmitCallOrInvoke(llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const Twine &Name="")
Emits a call or invoke instruction to the given function, depending on the current state of the EH st...
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOpenACCInitConstruct(const OpenACCInitConstruct &S)
void EmitOMPFlushDirective(const OMPFlushDirective &S)
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
JumpDest getJumpDestForLabel(const LabelDecl *S)
getBasicBlockForLabel - Return the LLVM basicblock that the specified label maps to.
void EmitCoreturnStmt(const CoreturnStmt &S)
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
SmallVector< llvm::ConvergenceControlInst *, 4 > ConvergenceTokenStack
Stack to track the controlled convergence tokens.
void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S)
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)
Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...
bool EmitSimpleStmt(const Stmt *S, ArrayRef< const Attr * > Attrs)
EmitSimpleStmt - Try to emit a "simple" statement which does not necessarily require an insertion poi...
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)
See CGDebugInfo::addInstToCurrentSourceAtom.
const LangOptions & getLangOpts() const
RValue EmitReferenceBindingToExpr(const Expr *E)
Emits a reference binding to the passed in expression.
void EmitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &S)
bool InNoConvergentAttributedStmt
True if the current statement has noconvergent attribute.
void EmitOpenACCWaitConstruct(const OpenACCWaitConstruct &S)
void EmitBlockAfterUses(llvm::BasicBlock *BB)
EmitBlockAfterUses - Emit the given block somewhere hopefully near its uses, and leave the insertion ...
void SimplifyForwardingBlocks(llvm::BasicBlock *BB)
SimplifyForwardingBlocks - If the given basic block is only a branch to another basic block,...
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
bool InNoMergeAttributedStmt
True if the current statement has nomerge attribute.
void EmitOMPScopeDirective(const OMPScopeDirective &S)
LValue MakeAddrLValueWithoutTBAA(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
const TargetInfo & getTarget() const
Address EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
void EmitGotoStmt(const GotoStmt &S)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPCancelDirective(const OMPCancelDirective &S)
const Expr * RetExpr
If a return statement is being visited, this holds the return statment's result expression.
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
void EmitForStmt(const ForStmt &S, ArrayRef< const Attr * > Attrs={})
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S)
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPInteropDirective(const OMPInteropDirective &S)
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
void EmitWhileStmt(const WhileStmt &S, ArrayRef< const Attr * > Attrs={})
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
Emit combined directive 'target parallel loop' as if its constituent constructs are 'target',...
void EmitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &S)
void ResolveBranchFixups(llvm::BasicBlock *Target)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
bool checkIfLoopMustProgress(const Expr *, bool HasEmptyBody)
Returns true if a loop must make progress, which means the mustprogress attribute can be added.
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
CGDebugInfo * getDebugInfo()
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPReverseDirective(const OMPReverseDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EmitOpenACCDataConstruct(const OpenACCDataConstruct &S)
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)
void EmitObjCAtTryStmt(const ObjCAtTryStmt &S)
const TargetCodeGenInfo & getTargetHooks() const
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void EmitSEHLeaveStmt(const SEHLeaveStmt &S)
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
bool InNoInlineAttributedStmt
True if the current statement has noinline attribute.
SmallVector< llvm::OperandBundleDef, 1 > getBundlesForFunclet(llvm::Value *Callee)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
void EmitCoroutineBody(const CoroutineBodyStmt &S)
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
ASTContext & getContext() const
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitIfStmt(const IfStmt &S)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
void 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 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 EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)
void EmitIndirectGotoStmt(const IndirectGotoStmt &S)
void MaybeEmitDeferredVarDeclInit(const VarDecl *var)
bool isObviouslyBranchWithoutCleanups(JumpDest Dest) const
isObviouslyBranchWithoutCleanups - Return true if a branch to the specified destination obviously has...
void EmitSEHTryStmt(const SEHTryStmt &S)
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S)
When instrumenting to collect profile data, the counts for some blocks such as switch cases need to n...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitOMPForDirective(const OMPForDirective &S)
void EmitLabel(const LabelDecl *D)
EmitLabel - Emit the block for the given label.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
void EmitContinueStmt(const ContinueStmt &S)
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
void ErrorUnsupported(const Stmt *S, const char *Type)
Print out an error that codegen doesn't support the specified stmt yet.
const LangOptions & getLangOpts() const
const llvm::DataLayout & getDataLayout() const
ASTContext & getContext() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
A saved depth on the scope stack.
bool encloses(stable_iterator I) const
Returns true if this scope encloses I.
static stable_iterator invalid()
static stable_iterator stable_end()
Create a stable reference to the bottom of the EH stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
llvm::Value * getPointer(CodeGenFunction &CGF) const
Address getAddress() const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
virtual bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, llvm::Type *Ty) const
Target hook to decide whether an inline asm operand can be passed by value.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Stmt *const * const_body_iterator
SourceLocation getLBracLoc() const
body_iterator body_begin()
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
ContinueStmt - This represents a continue.
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
DeferStmt - This represents a deferred statement.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
DoStmt - This represents a 'do/while' stmt.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
ForStmt - This represents a 'for (init;cond;inc)' stmt.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
const Expr * getSubExpr() const
FunctionType - C99 6.7.5.3 - Function Declarators.
CallingConv getCallConv() const
This represents a GCC inline-assembly statement extension.
GlobalDecl - represents a global declaration.
GotoStmt - This represents a direct goto.
LabelDecl * getLabel() const
IfStmt - This represents an if/then/else.
bool isNegatedConsteval() const
VarDecl * getConditionVariable()
Retrieve the variable declared in this "if" statement, if any.
IndirectGotoStmt - This represents an indirect goto.
LabelDecl * getConstantTarget()
getConstantTarget - Returns the fixed target of this indirect goto, if one exists.
Represents the declaration of a label.
LabelStmt * getStmt() const
LabelStmt - Represents a label, which has a substatement.
LabelDecl * getDecl() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool assumeFunctionsAreConvergent() const
Base class for BreakStmt and ContinueStmt.
Represents a point when we exit a loop.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType getCanonicalType() const
The collection of all-type qualifiers we support.
Represents a struct/union/class.
field_range fields() const
specific_decl_iterator< FieldDecl > field_iterator
field_iterator field_begin() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
SourceLocation getBeginLoc() const
const VarDecl * getNRVOCandidate() const
Retrieve the variable that might be used for the named return value optimization.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Likelihood
The likelihood of a branch being taken.
@ LH_Unlikely
Branch has the [[unlikely]] attribute.
@ LH_None
No attribute set or branches of the IfStmt have the same attribute.
@ LH_Likely
Branch has the [[likely]] attribute.
static const Attr * getLikelihoodAttr(const Stmt *S)
SourceLocation getBeginLoc() const LLVM_READONLY
static Likelihood getLikelihood(ArrayRef< const Attr * > Attrs)
StringLiteral - This represents a string literal expression, e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target, unsigned *StartToken=nullptr, unsigned *StartTokenByteOffset=nullptr) const
getLocationOfByte - Return a source location that points to the specified byte of this string literal...
StringRef getString() const
const SwitchCase * getNextSwitchCase() const
SwitchStmt - This represents a 'switch' stmt.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "switch" statement, if any.
SwitchCase * getSwitchCaseList()
Exposes information about the current target.
bool validateInputConstraint(MutableArrayRef< ConstraintInfo > OutputConstraints, ConstraintInfo &info) const
std::string simplifyConstraint(StringRef Constraint, SmallVectorImpl< ConstraintInfo > *OutCons=nullptr) const
StringRef getNormalizedGCCRegisterName(StringRef Name, bool ReturnCanonical=false) const
Returns the "normalized" GCC register name.
bool validateOutputConstraint(ConstraintInfo &Info) const
virtual std::string_view getClobbers() const =0
Returns a string of target-specific clobbers, in LLVM format.
const T * castAs() const
Member-template castAs<specific type>.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool isNRVOVariable() const
Determine whether this local variable can be used with the named return value optimization (NRVO).
WhileStmt - This represents a 'while' stmt.
SourceLocation getWhileLoc() const
SourceLocation getRParenLoc() const
VarDecl * getConditionVariable()
Retrieve the variable declared in this "while" statement, if any.
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
CapturedRegionKind
The different kinds of captured statement.
@ Asm
Assembly: we accept this only so that we can preprocess it.
@ Result
The result type of a method or function.
U cast(CodeGen::Address addr)
@ None
The alignment was not explicit in code.
Diagnostic wrappers for TextAPI types for error reporting.
cl::opt< bool > EnableSingleByteCoverage
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
void setScopeDepth(EHScopeStack::stable_iterator depth)
llvm::BasicBlock * getBlock() const
EHScopeStack::stable_iterator getScopeDepth() const
llvm::IntegerType * Int64Ty
llvm::IntegerType * IntPtrTy
llvm::PointerType * Int8PtrTy
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool hasMatchingInput() const
Return true if this output operand has a matching (tied) input operand.
unsigned getTiedOperand() const
bool allowsMemory() const
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