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!");
93 if (
const auto *
D = dyn_cast<OMPExecutableDirective>(S)) {
99 switch (S->getStmtClass()) {
101 case Stmt::CXXCatchStmtClass:
102 case Stmt::SEHExceptStmtClass:
103 case Stmt::SEHFinallyStmtClass:
104 case Stmt::MSDependentExistsStmtClass:
105 llvm_unreachable(
"invalid statement class to emit generically");
106 case Stmt::NullStmtClass:
107 case Stmt::CompoundStmtClass:
108 case Stmt::DeclStmtClass:
109 case Stmt::LabelStmtClass:
110 case Stmt::AttributedStmtClass:
111 case Stmt::GotoStmtClass:
112 case Stmt::BreakStmtClass:
113 case Stmt::ContinueStmtClass:
114 case Stmt::DefaultStmtClass:
115 case Stmt::CaseStmtClass:
116 case Stmt::SEHLeaveStmtClass:
117 llvm_unreachable(
"should have emitted these statements as simple");
119#define STMT(Type, Base)
120#define ABSTRACT_STMT(Op)
121#define EXPR(Type, Base) \
122 case Stmt::Type##Class:
123#include "clang/AST/StmtNodes.inc"
126 llvm::BasicBlock *incoming =
Builder.GetInsertBlock();
127 assert(incoming &&
"expression emission must have an insertion point");
131 llvm::BasicBlock *outgoing =
Builder.GetInsertBlock();
132 assert(outgoing &&
"expression emission cleared block!");
146 if (incoming != outgoing && outgoing->use_empty()) {
147 outgoing->eraseFromParent();
153 case Stmt::IndirectGotoStmtClass:
156 case Stmt::IfStmtClass:
EmitIfStmt(cast<IfStmt>(*S));
break;
157 case Stmt::WhileStmtClass:
EmitWhileStmt(cast<WhileStmt>(*S), Attrs);
break;
158 case Stmt::DoStmtClass:
EmitDoStmt(cast<DoStmt>(*S), Attrs);
break;
159 case Stmt::ForStmtClass:
EmitForStmt(cast<ForStmt>(*S), Attrs);
break;
161 case Stmt::ReturnStmtClass:
EmitReturnStmt(cast<ReturnStmt>(*S));
break;
163 case Stmt::SwitchStmtClass:
EmitSwitchStmt(cast<SwitchStmt>(*S));
break;
164 case Stmt::GCCAsmStmtClass:
165 case Stmt::MSAsmStmtClass:
EmitAsmStmt(cast<AsmStmt>(*S));
break;
166 case Stmt::CoroutineBodyStmtClass:
169 case Stmt::CoreturnStmtClass:
172 case Stmt::CapturedStmtClass: {
177 case Stmt::ObjCAtTryStmtClass:
180 case Stmt::ObjCAtCatchStmtClass:
182 "@catch statements should be handled by EmitObjCAtTryStmt");
183 case Stmt::ObjCAtFinallyStmtClass:
185 "@finally statements should be handled by EmitObjCAtTryStmt");
186 case Stmt::ObjCAtThrowStmtClass:
189 case Stmt::ObjCAtSynchronizedStmtClass:
192 case Stmt::ObjCForCollectionStmtClass:
195 case Stmt::ObjCAutoreleasePoolStmtClass:
199 case Stmt::CXXTryStmtClass:
202 case Stmt::CXXForRangeStmtClass:
205 case Stmt::SEHTryStmtClass:
208 case Stmt::OMPMetaDirectiveClass:
211 case Stmt::OMPCanonicalLoopClass:
214 case Stmt::OMPParallelDirectiveClass:
217 case Stmt::OMPSimdDirectiveClass:
220 case Stmt::OMPTileDirectiveClass:
223 case Stmt::OMPUnrollDirectiveClass:
226 case Stmt::OMPReverseDirectiveClass:
229 case Stmt::OMPInterchangeDirectiveClass:
232 case Stmt::OMPForDirectiveClass:
235 case Stmt::OMPForSimdDirectiveClass:
238 case Stmt::OMPSectionsDirectiveClass:
241 case Stmt::OMPSectionDirectiveClass:
244 case Stmt::OMPSingleDirectiveClass:
247 case Stmt::OMPMasterDirectiveClass:
250 case Stmt::OMPCriticalDirectiveClass:
253 case Stmt::OMPParallelForDirectiveClass:
256 case Stmt::OMPParallelForSimdDirectiveClass:
259 case Stmt::OMPParallelMasterDirectiveClass:
262 case Stmt::OMPParallelSectionsDirectiveClass:
265 case Stmt::OMPTaskDirectiveClass:
268 case Stmt::OMPTaskyieldDirectiveClass:
271 case Stmt::OMPErrorDirectiveClass:
274 case Stmt::OMPBarrierDirectiveClass:
277 case Stmt::OMPTaskwaitDirectiveClass:
280 case Stmt::OMPTaskgroupDirectiveClass:
283 case Stmt::OMPFlushDirectiveClass:
286 case Stmt::OMPDepobjDirectiveClass:
289 case Stmt::OMPScanDirectiveClass:
292 case Stmt::OMPOrderedDirectiveClass:
295 case Stmt::OMPAtomicDirectiveClass:
298 case Stmt::OMPTargetDirectiveClass:
301 case Stmt::OMPTeamsDirectiveClass:
304 case Stmt::OMPCancellationPointDirectiveClass:
307 case Stmt::OMPCancelDirectiveClass:
310 case Stmt::OMPTargetDataDirectiveClass:
313 case Stmt::OMPTargetEnterDataDirectiveClass:
316 case Stmt::OMPTargetExitDataDirectiveClass:
319 case Stmt::OMPTargetParallelDirectiveClass:
322 case Stmt::OMPTargetParallelForDirectiveClass:
325 case Stmt::OMPTaskLoopDirectiveClass:
328 case Stmt::OMPTaskLoopSimdDirectiveClass:
331 case Stmt::OMPMasterTaskLoopDirectiveClass:
334 case Stmt::OMPMaskedTaskLoopDirectiveClass:
337 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
339 cast<OMPMasterTaskLoopSimdDirective>(*S));
341 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
343 cast<OMPMaskedTaskLoopSimdDirective>(*S));
345 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
347 cast<OMPParallelMasterTaskLoopDirective>(*S));
349 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
351 cast<OMPParallelMaskedTaskLoopDirective>(*S));
353 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
355 cast<OMPParallelMasterTaskLoopSimdDirective>(*S));
357 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
359 cast<OMPParallelMaskedTaskLoopSimdDirective>(*S));
361 case Stmt::OMPDistributeDirectiveClass:
364 case Stmt::OMPTargetUpdateDirectiveClass:
367 case Stmt::OMPDistributeParallelForDirectiveClass:
369 cast<OMPDistributeParallelForDirective>(*S));
371 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
373 cast<OMPDistributeParallelForSimdDirective>(*S));
375 case Stmt::OMPDistributeSimdDirectiveClass:
378 case Stmt::OMPTargetParallelForSimdDirectiveClass:
380 cast<OMPTargetParallelForSimdDirective>(*S));
382 case Stmt::OMPTargetSimdDirectiveClass:
385 case Stmt::OMPTeamsDistributeDirectiveClass:
388 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
390 cast<OMPTeamsDistributeSimdDirective>(*S));
392 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
394 cast<OMPTeamsDistributeParallelForSimdDirective>(*S));
396 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
398 cast<OMPTeamsDistributeParallelForDirective>(*S));
400 case Stmt::OMPTargetTeamsDirectiveClass:
403 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
405 cast<OMPTargetTeamsDistributeDirective>(*S));
407 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
409 cast<OMPTargetTeamsDistributeParallelForDirective>(*S));
411 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
413 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(*S));
415 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
417 cast<OMPTargetTeamsDistributeSimdDirective>(*S));
419 case Stmt::OMPInteropDirectiveClass:
422 case Stmt::OMPDispatchDirectiveClass:
425 case Stmt::OMPScopeDirectiveClass:
428 case Stmt::OMPMaskedDirectiveClass:
431 case Stmt::OMPGenericLoopDirectiveClass:
434 case Stmt::OMPTeamsGenericLoopDirectiveClass:
437 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
439 cast<OMPTargetTeamsGenericLoopDirective>(*S));
441 case Stmt::OMPParallelGenericLoopDirectiveClass:
443 cast<OMPParallelGenericLoopDirective>(*S));
445 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
447 cast<OMPTargetParallelGenericLoopDirective>(*S));
449 case Stmt::OMPParallelMaskedDirectiveClass:
452 case Stmt::OMPAssumeDirectiveClass:
455 case Stmt::OpenACCComputeConstructClass:
458 case Stmt::OpenACCLoopConstructClass:
461 case Stmt::OpenACCCombinedConstructClass:
464 case Stmt::OpenACCDataConstructClass:
467 case Stmt::OpenACCEnterDataConstructClass:
470 case Stmt::OpenACCExitDataConstructClass:
473 case Stmt::OpenACCHostDataConstructClass:
476 case Stmt::OpenACCWaitConstructClass:
479 case Stmt::OpenACCInitConstructClass:
482 case Stmt::OpenACCShutdownConstructClass:
485 case Stmt::OpenACCSetConstructClass:
488 case Stmt::OpenACCUpdateConstructClass:
496 switch (S->getStmtClass()) {
499 case Stmt::NullStmtClass:
501 case Stmt::CompoundStmtClass:
504 case Stmt::DeclStmtClass:
507 case Stmt::LabelStmtClass:
510 case Stmt::AttributedStmtClass:
513 case Stmt::GotoStmtClass:
516 case Stmt::BreakStmtClass:
519 case Stmt::ContinueStmtClass:
522 case Stmt::DefaultStmtClass:
525 case Stmt::CaseStmtClass:
528 case Stmt::SEHLeaveStmtClass:
541 "LLVM IR generation of compound statement ('{}')");
544 LexicalScope
Scope(*
this, S.getSourceRange());
555 assert((!GetLast || (GetLast &&
ExprResult)) &&
556 "If GetLast is true then the CompoundStmt must have a StmtExprResult");
560 for (
auto *CurStmt : S.body()) {
568 if (
const auto *LS = dyn_cast<LabelStmt>(
ExprResult)) {
571 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(
ExprResult)) {
576 llvm_unreachable(
"unknown value statement");
603 llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
612 if (!BI || !BI->isUnconditional())
616 if (BI->getIterator() != BB->begin())
619 BB->replaceAllUsesWith(BI->getSuccessor(0));
620 BI->eraseFromParent();
621 BB->eraseFromParent();
625 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
630 if (IsFinished && BB->use_empty()) {
637 if (CurBB && CurBB->getParent())
638 CurFn->insert(std::next(CurBB->getIterator()), BB);
648 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
650 if (!CurBB || CurBB->getTerminator()) {
662 bool inserted =
false;
663 for (llvm::User *u : block->users()) {
664 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
665 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
677CodeGenFunction::JumpDest
679 JumpDest &Dest = LabelMap[
D];
680 if (Dest.isValid())
return Dest;
696 JumpDest &Dest = LabelMap[
D];
700 if (!Dest.isValid()) {
706 assert(!Dest.getScopeDepth().isValid() &&
"already emitted label!");
727 assert(!Labels.empty());
733 i = Labels.begin(), e = Labels.end(); i != e; ++i) {
734 assert(
CGF.LabelMap.count(*i));
743 ParentScope->Labels.append(Labels.begin(), Labels.end());
759 bool nomerge =
false;
760 bool noinline =
false;
761 bool alwaysinline =
false;
762 bool noconvergent =
false;
763 HLSLControlFlowHintAttr::Spelling flattenOrBranch =
764 HLSLControlFlowHintAttr::SpellingNotCalculated;
767 for (
const auto *A : S.getAttrs()) {
768 switch (A->getKind()) {
777 case attr::AlwaysInline:
780 case attr::NoConvergent:
783 case attr::MustTail: {
784 const Stmt *Sub = S.getSubStmt();
788 case attr::CXXAssume: {
789 const Expr *Assumption = cast<CXXAssumeAttr>(A)->getAssumption();
793 Builder.CreateAssumption(AssumptionVal);
796 case attr::HLSLControlFlowHint: {
797 flattenOrBranch = cast<HLSLControlFlowHintAttr>(A)->getSemanticSpelling();
807 EmitStmt(S.getSubStmt(), S.getAttrs());
830 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
837 cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(
V, CurBB);
843 const Stmt *Else = S.getElse();
847 if (S.isConsteval()) {
848 const Stmt *Executed = S.isNegatedConsteval() ? S.getThen() : Else;
850 RunCleanupsScope ExecutedScope(*
this);
858 LexicalScope ConditionScope(*
this, S.getCond()->getSourceRange());
864 if (S.getConditionVariable())
865 EmitDecl(*S.getConditionVariable());
873 const Stmt *Executed = S.getThen();
874 const Stmt *Skipped = Else;
876 std::swap(Executed, Skipped);
884 RunCleanupsScope ExecutedScope(*
this);
896 llvm::BasicBlock *ElseBlock = ContBlock;
927 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
937 RunCleanupsScope ThenScope(*
this);
953 RunCleanupsScope ElseScope(*
this);
984 bool CondIsConstInt =
985 !ControllingExpression ||
989 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
990 Result.Val.getInt().getBoolValue());
1004 if (HasEmptyBody && CondIsTrue) {
1005 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1023 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1027 const Stmt *Body = S.getBody();
1028 if (!Body || isa<NullStmt>(Body))
1030 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
1031 return Compound->body_empty();
1044 emitConvergenceLoopToken(LoopHeader.getBlock()));
1051 BreakContinueStack.push_back(BreakContinue(
LoopExit, LoopHeader));
1060 RunCleanupsScope ConditionScope(*
this);
1062 if (S.getConditionVariable())
1063 EmitDecl(*S.getConditionVariable());
1072 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1073 bool EmitBoolCondBranch = !
C || !
C->isOne();
1086 if (EmitBoolCondBranch) {
1087 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1088 if (ConditionScope.requiresCleanups())
1090 llvm::MDNode *Weights =
1091 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1093 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1095 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1097 if (ExitBlock !=
LoopExit.getBlock()) {
1103 diag::warn_attribute_has_no_effect_on_infinite_loop)
1104 << A << A->getRange();
1107 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1108 <<
SourceRange(S.getWhileLoc(), S.getRParenLoc());
1114 RunCleanupsScope BodyScope(*
this);
1124 BreakContinueStack.pop_back();
1127 ConditionScope.ForceCleanup();
1140 if (!EmitBoolCondBranch)
1160 BreakContinueStack.push_back(BreakContinue(
LoopExit, LoopCond));
1174 RunCleanupsScope BodyScope(*
this);
1191 BreakContinueStack.pop_back();
1195 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1196 bool EmitBoolCondBranch = !
C || !
C->isZero();
1205 if (EmitBoolCondBranch) {
1208 BoolCondVal, LoopBody,
LoopExit.getBlock(),
1209 createProfileWeightsForLoop(S.getCond(), BackedgeCount));
1219 if (!EmitBoolCondBranch)
1235 LexicalScope ForScope(*
this, S.getSourceRange());
1245 llvm::BasicBlock *CondBlock = CondDest.getBlock();
1258 LexicalScope ConditionScope(*
this, S.getSourceRange());
1269 Continue = CondDest;
1270 else if (!S.getConditionVariable())
1272 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1277 if (S.getConditionVariable()) {
1278 EmitDecl(*S.getConditionVariable());
1283 BreakContinueStack.back().ContinueBlock = Continue;
1291 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1294 if (ForScope.requiresCleanups())
1303 llvm::MDNode *Weights =
1304 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1306 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1309 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1311 if (ExitBlock !=
LoopExit.getBlock()) {
1330 RunCleanupsScope BodyScope(*
this);
1342 BreakContinueStack.pop_back();
1344 ConditionScope.ForceCleanup();
1349 ForScope.ForceCleanup();
1370 LexicalScope ForScope(*
this, S.getSourceRange());
1395 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1396 if (ForScope.requiresCleanups())
1405 llvm::MDNode *Weights =
1406 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1408 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1410 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1412 if (ExitBlock !=
LoopExit.getBlock()) {
1427 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1431 LexicalScope BodyScope(*
this, S.getSourceRange());
1441 BreakContinueStack.pop_back();
1445 ForScope.ForceCleanup();
1461void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1477struct SaveRetExprRAII {
1479 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1482 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1483 const Expr *OldRetExpr;
1492 if (calleeQualType->isFunctionPointerType() ||
1493 calleeQualType->isFunctionReferenceType() ||
1494 calleeQualType->isBlockPointerType() ||
1495 calleeQualType->isMemberFunctionPointerType()) {
1497 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1499 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1500 if (
auto methodDecl = CMCE->getMethodDecl()) {
1516 if (requiresReturnValueCheck()) {
1519 new llvm::GlobalVariable(
CGM.
getModule(), SLoc->getType(),
false,
1520 llvm::GlobalVariable::PrivateLinkage, SLoc);
1521 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1523 assert(ReturnLocation.
isValid() &&
"No valid return location");
1530 Builder.ClearInsertionPoint();
1534 const Expr *RV = S.getRetValue();
1544 SaveRetExprRAII SaveRetExpr(RV, *
this);
1546 RunCleanupsScope cleanupScope(*
this);
1547 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1548 RV = EWC->getSubExpr();
1552 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1555 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1565 if (
getLangOpts().ElideConstructors && S.getNRVOCandidate() &&
1566 S.getNRVOCandidate()->isNRVOVariable() &&
1577 if (llvm::Value *NRVOFlag =
NRVOFlags[S.getNRVOCandidate()])
1620 ++NumSimpleReturnExprs;
1622 cleanupScope.ForceCleanup();
1632 for (
const auto *I : S.decls())
1637 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1649 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1665 assert(S.getRHS() &&
"Expected RHS value in CaseStmt");
1667 llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(
getContext());
1668 llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(
getContext());
1678 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1682 llvm::APInt
Range = RHS - LHS;
1684 if (
Range.ult(llvm::APInt(
Range.getBitWidth(), 64))) {
1687 unsigned NCases =
Range.getZExtValue() + 1;
1692 uint64_t Weight = Total / NCases,
Rem = Total % NCases;
1693 for (
unsigned I = 0; I != NCases; ++I) {
1695 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1696 else if (SwitchLikelihood)
1697 SwitchLikelihood->push_back(LH);
1701 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1709 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1714 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1718 Builder.SetInsertPoint(CaseRangeBlock);
1722 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1726 llvm::MDNode *Weights =
nullptr;
1727 if (SwitchWeights) {
1729 uint64_t DefaultCount = (*SwitchWeights)[0];
1730 Weights = createProfileWeights(ThisCount, DefaultCount);
1735 (*SwitchWeights)[0] += ThisCount;
1736 }
else if (SwitchLikelihood)
1737 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
1739 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
1743 Builder.SetInsertPoint(RestoreBB);
1745 Builder.ClearInsertionPoint();
1766 llvm::ConstantInt *CaseVal =
1771 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.getLHS()))
1772 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1774 CE = dyn_cast<ConstantExpr>(S.getLHS());
1776 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1779 Dbg->EmitGlobalVariable(DE->getDecl(),
1780 APValue(llvm::APSInt(CaseVal->getValue())));
1783 if (SwitchLikelihood)
1791 isa<BreakStmt>(S.getSubStmt())) {
1792 JumpDest
Block = BreakContinueStack.back().BreakBlock;
1798 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1802 if (
Builder.GetInsertBlock()) {
1804 Builder.ClearInsertionPoint();
1814 SwitchInsn->addCase(CaseVal, CaseDest);
1830 const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt());
1833 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1835 llvm::ConstantInt *CaseVal =
1846 if (SwitchLikelihood)
1849 SwitchInsn->addCase(CaseVal, CaseDest);
1850 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1873 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1874 assert(DefaultBlock->empty() &&
1875 "EmitDefaultStmt: Default block already defined?");
1877 if (SwitchLikelihood)
1919 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
1933 if (!Case && isa<BreakStmt>(S))
1938 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
1942 bool StartedInLiveCode = FoundCase;
1943 unsigned StartSize = ResultStmts.size();
1950 bool HadSkippedDecl =
false;
1954 for (; Case && I !=
E; ++I) {
1970 for (++I; I !=
E; ++I)
1980 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
1995 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
2000 bool AnyDecls =
false;
2001 for (; I !=
E; ++I) {
2014 for (++I; I !=
E; ++I)
2031 ResultStmts.resize(StartSize);
2032 ResultStmts.push_back(S);
2056 ResultStmts.push_back(S);
2065 const llvm::APSInt &ConstantCondValue,
2071 const SwitchCase *Case = S.getSwitchCaseList();
2077 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2083 const CaseStmt *CS = cast<CaseStmt>(Case);
2085 if (CS->
getRHS())
return false;
2110 bool FoundCase =
false;
2117static std::optional<SmallVector<uint64_t, 16>>
2120 if (Likelihoods.size() <= 1)
2121 return std::nullopt;
2123 uint64_t NumUnlikely = 0;
2124 uint64_t NumNone = 0;
2125 uint64_t NumLikely = 0;
2126 for (
const auto LH : Likelihoods) {
2141 if (NumUnlikely == 0 && NumLikely == 0)
2142 return std::nullopt;
2150 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2151 const uint64_t
None = Likely / (NumNone + 1);
2152 const uint64_t Unlikely = 0;
2155 Result.reserve(Likelihoods.size());
2156 for (
const auto LH : Likelihoods) {
2159 Result.push_back(Unlikely);
2165 Result.push_back(Likely);
2175 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2178 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2182 llvm::APSInt ConstantCondValue;
2190 RunCleanupsScope ExecutedScope(*
this);
2197 if (S.getConditionVariable())
2198 EmitDecl(*S.getConditionVariable());
2203 SwitchInsn =
nullptr;
2207 for (
unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
2214 SwitchInsn = SavedSwitchInsn;
2222 RunCleanupsScope ConditionScope(*
this);
2227 if (S.getConditionVariable())
2228 EmitDecl(*S.getConditionVariable());
2236 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2240 unsigned NumCases = 0;
2241 for (
const SwitchCase *Case = S.getSwitchCaseList();
2244 if (isa<DefaultStmt>(Case))
2249 SwitchWeights->reserve(NumCases);
2252 SwitchWeights->push_back(DefaultCount);
2259 CaseRangeBlock = DefaultBlock;
2262 Builder.ClearInsertionPoint();
2266 JumpDest OuterContinue;
2267 if (!BreakContinueStack.empty())
2268 OuterContinue = BreakContinueStack.back().ContinueBlock;
2270 BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue));
2275 BreakContinueStack.pop_back();
2279 SwitchInsn->setDefaultDest(CaseRangeBlock);
2282 if (!DefaultBlock->getParent()) {
2285 if (ConditionScope.requiresCleanups()) {
2290 DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock());
2291 delete DefaultBlock;
2295 ConditionScope.ForceCleanup();
2304 auto *
Call = dyn_cast<CallExpr>(S.getCond());
2306 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2307 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2309 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2310 MDHelper.createUnpredictable());
2314 if (SwitchWeights) {
2315 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2316 "switch weights do not match switch cases");
2318 if (SwitchWeights->size() > 1)
2319 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2320 createProfileWeights(*SwitchWeights));
2321 delete SwitchWeights;
2322 }
else if (SwitchLikelihood) {
2323 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2324 "switch likelihoods do not match switch cases");
2325 std::optional<SmallVector<uint64_t, 16>> LHW =
2329 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2330 createProfileWeights(*LHW));
2332 delete SwitchLikelihood;
2334 SwitchInsn = SavedSwitchInsn;
2335 SwitchWeights = SavedSwitchWeights;
2336 SwitchLikelihood = SavedSwitchLikelihood;
2337 CaseRangeBlock = SavedCRBlock;
2345 while (*Constraint) {
2346 switch (*Constraint) {
2358 while (Constraint[1] && Constraint[1] !=
',')
2364 while (Constraint[1] && Constraint[1] == *Constraint)
2375 "Must pass output names to constraints with a symbolic name");
2377 bool result =
Target.resolveSymbolicName(Constraint, *OutCons, Index);
2378 assert(result &&
"Could not resolve symbolic name"); (void)result;
2379 Result += llvm::utostr(Index);
2397 std::string *GCCReg =
nullptr) {
2398 const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
2410 StringRef Register =
Attr->getLabel();
2411 assert(
Target.isValidGCCRegisterName(Register));
2415 if (
Target.validateOutputConstraint(Info) &&
2421 Register =
Target.getNormalizedGCCRegisterName(Register);
2422 if (GCCReg !=
nullptr)
2423 *GCCReg = Register.str();
2424 return (EarlyClobber ?
"&{" :
"{") + Register.str() +
"}";
2427std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2436 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2446 ConstraintStr +=
'*';
2450std::pair<llvm::Value *, llvm::Type *>
2452 const Expr *InputExpr,
2453 std::string &ConstraintStr) {
2461 llvm::APSInt IntResult;
2464 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2476 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2480 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2492 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2495 if (!StrVal.empty()) {
2498 unsigned StartToken = 0;
2499 unsigned ByteOffset = 0;
2503 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2504 if (StrVal[i] !=
'\n')
continue;
2506 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2507 Locs.push_back(llvm::ConstantAsMetadata::get(
2516 bool HasUnwindClobber,
bool ReadOnly,
2517 bool ReadNone,
bool NoMerge,
bool NoConvergent,
2519 const std::vector<llvm::Type *> &ResultRegTypes,
2520 const std::vector<llvm::Type *> &ArgElemTypes,
2522 std::vector<llvm::Value *> &RegResults) {
2523 if (!HasUnwindClobber)
2524 Result.addFnAttr(llvm::Attribute::NoUnwind);
2527 Result.addFnAttr(llvm::Attribute::NoMerge);
2529 if (!HasSideEffect) {
2531 Result.setDoesNotAccessMemory();
2533 Result.setOnlyReadsMemory();
2537 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
2539 auto Attr = llvm::Attribute::get(
2540 CGF.
getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2547 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S))
2548 Result.setMetadata(
"srcloc",
2552 llvm::Constant *
Loc =
2553 llvm::ConstantInt::get(CGF.
Int64Ty, S.getAsmLoc().getRawEncoding());
2554 Result.setMetadata(
"srcloc",
2556 llvm::ConstantAsMetadata::get(
Loc)));
2564 Result.addFnAttr(llvm::Attribute::Convergent);
2566 if (ResultRegTypes.size() == 1) {
2567 RegResults.push_back(&
Result);
2569 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2570 llvm::Value *Tmp = CGF.
Builder.CreateExtractValue(&
Result, i,
"asmresult");
2571 RegResults.push_back(Tmp);
2583 const llvm::BitVector &ResultTypeRequiresCast,
2584 const llvm::BitVector &ResultRegIsFlagReg) {
2589 assert(RegResults.size() == ResultRegTypes.size());
2590 assert(RegResults.size() == ResultTruncRegTypes.size());
2591 assert(RegResults.size() == ResultRegDests.size());
2594 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2595 assert(ResultRegIsFlagReg.size() <= ResultRegDests.size());
2597 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2598 llvm::Value *Tmp = RegResults[i];
2599 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2601 if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
2604 llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2);
2605 llvm::Value *IsBooleanValue =
2606 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two);
2608 Builder.CreateCall(FnAssume, IsBooleanValue);
2613 if (ResultRegTypes[i] != TruncTy) {
2617 if (TruncTy->isFloatingPointTy())
2618 Tmp =
Builder.CreateFPTrunc(Tmp, TruncTy);
2619 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2622 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
2623 Tmp =
Builder.CreateIntToPtr(Tmp, TruncTy);
2624 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2628 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
2629 Tmp =
Builder.CreateTrunc(Tmp, TruncTy);
2630 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2631 Tmp =
Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2632 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2633 Tmp =
Builder.CreateBitCast(Tmp, TruncTy);
2637 LValue Dest = ResultRegDests[i];
2640 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2651 const Expr *OutExpr = S.getOutputExpr(i);
2653 diag::err_store_value_to_reg);
2664 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2667 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2668 Asm = GCCAsm->getAsmString()->getString();
2672 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2673 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2674 {StrTy->getType()},
false);
2675 auto UBF = CGF->
CGM.
getModule().getOrInsertFunction(Name, FnTy);
2677 CGF->
Builder.CreateCall(UBF, {StrTy});
2682 CodeGenFunction::RunCleanupsScope Cleanups(*
this);
2685 std::string AsmString = S.generateAsmString(
getContext());
2692 bool IsValidTargetAsm =
true;
2693 for (
unsigned i = 0, e = S.getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2695 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2696 Name = GAS->getOutputName(i);
2699 if (IsHipStdPar && !IsValid)
2700 IsValidTargetAsm =
false;
2702 assert(IsValid &&
"Failed to parse output constraint");
2703 OutputConstraintInfos.push_back(Info);
2706 for (
unsigned i = 0, e = S.getNumInputs(); i != e && IsValidTargetAsm; i++) {
2708 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2709 Name = GAS->getInputName(i);
2713 if (IsHipStdPar && !IsValid)
2714 IsValidTargetAsm =
false;
2716 assert(IsValid &&
"Failed to parse input constraint");
2717 InputConstraintInfos.push_back(Info);
2720 if (!IsValidTargetAsm)
2723 std::string Constraints;
2725 std::vector<LValue> ResultRegDests;
2726 std::vector<QualType> ResultRegQualTys;
2727 std::vector<llvm::Type *> ResultRegTypes;
2728 std::vector<llvm::Type *> ResultTruncRegTypes;
2729 std::vector<llvm::Type *> ArgTypes;
2730 std::vector<llvm::Type *> ArgElemTypes;
2731 std::vector<llvm::Value*> Args;
2732 llvm::BitVector ResultTypeRequiresCast;
2733 llvm::BitVector ResultRegIsFlagReg;
2736 std::string InOutConstraints;
2737 std::vector<llvm::Value*> InOutArgs;
2738 std::vector<llvm::Type*> InOutArgTypes;
2739 std::vector<llvm::Type*> InOutArgElemTypes;
2742 std::vector<std::string> OutputConstraints;
2745 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2753 bool ReadOnly =
true, ReadNone =
true;
2755 for (
unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
2759 std::string OutputConstraint(S.getOutputConstraint(i));
2763 const Expr *OutExpr = S.getOutputExpr(i);
2772 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2773 CGM.
Error(S.getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2775 OutputConstraints.push_back(OutputConstraint);
2777 if (!Constraints.empty())
2787 Constraints +=
"=" + OutputConstraint;
2788 ResultRegQualTys.push_back(QTy);
2789 ResultRegDests.push_back(Dest);
2791 bool IsFlagReg = llvm::StringRef(OutputConstraint).starts_with(
"{@cc");
2792 ResultRegIsFlagReg.push_back(IsFlagReg);
2797 Ty->isAggregateType());
2799 ResultTruncRegTypes.push_back(Ty);
2800 ResultTypeRequiresCast.push_back(RequiresCast);
2809 ResultRegTypes.push_back(Ty);
2815 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2820 assert(InputNo != S.getNumInputs() &&
"Didn't find matching input!");
2822 QualType InputTy = S.getInputExpr(InputNo)->getType();
2831 if (llvm::Type* AdjTy =
2833 ResultRegTypes.back()))
2834 ResultRegTypes.back() = AdjTy;
2837 diag::err_asm_invalid_type_in_input)
2838 << OutExpr->
getType() << OutputConstraint;
2842 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
2843 LargestVectorWidth =
2844 std::max((uint64_t)LargestVectorWidth,
2845 VT->getPrimitiveSizeInBits().getKnownMinValue());
2856 ArgTypes.push_back(DestAddr.
getType());
2859 Constraints +=
"=*";
2860 Constraints += OutputConstraint;
2861 ReadOnly = ReadNone =
false;
2865 InOutConstraints +=
',';
2867 const Expr *InputExpr = S.getOutputExpr(i);
2869 llvm::Type *ArgElemType;
2870 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
2871 Info, Dest, InputExpr->
getType(), InOutConstraints,
2874 if (llvm::Type* AdjTy =
2877 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2880 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2881 LargestVectorWidth =
2882 std::max((uint64_t)LargestVectorWidth,
2883 VT->getPrimitiveSizeInBits().getKnownMinValue());
2886 InOutConstraints += llvm::utostr(i);
2888 InOutConstraints += OutputConstraint;
2890 InOutArgTypes.push_back(Arg->getType());
2891 InOutArgElemTypes.push_back(ArgElemType);
2892 InOutArgs.push_back(Arg);
2898 if (isa<MSAsmStmt>(&S)) {
2904 *
this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
2905 ResultRegDests, AsmString, S.getNumOutputs());
2910 for (
unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
2911 const Expr *InputExpr = S.getInputExpr(i);
2918 if (!Constraints.empty())
2922 std::string InputConstraint(S.getInputConstraint(i));
2924 &OutputConstraintInfos);
2930 std::string ReplaceConstraint (InputConstraint);
2932 llvm::Type *ArgElemType;
2933 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
2942 QualType OutputType = S.getOutputExpr(Output)->getType();
2948 if (isa<llvm::PointerType>(Arg->getType()))
2951 if (isa<llvm::IntegerType>(OutputTy))
2952 Arg =
Builder.CreateZExt(Arg, OutputTy);
2953 else if (isa<llvm::PointerType>(OutputTy))
2955 else if (OutputTy->isFloatingPointTy())
2956 Arg =
Builder.CreateFPExt(Arg, OutputTy);
2959 ReplaceConstraint = OutputConstraints[Output];
2961 if (llvm::Type* AdjTy =
2964 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2967 << InputExpr->
getType() << InputConstraint;
2970 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2971 LargestVectorWidth =
2972 std::max((uint64_t)LargestVectorWidth,
2973 VT->getPrimitiveSizeInBits().getKnownMinValue());
2975 ArgTypes.push_back(Arg->getType());
2976 ArgElemTypes.push_back(ArgElemType);
2977 Args.push_back(Arg);
2978 Constraints += InputConstraint;
2982 for (
unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
2983 ArgTypes.push_back(InOutArgTypes[i]);
2984 ArgElemTypes.push_back(InOutArgElemTypes[i]);
2985 Args.push_back(InOutArgs[i]);
2987 Constraints += InOutConstraints;
2991 llvm::BasicBlock *Fallthrough =
nullptr;
2992 bool IsGCCAsmGoto =
false;
2993 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S)) {
2994 IsGCCAsmGoto = GS->isAsmGoto();
2996 for (
const auto *
E : GS->labels()) {
2998 Transfer.push_back(Dest.getBlock());
2999 if (!Constraints.empty())
3001 Constraints +=
"!i";
3007 bool HasUnwindClobber =
false;
3010 for (
unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
3011 StringRef Clobber = S.getClobber(i);
3013 if (Clobber ==
"memory")
3014 ReadOnly = ReadNone =
false;
3015 else if (Clobber ==
"unwind") {
3016 HasUnwindClobber =
true;
3018 }
else if (Clobber !=
"cc") {
3023 diag::warn_stack_clash_protection_inline_asm);
3027 if (isa<MSAsmStmt>(&S)) {
3028 if (Clobber ==
"eax" || Clobber ==
"edx") {
3029 if (Constraints.find(
"=&A") != std::string::npos)
3031 std::string::size_type position1 =
3032 Constraints.find(
"={" + Clobber.str() +
"}");
3033 if (position1 != std::string::npos) {
3034 Constraints.insert(position1 + 1,
"&");
3037 std::string::size_type position2 = Constraints.find(
"=A");
3038 if (position2 != std::string::npos) {
3039 Constraints.insert(position2 + 1,
"&");
3044 if (!Constraints.empty())
3047 Constraints +=
"~{";
3048 Constraints += Clobber;
3052 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
3053 "unwind clobber can't be used with asm goto");
3057 if (!MachineClobbers.empty()) {
3058 if (!Constraints.empty())
3060 Constraints += MachineClobbers;
3063 llvm::Type *ResultType;
3064 if (ResultRegTypes.empty())
3066 else if (ResultRegTypes.size() == 1)
3067 ResultType = ResultRegTypes[0];
3069 ResultType = llvm::StructType::get(
getLLVMContext(), ResultRegTypes);
3071 llvm::FunctionType *FTy =
3072 llvm::FunctionType::get(ResultType, ArgTypes,
false);
3074 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
3076 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3078 ? llvm::InlineAsm::AD_ATT
3079 : llvm::InlineAsm::AD_Intel;
3080 llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ?
3081 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3083 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3084 FTy, AsmString, Constraints, HasSideEffect,
3085 false, AsmDialect, HasUnwindClobber);
3086 std::vector<llvm::Value*> RegResults;
3087 llvm::CallBrInst *CBR;
3088 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3091 CBR =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3096 ArgElemTypes, *
this, RegResults);
3100 if (!RegResults.empty()) {
3102 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3103 llvm::Twine SynthName = Dest->getName() +
".split";
3105 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3106 Builder.SetInsertPoint(SynthBB);
3108 if (ResultRegTypes.size() == 1) {
3109 CBRRegResults[SynthBB].push_back(CBR);
3111 for (
unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3112 llvm::Value *Tmp =
Builder.CreateExtractValue(CBR, j,
"asmresult");
3113 CBRRegResults[SynthBB].push_back(Tmp);
3119 CBR->setIndirectDest(i++, SynthBB);
3122 }
else if (HasUnwindClobber) {
3127 ArgElemTypes, *
this, RegResults);
3134 ArgElemTypes, *
this, RegResults);
3137 EmitAsmStores(*
this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3138 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3139 ResultRegIsFlagReg);
3144 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3145 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3146 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3147 Builder.SetInsertPoint(Succ, --(Succ->end()));
3148 EmitAsmStores(*
this, S, CBRRegResults[Succ], ResultRegTypes,
3149 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3150 ResultTypeRequiresCast, ResultRegIsFlagReg);
3156 const RecordDecl *RD = S.getCapturedRecordDecl();
3165 E = S.capture_init_end();
3166 I !=
E; ++I, ++CurField) {
3168 if (CurField->hasCapturedVLAType()) {
3186 CGCapturedStmtRAII CapInfoRAII(CGF,
new CGCapturedStmtInfo(S, K));
3187 llvm::Function *F = CGF.GenerateCapturedStmtFunction(S);
3188 delete CGF.CapturedStmtInfo;
3205 "CapturedStmtInfo should be set when generating the captured function");
3207 const RecordDecl *RD = S.getCapturedRecordDecl();
3209 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3222 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3226 F->addFnAttr(llvm::Attribute::NoUnwind);
3238 for (
auto *FD : RD->
fields()) {
3239 if (FD->hasCapturedVLAType()) {
3243 auto VAT = FD->getCapturedVLAType();
3244 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3265 for (
auto &I : *BB) {
3266 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3273CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3275 assert(ParentToken);
3277 llvm::Value *bundleArgs[] = {ParentToken};
3278 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3279 auto *Output = llvm::CallBase::addOperandBundle(
3280 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3281 Input->replaceAllUsesWith(Output);
3282 Input->eraseFromParent();
3286llvm::ConvergenceControlInst *
3287CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
3288 CGBuilderTy::InsertPoint IP =
Builder.saveIP();
3292 Builder.SetInsertPoint(BB->getFirstInsertionPt());
3294 llvm::CallBase *CB =
Builder.CreateIntrinsic(
3295 llvm::Intrinsic::experimental_convergence_loop, {}, {});
3298 CB = addConvergenceControlToken(CB);
3299 return cast<llvm::ConvergenceControlInst>(CB);
3302llvm::ConvergenceControlInst *
3303CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3304 llvm::BasicBlock *BB = &F->getEntryBlock();
3313 CGBuilderTy::InsertPoint IP =
Builder.saveIP();
3314 Builder.SetInsertPoint(&BB->front());
3315 llvm::CallBase *I =
Builder.CreateIntrinsic(
3316 llvm::Intrinsic::experimental_convergence_entry, {}, {});
3317 assert(isa<llvm::IntrinsicInst>(I));
3320 return cast<llvm::ConvergenceControlInst>(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 llvm::ConvergenceControlInst * getConvergenceToken(llvm::BasicBlock *BB)
static void EmitHipStdParUnsupportedAsm(CodeGenFunction *CGF, const AsmStmt &S)
static std::optional< SmallVector< uint64_t, 16 > > getLikelihoodWeights(ArrayRef< Stmt::Likelihood > Likelihoods)
static llvm::MDNode * getAsmSrcLocInfo(const StringLiteral *Str, CodeGenFunction &CGF)
getAsmSrcLocInfo - Return the !srcloc metadata node to attach to an inline asm call instruction.
static std::string SimplifyConstraint(const char *Constraint, const TargetInfo &Target, SmallVectorImpl< TargetInfo::ConstraintInfo > *OutCons=nullptr)
static bool isSwiftAsyncCallee(const CallExpr *CE)
Determine if the given call uses the swiftasync calling convention.
static CSFC_Result CollectStatementsForCase(const Stmt *S, const SwitchCase *Case, bool &FoundCase, SmallVectorImpl< const Stmt * > &ResultStmts)
static void EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S, const llvm::ArrayRef< llvm::Value * > RegResults, const llvm::ArrayRef< llvm::Type * > ResultRegTypes, const llvm::ArrayRef< llvm::Type * > ResultTruncRegTypes, const llvm::ArrayRef< LValue > ResultRegDests, const llvm::ArrayRef< QualType > ResultRegQualTys, const llvm::BitVector &ResultTypeRequiresCast, const llvm::BitVector &ResultRegIsFlagReg)
static bool hasEmptyLoopBody(const LoopStmt &S)
CSFC_Result
CollectStatementsForCase - Given the body of a 'switch' statement and a constant value that is being ...
static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, bool HasUnwindClobber, bool ReadOnly, bool ReadNone, bool NoMerge, bool NoConvergent, const AsmStmt &S, const std::vector< llvm::Type * > &ResultRegTypes, const std::vector< llvm::Type * > &ArgElemTypes, CodeGenFunction &CGF, std::vector< llvm::Value * > &RegResults)
llvm::MachO::Target Target
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Defines the SourceManager interface.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
bool toIntegralConstant(APSInt &Result, QualType SrcTy, const ASTContext &Ctx) const
Try to convert this value to an integral constant.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
QualType 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 ...
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::PointerType * getType() const
Return the type of the pointer value.
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
A scoped helper to set the current debug location to the specified location or preferred location of ...
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateFlagStore(bool Value, llvm::Value *Addr)
Emit a store to an i1 flag variable.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
CGFunctionInfo - Class to encapsulate the information about a function definition.
ABIArgInfo & getReturnInfo()
CallingConv getASTCallingConvention() const
getASTCallingConvention() - Return the AST-specified calling convention.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
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 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)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
bool checkIfLoopMustProgress(const Expr *, bool HasEmptyBody)
Returns true if a loop must make progress, which means the mustprogress attribute can be added.
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 EmitWhileStmt(const WhileStmt &S, ArrayRef< const Attr * > Attrs={})
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...
void EmitOMPReverseDirective(const OMPReverseDirective &S)
static bool hasScalarEvaluationKind(QualType T)
void EmitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &S)
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 EmitOpenACCInitConstruct(const OpenACCInitConstruct &S)
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)
SmallVector< llvm::ConvergenceControlInst *, 4 > ConvergenceTokenStack
Stack to track the controlled convergence tokens.
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 EmitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &S)
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
bool InNoConvergentAttributedStmt
True if the current statement has noconvergent attribute.
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
SmallVector< llvm::OperandBundleDef, 1 > getBundlesForFunclet(llvm::Value *Callee)
void EmitOpenACCWaitConstruct(const OpenACCWaitConstruct &S)
llvm::Value * EmitCheckedArgForAssume(const Expr *E)
Emits an argument for a call to a __builtin_assume.
void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
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.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field)
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 EmitOMPFlushDirective(const OMPFlushDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &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.
void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef< const Attr * > Attrs={})
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 EmitForStmt(const ForStmt &S, ArrayRef< const Attr * > Attrs={})
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
void EmitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &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,...
void EmitOpenACCDataConstruct(const OpenACCDataConstruct &S)
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
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
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)
void EmitOMPScopeDirective(const OMPScopeDirective &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 EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
ASTContext & getContext() const
void EmitOpenACCLoopConstruct(const OpenACCLoopConstruct &S)
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 EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
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)
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
llvm::Type * ConvertType(QualType T)
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
void EmitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &S)
llvm::CallBase * EmitCallOrInvoke(llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const Twine &Name="")
HLSLControlFlowHintAttr::Spelling HLSLControlFlowAttr
HLSL Branch attribute.
void EmitDoStmt(const DoStmt &S, ArrayRef< const Attr * > Attrs={})
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)
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 EmitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &S)
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &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)
void EmitOpenACCSetConstruct(const OpenACCSetConstruct &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 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 EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void 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.
bool shouldEmitConvergenceTokens() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
SanitizerMetadata * getSanitizerMetadata()
ASTContext & getContext() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn)
Assign counters to regions and configure them for PGO of a given function.
void markStmtMaybeUsed(const Stmt *S)
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.
llvm::Value * getPointer(CodeGenFunction &CGF) const
Address getAddress() const
void pop()
End the current loop.
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
virtual void addReturnRegisterOutputs(CodeGen::CodeGenFunction &CGF, CodeGen::LValue ReturnValue, std::string &Constraints, std::vector< llvm::Type * > &ResultRegTypes, std::vector< llvm::Type * > &ResultTruncRegTypes, std::vector< CodeGen::LValue > &ResultRegDests, std::string &AsmString, unsigned NumOutputs) const
Adds constraints and types for result registers.
virtual bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, llvm::Type *Ty) const
Target hook to decide whether an inline asm operand can be passed by value.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Stmt *const * const_body_iterator
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
ContinueStmt - This represents a continue.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
DoStmt - This represents a 'do/while' stmt.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
ForStmt - This represents a 'for (init;cond;inc)' stmt.
const Expr * getSubExpr() const
FunctionType - C99 6.7.5.3 - Function Declarators.
CallingConv getCallConv() const
This represents a GCC inline-assembly statement extension.
GlobalDecl - represents a global declaration.
GotoStmt - This represents a direct goto.
IfStmt - This represents an if/then/else.
IndirectGotoStmt - This represents an indirect goto.
Represents the declaration of a label.
LabelStmt - Represents a label, which has a substatement.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool assumeFunctionsAreConvergent() const
Represents a point when we exit a loop.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType getCanonicalType() const
The collection of all-type qualifiers we support.
Represents a struct/union/class.
field_range fields() const
field_iterator field_begin() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
StmtClass getStmtClass() const
Likelihood
The likelihood of a branch being taken.
@ LH_Unlikely
Branch has the [[unlikely]] attribute.
@ LH_None
No attribute set or branches of the IfStmt have the same attribute.
@ LH_Likely
Branch has the [[likely]] attribute.
static const Attr * getLikelihoodAttr(const Stmt *S)
SourceLocation getBeginLoc() const LLVM_READONLY
static Likelihood getLikelihood(ArrayRef< const Attr * > Attrs)
StringLiteral - This represents a string literal expression, e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target, unsigned *StartToken=nullptr, unsigned *StartTokenByteOffset=nullptr) const
getLocationOfByte - Return a source location that points to the specified byte of this string literal...
StringRef getString() const
const SwitchCase * getNextSwitchCase() const
SwitchStmt - This represents a 'switch' stmt.
Exposes information about the current target.
bool validateInputConstraint(MutableArrayRef< ConstraintInfo > OutputConstraints, ConstraintInfo &info) const
StringRef getNormalizedGCCRegisterName(StringRef Name, bool ReturnCanonical=false) const
Returns the "normalized" GCC register name.
bool validateOutputConstraint(ConstraintInfo &Info) const
virtual std::string_view getClobbers() const =0
Returns a string of target-specific clobbers, in LLVM format.
Token - This structure provides full information about a lexed token.
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
WhileStmt - This represents a 'while' stmt.
Defines the clang::TargetInfo interface.
bool Rem(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool Ret(InterpState &S, CodePtr &PC)
The JSON file list parser is used to communicate input to InstallAPI.
CapturedRegionKind
The different kinds of captured statement.
@ Asm
Assembly: we accept this only so that we can preprocess it.
@ Result
The result type of a method or function.
Diagnostic wrappers for TextAPI types for error reporting.
cl::opt< bool > EnableSingleByteCoverage
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
void setScopeDepth(EHScopeStack::stable_iterator depth)
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