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"
40using namespace CodeGen;
50void CodeGenFunction::EmitStopPoint(
const Stmt *S) {
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 ('{}')");
498 LexicalScope
Scope(*
this, S.getSourceRange());
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);
631CodeGenFunction::JumpDest
633 JumpDest &Dest = LabelMap[D];
634 if (Dest.isValid())
return Dest;
650 JumpDest &Dest = LabelMap[D];
654 if (!Dest.isValid()) {
660 assert(!Dest.getScopeDepth().isValid() &&
"already emitted label!");
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();
791 RunCleanupsScope ExecutedScope(*
this);
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);
824 RunCleanupsScope ExecutedScope(*
this);
835 llvm::BasicBlock *ElseBlock = ContBlock;
866 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
876 RunCleanupsScope ThenScope(*
this);
882 if (
const Stmt *Else = S.getElse()) {
892 RunCleanupsScope ElseScope(*
this);
923 BreakContinueStack.push_back(BreakContinue(
LoopExit, LoopHeader));
932 RunCleanupsScope ConditionScope(*
this);
934 if (S.getConditionVariable())
935 EmitDecl(*S.getConditionVariable());
944 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
945 bool CondIsConstInt =
C !=
nullptr;
946 bool EmitBoolCondBranch = !CondIsConstInt || !
C->isOne();
959 if (EmitBoolCondBranch) {
960 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
961 if (ConditionScope.requiresCleanups())
963 llvm::MDNode *Weights =
964 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
966 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
968 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
970 if (ExitBlock !=
LoopExit.getBlock()) {
976 diag::warn_attribute_has_no_effect_on_infinite_loop)
977 << A << A->getRange();
980 diag::note_attribute_has_no_effect_on_infinite_loop_here)
987 RunCleanupsScope BodyScope(*
this);
997 BreakContinueStack.pop_back();
1000 ConditionScope.ForceCleanup();
1013 if (!EmitBoolCondBranch)
1030 BreakContinueStack.push_back(BreakContinue(
LoopExit, LoopCond));
1040 RunCleanupsScope BodyScope(*
this);
1057 BreakContinueStack.pop_back();
1061 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1062 bool CondIsConstInt =
C;
1063 bool EmitBoolCondBranch = !
C || !
C->isZero();
1072 if (EmitBoolCondBranch) {
1075 BoolCondVal, LoopBody,
LoopExit.getBlock(),
1076 createProfileWeightsForLoop(S.getCond(), BackedgeCount));
1086 if (!EmitBoolCondBranch)
1099 LexicalScope ForScope(*
this, S.getSourceRange());
1109 llvm::BasicBlock *CondBlock = CondDest.getBlock();
1113 bool CondIsConstInt =
1123 LexicalScope ConditionScope(*
this, S.getSourceRange());
1134 Continue = CondDest;
1135 else if (!S.getConditionVariable())
1137 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1142 if (S.getConditionVariable()) {
1143 EmitDecl(*S.getConditionVariable());
1148 BreakContinueStack.back().ContinueBlock = Continue;
1156 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1159 if (ForScope.requiresCleanups())
1168 llvm::MDNode *Weights =
1169 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1171 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1174 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1176 if (ExitBlock !=
LoopExit.getBlock()) {
1195 RunCleanupsScope BodyScope(*
this);
1207 BreakContinueStack.pop_back();
1209 ConditionScope.ForceCleanup();
1214 ForScope.ForceCleanup();
1232 LexicalScope ForScope(*
this, S.getSourceRange());
1254 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1255 if (ForScope.requiresCleanups())
1264 llvm::MDNode *Weights =
1265 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1267 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1269 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1271 if (ExitBlock !=
LoopExit.getBlock()) {
1286 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1290 LexicalScope BodyScope(*
this, S.getSourceRange());
1300 BreakContinueStack.pop_back();
1304 ForScope.ForceCleanup();
1317void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1333struct SaveRetExprRAII {
1335 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1338 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1339 const Expr *OldRetExpr;
1350 if (calleeQualType->isFunctionPointerType() ||
1351 calleeQualType->isFunctionReferenceType() ||
1352 calleeQualType->isBlockPointerType() ||
1353 calleeQualType->isMemberFunctionPointerType()) {
1355 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1357 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1358 if (
auto methodDecl = CMCE->getMethodDecl()) {
1369 auto CI = cast<llvm::CallInst>(&
Builder.GetInsertBlock()->back());
1370 CI->setTailCallKind(llvm::CallInst::TCK_MustTail);
1372 Builder.ClearInsertionPoint();
1380 if (requiresReturnValueCheck()) {
1383 new llvm::GlobalVariable(
CGM.
getModule(), SLoc->getType(),
false,
1384 llvm::GlobalVariable::PrivateLinkage, SLoc);
1385 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1387 assert(ReturnLocation.
isValid() &&
"No valid return location");
1394 Builder.ClearInsertionPoint();
1398 const Expr *RV = S.getRetValue();
1408 SaveRetExprRAII SaveRetExpr(RV, *
this);
1410 RunCleanupsScope cleanupScope(*
this);
1411 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1412 RV = EWC->getSubExpr();
1416 if (
getLangOpts().ElideConstructors && S.getNRVOCandidate() &&
1417 S.getNRVOCandidate()->isNRVOVariable() &&
1428 if (llvm::Value *NRVOFlag =
NRVOFlags[S.getNRVOCandidate()])
1435 if (
auto *CE = dyn_cast<CallExpr>(RV))
1467 ++NumSimpleReturnExprs;
1469 cleanupScope.ForceCleanup();
1479 for (
const auto *I : S.decls())
1484 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1496 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1512 assert(S.getRHS() &&
"Expected RHS value in CaseStmt");
1514 llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(
getContext());
1515 llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(
getContext());
1525 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1529 llvm::APInt
Range = RHS - LHS;
1531 if (
Range.ult(llvm::APInt(
Range.getBitWidth(), 64))) {
1534 unsigned NCases =
Range.getZExtValue() + 1;
1539 uint64_t Weight = Total / NCases,
Rem = Total % NCases;
1540 for (
unsigned I = 0; I != NCases; ++I) {
1542 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1543 else if (SwitchLikelihood)
1544 SwitchLikelihood->push_back(LH);
1548 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1556 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1561 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1565 Builder.SetInsertPoint(CaseRangeBlock);
1569 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1573 llvm::MDNode *Weights =
nullptr;
1574 if (SwitchWeights) {
1576 uint64_t DefaultCount = (*SwitchWeights)[0];
1577 Weights = createProfileWeights(ThisCount, DefaultCount);
1582 (*SwitchWeights)[0] += ThisCount;
1583 }
else if (SwitchLikelihood)
1584 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
1586 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
1590 Builder.SetInsertPoint(RestoreBB);
1592 Builder.ClearInsertionPoint();
1613 llvm::ConstantInt *CaseVal =
1618 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.getLHS()))
1619 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1621 CE = dyn_cast<ConstantExpr>(S.getLHS());
1623 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1626 Dbg->EmitGlobalVariable(DE->getDecl(),
1627 APValue(llvm::APSInt(CaseVal->getValue())));
1630 if (SwitchLikelihood)
1638 isa<BreakStmt>(S.getSubStmt())) {
1639 JumpDest
Block = BreakContinueStack.back().BreakBlock;
1645 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1649 if (
Builder.GetInsertBlock()) {
1651 Builder.ClearInsertionPoint();
1661 SwitchInsn->addCase(CaseVal, CaseDest);
1677 const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt());
1680 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1682 llvm::ConstantInt *CaseVal =
1693 if (SwitchLikelihood)
1696 SwitchInsn->addCase(CaseVal, CaseDest);
1697 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1720 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1721 assert(DefaultBlock->empty() &&
1722 "EmitDefaultStmt: Default block already defined?");
1724 if (SwitchLikelihood)
1766 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
1780 if (!Case && isa<BreakStmt>(S))
1785 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
1789 bool StartedInLiveCode = FoundCase;
1790 unsigned StartSize = ResultStmts.size();
1797 bool HadSkippedDecl =
false;
1801 for (; Case && I != E; ++I) {
1817 for (++I; I != E; ++I)
1827 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
1842 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
1847 bool AnyDecls =
false;
1848 for (; I != E; ++I) {
1861 for (++I; I != E; ++I)
1878 ResultStmts.resize(StartSize);
1879 ResultStmts.push_back(S);
1903 ResultStmts.push_back(S);
1912 const llvm::APSInt &ConstantCondValue,
1918 const SwitchCase *Case = S.getSwitchCaseList();
1924 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
1930 const CaseStmt *CS = cast<CaseStmt>(Case);
1932 if (CS->
getRHS())
return false;
1957 bool FoundCase =
false;
1964static std::optional<SmallVector<uint64_t, 16>>
1967 if (Likelihoods.size() <= 1)
1968 return std::nullopt;
1970 uint64_t NumUnlikely = 0;
1971 uint64_t NumNone = 0;
1972 uint64_t NumLikely = 0;
1973 for (
const auto LH : Likelihoods) {
1988 if (NumUnlikely == 0 && NumLikely == 0)
1989 return std::nullopt;
1997 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
1998 const uint64_t
None = Likely / (NumNone + 1);
1999 const uint64_t Unlikely = 0;
2002 Result.reserve(Likelihoods.size());
2003 for (
const auto LH : Likelihoods) {
2006 Result.push_back(Unlikely);
2012 Result.push_back(Likely);
2022 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2025 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2029 llvm::APSInt ConstantCondValue;
2037 RunCleanupsScope ExecutedScope(*
this);
2044 if (S.getConditionVariable())
2045 EmitDecl(*S.getConditionVariable());
2050 SwitchInsn =
nullptr;
2054 for (
unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
2060 SwitchInsn = SavedSwitchInsn;
2068 RunCleanupsScope ConditionScope(*
this);
2073 if (S.getConditionVariable())
2074 EmitDecl(*S.getConditionVariable());
2082 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2086 unsigned NumCases = 0;
2087 for (
const SwitchCase *Case = S.getSwitchCaseList();
2090 if (isa<DefaultStmt>(Case))
2095 SwitchWeights->reserve(NumCases);
2098 SwitchWeights->push_back(DefaultCount);
2105 CaseRangeBlock = DefaultBlock;
2108 Builder.ClearInsertionPoint();
2112 JumpDest OuterContinue;
2113 if (!BreakContinueStack.empty())
2114 OuterContinue = BreakContinueStack.back().ContinueBlock;
2116 BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue));
2121 BreakContinueStack.pop_back();
2125 SwitchInsn->setDefaultDest(CaseRangeBlock);
2128 if (!DefaultBlock->getParent()) {
2131 if (ConditionScope.requiresCleanups()) {
2136 DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock());
2137 delete DefaultBlock;
2141 ConditionScope.ForceCleanup();
2150 auto *
Call = dyn_cast<CallExpr>(S.getCond());
2152 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2153 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2155 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2156 MDHelper.createUnpredictable());
2160 if (SwitchWeights) {
2161 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2162 "switch weights do not match switch cases");
2164 if (SwitchWeights->size() > 1)
2165 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2166 createProfileWeights(*SwitchWeights));
2167 delete SwitchWeights;
2168 }
else if (SwitchLikelihood) {
2169 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2170 "switch likelihoods do not match switch cases");
2171 std::optional<SmallVector<uint64_t, 16>> LHW =
2175 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2176 createProfileWeights(*LHW));
2178 delete SwitchLikelihood;
2180 SwitchInsn = SavedSwitchInsn;
2181 SwitchWeights = SavedSwitchWeights;
2182 SwitchLikelihood = SavedSwitchLikelihood;
2183 CaseRangeBlock = SavedCRBlock;
2191 while (*Constraint) {
2192 switch (*Constraint) {
2204 while (Constraint[1] && Constraint[1] !=
',')
2210 while (Constraint[1] && Constraint[1] == *Constraint)
2221 "Must pass output names to constraints with a symbolic name");
2223 bool result =
Target.resolveSymbolicName(Constraint, *OutCons, Index);
2224 assert(result &&
"Could not resolve symbolic name"); (void)result;
2225 Result += llvm::utostr(Index);
2243 std::string *GCCReg =
nullptr) {
2244 const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
2253 AsmLabelAttr *
Attr = Variable->getAttr<AsmLabelAttr>();
2256 StringRef Register =
Attr->getLabel();
2257 assert(
Target.isValidGCCRegisterName(Register));
2261 if (
Target.validateOutputConstraint(Info) &&
2267 Register =
Target.getNormalizedGCCRegisterName(Register);
2268 if (GCCReg !=
nullptr)
2269 *GCCReg = Register.str();
2270 return (EarlyClobber ?
"&{" :
"{") + Register.str() +
"}";
2273std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2282 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2293 ConstraintStr +=
'*';
2297std::pair<llvm::Value *, llvm::Type *>
2299 const Expr *InputExpr,
2300 std::string &ConstraintStr) {
2308 llvm::APSInt IntResult;
2311 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2323 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2327 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2339 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2342 if (!StrVal.empty()) {
2345 unsigned StartToken = 0;
2346 unsigned ByteOffset = 0;
2350 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2351 if (StrVal[i] !=
'\n')
continue;
2353 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2354 Locs.push_back(llvm::ConstantAsMetadata::get(
2363 bool HasUnwindClobber,
bool ReadOnly,
2364 bool ReadNone,
bool NoMerge,
const AsmStmt &S,
2365 const std::vector<llvm::Type *> &ResultRegTypes,
2366 const std::vector<llvm::Type *> &ArgElemTypes,
2368 std::vector<llvm::Value *> &RegResults) {
2369 if (!HasUnwindClobber)
2370 Result.addFnAttr(llvm::Attribute::NoUnwind);
2373 Result.addFnAttr(llvm::Attribute::NoMerge);
2375 if (!HasSideEffect) {
2377 Result.setDoesNotAccessMemory();
2379 Result.setOnlyReadsMemory();
2383 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
2385 auto Attr = llvm::Attribute::get(
2386 CGF.
getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2393 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S))
2394 Result.setMetadata(
"srcloc",
2398 llvm::Constant *Loc =
2399 llvm::ConstantInt::get(CGF.
Int64Ty, S.getAsmLoc().getRawEncoding());
2400 Result.setMetadata(
"srcloc",
2402 llvm::ConstantAsMetadata::get(Loc)));
2410 Result.addFnAttr(llvm::Attribute::Convergent);
2412 if (ResultRegTypes.size() == 1) {
2413 RegResults.push_back(&
Result);
2415 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2416 llvm::Value *Tmp = CGF.
Builder.CreateExtractValue(&
Result, i,
"asmresult");
2417 RegResults.push_back(Tmp);
2429 const llvm::BitVector &ResultTypeRequiresCast,
2430 const llvm::BitVector &ResultRegIsFlagReg) {
2435 assert(RegResults.size() == ResultRegTypes.size());
2436 assert(RegResults.size() == ResultTruncRegTypes.size());
2437 assert(RegResults.size() == ResultRegDests.size());
2440 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2441 assert(ResultRegIsFlagReg.size() <= ResultRegDests.size());
2443 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2444 llvm::Value *Tmp = RegResults[i];
2445 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2447 if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
2450 llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2);
2451 llvm::Value *IsBooleanValue =
2452 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two);
2454 Builder.CreateCall(FnAssume, IsBooleanValue);
2459 if (ResultRegTypes[i] != TruncTy) {
2463 if (TruncTy->isFloatingPointTy())
2464 Tmp =
Builder.CreateFPTrunc(Tmp, TruncTy);
2465 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2468 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
2469 Tmp =
Builder.CreateIntToPtr(Tmp, TruncTy);
2470 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2474 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
2475 Tmp =
Builder.CreateTrunc(Tmp, TruncTy);
2476 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2477 Tmp =
Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2478 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2479 Tmp =
Builder.CreateBitCast(Tmp, TruncTy);
2483 LValue Dest = ResultRegDests[i];
2486 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2497 const Expr *OutExpr = S.getOutputExpr(i);
2499 diag::err_store_value_to_reg);
2510 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2513 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2514 Asm = GCCAsm->getAsmString()->getString();
2518 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2519 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2520 {StrTy->getType()},
false);
2521 auto UBF = CGF->
CGM.
getModule().getOrInsertFunction(Name, FnTy);
2523 CGF->
Builder.CreateCall(UBF, {StrTy});
2528 CodeGenFunction::RunCleanupsScope Cleanups(*
this);
2531 std::string AsmString = S.generateAsmString(
getContext());
2538 bool IsValidTargetAsm =
true;
2539 for (
unsigned i = 0, e = S.getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2541 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2542 Name = GAS->getOutputName(i);
2545 if (IsHipStdPar && !IsValid)
2546 IsValidTargetAsm =
false;
2548 assert(IsValid &&
"Failed to parse output constraint");
2549 OutputConstraintInfos.push_back(Info);
2552 for (
unsigned i = 0, e = S.getNumInputs(); i != e && IsValidTargetAsm; i++) {
2554 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2555 Name = GAS->getInputName(i);
2559 if (IsHipStdPar && !IsValid)
2560 IsValidTargetAsm =
false;
2562 assert(IsValid &&
"Failed to parse input constraint");
2563 InputConstraintInfos.push_back(Info);
2566 if (!IsValidTargetAsm)
2569 std::string Constraints;
2571 std::vector<LValue> ResultRegDests;
2572 std::vector<QualType> ResultRegQualTys;
2573 std::vector<llvm::Type *> ResultRegTypes;
2574 std::vector<llvm::Type *> ResultTruncRegTypes;
2575 std::vector<llvm::Type *> ArgTypes;
2576 std::vector<llvm::Type *> ArgElemTypes;
2577 std::vector<llvm::Value*> Args;
2578 llvm::BitVector ResultTypeRequiresCast;
2579 llvm::BitVector ResultRegIsFlagReg;
2582 std::string InOutConstraints;
2583 std::vector<llvm::Value*> InOutArgs;
2584 std::vector<llvm::Type*> InOutArgTypes;
2585 std::vector<llvm::Type*> InOutArgElemTypes;
2588 std::vector<std::string> OutputConstraints;
2591 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2599 bool ReadOnly =
true, ReadNone =
true;
2601 for (
unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
2605 std::string OutputConstraint(S.getOutputConstraint(i));
2609 const Expr *OutExpr = S.getOutputExpr(i);
2618 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2619 CGM.
Error(S.getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2621 OutputConstraints.push_back(OutputConstraint);
2623 if (!Constraints.empty())
2633 Constraints +=
"=" + OutputConstraint;
2634 ResultRegQualTys.push_back(QTy);
2635 ResultRegDests.push_back(Dest);
2637 bool IsFlagReg = llvm::StringRef(OutputConstraint).starts_with(
"{@cc");
2638 ResultRegIsFlagReg.push_back(IsFlagReg);
2643 Ty->isAggregateType());
2645 ResultTruncRegTypes.push_back(Ty);
2646 ResultTypeRequiresCast.push_back(RequiresCast);
2652 ResultRegTypes.push_back(Ty);
2658 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2663 assert(InputNo != S.getNumInputs() &&
"Didn't find matching input!");
2665 QualType InputTy = S.getInputExpr(InputNo)->getType();
2674 if (llvm::Type* AdjTy =
2676 ResultRegTypes.back()))
2677 ResultRegTypes.back() = AdjTy;
2680 diag::err_asm_invalid_type_in_input)
2681 << OutExpr->
getType() << OutputConstraint;
2685 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
2686 LargestVectorWidth =
2687 std::max((uint64_t)LargestVectorWidth,
2688 VT->getPrimitiveSizeInBits().getKnownMinValue());
2699 ArgTypes.push_back(DestAddr.
getType());
2702 Constraints +=
"=*";
2703 Constraints += OutputConstraint;
2704 ReadOnly = ReadNone =
false;
2708 InOutConstraints +=
',';
2710 const Expr *InputExpr = S.getOutputExpr(i);
2712 llvm::Type *ArgElemType;
2713 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
2714 Info, Dest, InputExpr->
getType(), InOutConstraints,
2717 if (llvm::Type* AdjTy =
2720 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2723 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2724 LargestVectorWidth =
2725 std::max((uint64_t)LargestVectorWidth,
2726 VT->getPrimitiveSizeInBits().getKnownMinValue());
2729 InOutConstraints += llvm::utostr(i);
2731 InOutConstraints += OutputConstraint;
2733 InOutArgTypes.push_back(Arg->getType());
2734 InOutArgElemTypes.push_back(ArgElemType);
2735 InOutArgs.push_back(Arg);
2741 if (isa<MSAsmStmt>(&S)) {
2747 *
this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
2748 ResultRegDests, AsmString, S.getNumOutputs());
2753 for (
unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
2754 const Expr *InputExpr = S.getInputExpr(i);
2761 if (!Constraints.empty())
2765 std::string InputConstraint(S.getInputConstraint(i));
2767 &OutputConstraintInfos);
2773 std::string ReplaceConstraint (InputConstraint);
2775 llvm::Type *ArgElemType;
2776 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
2785 QualType OutputType = S.getOutputExpr(Output)->getType();
2791 if (isa<llvm::PointerType>(Arg->getType()))
2794 if (isa<llvm::IntegerType>(OutputTy))
2795 Arg =
Builder.CreateZExt(Arg, OutputTy);
2796 else if (isa<llvm::PointerType>(OutputTy))
2798 else if (OutputTy->isFloatingPointTy())
2799 Arg =
Builder.CreateFPExt(Arg, OutputTy);
2802 ReplaceConstraint = OutputConstraints[Output];
2804 if (llvm::Type* AdjTy =
2807 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2810 << InputExpr->
getType() << InputConstraint;
2813 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2814 LargestVectorWidth =
2815 std::max((uint64_t)LargestVectorWidth,
2816 VT->getPrimitiveSizeInBits().getKnownMinValue());
2818 ArgTypes.push_back(Arg->getType());
2819 ArgElemTypes.push_back(ArgElemType);
2820 Args.push_back(Arg);
2821 Constraints += InputConstraint;
2825 for (
unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
2826 ArgTypes.push_back(InOutArgTypes[i]);
2827 ArgElemTypes.push_back(InOutArgElemTypes[i]);
2828 Args.push_back(InOutArgs[i]);
2830 Constraints += InOutConstraints;
2834 llvm::BasicBlock *Fallthrough =
nullptr;
2835 bool IsGCCAsmGoto =
false;
2836 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S)) {
2837 IsGCCAsmGoto = GS->isAsmGoto();
2839 for (
const auto *E : GS->labels()) {
2841 Transfer.push_back(Dest.getBlock());
2842 if (!Constraints.empty())
2844 Constraints +=
"!i";
2850 bool HasUnwindClobber =
false;
2853 for (
unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
2854 StringRef Clobber = S.getClobber(i);
2856 if (Clobber ==
"memory")
2857 ReadOnly = ReadNone =
false;
2858 else if (Clobber ==
"unwind") {
2859 HasUnwindClobber =
true;
2861 }
else if (Clobber !=
"cc") {
2866 diag::warn_stack_clash_protection_inline_asm);
2870 if (isa<MSAsmStmt>(&S)) {
2871 if (Clobber ==
"eax" || Clobber ==
"edx") {
2872 if (Constraints.find(
"=&A") != std::string::npos)
2874 std::string::size_type position1 =
2875 Constraints.find(
"={" + Clobber.str() +
"}");
2876 if (position1 != std::string::npos) {
2877 Constraints.insert(position1 + 1,
"&");
2880 std::string::size_type position2 = Constraints.find(
"=A");
2881 if (position2 != std::string::npos) {
2882 Constraints.insert(position2 + 1,
"&");
2887 if (!Constraints.empty())
2890 Constraints +=
"~{";
2891 Constraints += Clobber;
2895 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
2896 "unwind clobber can't be used with asm goto");
2900 if (!MachineClobbers.empty()) {
2901 if (!Constraints.empty())
2903 Constraints += MachineClobbers;
2906 llvm::Type *ResultType;
2907 if (ResultRegTypes.empty())
2909 else if (ResultRegTypes.size() == 1)
2910 ResultType = ResultRegTypes[0];
2912 ResultType = llvm::StructType::get(
getLLVMContext(), ResultRegTypes);
2914 llvm::FunctionType *FTy =
2915 llvm::FunctionType::get(ResultType, ArgTypes,
false);
2917 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
2919 llvm::InlineAsm::AsmDialect GnuAsmDialect =
2921 ? llvm::InlineAsm::AD_ATT
2922 : llvm::InlineAsm::AD_Intel;
2923 llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ?
2924 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
2926 llvm::InlineAsm *IA = llvm::InlineAsm::get(
2927 FTy, AsmString, Constraints, HasSideEffect,
2928 false, AsmDialect, HasUnwindClobber);
2929 std::vector<llvm::Value*> RegResults;
2930 llvm::CallBrInst *CBR;
2931 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
2934 CBR =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
2942 if (!RegResults.empty()) {
2944 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
2945 llvm::Twine SynthName = Dest->getName() +
".split";
2947 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
2948 Builder.SetInsertPoint(SynthBB);
2950 if (ResultRegTypes.size() == 1) {
2951 CBRRegResults[SynthBB].push_back(CBR);
2953 for (
unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
2954 llvm::Value *Tmp =
Builder.CreateExtractValue(CBR, j,
"asmresult");
2955 CBRRegResults[SynthBB].push_back(Tmp);
2961 CBR->setIndirectDest(i++, SynthBB);
2964 }
else if (HasUnwindClobber) {
2977 EmitAsmStores(*
this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
2978 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
2979 ResultRegIsFlagReg);
2984 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
2985 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
2986 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
2987 Builder.SetInsertPoint(Succ, --(Succ->end()));
2988 EmitAsmStores(*
this, S, CBRRegResults[Succ], ResultRegTypes,
2989 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
2990 ResultTypeRequiresCast, ResultRegIsFlagReg);
2996 const RecordDecl *RD = S.getCapturedRecordDecl();
3005 E = S.capture_init_end();
3006 I != E; ++I, ++CurField) {
3008 if (CurField->hasCapturedVLAType()) {
3026 CGCapturedStmtRAII CapInfoRAII(CGF,
new CGCapturedStmtInfo(S, K));
3027 llvm::Function *F = CGF.GenerateCapturedStmtFunction(S);
3028 delete CGF.CapturedStmtInfo;
3045 "CapturedStmtInfo should be set when generating the captured function");
3047 const RecordDecl *RD = S.getCapturedRecordDecl();
3049 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3062 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3066 F->addFnAttr(llvm::Attribute::NoUnwind);
3078 for (
auto *FD : RD->
fields()) {
3079 if (FD->hasCapturedVLAType()) {
3083 auto VAT = FD->getCapturedVLAType();
3084 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
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::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 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 void makeTailCallIfSwiftAsync(const CallExpr *CE, CGBuilderTy &Builder, const CGFunctionInfo *CurFnInfo)
If we have 'return f(...);', where both caller and callee are SwiftAsync, codegen it as 'tail call ....
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)
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.
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 ...
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::Value * getPointer() const
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 * 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.
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.
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)
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitForStmt(const ForStmt &S, ArrayRef< const Attr * > Attrs=std::nullopt)
void EmitGotoStmt(const GotoStmt &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
static bool ContainsLabel(const Stmt *S, bool IgnoreCaseStmts=false)
ContainsLabel - Return true if the statement contains a label in it.
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.
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...
void EmitSehCppScopeBegin()
void EmitIfStmt(const IfStmt &S)
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
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 EmitOMPAtomicDirective(const OMPAtomicDirective &S)
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
Address EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
static bool hasScalarEvaluationKind(QualType T)
CGCapturedStmtInfo * CapturedStmtInfo
void EmitIndirectGotoStmt(const IndirectGotoStmt &S)
void EmitDecl(const Decl &D)
EmitDecl - Emit a declaration.
void EmitCXXTryStmt(const CXXTryStmt &S)
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 EmitLabel(const LabelDecl *D)
EmitLabel - Emit the block for the given label.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitCaseStmt(const CaseStmt &S, ArrayRef< const Attr * > Attrs)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitDefaultStmt(const DefaultStmt &S, ArrayRef< const Attr * > Attrs)
const LangOptions & getLangOpts() const
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
SmallVector< llvm::OperandBundleDef, 1 > getBundlesForFunclet(llvm::Value *Callee)
void SimplifyForwardingBlocks(llvm::BasicBlock *BB)
SimplifyForwardingBlocks - If the given basic block is only a branch to another basic block,...
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
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...
void EmitBlockAfterUses(llvm::BasicBlock *BB)
EmitBlockAfterUses - Emit the given block somewhere hopefully near its uses, and leave the insertion ...
void EmitContinueStmt(const ContinueStmt &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
bool InNoMergeAttributedStmt
True if the current statement has nomerge attribute.
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
LValue MakeAddrLValueWithoutTBAA(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
JumpDest ReturnBlock
ReturnBlock - Unified return block.
bool checkIfLoopMustProgress(bool HasConstantCond)
Returns true if a loop must make progress, which means the mustprogress attribute can be added.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field)
void EmitOMPFlushDirective(const OMPFlushDirective &S)
void EmitSEHLeaveStmt(const SEHLeaveStmt &S)
void EmitAttributedStmt(const AttributedStmt &S)
void EmitOMPCancelDirective(const OMPCancelDirective &S)
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitCaseStmtRange(const CaseStmt &S, ArrayRef< const Attr * > Attrs)
const TargetInfo & getTarget() const
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitLabelStmt(const LabelStmt &S)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
const Expr * RetExpr
If a return statement is being visited, this holds the return statment's result expression.
void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init)
void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit)
EmitComplexExprIntoLValue - Emit the given expression of complex type and place its result into the s...
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S)
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
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 EmitOMPParallelForDirective(const OMPParallelForDirective &S)
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
uint64_t getCurrentProfileCount()
Get the profiler's current count.
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 EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)
Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...
void EmitSwitchStmt(const SwitchStmt &S)
CGDebugInfo * getDebugInfo()
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
void EmitSEHTryStmt(const SEHTryStmt &S)
void EmitOMPInteropDirective(const OMPInteropDirective &S)
const TargetCodeGenInfo & getTargetHooks() const
RValue EmitReferenceBindingToExpr(const Expr *E)
Emits a reference binding to the passed in expression.
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
void EmitDeclStmt(const DeclStmt &S)
bool InNoInlineAttributedStmt
True if the current statement has noinline attribute.
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitCoroutineBody(const CoroutineBodyStmt &S)
Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
void EmitDoStmt(const DoStmt &S, ArrayRef< const Attr * > Attrs=std::nullopt)
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
ASTContext & getContext() const
Address CreateMemTemp(QualType T, const Twine &Name="tmp", Address *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef< const Attr * > Attrs=std::nullopt)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
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)
JumpDest getJumpDestForLabel(const LabelDecl *S)
getBasicBlockForLabel - Return the LLVM basicblock that the specified label maps to.
void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S)
llvm::Function * EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K)
llvm::Type * ConvertType(QualType T)
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
llvm::CallBase * EmitCallOrInvoke(llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const Twine &Name="")
bool InAlwaysInlineAttributedStmt
True if the current statement has always_inline attribute.
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitOpenACCComputeConstruct(const OpenACCComputeConstruct &S)
void EmitOMPSimdDirective(const OMPSimdDirective &S)
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S)
void EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
LValue InitCapturedStruct(const CapturedStmt &S)
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitReturnStmt(const ReturnStmt &S)
unsigned NextCleanupDestIndex
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
static bool mightAddDeclToScope(const Stmt *S)
Determine if the given statement might introduce a declaration into the current scope,...
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
static bool hasAggregateEvaluationKind(QualType T)
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
void EmitBreakStmt(const BreakStmt &S)
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV)
const CallExpr * MustTailCall
const CGFunctionInfo * CurFnInfo
bool isObviouslyBranchWithoutCleanups(JumpDest Dest) const
isObviouslyBranchWithoutCleanups - Return true if a branch to the specified destination obviously has...
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
void EmitCoreturnStmt(const CoreturnStmt &S)
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs=std::nullopt)
EmitStmt - Emit the code for the statement.
void EmitWhileStmt(const WhileStmt &S, ArrayRef< const Attr * > Attrs=std::nullopt)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)
llvm::LLVMContext & getLLVMContext()
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
bool SawAsmBlock
Whether we processed a Microsoft-style asm block during CodeGen.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
void ResolveBranchFixups(llvm::BasicBlock *Target)
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
llvm::BasicBlock * GetIndirectGotoBlock()
void EmitAsmStmt(const AsmStmt &S)
void EmitObjCAtTryStmt(const ObjCAtTryStmt &S)
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
static bool containsBreak(const Stmt *S)
containsBreak - Return true if the statement contains a break out of it.
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.
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=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(CodeGenFunction &CGF) 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)
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 * 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.
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.
@ Result
The result type of a method or function.
YAML serialization mapping.
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)
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