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"
41using namespace CodeGen;
54 Loc = S->getBeginLoc();
62 assert(S &&
"Null statement?");
63 PGO->setCurrentStmt(S);
79 assert(!isa<DeclStmt>(*S) &&
"Unexpected DeclStmt!");
80 PGO->markStmtMaybeUsed(S);
94 if (
const auto *
D = dyn_cast<OMPExecutableDirective>(S)) {
100 switch (S->getStmtClass()) {
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::SEHLeaveStmtClass:
118 case Stmt::SYCLKernelCallStmtClass:
119 llvm_unreachable(
"should have emitted these statements as simple");
121#define STMT(Type, Base)
122#define ABSTRACT_STMT(Op)
123#define EXPR(Type, Base) \
124 case Stmt::Type##Class:
125#include "clang/AST/StmtNodes.inc"
128 llvm::BasicBlock *incoming =
Builder.GetInsertBlock();
129 assert(incoming &&
"expression emission must have an insertion point");
133 llvm::BasicBlock *outgoing =
Builder.GetInsertBlock();
134 assert(outgoing &&
"expression emission cleared block!");
148 if (incoming != outgoing && outgoing->use_empty()) {
149 outgoing->eraseFromParent();
155 case Stmt::IndirectGotoStmtClass:
158 case Stmt::IfStmtClass:
EmitIfStmt(cast<IfStmt>(*S));
break;
159 case Stmt::WhileStmtClass:
EmitWhileStmt(cast<WhileStmt>(*S), Attrs);
break;
160 case Stmt::DoStmtClass:
EmitDoStmt(cast<DoStmt>(*S), Attrs);
break;
161 case Stmt::ForStmtClass:
EmitForStmt(cast<ForStmt>(*S), Attrs);
break;
163 case Stmt::ReturnStmtClass:
EmitReturnStmt(cast<ReturnStmt>(*S));
break;
165 case Stmt::SwitchStmtClass:
EmitSwitchStmt(cast<SwitchStmt>(*S));
break;
166 case Stmt::GCCAsmStmtClass:
167 case Stmt::MSAsmStmtClass:
EmitAsmStmt(cast<AsmStmt>(*S));
break;
168 case Stmt::CoroutineBodyStmtClass:
171 case Stmt::CoreturnStmtClass:
174 case Stmt::CapturedStmtClass: {
179 case Stmt::ObjCAtTryStmtClass:
182 case Stmt::ObjCAtCatchStmtClass:
184 "@catch statements should be handled by EmitObjCAtTryStmt");
185 case Stmt::ObjCAtFinallyStmtClass:
187 "@finally statements should be handled by EmitObjCAtTryStmt");
188 case Stmt::ObjCAtThrowStmtClass:
191 case Stmt::ObjCAtSynchronizedStmtClass:
194 case Stmt::ObjCForCollectionStmtClass:
197 case Stmt::ObjCAutoreleasePoolStmtClass:
201 case Stmt::CXXTryStmtClass:
204 case Stmt::CXXForRangeStmtClass:
207 case Stmt::SEHTryStmtClass:
210 case Stmt::OMPMetaDirectiveClass:
213 case Stmt::OMPCanonicalLoopClass:
216 case Stmt::OMPParallelDirectiveClass:
219 case Stmt::OMPSimdDirectiveClass:
222 case Stmt::OMPTileDirectiveClass:
225 case Stmt::OMPStripeDirectiveClass:
228 case Stmt::OMPUnrollDirectiveClass:
231 case Stmt::OMPReverseDirectiveClass:
234 case Stmt::OMPInterchangeDirectiveClass:
237 case Stmt::OMPForDirectiveClass:
240 case Stmt::OMPForSimdDirectiveClass:
243 case Stmt::OMPSectionsDirectiveClass:
246 case Stmt::OMPSectionDirectiveClass:
249 case Stmt::OMPSingleDirectiveClass:
252 case Stmt::OMPMasterDirectiveClass:
255 case Stmt::OMPCriticalDirectiveClass:
258 case Stmt::OMPParallelForDirectiveClass:
261 case Stmt::OMPParallelForSimdDirectiveClass:
264 case Stmt::OMPParallelMasterDirectiveClass:
267 case Stmt::OMPParallelSectionsDirectiveClass:
270 case Stmt::OMPTaskDirectiveClass:
273 case Stmt::OMPTaskyieldDirectiveClass:
276 case Stmt::OMPErrorDirectiveClass:
279 case Stmt::OMPBarrierDirectiveClass:
282 case Stmt::OMPTaskwaitDirectiveClass:
285 case Stmt::OMPTaskgroupDirectiveClass:
288 case Stmt::OMPFlushDirectiveClass:
291 case Stmt::OMPDepobjDirectiveClass:
294 case Stmt::OMPScanDirectiveClass:
297 case Stmt::OMPOrderedDirectiveClass:
300 case Stmt::OMPAtomicDirectiveClass:
303 case Stmt::OMPTargetDirectiveClass:
306 case Stmt::OMPTeamsDirectiveClass:
309 case Stmt::OMPCancellationPointDirectiveClass:
312 case Stmt::OMPCancelDirectiveClass:
315 case Stmt::OMPTargetDataDirectiveClass:
318 case Stmt::OMPTargetEnterDataDirectiveClass:
321 case Stmt::OMPTargetExitDataDirectiveClass:
324 case Stmt::OMPTargetParallelDirectiveClass:
327 case Stmt::OMPTargetParallelForDirectiveClass:
330 case Stmt::OMPTaskLoopDirectiveClass:
333 case Stmt::OMPTaskLoopSimdDirectiveClass:
336 case Stmt::OMPMasterTaskLoopDirectiveClass:
339 case Stmt::OMPMaskedTaskLoopDirectiveClass:
342 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
344 cast<OMPMasterTaskLoopSimdDirective>(*S));
346 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
348 cast<OMPMaskedTaskLoopSimdDirective>(*S));
350 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
352 cast<OMPParallelMasterTaskLoopDirective>(*S));
354 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
356 cast<OMPParallelMaskedTaskLoopDirective>(*S));
358 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
360 cast<OMPParallelMasterTaskLoopSimdDirective>(*S));
362 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
364 cast<OMPParallelMaskedTaskLoopSimdDirective>(*S));
366 case Stmt::OMPDistributeDirectiveClass:
369 case Stmt::OMPTargetUpdateDirectiveClass:
372 case Stmt::OMPDistributeParallelForDirectiveClass:
374 cast<OMPDistributeParallelForDirective>(*S));
376 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
378 cast<OMPDistributeParallelForSimdDirective>(*S));
380 case Stmt::OMPDistributeSimdDirectiveClass:
383 case Stmt::OMPTargetParallelForSimdDirectiveClass:
385 cast<OMPTargetParallelForSimdDirective>(*S));
387 case Stmt::OMPTargetSimdDirectiveClass:
390 case Stmt::OMPTeamsDistributeDirectiveClass:
393 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
395 cast<OMPTeamsDistributeSimdDirective>(*S));
397 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
399 cast<OMPTeamsDistributeParallelForSimdDirective>(*S));
401 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
403 cast<OMPTeamsDistributeParallelForDirective>(*S));
405 case Stmt::OMPTargetTeamsDirectiveClass:
408 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
410 cast<OMPTargetTeamsDistributeDirective>(*S));
412 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
414 cast<OMPTargetTeamsDistributeParallelForDirective>(*S));
416 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
418 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(*S));
420 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
422 cast<OMPTargetTeamsDistributeSimdDirective>(*S));
424 case Stmt::OMPInteropDirectiveClass:
427 case Stmt::OMPDispatchDirectiveClass:
430 case Stmt::OMPScopeDirectiveClass:
433 case Stmt::OMPMaskedDirectiveClass:
436 case Stmt::OMPGenericLoopDirectiveClass:
439 case Stmt::OMPTeamsGenericLoopDirectiveClass:
442 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
444 cast<OMPTargetTeamsGenericLoopDirective>(*S));
446 case Stmt::OMPParallelGenericLoopDirectiveClass:
448 cast<OMPParallelGenericLoopDirective>(*S));
450 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
452 cast<OMPTargetParallelGenericLoopDirective>(*S));
454 case Stmt::OMPParallelMaskedDirectiveClass:
457 case Stmt::OMPAssumeDirectiveClass:
460 case Stmt::OpenACCComputeConstructClass:
463 case Stmt::OpenACCLoopConstructClass:
466 case Stmt::OpenACCCombinedConstructClass:
469 case Stmt::OpenACCDataConstructClass:
472 case Stmt::OpenACCEnterDataConstructClass:
475 case Stmt::OpenACCExitDataConstructClass:
478 case Stmt::OpenACCHostDataConstructClass:
481 case Stmt::OpenACCWaitConstructClass:
484 case Stmt::OpenACCInitConstructClass:
487 case Stmt::OpenACCShutdownConstructClass:
490 case Stmt::OpenACCSetConstructClass:
493 case Stmt::OpenACCUpdateConstructClass:
496 case Stmt::OpenACCAtomicConstructClass:
499 case Stmt::OpenACCCacheConstructClass:
507 switch (S->getStmtClass()) {
510 case Stmt::NullStmtClass:
512 case Stmt::CompoundStmtClass:
515 case Stmt::DeclStmtClass:
518 case Stmt::LabelStmtClass:
521 case Stmt::AttributedStmtClass:
524 case Stmt::GotoStmtClass:
527 case Stmt::BreakStmtClass:
530 case Stmt::ContinueStmtClass:
533 case Stmt::DefaultStmtClass:
536 case Stmt::CaseStmtClass:
539 case Stmt::SEHLeaveStmtClass:
542 case Stmt::SYCLKernelCallStmtClass:
569 "LLVM IR generation of compound statement ('{}')");
583 assert((!GetLast || (GetLast &&
ExprResult)) &&
584 "If GetLast is true then the CompoundStmt must have a StmtExprResult");
588 for (
auto *CurStmt : S.body()) {
596 if (
const auto *LS = dyn_cast<LabelStmt>(
ExprResult)) {
599 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(
ExprResult)) {
604 llvm_unreachable(
"unknown value statement");
631 llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
640 if (!BI || !BI->isUnconditional())
644 if (BI->getIterator() != BB->begin())
647 BB->replaceAllUsesWith(BI->getSuccessor(0));
648 BI->eraseFromParent();
649 BB->eraseFromParent();
653 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
658 if (IsFinished && BB->use_empty()) {
665 if (CurBB && CurBB->getParent())
666 CurFn->insert(std::next(CurBB->getIterator()), BB);
676 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
678 if (!CurBB || CurBB->getTerminator()) {
690 bool inserted =
false;
691 for (llvm::User *u : block->users()) {
692 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
693 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
708 if (Dest.
isValid())
return Dest;
755 assert(!Labels.empty());
770 ParentScope->Labels.append(Labels.begin(), Labels.end());
786 bool nomerge =
false;
787 bool noinline =
false;
788 bool alwaysinline =
false;
789 bool noconvergent =
false;
790 HLSLControlFlowHintAttr::Spelling flattenOrBranch =
791 HLSLControlFlowHintAttr::SpellingNotCalculated;
793 const AtomicAttr *AA =
nullptr;
795 for (
const auto *A : S.getAttrs()) {
796 switch (A->getKind()) {
805 case attr::AlwaysInline:
808 case attr::NoConvergent:
811 case attr::MustTail: {
812 const Stmt *Sub = S.getSubStmt();
816 case attr::CXXAssume: {
817 const Expr *Assumption = cast<CXXAssumeAttr>(A)->getAssumption();
821 Builder.CreateAssumption(AssumptionVal);
825 AA = cast<AtomicAttr>(A);
827 case attr::HLSLControlFlowHint: {
828 flattenOrBranch = cast<HLSLControlFlowHintAttr>(A)->getSemanticSpelling();
839 EmitStmt(S.getSubStmt(), S.getAttrs());
864 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
871 cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(
V, CurBB);
874 if (CurBB && CurBB->getTerminator())
879 const Stmt *Else = S.getElse();
883 if (S.isConsteval()) {
884 const Stmt *Executed = S.isNegatedConsteval() ? S.getThen() : Else;
894 LexicalScope ConditionScope(*
this, S.getCond()->getSourceRange());
900 if (S.getConditionVariable())
901 EmitDecl(*S.getConditionVariable());
909 const Stmt *Executed = S.getThen();
910 const Stmt *Skipped = Else;
912 std::swap(Executed, Skipped);
924 PGO->markStmtMaybeUsed(Skipped);
933 llvm::BasicBlock *ElseBlock = ContBlock;
963 S.getConditionVariable());
967 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
1013 bool HasEmptyBody) {
1024 bool CondIsConstInt =
1025 !ControllingExpression ||
1029 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
1030 Result.Val.getInt().getBoolValue());
1044 if (HasEmptyBody && CondIsTrue) {
1045 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1063 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1067 const Stmt *Body = S.getBody();
1068 if (!Body || isa<NullStmt>(Body))
1070 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
1071 return Compound->body_empty();
1084 emitConvergenceLoopToken(LoopHeader.
getBlock()));
1091 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopHeader));
1102 if (S.getConditionVariable())
1103 EmitDecl(*S.getConditionVariable());
1114 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1115 bool EmitBoolCondBranch = !
C || !
C->isOne();
1128 if (EmitBoolCondBranch) {
1129 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1132 llvm::MDNode *Weights =
1133 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1135 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1137 auto *I =
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1143 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1147 if (ExitBlock !=
LoopExit.getBlock()) {
1153 diag::warn_attribute_has_no_effect_on_infinite_loop)
1154 << A << A->getRange();
1157 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1158 <<
SourceRange(S.getWhileLoc(), S.getRParenLoc());
1174 BreakContinueStack.pop_back();
1190 if (!EmitBoolCondBranch)
1210 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, LoopCond));
1241 BreakContinueStack.pop_back();
1245 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1246 bool EmitBoolCondBranch = !
C || !
C->isZero();
1255 if (EmitBoolCondBranch) {
1257 auto *I =
Builder.CreateCondBr(
1258 BoolCondVal, LoopBody,
LoopExit.getBlock(),
1259 createProfileWeightsForLoop(S.getCond(), BackedgeCount));
1266 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1278 if (!EmitBoolCondBranch)
1304 llvm::BasicBlock *CondBlock = CondDest.
getBlock();
1317 LexicalScope ConditionScope(*
this, S.getSourceRange());
1328 Continue = CondDest;
1329 else if (!S.getConditionVariable())
1331 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1336 if (S.getConditionVariable()) {
1337 EmitDecl(*S.getConditionVariable());
1342 BreakContinueStack.back().ContinueBlock = Continue;
1350 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1365 llvm::MDNode *Weights =
1366 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1368 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1371 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1376 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1380 if (ExitBlock !=
LoopExit.getBlock()) {
1405 auto *FinalBodyBB =
Builder.GetInsertBlock();
1415 BreakContinueStack.pop_back();
1474 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1484 llvm::MDNode *Weights =
1485 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1487 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1489 auto *I =
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1494 if (
auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1498 if (ExitBlock !=
LoopExit.getBlock()) {
1513 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
1523 auto *FinalBodyBB =
Builder.GetInsertBlock();
1530 BreakContinueStack.pop_back();
1556void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1572struct SaveRetExprRAII {
1574 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1577 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1578 const Expr *OldRetExpr;
1587 if (calleeQualType->isFunctionPointerType() ||
1588 calleeQualType->isFunctionReferenceType() ||
1589 calleeQualType->isBlockPointerType() ||
1590 calleeQualType->isMemberFunctionPointerType()) {
1592 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1594 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1595 if (
auto methodDecl = CMCE->getMethodDecl()) {
1612 if (requiresReturnValueCheck()) {
1615 new llvm::GlobalVariable(
CGM.
getModule(), SLoc->getType(),
false,
1616 llvm::GlobalVariable::PrivateLinkage, SLoc);
1617 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1619 assert(ReturnLocation.
isValid() &&
"No valid return location");
1626 Builder.ClearInsertionPoint();
1630 const Expr *RV = S.getRetValue();
1640 SaveRetExprRAII SaveRetExpr(RV, *
this);
1643 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1644 RV = EWC->getSubExpr();
1648 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1651 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1661 if (
getLangOpts().ElideConstructors && S.getNRVOCandidate() &&
1662 S.getNRVOCandidate()->isNRVOVariable() &&
1673 if (llvm::Value *NRVOFlag =
NRVOFlags[S.getNRVOCandidate()])
1719 ++NumSimpleReturnExprs;
1731 for (
const auto *I : S.decls())
1736 ->
const BreakContinue * {
1737 if (!S.hasLabelTarget())
1738 return &BreakContinueStack.back();
1740 const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
1741 assert(LoopOrSwitch &&
"break/continue target not set?");
1742 for (
const BreakContinue &BC : llvm::reverse(BreakContinueStack))
1743 if (BC.LoopOrSwitch == LoopOrSwitch)
1746 llvm_unreachable(
"break/continue target not found");
1750 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1763 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1780 assert(S.getRHS() &&
"Expected RHS value in CaseStmt");
1782 llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(
getContext());
1783 llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(
getContext());
1793 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1797 llvm::APInt
Range = RHS - LHS;
1799 if (
Range.ult(llvm::APInt(
Range.getBitWidth(), 64))) {
1802 unsigned NCases =
Range.getZExtValue() + 1;
1807 uint64_t Weight = Total / NCases, Rem = Total % NCases;
1808 for (
unsigned I = 0; I != NCases; ++I) {
1810 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1811 else if (SwitchLikelihood)
1812 SwitchLikelihood->push_back(LH);
1816 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1824 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1829 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1833 Builder.SetInsertPoint(CaseRangeBlock);
1837 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1841 llvm::MDNode *Weights =
nullptr;
1842 if (SwitchWeights) {
1844 uint64_t DefaultCount = (*SwitchWeights)[0];
1845 Weights = createProfileWeights(ThisCount, DefaultCount);
1850 (*SwitchWeights)[0] += ThisCount;
1851 }
else if (SwitchLikelihood)
1852 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
1854 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
1858 Builder.SetInsertPoint(RestoreBB);
1860 Builder.ClearInsertionPoint();
1881 llvm::ConstantInt *CaseVal =
1886 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.getLHS()))
1887 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1889 CE = dyn_cast<ConstantExpr>(S.getLHS());
1891 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1894 Dbg->EmitGlobalVariable(DE->getDecl(),
1895 APValue(llvm::APSInt(CaseVal->getValue())));
1898 if (SwitchLikelihood)
1906 isa<BreakStmt>(S.getSubStmt())) {
1913 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1917 if (
Builder.GetInsertBlock()) {
1919 Builder.ClearInsertionPoint();
1929 SwitchInsn->addCase(CaseVal, CaseDest);
1945 const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt());
1948 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1950 llvm::ConstantInt *CaseVal =
1961 if (SwitchLikelihood)
1964 SwitchInsn->addCase(CaseVal, CaseDest);
1965 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1988 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1989 assert(DefaultBlock->empty() &&
1990 "EmitDefaultStmt: Default block already defined?");
1992 if (SwitchLikelihood)
2034 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
2048 if (!Case && isa<BreakStmt>(S))
2053 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
2057 bool StartedInLiveCode = FoundCase;
2058 unsigned StartSize = ResultStmts.size();
2065 bool HadSkippedDecl =
false;
2069 for (; Case && I !=
E; ++I) {
2085 for (++I; I !=
E; ++I)
2095 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
2110 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
2115 bool AnyDecls =
false;
2116 for (; I !=
E; ++I) {
2129 for (++I; I !=
E; ++I)
2146 ResultStmts.resize(StartSize);
2147 ResultStmts.push_back(S);
2171 ResultStmts.push_back(S);
2180 const llvm::APSInt &ConstantCondValue,
2186 const SwitchCase *Case = S.getSwitchCaseList();
2192 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2198 const CaseStmt *CS = cast<CaseStmt>(Case);
2200 if (CS->
getRHS())
return false;
2225 bool FoundCase =
false;
2232static std::optional<SmallVector<uint64_t, 16>>
2235 if (Likelihoods.size() <= 1)
2236 return std::nullopt;
2238 uint64_t NumUnlikely = 0;
2239 uint64_t NumNone = 0;
2240 uint64_t NumLikely = 0;
2241 for (
const auto LH : Likelihoods) {
2256 if (NumUnlikely == 0 && NumLikely == 0)
2257 return std::nullopt;
2265 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2266 const uint64_t
None = Likely / (NumNone + 1);
2267 const uint64_t Unlikely = 0;
2270 Result.reserve(Likelihoods.size());
2271 for (
const auto LH : Likelihoods) {
2274 Result.push_back(Unlikely);
2280 Result.push_back(Likely);
2290 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2293 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2297 llvm::APSInt ConstantCondValue;
2312 if (S.getConditionVariable())
2313 EmitDecl(*S.getConditionVariable(),
true);
2318 SwitchInsn =
nullptr;
2325 PGO->markStmtMaybeUsed(S.getBody());
2329 SwitchInsn = SavedSwitchInsn;
2342 if (S.getConditionVariable())
2343 EmitDecl(*S.getConditionVariable());
2352 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2357 llvm::ConstantInt *BranchHintConstant =
2359 HLSLControlFlowHintAttr::Spelling::Microsoft_branch
2362 llvm::Metadata *Vals[] = {MDHelper.createString(
"hlsl.controlflow.hint"),
2363 MDHelper.createConstant(BranchHintConstant)};
2364 SwitchInsn->setMetadata(
"hlsl.controlflow.hint",
2368 if (PGO->haveRegionCounts()) {
2370 uint64_t DefaultCount = 0;
2371 unsigned NumCases = 0;
2372 for (
const SwitchCase *Case = S.getSwitchCaseList();
2374 Case = Case->getNextSwitchCase()) {
2375 if (isa<DefaultStmt>(Case))
2380 SwitchWeights->reserve(NumCases);
2383 SwitchWeights->push_back(DefaultCount);
2390 CaseRangeBlock = DefaultBlock;
2393 Builder.ClearInsertionPoint();
2398 if (!BreakContinueStack.empty())
2399 OuterContinue = BreakContinueStack.back().ContinueBlock;
2401 BreakContinueStack.push_back(BreakContinue(S, SwitchExit, OuterContinue));
2406 BreakContinueStack.pop_back();
2410 SwitchInsn->setDefaultDest(CaseRangeBlock);
2413 if (!DefaultBlock->getParent()) {
2421 DefaultBlock->replaceAllUsesWith(SwitchExit.
getBlock());
2422 delete DefaultBlock;
2435 auto *
Call = dyn_cast<CallExpr>(S.getCond());
2437 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2438 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2440 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2441 MDHelper.createUnpredictable());
2445 if (SwitchWeights) {
2446 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2447 "switch weights do not match switch cases");
2449 if (SwitchWeights->size() > 1)
2450 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2451 createProfileWeights(*SwitchWeights));
2452 delete SwitchWeights;
2453 }
else if (SwitchLikelihood) {
2454 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2455 "switch likelihoods do not match switch cases");
2456 std::optional<SmallVector<uint64_t, 16>> LHW =
2460 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2461 createProfileWeights(*LHW));
2463 delete SwitchLikelihood;
2465 SwitchInsn = SavedSwitchInsn;
2466 SwitchWeights = SavedSwitchWeights;
2467 SwitchLikelihood = SavedSwitchLikelihood;
2468 CaseRangeBlock = SavedCRBlock;
2476 while (*Constraint) {
2477 switch (*Constraint) {
2489 while (Constraint[1] && Constraint[1] !=
',')
2495 while (Constraint[1] && Constraint[1] == *Constraint)
2506 "Must pass output names to constraints with a symbolic name");
2508 bool result =
Target.resolveSymbolicName(Constraint, *OutCons, Index);
2509 assert(result &&
"Could not resolve symbolic name"); (void)result;
2510 Result += llvm::utostr(Index);
2528 std::string *GCCReg =
nullptr) {
2529 const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
2541 StringRef Register =
Attr->getLabel();
2542 assert(
Target.isValidGCCRegisterName(Register));
2546 if (
Target.validateOutputConstraint(Info) &&
2552 Register =
Target.getNormalizedGCCRegisterName(Register);
2553 if (GCCReg !=
nullptr)
2554 *GCCReg = Register.str();
2555 return (EarlyClobber ?
"&{" :
"{") + Register.str() +
"}";
2558std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2567 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2577 ConstraintStr +=
'*';
2581std::pair<llvm::Value *, llvm::Type *>
2583 const Expr *InputExpr,
2584 std::string &ConstraintStr) {
2592 llvm::APSInt IntResult;
2595 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2607 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2611 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2623 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2626 if (!StrVal.empty()) {
2629 unsigned StartToken = 0;
2630 unsigned ByteOffset = 0;
2634 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2635 if (StrVal[i] !=
'\n')
continue;
2637 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2638 Locs.push_back(llvm::ConstantAsMetadata::get(
2647 bool HasUnwindClobber,
bool ReadOnly,
2648 bool ReadNone,
bool NoMerge,
bool NoConvergent,
2650 const std::vector<llvm::Type *> &ResultRegTypes,
2651 const std::vector<llvm::Type *> &ArgElemTypes,
2653 std::vector<llvm::Value *> &RegResults) {
2654 if (!HasUnwindClobber)
2655 Result.addFnAttr(llvm::Attribute::NoUnwind);
2658 Result.addFnAttr(llvm::Attribute::NoMerge);
2660 if (!HasSideEffect) {
2662 Result.setDoesNotAccessMemory();
2664 Result.setOnlyReadsMemory();
2668 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
2670 auto Attr = llvm::Attribute::get(
2671 CGF.
getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2679 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S);
2681 (SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))) {
2686 llvm::Constant *
Loc =
2687 llvm::ConstantInt::get(CGF.
Int64Ty, S.getAsmLoc().getRawEncoding());
2688 Result.setMetadata(
"srcloc",
2690 llvm::ConstantAsMetadata::get(
Loc)));
2701 Result.addFnAttr(llvm::Attribute::Convergent);
2703 if (ResultRegTypes.size() == 1) {
2704 RegResults.push_back(&
Result);
2706 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2707 llvm::Value *Tmp = CGF.
Builder.CreateExtractValue(&
Result, i,
"asmresult");
2708 RegResults.push_back(Tmp);
2720 const llvm::BitVector &ResultTypeRequiresCast,
2721 const llvm::BitVector &ResultRegIsFlagReg) {
2726 assert(RegResults.size() == ResultRegTypes.size());
2727 assert(RegResults.size() == ResultTruncRegTypes.size());
2728 assert(RegResults.size() == ResultRegDests.size());
2731 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2732 assert(ResultRegIsFlagReg.size() <= ResultRegDests.size());
2734 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2735 llvm::Value *Tmp = RegResults[i];
2736 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2738 if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
2741 llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2);
2742 llvm::Value *IsBooleanValue =
2743 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two);
2745 Builder.CreateCall(FnAssume, IsBooleanValue);
2750 if (ResultRegTypes[i] != TruncTy) {
2754 if (TruncTy->isFloatingPointTy())
2755 Tmp =
Builder.CreateFPTrunc(Tmp, TruncTy);
2756 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2759 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
2760 Tmp =
Builder.CreateIntToPtr(Tmp, TruncTy);
2761 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2765 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
2766 Tmp =
Builder.CreateTrunc(Tmp, TruncTy);
2767 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2768 Tmp =
Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2769 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2770 Tmp =
Builder.CreateBitCast(Tmp, TruncTy);
2775 LValue Dest = ResultRegDests[i];
2778 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2790 const Expr *OutExpr = S.getOutputExpr(i);
2792 diag::err_store_value_to_reg);
2803 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2806 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2807 Asm = GCCAsm->getAsmString();
2811 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2812 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2813 {StrTy->getType()},
false);
2814 auto UBF = CGF->
CGM.
getModule().getOrInsertFunction(Name, FnTy);
2816 CGF->
Builder.CreateCall(UBF, {StrTy});
2824 std::string AsmString = S.generateAsmString(
getContext());
2831 bool IsValidTargetAsm =
true;
2832 for (
unsigned i = 0, e = S.getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2834 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2835 Name = GAS->getOutputName(i);
2838 if (IsHipStdPar && !IsValid)
2839 IsValidTargetAsm =
false;
2841 assert(IsValid &&
"Failed to parse output constraint");
2842 OutputConstraintInfos.push_back(Info);
2845 for (
unsigned i = 0, e = S.getNumInputs(); i != e && IsValidTargetAsm; i++) {
2847 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2848 Name = GAS->getInputName(i);
2852 if (IsHipStdPar && !IsValid)
2853 IsValidTargetAsm =
false;
2855 assert(IsValid &&
"Failed to parse input constraint");
2856 InputConstraintInfos.push_back(Info);
2859 if (!IsValidTargetAsm)
2862 std::string Constraints;
2864 std::vector<LValue> ResultRegDests;
2865 std::vector<QualType> ResultRegQualTys;
2866 std::vector<llvm::Type *> ResultRegTypes;
2867 std::vector<llvm::Type *> ResultTruncRegTypes;
2868 std::vector<llvm::Type *> ArgTypes;
2869 std::vector<llvm::Type *> ArgElemTypes;
2870 std::vector<llvm::Value*> Args;
2871 llvm::BitVector ResultTypeRequiresCast;
2872 llvm::BitVector ResultRegIsFlagReg;
2875 std::string InOutConstraints;
2876 std::vector<llvm::Value*> InOutArgs;
2877 std::vector<llvm::Type*> InOutArgTypes;
2878 std::vector<llvm::Type*> InOutArgElemTypes;
2881 std::vector<std::string> OutputConstraints;
2884 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2892 bool ReadOnly =
true, ReadNone =
true;
2894 for (
unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
2898 std::string OutputConstraint(S.getOutputConstraint(i));
2902 const Expr *OutExpr = S.getOutputExpr(i);
2911 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2912 CGM.
Error(S.getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2914 OutputConstraints.push_back(OutputConstraint);
2916 if (!Constraints.empty())
2926 Constraints +=
"=" + OutputConstraint;
2927 ResultRegQualTys.push_back(QTy);
2928 ResultRegDests.push_back(Dest);
2930 bool IsFlagReg = llvm::StringRef(OutputConstraint).starts_with(
"{@cc");
2931 ResultRegIsFlagReg.push_back(IsFlagReg);
2936 Ty->isAggregateType());
2938 ResultTruncRegTypes.push_back(Ty);
2939 ResultTypeRequiresCast.push_back(RequiresCast);
2948 ResultRegTypes.push_back(Ty);
2954 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2959 assert(InputNo != S.getNumInputs() &&
"Didn't find matching input!");
2961 QualType InputTy = S.getInputExpr(InputNo)->getType();
2970 if (llvm::Type* AdjTy =
2972 ResultRegTypes.back()))
2973 ResultRegTypes.back() = AdjTy;
2976 diag::err_asm_invalid_type_in_input)
2977 << OutExpr->
getType() << OutputConstraint;
2981 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
2982 LargestVectorWidth =
2983 std::max((uint64_t)LargestVectorWidth,
2984 VT->getPrimitiveSizeInBits().getKnownMinValue());
2995 ArgTypes.push_back(DestAddr.
getType());
2998 Constraints +=
"=*";
2999 Constraints += OutputConstraint;
3000 ReadOnly = ReadNone =
false;
3004 InOutConstraints +=
',';
3006 const Expr *InputExpr = S.getOutputExpr(i);
3008 llvm::Type *ArgElemType;
3009 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
3010 Info, Dest, InputExpr->
getType(), InOutConstraints,
3013 if (llvm::Type* AdjTy =
3016 Arg =
Builder.CreateBitCast(Arg, AdjTy);
3019 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3020 LargestVectorWidth =
3021 std::max((uint64_t)LargestVectorWidth,
3022 VT->getPrimitiveSizeInBits().getKnownMinValue());
3025 InOutConstraints += llvm::utostr(i);
3027 InOutConstraints += OutputConstraint;
3029 InOutArgTypes.push_back(Arg->getType());
3030 InOutArgElemTypes.push_back(ArgElemType);
3031 InOutArgs.push_back(Arg);
3037 if (isa<MSAsmStmt>(&S)) {
3043 *
this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
3044 ResultRegDests, AsmString, S.getNumOutputs());
3049 for (
unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
3050 const Expr *InputExpr = S.getInputExpr(i);
3057 if (!Constraints.empty())
3061 std::string InputConstraint(S.getInputConstraint(i));
3063 &OutputConstraintInfos);
3069 std::string ReplaceConstraint (InputConstraint);
3071 llvm::Type *ArgElemType;
3072 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
3081 QualType OutputType = S.getOutputExpr(Output)->getType();
3087 if (isa<llvm::PointerType>(Arg->getType()))
3090 if (isa<llvm::IntegerType>(OutputTy))
3091 Arg =
Builder.CreateZExt(Arg, OutputTy);
3092 else if (isa<llvm::PointerType>(OutputTy))
3094 else if (OutputTy->isFloatingPointTy())
3095 Arg =
Builder.CreateFPExt(Arg, OutputTy);
3098 ReplaceConstraint = OutputConstraints[Output];
3100 if (llvm::Type* AdjTy =
3103 Arg =
Builder.CreateBitCast(Arg, AdjTy);
3106 << InputExpr->
getType() << InputConstraint;
3109 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
3110 LargestVectorWidth =
3111 std::max((uint64_t)LargestVectorWidth,
3112 VT->getPrimitiveSizeInBits().getKnownMinValue());
3114 ArgTypes.push_back(Arg->getType());
3115 ArgElemTypes.push_back(ArgElemType);
3116 Args.push_back(Arg);
3117 Constraints += InputConstraint;
3121 for (
unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
3122 ArgTypes.push_back(InOutArgTypes[i]);
3123 ArgElemTypes.push_back(InOutArgElemTypes[i]);
3124 Args.push_back(InOutArgs[i]);
3126 Constraints += InOutConstraints;
3130 llvm::BasicBlock *Fallthrough =
nullptr;
3131 bool IsGCCAsmGoto =
false;
3132 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S)) {
3133 IsGCCAsmGoto = GS->isAsmGoto();
3135 for (
const auto *
E : GS->labels()) {
3137 Transfer.push_back(Dest.
getBlock());
3138 if (!Constraints.empty())
3140 Constraints +=
"!i";
3146 bool HasUnwindClobber =
false;
3149 for (
unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
3150 std::string Clobber = S.getClobber(i);
3152 if (Clobber ==
"memory")
3153 ReadOnly = ReadNone =
false;
3154 else if (Clobber ==
"unwind") {
3155 HasUnwindClobber =
true;
3157 }
else if (Clobber !=
"cc") {
3162 diag::warn_stack_clash_protection_inline_asm);
3166 if (isa<MSAsmStmt>(&S)) {
3167 if (Clobber ==
"eax" || Clobber ==
"edx") {
3168 if (Constraints.find(
"=&A") != std::string::npos)
3170 std::string::size_type position1 =
3171 Constraints.find(
"={" + Clobber +
"}");
3172 if (position1 != std::string::npos) {
3173 Constraints.insert(position1 + 1,
"&");
3176 std::string::size_type position2 = Constraints.find(
"=A");
3177 if (position2 != std::string::npos) {
3178 Constraints.insert(position2 + 1,
"&");
3183 if (!Constraints.empty())
3186 Constraints +=
"~{";
3187 Constraints += Clobber;
3191 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
3192 "unwind clobber can't be used with asm goto");
3196 if (!MachineClobbers.empty()) {
3197 if (!Constraints.empty())
3199 Constraints += MachineClobbers;
3202 llvm::Type *ResultType;
3203 if (ResultRegTypes.empty())
3205 else if (ResultRegTypes.size() == 1)
3206 ResultType = ResultRegTypes[0];
3208 ResultType = llvm::StructType::get(
getLLVMContext(), ResultRegTypes);
3210 llvm::FunctionType *FTy =
3211 llvm::FunctionType::get(ResultType, ArgTypes,
false);
3213 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
3215 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3217 ? llvm::InlineAsm::AD_ATT
3218 : llvm::InlineAsm::AD_Intel;
3219 llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ?
3220 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3222 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3223 FTy, AsmString, Constraints, HasSideEffect,
3224 false, AsmDialect, HasUnwindClobber);
3225 std::vector<llvm::Value*> RegResults;
3226 llvm::CallBrInst *CBR;
3227 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3230 CBR =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3235 ArgElemTypes, *
this, RegResults);
3239 if (!RegResults.empty()) {
3241 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3242 llvm::Twine SynthName = Dest->getName() +
".split";
3244 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3245 Builder.SetInsertPoint(SynthBB);
3247 if (ResultRegTypes.size() == 1) {
3248 CBRRegResults[SynthBB].push_back(CBR);
3250 for (
unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3251 llvm::Value *Tmp =
Builder.CreateExtractValue(CBR, j,
"asmresult");
3252 CBRRegResults[SynthBB].push_back(Tmp);
3258 CBR->setIndirectDest(i++, SynthBB);
3261 }
else if (HasUnwindClobber) {
3266 ArgElemTypes, *
this, RegResults);
3273 ArgElemTypes, *
this, RegResults);
3276 EmitAsmStores(*
this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3277 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3278 ResultRegIsFlagReg);
3283 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3284 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3285 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3286 Builder.SetInsertPoint(Succ, --(Succ->end()));
3287 EmitAsmStores(*
this, S, CBRRegResults[Succ], ResultRegTypes,
3288 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3289 ResultTypeRequiresCast, ResultRegIsFlagReg);
3295 const RecordDecl *RD = S.getCapturedRecordDecl();
3304 E = S.capture_init_end();
3305 I !=
E; ++I, ++CurField) {
3307 if (CurField->hasCapturedVLAType()) {
3344 "CapturedStmtInfo should be set when generating the captured function");
3346 const RecordDecl *RD = S.getCapturedRecordDecl();
3348 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3361 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3365 F->addFnAttr(llvm::Attribute::NoUnwind);
3377 for (
auto *FD : RD->
fields()) {
3378 if (FD->hasCapturedVLAType()) {
3382 auto VAT = FD->getCapturedVLAType();
3383 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3394 PGO->assignRegionCounters(
GlobalDecl(CD), F);
3404 for (
auto &I : *BB) {
3405 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3412CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3414 assert(ParentToken);
3416 llvm::Value *bundleArgs[] = {ParentToken};
3417 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3418 auto *Output = llvm::CallBase::addOperandBundle(
3419 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3420 Input->replaceAllUsesWith(Output);
3421 Input->eraseFromParent();
3425llvm::ConvergenceControlInst *
3426CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
3428 assert(ParentToken);
3429 return llvm::ConvergenceControlInst::CreateLoop(*BB, ParentToken);
3432llvm::ConvergenceControlInst *
3433CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3434 llvm::BasicBlock *BB = &F->getEntryBlock();
3442 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 std::string SimplifyConstraint(const char *Constraint, const TargetInfo &Target, SmallVectorImpl< TargetInfo::ConstraintInfo > *OutCons=nullptr)
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 llvm::BitVector &ResultRegIsFlagReg)
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.
Attr - This represents one attribute.
Represents an attribute applied to a statement.
BreakStmt - This represents a break.
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
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.
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.
bool hasProfileClangInstr() const
Check if Clang profile instrumenation is on.
bool hasReducedDebugInfo() const
Check if type and variable info should be emitted.
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 * CreateFlagStore(bool Value, llvm::Value *Addr)
Emit a store to an i1 flag variable.
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()
CallingConv getASTCallingConvention() const
getASTCallingConvention() - Return the AST-specified calling convention.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
API for captured statement code generation.
virtual llvm::Value * getContextValue() const
virtual void setContextValue(llvm::Value *V)
bool isCXXThisExprCaptured() const
virtual FieldDecl * getThisFieldDecl() const
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual StringRef getHelperName() const
Get the name of the capture helper.
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 addLabel(const LabelDecl *label)
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 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 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)
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)
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.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
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
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
void Error(SourceLocation loc, StringRef error)
Emit a general error that something can't be done.
bool shouldEmitConvergenceTokens() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
SanitizerMetadata * getSanitizerMetadata()
ASTContext & getContext() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
A saved depth on the scope stack.
bool encloses(stable_iterator I) const
Returns true if this scope encloses I.
static stable_iterator invalid()
stable_iterator getInnermostNormalCleanup() const
Returns the innermost normal cleanup on the stack, or stable_end() if there are no normal cleanups.
stable_iterator stable_begin() const
Create a stable reference to the top of the EH stack.
bool empty() const
Determines whether the exception-scopes stack is empty.
bool hasNormalCleanups() const
Determines whether there are any normal cleanups on the stack.
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
void pop()
End the current loop.
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
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 void addReturnRegisterOutputs(CodeGen::CodeGenFunction &CGF, CodeGen::LValue ReturnValue, std::string &Constraints, std::vector< llvm::Type * > &ResultRegTypes, std::vector< llvm::Type * > &ResultTruncRegTypes, std::vector< CodeGen::LValue > &ResultRegDests, std::string &AsmString, unsigned NumOutputs) const
Adds constraints and types for result registers.
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
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
ContinueStmt - This represents a continue.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
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
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, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) 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.
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.
IfStmt - This represents an if/then/else.
IndirectGotoStmt - This represents an indirect goto.
Represents the declaration of a label.
LabelStmt - Represents a label, which has a substatement.
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.
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
field_iterator field_begin() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
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
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.
Exposes information about the current target.
bool validateInputConstraint(MutableArrayRef< ConstraintInfo > OutputConstraints, ConstraintInfo &info) 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.
Token - This structure provides full information about a lexed token.
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
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.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
WhileStmt - This represents a 'while' stmt.
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
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.
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 * Int32Ty
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
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