27 #include "llvm/ADT/ArrayRef.h"
28 #include "llvm/ADT/DenseMap.h"
29 #include "llvm/ADT/SmallSet.h"
30 #include "llvm/ADT/StringExtras.h"
31 #include "llvm/IR/Assumptions.h"
32 #include "llvm/IR/DataLayout.h"
33 #include "llvm/IR/InlineAsm.h"
34 #include "llvm/IR/Intrinsics.h"
35 #include "llvm/IR/MDBuilder.h"
36 #include "llvm/Support/SaveAndRestore.h"
39 using namespace clang;
40 using namespace CodeGen;
53 Loc = S->getBeginLoc();
61 assert(S &&
"Null statement?");
78 assert(!isa<DeclStmt>(*S) &&
"Unexpected DeclStmt!");
92 if (
const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
98 switch (S->getStmtClass()) {
100 case Stmt::CXXCatchStmtClass:
101 case Stmt::SEHExceptStmtClass:
102 case Stmt::SEHFinallyStmtClass:
103 case Stmt::MSDependentExistsStmtClass:
104 llvm_unreachable(
"invalid statement class to emit generically");
105 case Stmt::NullStmtClass:
106 case Stmt::CompoundStmtClass:
107 case Stmt::DeclStmtClass:
108 case Stmt::LabelStmtClass:
109 case Stmt::AttributedStmtClass:
110 case Stmt::GotoStmtClass:
111 case Stmt::BreakStmtClass:
112 case Stmt::ContinueStmtClass:
113 case Stmt::DefaultStmtClass:
114 case Stmt::CaseStmtClass:
115 case Stmt::SEHLeaveStmtClass:
116 llvm_unreachable(
"should have emitted these statements as simple");
118 #define STMT(Type, Base)
119 #define ABSTRACT_STMT(Op)
120 #define EXPR(Type, Base) \
121 case Stmt::Type##Class:
122 #include "clang/AST/StmtNodes.inc"
125 llvm::BasicBlock *incoming =
Builder.GetInsertBlock();
126 assert(incoming &&
"expression emission must have an insertion point");
130 llvm::BasicBlock *outgoing =
Builder.GetInsertBlock();
131 assert(outgoing &&
"expression emission cleared block!");
145 if (incoming != outgoing && outgoing->use_empty()) {
146 outgoing->eraseFromParent();
152 case Stmt::IndirectGotoStmtClass:
155 case Stmt::IfStmtClass:
EmitIfStmt(cast<IfStmt>(*S));
break;
156 case Stmt::WhileStmtClass:
EmitWhileStmt(cast<WhileStmt>(*S), Attrs);
break;
157 case Stmt::DoStmtClass:
EmitDoStmt(cast<DoStmt>(*S), Attrs);
break;
158 case Stmt::ForStmtClass:
EmitForStmt(cast<ForStmt>(*S), Attrs);
break;
160 case Stmt::ReturnStmtClass:
EmitReturnStmt(cast<ReturnStmt>(*S));
break;
162 case Stmt::SwitchStmtClass:
EmitSwitchStmt(cast<SwitchStmt>(*S));
break;
163 case Stmt::GCCAsmStmtClass:
164 case Stmt::MSAsmStmtClass:
EmitAsmStmt(cast<AsmStmt>(*S));
break;
165 case Stmt::CoroutineBodyStmtClass:
168 case Stmt::CoreturnStmtClass:
171 case Stmt::CapturedStmtClass: {
176 case Stmt::ObjCAtTryStmtClass:
179 case Stmt::ObjCAtCatchStmtClass:
181 "@catch statements should be handled by EmitObjCAtTryStmt");
182 case Stmt::ObjCAtFinallyStmtClass:
184 "@finally statements should be handled by EmitObjCAtTryStmt");
185 case Stmt::ObjCAtThrowStmtClass:
188 case Stmt::ObjCAtSynchronizedStmtClass:
191 case Stmt::ObjCForCollectionStmtClass:
194 case Stmt::ObjCAutoreleasePoolStmtClass:
198 case Stmt::CXXTryStmtClass:
201 case Stmt::CXXForRangeStmtClass:
204 case Stmt::SEHTryStmtClass:
207 case Stmt::OMPMetaDirectiveClass:
210 case Stmt::OMPCanonicalLoopClass:
213 case Stmt::OMPParallelDirectiveClass:
216 case Stmt::OMPSimdDirectiveClass:
219 case Stmt::OMPTileDirectiveClass:
222 case Stmt::OMPUnrollDirectiveClass:
225 case Stmt::OMPForDirectiveClass:
228 case Stmt::OMPForSimdDirectiveClass:
231 case Stmt::OMPSectionsDirectiveClass:
234 case Stmt::OMPSectionDirectiveClass:
237 case Stmt::OMPSingleDirectiveClass:
240 case Stmt::OMPMasterDirectiveClass:
243 case Stmt::OMPCriticalDirectiveClass:
246 case Stmt::OMPParallelForDirectiveClass:
249 case Stmt::OMPParallelForSimdDirectiveClass:
252 case Stmt::OMPParallelMasterDirectiveClass:
255 case Stmt::OMPParallelSectionsDirectiveClass:
258 case Stmt::OMPTaskDirectiveClass:
261 case Stmt::OMPTaskyieldDirectiveClass:
264 case Stmt::OMPErrorDirectiveClass:
267 case Stmt::OMPBarrierDirectiveClass:
270 case Stmt::OMPTaskwaitDirectiveClass:
273 case Stmt::OMPTaskgroupDirectiveClass:
276 case Stmt::OMPFlushDirectiveClass:
279 case Stmt::OMPDepobjDirectiveClass:
282 case Stmt::OMPScanDirectiveClass:
285 case Stmt::OMPOrderedDirectiveClass:
288 case Stmt::OMPAtomicDirectiveClass:
291 case Stmt::OMPTargetDirectiveClass:
294 case Stmt::OMPTeamsDirectiveClass:
297 case Stmt::OMPCancellationPointDirectiveClass:
300 case Stmt::OMPCancelDirectiveClass:
303 case Stmt::OMPTargetDataDirectiveClass:
306 case Stmt::OMPTargetEnterDataDirectiveClass:
309 case Stmt::OMPTargetExitDataDirectiveClass:
312 case Stmt::OMPTargetParallelDirectiveClass:
315 case Stmt::OMPTargetParallelForDirectiveClass:
318 case Stmt::OMPTaskLoopDirectiveClass:
321 case Stmt::OMPTaskLoopSimdDirectiveClass:
324 case Stmt::OMPMasterTaskLoopDirectiveClass:
327 case Stmt::OMPMaskedTaskLoopDirectiveClass:
328 llvm_unreachable(
"masked taskloop directive not supported yet.");
330 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
332 cast<OMPMasterTaskLoopSimdDirective>(*S));
334 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
335 llvm_unreachable(
"masked taskloop simd directive not supported yet.");
337 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
339 cast<OMPParallelMasterTaskLoopDirective>(*S));
341 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
342 llvm_unreachable(
"parallel masked taskloop directive not supported yet.");
344 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
346 cast<OMPParallelMasterTaskLoopSimdDirective>(*S));
348 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
350 "parallel masked taskloop simd directive not supported yet.");
352 case Stmt::OMPDistributeDirectiveClass:
355 case Stmt::OMPTargetUpdateDirectiveClass:
358 case Stmt::OMPDistributeParallelForDirectiveClass:
360 cast<OMPDistributeParallelForDirective>(*S));
362 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
364 cast<OMPDistributeParallelForSimdDirective>(*S));
366 case Stmt::OMPDistributeSimdDirectiveClass:
369 case Stmt::OMPTargetParallelForSimdDirectiveClass:
371 cast<OMPTargetParallelForSimdDirective>(*S));
373 case Stmt::OMPTargetSimdDirectiveClass:
376 case Stmt::OMPTeamsDistributeDirectiveClass:
379 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
381 cast<OMPTeamsDistributeSimdDirective>(*S));
383 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
385 cast<OMPTeamsDistributeParallelForSimdDirective>(*S));
387 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
389 cast<OMPTeamsDistributeParallelForDirective>(*S));
391 case Stmt::OMPTargetTeamsDirectiveClass:
394 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
396 cast<OMPTargetTeamsDistributeDirective>(*S));
398 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
400 cast<OMPTargetTeamsDistributeParallelForDirective>(*S));
402 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
404 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(*S));
406 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
408 cast<OMPTargetTeamsDistributeSimdDirective>(*S));
410 case Stmt::OMPInteropDirectiveClass:
413 case Stmt::OMPDispatchDirectiveClass:
416 case Stmt::OMPScopeDirectiveClass:
417 llvm_unreachable(
"scope not supported with FE outlining");
418 case Stmt::OMPMaskedDirectiveClass:
421 case Stmt::OMPGenericLoopDirectiveClass:
424 case Stmt::OMPTeamsGenericLoopDirectiveClass:
427 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
429 cast<OMPTargetTeamsGenericLoopDirective>(*S));
431 case Stmt::OMPParallelGenericLoopDirectiveClass:
433 cast<OMPParallelGenericLoopDirective>(*S));
435 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
437 cast<OMPTargetParallelGenericLoopDirective>(*S));
439 case Stmt::OMPParallelMaskedDirectiveClass:
442 case Stmt::OpenACCComputeConstructClass:
450 switch (S->getStmtClass()) {
453 case Stmt::NullStmtClass:
455 case Stmt::CompoundStmtClass:
458 case Stmt::DeclStmtClass:
461 case Stmt::LabelStmtClass:
464 case Stmt::AttributedStmtClass:
467 case Stmt::GotoStmtClass:
470 case Stmt::BreakStmtClass:
473 case Stmt::ContinueStmtClass:
476 case Stmt::DefaultStmtClass:
479 case Stmt::CaseStmtClass:
482 case Stmt::SEHLeaveStmtClass:
495 "LLVM IR generation of compound statement ('{}')");
509 assert((!GetLast || (GetLast &&
ExprResult)) &&
510 "If GetLast is true then the CompoundStmt must have a StmtExprResult");
514 for (
auto *CurStmt : S.body()) {
522 if (
const auto *LS = dyn_cast<LabelStmt>(
ExprResult)) {
525 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(
ExprResult)) {
530 llvm_unreachable(
"unknown value statement");
557 llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
566 if (!BI || !BI->isUnconditional())
570 if (BI->getIterator() != BB->begin())
573 BB->replaceAllUsesWith(BI->getSuccessor(0));
574 BI->eraseFromParent();
575 BB->eraseFromParent();
579 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
584 if (IsFinished && BB->use_empty()) {
591 if (CurBB && CurBB->getParent())
592 CurFn->insert(std::next(CurBB->getIterator()), BB);
602 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
604 if (!CurBB || CurBB->getTerminator()) {
616 bool inserted =
false;
617 for (llvm::User *u : block->users()) {
618 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
619 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
634 if (Dest.
isValid())
return Dest;
681 assert(!Labels.empty());
687 i = Labels.begin(), e = Labels.end(); i != e; ++i) {
688 assert(
CGF.LabelMap.count(*i));
697 ParentScope->Labels.append(Labels.begin(), Labels.end());
713 bool nomerge =
false;
714 bool noinline =
false;
715 bool alwaysinline =
false;
718 for (
const auto *A : S.getAttrs()) {
719 switch (A->getKind()) {
728 case attr::AlwaysInline:
731 case attr::MustTail: {
732 const Stmt *Sub = S.getSubStmt();
736 case attr::CXXAssume: {
737 const Expr *Assumption = cast<CXXAssumeAttr>(A)->getAssumption();
741 Builder.CreateAssumption(AssumptionVal);
750 EmitStmt(S.getSubStmt(), S.getAttrs());
773 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
780 cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(
V, CurBB);
788 if (S.isConsteval()) {
789 const Stmt *Executed = S.isNegatedConsteval() ? S.getThen() : S.getElse();
799 LexicalScope ConditionScope(*
this, S.getCond()->getSourceRange());
804 if (S.getConditionVariable())
805 EmitDecl(*S.getConditionVariable());
813 const Stmt *Executed = S.getThen();
814 const Stmt *Skipped = S.getElse();
816 std::swap(Executed, Skipped);
835 llvm::BasicBlock *ElseBlock = ContBlock;
866 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
882 if (
const Stmt *Else = S.getElse()) {
914 CodeGenOptions::FiniteLoopsKind::Never)
923 bool CondIsConstInt =
924 !ControllingExpression ||
928 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
929 Result.Val.getInt().getBoolValue());
941 CodeGenOptions::FiniteLoopsKind::Always ||
943 if (HasEmptyBody && CondIsTrue) {
944 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
962 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
966 const Stmt *Body = S.getBody();
967 if (!Body || isa<NullStmt>(Body))
969 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
970 return Compound->body_empty();
990 BreakContinueStack.push_back(BreakContinue(
LoopExit, LoopHeader));
1001 if (S.getConditionVariable())
1002 EmitDecl(*S.getConditionVariable());
1011 llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1012 bool EmitBoolCondBranch = !C || !C->isOne();
1025 if (EmitBoolCondBranch) {
1026 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1029 llvm::MDNode *Weights =
1030 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1032 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1034 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1036 if (ExitBlock !=
LoopExit.getBlock()) {
1042 diag::warn_attribute_has_no_effect_on_infinite_loop)
1043 << A << A->getRange();
1046 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1047 <<
SourceRange(S.getWhileLoc(), S.getRParenLoc());
1063 BreakContinueStack.pop_back();
1079 if (!EmitBoolCondBranch)
1099 BreakContinueStack.push_back(BreakContinue(
LoopExit, LoopCond));
1131 BreakContinueStack.pop_back();
1135 llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1136 bool EmitBoolCondBranch = !C || !C->isZero();
1145 if (EmitBoolCondBranch) {
1148 BoolCondVal, LoopBody,
LoopExit.getBlock(),
1149 createProfileWeightsForLoop(S.getCond(), BackedgeCount));
1159 if (!EmitBoolCondBranch)
1185 llvm::BasicBlock *CondBlock = CondDest.
getBlock();
1199 LexicalScope ConditionScope(*
this, S.getSourceRange());
1210 Continue = CondDest;
1211 else if (!S.getConditionVariable())
1213 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1218 if (S.getConditionVariable()) {
1219 EmitDecl(*S.getConditionVariable());
1224 BreakContinueStack.back().ContinueBlock = Continue;
1232 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1244 llvm::MDNode *Weights =
1245 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1247 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1250 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1252 if (ExitBlock !=
LoopExit.getBlock()) {
1283 BreakContinueStack.pop_back();
1337 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1347 llvm::MDNode *Weights =
1348 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1350 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1352 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1354 if (ExitBlock !=
LoopExit.getBlock()) {
1369 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1383 BreakContinueStack.pop_back();
1403 void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1419 struct SaveRetExprRAII {
1421 : OldRetExpr(CGF.
RetExpr), CGF(CGF) {
1424 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1425 const Expr *OldRetExpr;
1434 if (calleeQualType->isFunctionPointerType() ||
1435 calleeQualType->isFunctionReferenceType() ||
1436 calleeQualType->isBlockPointerType() ||
1437 calleeQualType->isMemberFunctionPointerType()) {
1439 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1441 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1442 if (
auto methodDecl = CMCE->getMethodDecl()) {
1458 if (requiresReturnValueCheck()) {
1461 new llvm::GlobalVariable(
CGM.
getModule(), SLoc->getType(),
false,
1462 llvm::GlobalVariable::PrivateLinkage, SLoc);
1463 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1465 assert(ReturnLocation.
isValid() &&
"No valid return location");
1472 Builder.ClearInsertionPoint();
1476 const Expr *RV = S.getRetValue();
1486 SaveRetExprRAII SaveRetExpr(RV, *
this);
1489 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1490 RV = EWC->getSubExpr();
1494 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1497 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1507 if (
getLangOpts().ElideConstructors && S.getNRVOCandidate() &&
1508 S.getNRVOCandidate()->isNRVOVariable() &&
1519 if (llvm::Value *NRVOFlag =
NRVOFlags[S.getNRVOCandidate()])
1556 ++NumSimpleReturnExprs;
1568 for (
const auto *I : S.decls())
1573 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1585 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1601 assert(S.getRHS() &&
"Expected RHS value in CaseStmt");
1614 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1623 unsigned NCases =
Range.getZExtValue() + 1;
1628 uint64_t Weight = Total / NCases,
Rem = Total % NCases;
1629 for (
unsigned I = 0; I != NCases; ++I) {
1631 SwitchWeights->push_back(Weight + (
Rem ? 1 : 0));
1632 else if (SwitchLikelihood)
1633 SwitchLikelihood->push_back(LH);
1637 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1645 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1650 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1654 Builder.SetInsertPoint(CaseRangeBlock);
1658 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1662 llvm::MDNode *Weights =
nullptr;
1663 if (SwitchWeights) {
1665 uint64_t DefaultCount = (*SwitchWeights)[0];
1666 Weights = createProfileWeights(ThisCount, DefaultCount);
1671 (*SwitchWeights)[0] += ThisCount;
1672 }
else if (SwitchLikelihood)
1673 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
1675 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
1679 Builder.SetInsertPoint(RestoreBB);
1681 Builder.ClearInsertionPoint();
1702 llvm::ConstantInt *CaseVal =
1707 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.getLHS()))
1708 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1710 CE = dyn_cast<ConstantExpr>(S.getLHS());
1712 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1715 Dbg->EmitGlobalVariable(DE->getDecl(),
1719 if (SwitchLikelihood)
1727 isa<BreakStmt>(S.getSubStmt())) {
1734 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1738 if (
Builder.GetInsertBlock()) {
1740 Builder.ClearInsertionPoint();
1750 SwitchInsn->addCase(CaseVal, CaseDest);
1766 const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt());
1769 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1771 llvm::ConstantInt *CaseVal =
1782 if (SwitchLikelihood)
1785 SwitchInsn->addCase(CaseVal, CaseDest);
1786 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1809 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1810 assert(DefaultBlock->empty() &&
1811 "EmitDefaultStmt: Default block already defined?");
1813 if (SwitchLikelihood)
1855 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
1869 if (!Case && isa<BreakStmt>(S))
1874 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
1878 bool StartedInLiveCode = FoundCase;
1879 unsigned StartSize = ResultStmts.size();
1886 bool HadSkippedDecl =
false;
1890 for (; Case && I != E; ++I) {
1906 for (++I; I != E; ++I)
1916 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
1931 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
1936 bool AnyDecls =
false;
1937 for (; I != E; ++I) {
1950 for (++I; I != E; ++I)
1967 ResultStmts.resize(StartSize);
1968 ResultStmts.push_back(S);
1992 ResultStmts.push_back(S);
2007 const SwitchCase *Case = S.getSwitchCaseList();
2013 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2019 const CaseStmt *CS = cast<CaseStmt>(Case);
2021 if (CS->
getRHS())
return false;
2046 bool FoundCase =
false;
2053 static std::optional<SmallVector<uint64_t, 16>>
2056 if (Likelihoods.size() <= 1)
2057 return std::nullopt;
2062 for (
const auto LH : Likelihoods) {
2077 if (NumUnlikely == 0 && NumLikely == 0)
2078 return std::nullopt;
2086 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2087 const uint64_t None = Likely / (NumNone + 1);
2091 Result.reserve(Likelihoods.size());
2092 for (
const auto LH : Likelihoods) {
2095 Result.push_back(Unlikely);
2098 Result.push_back(None);
2101 Result.push_back(Likely);
2111 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2114 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2133 if (S.getConditionVariable())
2134 EmitDecl(*S.getConditionVariable());
2139 SwitchInsn =
nullptr;
2143 for (
unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
2149 SwitchInsn = SavedSwitchInsn;
2162 if (S.getConditionVariable())
2163 EmitDecl(*S.getConditionVariable());
2171 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2175 unsigned NumCases = 0;
2176 for (
const SwitchCase *Case = S.getSwitchCaseList();
2178 Case = Case->getNextSwitchCase()) {
2179 if (isa<DefaultStmt>(Case))
2184 SwitchWeights->reserve(NumCases);
2187 SwitchWeights->push_back(DefaultCount);
2194 CaseRangeBlock = DefaultBlock;
2197 Builder.ClearInsertionPoint();
2202 if (!BreakContinueStack.empty())
2203 OuterContinue = BreakContinueStack.back().ContinueBlock;
2205 BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue));
2210 BreakContinueStack.pop_back();
2214 SwitchInsn->setDefaultDest(CaseRangeBlock);
2217 if (!DefaultBlock->getParent()) {
2225 DefaultBlock->replaceAllUsesWith(SwitchExit.
getBlock());
2226 delete DefaultBlock;
2239 auto *Call = dyn_cast<CallExpr>(S.getCond());
2241 auto *FD = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
2242 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2244 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2245 MDHelper.createUnpredictable());
2249 if (SwitchWeights) {
2250 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2251 "switch weights do not match switch cases");
2253 if (SwitchWeights->size() > 1)
2254 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2255 createProfileWeights(*SwitchWeights));
2256 delete SwitchWeights;
2257 }
else if (SwitchLikelihood) {
2258 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2259 "switch likelihoods do not match switch cases");
2260 std::optional<SmallVector<uint64_t, 16>> LHW =
2264 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2265 createProfileWeights(*LHW));
2267 delete SwitchLikelihood;
2269 SwitchInsn = SavedSwitchInsn;
2270 SwitchWeights = SavedSwitchWeights;
2271 SwitchLikelihood = SavedSwitchLikelihood;
2272 CaseRangeBlock = SavedCRBlock;
2280 while (*Constraint) {
2281 switch (*Constraint) {
2283 Result +=
Target.convertConstraint(Constraint);
2293 while (Constraint[1] && Constraint[1] !=
',')
2298 Result += *Constraint;
2299 while (Constraint[1] && Constraint[1] == *Constraint)
2310 "Must pass output names to constraints with a symbolic name");
2312 bool result =
Target.resolveSymbolicName(Constraint, *OutCons, Index);
2313 assert(result &&
"Could not resolve symbolic name"); (void)result;
2314 Result += llvm::utostr(Index);
2332 std::string *GCCReg =
nullptr) {
2333 const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
2342 AsmLabelAttr *
Attr = Variable->getAttr<AsmLabelAttr>();
2345 StringRef Register =
Attr->getLabel();
2346 assert(
Target.isValidGCCRegisterName(Register));
2350 if (
Target.validateOutputConstraint(Info) &&
2356 Register =
Target.getNormalizedGCCRegisterName(Register);
2357 if (GCCReg !=
nullptr)
2358 *GCCReg = Register.str();
2359 return (EarlyClobber ?
"&{" :
"{") + Register.str() +
"}";
2362 std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2371 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2381 ConstraintStr +=
'*';
2385 std::pair<llvm::Value *, llvm::Type *>
2387 const Expr *InputExpr,
2388 std::string &ConstraintStr) {
2399 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2404 return {llvm::ConstantInt::get(
getLLVMContext(), Result.Val.getInt()),
2411 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2415 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2427 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2430 if (!StrVal.empty()) {
2433 unsigned StartToken = 0;
2434 unsigned ByteOffset = 0;
2438 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2439 if (StrVal[i] !=
'\n')
continue;
2441 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2442 Locs.push_back(llvm::ConstantAsMetadata::get(
2451 bool HasUnwindClobber,
bool ReadOnly,
2452 bool ReadNone,
bool NoMerge,
const AsmStmt &S,
2453 const std::vector<llvm::Type *> &ResultRegTypes,
2454 const std::vector<llvm::Type *> &ArgElemTypes,
2456 std::vector<llvm::Value *> &RegResults) {
2457 if (!HasUnwindClobber)
2458 Result.addFnAttr(llvm::Attribute::NoUnwind);
2461 Result.addFnAttr(llvm::Attribute::NoMerge);
2463 if (!HasSideEffect) {
2465 Result.setDoesNotAccessMemory();
2467 Result.setOnlyReadsMemory();
2471 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
2473 auto Attr = llvm::Attribute::get(
2474 CGF.
getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2475 Result.addParamAttr(Pair.index(),
Attr);
2481 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S))
2482 Result.setMetadata(
"srcloc",
2486 llvm::Constant *
Loc =
2487 llvm::ConstantInt::get(CGF.
Int64Ty, S.getAsmLoc().getRawEncoding());
2488 Result.setMetadata(
"srcloc",
2490 llvm::ConstantAsMetadata::get(
Loc)));
2498 Result.addFnAttr(llvm::Attribute::Convergent);
2500 if (ResultRegTypes.size() == 1) {
2501 RegResults.push_back(&Result);
2503 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2504 llvm::Value *Tmp = CGF.
Builder.CreateExtractValue(&Result, i,
"asmresult");
2505 RegResults.push_back(Tmp);
2517 const llvm::BitVector &ResultTypeRequiresCast,
2518 const llvm::BitVector &ResultRegIsFlagReg) {
2523 assert(RegResults.size() == ResultRegTypes.size());
2524 assert(RegResults.size() == ResultTruncRegTypes.size());
2525 assert(RegResults.size() == ResultRegDests.size());
2528 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2529 assert(ResultRegIsFlagReg.size() <= ResultRegDests.size());
2531 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2532 llvm::Value *Tmp = RegResults[i];
2533 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2535 if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
2538 llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2);
2539 llvm::Value *IsBooleanValue =
2540 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two);
2542 Builder.CreateCall(FnAssume, IsBooleanValue);
2547 if (ResultRegTypes[i] != TruncTy) {
2551 if (TruncTy->isFloatingPointTy())
2552 Tmp =
Builder.CreateFPTrunc(Tmp, TruncTy);
2553 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2556 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
2557 Tmp =
Builder.CreateIntToPtr(Tmp, TruncTy);
2558 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2562 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
2563 Tmp =
Builder.CreateTrunc(Tmp, TruncTy);
2564 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2565 Tmp =
Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2566 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2567 Tmp =
Builder.CreateBitCast(Tmp, TruncTy);
2571 LValue Dest = ResultRegDests[i];
2574 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2585 const Expr *OutExpr = S.getOutputExpr(i);
2587 diag::err_store_value_to_reg);
2598 constexpr
auto Name =
"__ASM__hipstdpar_unsupported";
2601 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2602 Asm = GCCAsm->getAsmString()->getString();
2606 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2607 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2608 {StrTy->getType()},
false);
2609 auto UBF = CGF->
CGM.
getModule().getOrInsertFunction(Name, FnTy);
2611 CGF->
Builder.CreateCall(UBF, {StrTy});
2619 std::string AsmString = S.generateAsmString(
getContext());
2626 bool IsValidTargetAsm =
true;
2627 for (
unsigned i = 0, e = S.getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2629 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2630 Name = GAS->getOutputName(i);
2633 if (IsHipStdPar && !IsValid)
2634 IsValidTargetAsm =
false;
2636 assert(IsValid &&
"Failed to parse output constraint");
2637 OutputConstraintInfos.push_back(Info);
2640 for (
unsigned i = 0, e = S.getNumInputs(); i != e && IsValidTargetAsm; i++) {
2642 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2643 Name = GAS->getInputName(i);
2647 if (IsHipStdPar && !IsValid)
2648 IsValidTargetAsm =
false;
2650 assert(IsValid &&
"Failed to parse input constraint");
2651 InputConstraintInfos.push_back(Info);
2654 if (!IsValidTargetAsm)
2657 std::string Constraints;
2659 std::vector<LValue> ResultRegDests;
2660 std::vector<QualType> ResultRegQualTys;
2661 std::vector<llvm::Type *> ResultRegTypes;
2662 std::vector<llvm::Type *> ResultTruncRegTypes;
2663 std::vector<llvm::Type *> ArgTypes;
2664 std::vector<llvm::Type *> ArgElemTypes;
2665 std::vector<llvm::Value*> Args;
2666 llvm::BitVector ResultTypeRequiresCast;
2667 llvm::BitVector ResultRegIsFlagReg;
2670 std::string InOutConstraints;
2671 std::vector<llvm::Value*> InOutArgs;
2672 std::vector<llvm::Type*> InOutArgTypes;
2673 std::vector<llvm::Type*> InOutArgElemTypes;
2676 std::vector<std::string> OutputConstraints;
2679 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2687 bool ReadOnly =
true, ReadNone =
true;
2689 for (
unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
2693 std::string OutputConstraint(S.getOutputConstraint(i));
2697 const Expr *OutExpr = S.getOutputExpr(i);
2706 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2707 CGM.
Error(S.getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2709 OutputConstraints.push_back(OutputConstraint);
2711 if (!Constraints.empty())
2721 Constraints +=
"=" + OutputConstraint;
2722 ResultRegQualTys.push_back(QTy);
2723 ResultRegDests.push_back(Dest);
2725 bool IsFlagReg = llvm::StringRef(OutputConstraint).starts_with(
"{@cc");
2726 ResultRegIsFlagReg.push_back(IsFlagReg);
2731 Ty->isAggregateType());
2733 ResultTruncRegTypes.push_back(Ty);
2734 ResultTypeRequiresCast.push_back(RequiresCast);
2740 ResultRegTypes.push_back(Ty);
2746 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2751 assert(InputNo != S.getNumInputs() &&
"Didn't find matching input!");
2753 QualType InputTy = S.getInputExpr(InputNo)->getType();
2762 if (llvm::Type* AdjTy =
2764 ResultRegTypes.back()))
2765 ResultRegTypes.back() = AdjTy;
2768 diag::err_asm_invalid_type_in_input)
2769 << OutExpr->
getType() << OutputConstraint;
2773 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
2774 LargestVectorWidth =
2776 VT->getPrimitiveSizeInBits().getKnownMinValue());
2787 ArgTypes.push_back(DestAddr.
getType());
2790 Constraints +=
"=*";
2791 Constraints += OutputConstraint;
2792 ReadOnly = ReadNone =
false;
2796 InOutConstraints +=
',';
2798 const Expr *InputExpr = S.getOutputExpr(i);
2800 llvm::Type *ArgElemType;
2801 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
2802 Info, Dest, InputExpr->
getType(), InOutConstraints,
2805 if (llvm::Type* AdjTy =
2808 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2811 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2812 LargestVectorWidth =
2814 VT->getPrimitiveSizeInBits().getKnownMinValue());
2817 InOutConstraints += llvm::utostr(i);
2819 InOutConstraints += OutputConstraint;
2821 InOutArgTypes.push_back(Arg->getType());
2822 InOutArgElemTypes.push_back(ArgElemType);
2823 InOutArgs.push_back(Arg);
2829 if (isa<MSAsmStmt>(&S)) {
2835 *
this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
2836 ResultRegDests, AsmString, S.getNumOutputs());
2841 for (
unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
2842 const Expr *InputExpr = S.getInputExpr(i);
2849 if (!Constraints.empty())
2853 std::string InputConstraint(S.getInputConstraint(i));
2855 &OutputConstraintInfos);
2861 std::string ReplaceConstraint (InputConstraint);
2863 llvm::Type *ArgElemType;
2864 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
2873 QualType OutputType = S.getOutputExpr(Output)->getType();
2879 if (isa<llvm::PointerType>(Arg->getType()))
2882 if (isa<llvm::IntegerType>(OutputTy))
2883 Arg =
Builder.CreateZExt(Arg, OutputTy);
2884 else if (isa<llvm::PointerType>(OutputTy))
2886 else if (OutputTy->isFloatingPointTy())
2887 Arg =
Builder.CreateFPExt(Arg, OutputTy);
2890 ReplaceConstraint = OutputConstraints[Output];
2892 if (llvm::Type* AdjTy =
2895 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2898 << InputExpr->
getType() << InputConstraint;
2901 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2902 LargestVectorWidth =
2904 VT->getPrimitiveSizeInBits().getKnownMinValue());
2906 ArgTypes.push_back(Arg->getType());
2907 ArgElemTypes.push_back(ArgElemType);
2908 Args.push_back(Arg);
2909 Constraints += InputConstraint;
2913 for (
unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
2914 ArgTypes.push_back(InOutArgTypes[i]);
2915 ArgElemTypes.push_back(InOutArgElemTypes[i]);
2916 Args.push_back(InOutArgs[i]);
2918 Constraints += InOutConstraints;
2922 llvm::BasicBlock *Fallthrough =
nullptr;
2923 bool IsGCCAsmGoto =
false;
2924 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S)) {
2925 IsGCCAsmGoto = GS->isAsmGoto();
2927 for (
const auto *E : GS->labels()) {
2929 Transfer.push_back(Dest.
getBlock());
2930 if (!Constraints.empty())
2932 Constraints +=
"!i";
2938 bool HasUnwindClobber =
false;
2941 for (
unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
2942 StringRef Clobber = S.getClobber(i);
2944 if (Clobber ==
"memory")
2945 ReadOnly = ReadNone =
false;
2946 else if (Clobber ==
"unwind") {
2947 HasUnwindClobber =
true;
2949 }
else if (Clobber !=
"cc") {
2954 diag::warn_stack_clash_protection_inline_asm);
2958 if (isa<MSAsmStmt>(&S)) {
2959 if (Clobber ==
"eax" || Clobber ==
"edx") {
2960 if (Constraints.find(
"=&A") != std::string::npos)
2962 std::string::size_type position1 =
2963 Constraints.find(
"={" + Clobber.str() +
"}");
2964 if (position1 != std::string::npos) {
2965 Constraints.insert(position1 + 1,
"&");
2968 std::string::size_type position2 = Constraints.find(
"=A");
2969 if (position2 != std::string::npos) {
2970 Constraints.insert(position2 + 1,
"&");
2975 if (!Constraints.empty())
2978 Constraints +=
"~{";
2979 Constraints += Clobber;
2983 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
2984 "unwind clobber can't be used with asm goto");
2988 if (!MachineClobbers.empty()) {
2989 if (!Constraints.empty())
2991 Constraints += MachineClobbers;
2994 llvm::Type *ResultType;
2995 if (ResultRegTypes.empty())
2997 else if (ResultRegTypes.size() == 1)
2998 ResultType = ResultRegTypes[0];
3000 ResultType = llvm::StructType::get(
getLLVMContext(), ResultRegTypes);
3002 llvm::FunctionType *FTy =
3003 llvm::FunctionType::get(ResultType, ArgTypes,
false);
3005 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
3007 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3009 ? llvm::InlineAsm::AD_ATT
3010 : llvm::InlineAsm::AD_Intel;
3011 llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ?
3012 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3014 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3015 FTy, AsmString, Constraints, HasSideEffect,
3016 false, AsmDialect, HasUnwindClobber);
3017 std::vector<llvm::Value*> RegResults;
3018 llvm::CallBrInst *CBR;
3019 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3022 CBR =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3030 if (!RegResults.empty()) {
3032 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3033 llvm::Twine SynthName = Dest->getName() +
".split";
3035 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3036 Builder.SetInsertPoint(SynthBB);
3038 if (ResultRegTypes.size() == 1) {
3039 CBRRegResults[SynthBB].push_back(CBR);
3041 for (
unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3042 llvm::Value *Tmp =
Builder.CreateExtractValue(CBR, j,
"asmresult");
3043 CBRRegResults[SynthBB].push_back(Tmp);
3049 CBR->setIndirectDest(i++, SynthBB);
3052 }
else if (HasUnwindClobber) {
3058 llvm::CallInst *Result =
3065 EmitAsmStores(*
this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3066 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3067 ResultRegIsFlagReg);
3072 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3073 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3074 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3075 Builder.SetInsertPoint(Succ, --(Succ->end()));
3076 EmitAsmStores(*
this, S, CBRRegResults[Succ], ResultRegTypes,
3077 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3078 ResultTypeRequiresCast, ResultRegIsFlagReg);
3084 const RecordDecl *RD = S.getCapturedRecordDecl();
3093 E = S.capture_init_end();
3094 I != E; ++I, ++CurField) {
3096 if (CurField->hasCapturedVLAType()) {
3133 "CapturedStmtInfo should be set when generating the captured function");
3135 const RecordDecl *RD = S.getCapturedRecordDecl();
3137 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3150 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3154 F->addFnAttr(llvm::Attribute::NoUnwind);
3166 for (
auto *FD : RD->
fields()) {
3167 if (FD->hasCapturedVLAType()) {
3171 auto VAT = FD->getCapturedVLAType();
3172 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3193 llvm::IntrinsicInst *getConvergenceToken(llvm::BasicBlock *BB) {
3194 for (
auto &I : *BB) {
3195 auto *II = dyn_cast<llvm::IntrinsicInst>(&I);
3196 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID()))
3205 CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input,
3206 llvm::Value *ParentToken) {
3207 llvm::Value *bundleArgs[] = {ParentToken};
3208 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3209 auto Output = llvm::CallBase::addOperandBundle(
3210 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input);
3211 Input->replaceAllUsesWith(Output);
3212 Input->eraseFromParent();
3216 llvm::IntrinsicInst *
3217 CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB,
3218 llvm::Value *ParentToken) {
3219 CGBuilderTy::InsertPoint IP =
Builder.saveIP();
3223 Builder.SetInsertPoint(BB->getFirstInsertionPt());
3225 llvm::CallBase *CB =
Builder.CreateIntrinsic(
3226 llvm::Intrinsic::experimental_convergence_loop, {}, {});
3229 llvm::CallBase *I = addConvergenceControlToken(CB, ParentToken);
3230 return cast<llvm::IntrinsicInst>(I);
3233 llvm::IntrinsicInst *
3234 CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3235 llvm::BasicBlock *BB = &F->getEntryBlock();
3236 llvm::IntrinsicInst *
Token = getConvergenceToken(BB);
3244 CGBuilderTy::InsertPoint IP =
Builder.saveIP();
3245 Builder.SetInsertPoint(&BB->front());
3246 llvm::CallBase *I =
Builder.CreateIntrinsic(
3247 llvm::Intrinsic::experimental_convergence_entry, {}, {});
3248 assert(isa<llvm::IntrinsicInst>(I));
3251 return cast<llvm::IntrinsicInst>(I);
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 void EmitHipStdParUnsupportedAsm(CodeGenFunction *CGF, const AsmStmt &S)
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 void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, bool HasUnwindClobber, bool ReadOnly, bool ReadNone, bool NoMerge, const AsmStmt &S, const std::vector< llvm::Type * > &ResultRegTypes, const std::vector< llvm::Type * > &ArgElemTypes, CodeGenFunction &CGF, std::vector< llvm::Value * > &RegResults)
static CSFC_Result CollectStatementsForCase(const Stmt *S, const SwitchCase *Case, bool &FoundCase, SmallVectorImpl< const Stmt * > &ResultStmts)
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::optional< SmallVector< uint64_t, 16 > > getLikelihoodWeights(ArrayRef< Stmt::Likelihood > Likelihoods)
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 ...
llvm::MachO::Target Target
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Defines the SourceManager interface.
__DEVICE__ int max(int __a, int __b)
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 getTagDeclType(const TagDecl *Decl) const
Return the unique reference to the type for the specified TagDecl (struct/union/class/enum) decl.
QualType getRecordType(const RecordDecl *Decl) const
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.
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 ...
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.
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::StoreInst * CreateFlagStore(bool Value, llvm::Value *Addr)
Emit a store to an i1 flag variable.
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.
CallingConv getASTCallingConvention() const
getASTCallingConvention() - Return the AST-specified calling convention.
ABIArgInfo & getReturnInfo()
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
API for captured statement code generation.
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.
virtual llvm::Value * getContextValue() const
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 EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitCXXTryStmt(const CXXTryStmt &S)
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...
LValue EmitLValueForField(LValue Base, const FieldDecl *Field)
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 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)
LValue InitCapturedStruct(const CapturedStmt &S)
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 EmitDecl(const Decl &D)
EmitDecl - Emit a declaration.
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
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)
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...
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
llvm::LLVMContext & getLLVMContext()
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)
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
RValue EmitReferenceBindingToExpr(const Expr *E)
Emits a reference binding to the passed in expression.
void EmitForStmt(const ForStmt &S, ArrayRef< const Attr * > Attrs=std::nullopt)
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.
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 EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
Address EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
void EmitGotoStmt(const GotoStmt &S)
ASTContext & getContext() const
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 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 EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
Emit combined directive 'target parallel loop' as if its constituent constructs are 'target',...
uint64_t getCurrentProfileCount()
Get the profiler's current count.
void ResolveBranchFixups(llvm::BasicBlock *Target)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitWhileStmt(const WhileStmt &S, ArrayRef< const Attr * > Attrs=std::nullopt)
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
bool checkIfLoopMustProgress(const Expr *, bool HasEmptyBody)
Returns true if a loop must make progress, which means the mustprogress attribute can be added.
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
SmallVector< llvm::IntrinsicInst *, 4 > ConvergenceTokenStack
Stack to track the controlled convergence tokens.
void EmitObjCAtTryStmt(const ObjCAtTryStmt &S)
const TargetInfo & getTarget() const
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void EmitSEHLeaveStmt(const SEHLeaveStmt &S)
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
bool InNoInlineAttributedStmt
True if the current statement has noinline attribute.
SmallVector< llvm::OperandBundleDef, 1 > getBundlesForFunclet(llvm::Value *Callee)
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 EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
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 EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S)
Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
EmitCompoundStmt - Emit a compound statement {..} node.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
CGDebugInfo * getDebugInfo()
void EmitDoStmt(const DoStmt &S, ArrayRef< const Attr * > Attrs=std::nullopt)
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 EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &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.
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 EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void EmitOpenACCComputeConstruct(const OpenACCComputeConstruct &S)
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)
const TargetCodeGenInfo & getTargetHooks() const
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.
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
llvm::BasicBlock * GetIndirectGotoBlock()
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs=std::nullopt)
EmitStmt - Emit the code for the statement.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
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::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
const CallExpr * MustTailCall
const CGFunctionInfo * CurFnInfo
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 EmitOMPAtomicDirective(const OMPAtomicDirective &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)
bool SawAsmBlock
Whether we processed a Microsoft-style asm block during CodeGen.
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)
void EmitIndirectGotoStmt(const IndirectGotoStmt &S)
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 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.
void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef< const Attr * > Attrs=std::nullopt)
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
void EmitContinueStmt(const ContinueStmt &S)
const LangOptions & getLangOpts() const
This class organizes the cross-function state that is used while generating LLVM code.
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
void ErrorUnsupported(const Stmt *S, const char *Type)
Print out an error that codegen doesn't support the specified stmt yet.
llvm::Module & getModule() const
const LangOptions & getLangOpts() const
SanitizerMetadata * getSanitizerMetadata()
llvm::LLVMContext & getLLVMContext()
void Error(SourceLocation loc, StringRef error)
Emit a general error that something can't be done.
bool shouldEmitConvergenceTokens() const
DiagnosticsEngine & getDiags() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys=std::nullopt)
void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn)
Assign counters to regions and configure them for PGO of a given function.
void setCurrentStmt(const Stmt *S)
If the execution count for the current statement is known, record that as the current count.
bool haveRegionCounts() const
Whether or not we have PGO region data for the current function.
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.
Address getAddress() const
llvm::Value * getPointer(CodeGenFunction &CGF) 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)
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
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 * getStmt() const
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
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
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.
WhileStmt - This represents a 'while' stmt.
Defines the clang::TargetInfo interface.
bool Rem(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
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.
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...
llvm::BasicBlock * getBlock() const
void setScopeDepth(EHScopeStack::stable_iterator depth)
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
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