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::OMPReverseDirectiveClass:
228 case Stmt::OMPInterchangeDirectiveClass:
231 case Stmt::OMPForDirectiveClass:
234 case Stmt::OMPForSimdDirectiveClass:
237 case Stmt::OMPSectionsDirectiveClass:
240 case Stmt::OMPSectionDirectiveClass:
243 case Stmt::OMPSingleDirectiveClass:
246 case Stmt::OMPMasterDirectiveClass:
249 case Stmt::OMPCriticalDirectiveClass:
252 case Stmt::OMPParallelForDirectiveClass:
255 case Stmt::OMPParallelForSimdDirectiveClass:
258 case Stmt::OMPParallelMasterDirectiveClass:
261 case Stmt::OMPParallelSectionsDirectiveClass:
264 case Stmt::OMPTaskDirectiveClass:
267 case Stmt::OMPTaskyieldDirectiveClass:
270 case Stmt::OMPErrorDirectiveClass:
273 case Stmt::OMPBarrierDirectiveClass:
276 case Stmt::OMPTaskwaitDirectiveClass:
279 case Stmt::OMPTaskgroupDirectiveClass:
282 case Stmt::OMPFlushDirectiveClass:
285 case Stmt::OMPDepobjDirectiveClass:
288 case Stmt::OMPScanDirectiveClass:
291 case Stmt::OMPOrderedDirectiveClass:
294 case Stmt::OMPAtomicDirectiveClass:
297 case Stmt::OMPTargetDirectiveClass:
300 case Stmt::OMPTeamsDirectiveClass:
303 case Stmt::OMPCancellationPointDirectiveClass:
306 case Stmt::OMPCancelDirectiveClass:
309 case Stmt::OMPTargetDataDirectiveClass:
312 case Stmt::OMPTargetEnterDataDirectiveClass:
315 case Stmt::OMPTargetExitDataDirectiveClass:
318 case Stmt::OMPTargetParallelDirectiveClass:
321 case Stmt::OMPTargetParallelForDirectiveClass:
324 case Stmt::OMPTaskLoopDirectiveClass:
327 case Stmt::OMPTaskLoopSimdDirectiveClass:
330 case Stmt::OMPMasterTaskLoopDirectiveClass:
333 case Stmt::OMPMaskedTaskLoopDirectiveClass:
334 llvm_unreachable(
"masked taskloop directive not supported yet.");
336 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
338 cast<OMPMasterTaskLoopSimdDirective>(*S));
340 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
341 llvm_unreachable(
"masked taskloop simd directive not supported yet.");
343 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
345 cast<OMPParallelMasterTaskLoopDirective>(*S));
347 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
348 llvm_unreachable(
"parallel masked taskloop directive not supported yet.");
350 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
352 cast<OMPParallelMasterTaskLoopSimdDirective>(*S));
354 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
356 "parallel masked taskloop simd directive not supported yet.");
358 case Stmt::OMPDistributeDirectiveClass:
361 case Stmt::OMPTargetUpdateDirectiveClass:
364 case Stmt::OMPDistributeParallelForDirectiveClass:
366 cast<OMPDistributeParallelForDirective>(*S));
368 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
370 cast<OMPDistributeParallelForSimdDirective>(*S));
372 case Stmt::OMPDistributeSimdDirectiveClass:
375 case Stmt::OMPTargetParallelForSimdDirectiveClass:
377 cast<OMPTargetParallelForSimdDirective>(*S));
379 case Stmt::OMPTargetSimdDirectiveClass:
382 case Stmt::OMPTeamsDistributeDirectiveClass:
385 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
387 cast<OMPTeamsDistributeSimdDirective>(*S));
389 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
391 cast<OMPTeamsDistributeParallelForSimdDirective>(*S));
393 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
395 cast<OMPTeamsDistributeParallelForDirective>(*S));
397 case Stmt::OMPTargetTeamsDirectiveClass:
400 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
402 cast<OMPTargetTeamsDistributeDirective>(*S));
404 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
406 cast<OMPTargetTeamsDistributeParallelForDirective>(*S));
408 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
410 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(*S));
412 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
414 cast<OMPTargetTeamsDistributeSimdDirective>(*S));
416 case Stmt::OMPInteropDirectiveClass:
419 case Stmt::OMPDispatchDirectiveClass:
422 case Stmt::OMPScopeDirectiveClass:
425 case Stmt::OMPMaskedDirectiveClass:
428 case Stmt::OMPGenericLoopDirectiveClass:
431 case Stmt::OMPTeamsGenericLoopDirectiveClass:
434 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
436 cast<OMPTargetTeamsGenericLoopDirective>(*S));
438 case Stmt::OMPParallelGenericLoopDirectiveClass:
440 cast<OMPParallelGenericLoopDirective>(*S));
442 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
444 cast<OMPTargetParallelGenericLoopDirective>(*S));
446 case Stmt::OMPParallelMaskedDirectiveClass:
449 case Stmt::OMPAssumeDirectiveClass:
452 case Stmt::OpenACCComputeConstructClass:
455 case Stmt::OpenACCLoopConstructClass:
458 case Stmt::OpenACCCombinedConstructClass:
461 case Stmt::OpenACCDataConstructClass:
464 case Stmt::OpenACCEnterDataConstructClass:
467 case Stmt::OpenACCExitDataConstructClass:
470 case Stmt::OpenACCHostDataConstructClass:
473 case Stmt::OpenACCWaitConstructClass:
476 case Stmt::OpenACCInitConstructClass:
479 case Stmt::OpenACCShutdownConstructClass:
487 switch (S->getStmtClass()) {
490 case Stmt::NullStmtClass:
492 case Stmt::CompoundStmtClass:
495 case Stmt::DeclStmtClass:
498 case Stmt::LabelStmtClass:
501 case Stmt::AttributedStmtClass:
504 case Stmt::GotoStmtClass:
507 case Stmt::BreakStmtClass:
510 case Stmt::ContinueStmtClass:
513 case Stmt::DefaultStmtClass:
516 case Stmt::CaseStmtClass:
519 case Stmt::SEHLeaveStmtClass:
532 "LLVM IR generation of compound statement ('{}')");
535 LexicalScope
Scope(*
this, S.getSourceRange());
546 assert((!GetLast || (GetLast &&
ExprResult)) &&
547 "If GetLast is true then the CompoundStmt must have a StmtExprResult");
551 for (
auto *CurStmt : S.body()) {
559 if (
const auto *LS = dyn_cast<LabelStmt>(
ExprResult)) {
562 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(
ExprResult)) {
567 llvm_unreachable(
"unknown value statement");
594 llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
603 if (!BI || !BI->isUnconditional())
607 if (BI->getIterator() != BB->begin())
610 BB->replaceAllUsesWith(BI->getSuccessor(0));
611 BI->eraseFromParent();
612 BB->eraseFromParent();
616 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
621 if (IsFinished && BB->use_empty()) {
628 if (CurBB && CurBB->getParent())
629 CurFn->insert(std::next(CurBB->getIterator()), BB);
639 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
641 if (!CurBB || CurBB->getTerminator()) {
653 bool inserted =
false;
654 for (llvm::User *u : block->users()) {
655 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
656 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
668CodeGenFunction::JumpDest
670 JumpDest &Dest = LabelMap[
D];
671 if (Dest.isValid())
return Dest;
687 JumpDest &Dest = LabelMap[
D];
691 if (!Dest.isValid()) {
697 assert(!Dest.getScopeDepth().isValid() &&
"already emitted label!");
718 assert(!Labels.empty());
724 i = Labels.begin(), e = Labels.end(); i != e; ++i) {
725 assert(
CGF.LabelMap.count(*i));
734 ParentScope->Labels.append(Labels.begin(), Labels.end());
750 bool nomerge =
false;
751 bool noinline =
false;
752 bool alwaysinline =
false;
753 bool noconvergent =
false;
756 for (
const auto *A : S.getAttrs()) {
757 switch (A->getKind()) {
766 case attr::AlwaysInline:
769 case attr::NoConvergent:
772 case attr::MustTail: {
773 const Stmt *Sub = S.getSubStmt();
777 case attr::CXXAssume: {
778 const Expr *Assumption = cast<CXXAssumeAttr>(A)->getAssumption();
782 Builder.CreateAssumption(AssumptionVal);
792 EmitStmt(S.getSubStmt(), S.getAttrs());
815 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
822 cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(
V, CurBB);
828 const Stmt *Else = S.getElse();
832 if (S.isConsteval()) {
833 const Stmt *Executed = S.isNegatedConsteval() ? S.getThen() : Else;
835 RunCleanupsScope ExecutedScope(*
this);
843 LexicalScope ConditionScope(*
this, S.getCond()->getSourceRange());
849 if (S.getConditionVariable())
850 EmitDecl(*S.getConditionVariable());
858 const Stmt *Executed = S.getThen();
859 const Stmt *Skipped = Else;
861 std::swap(Executed, Skipped);
869 RunCleanupsScope ExecutedScope(*
this);
880 llvm::BasicBlock *ElseBlock = ContBlock;
911 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
921 RunCleanupsScope ThenScope(*
this);
937 RunCleanupsScope ElseScope(*
this);
968 bool CondIsConstInt =
969 !ControllingExpression ||
973 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
974 Result.Val.getInt().getBoolValue());
988 if (HasEmptyBody && CondIsTrue) {
989 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1007 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1011 const Stmt *Body = S.getBody();
1012 if (!Body || isa<NullStmt>(Body))
1014 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
1015 return Compound->body_empty();
1028 emitConvergenceLoopToken(LoopHeader.getBlock()));
1035 BreakContinueStack.push_back(BreakContinue(
LoopExit, LoopHeader));
1044 RunCleanupsScope ConditionScope(*
this);
1046 if (S.getConditionVariable())
1047 EmitDecl(*S.getConditionVariable());
1056 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1057 bool EmitBoolCondBranch = !
C || !
C->isOne();
1070 if (EmitBoolCondBranch) {
1071 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1072 if (ConditionScope.requiresCleanups())
1074 llvm::MDNode *Weights =
1075 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1077 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1079 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1081 if (ExitBlock !=
LoopExit.getBlock()) {
1087 diag::warn_attribute_has_no_effect_on_infinite_loop)
1088 << A << A->getRange();
1091 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1092 <<
SourceRange(S.getWhileLoc(), S.getRParenLoc());
1098 RunCleanupsScope BodyScope(*
this);
1108 BreakContinueStack.pop_back();
1111 ConditionScope.ForceCleanup();
1124 if (!EmitBoolCondBranch)
1144 BreakContinueStack.push_back(BreakContinue(
LoopExit, LoopCond));
1158 RunCleanupsScope BodyScope(*
this);
1175 BreakContinueStack.pop_back();
1179 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1180 bool EmitBoolCondBranch = !
C || !
C->isZero();
1189 if (EmitBoolCondBranch) {
1192 BoolCondVal, LoopBody,
LoopExit.getBlock(),
1193 createProfileWeightsForLoop(S.getCond(), BackedgeCount));
1203 if (!EmitBoolCondBranch)
1219 LexicalScope ForScope(*
this, S.getSourceRange());
1229 llvm::BasicBlock *CondBlock = CondDest.getBlock();
1242 LexicalScope ConditionScope(*
this, S.getSourceRange());
1253 Continue = CondDest;
1254 else if (!S.getConditionVariable())
1256 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1261 if (S.getConditionVariable()) {
1262 EmitDecl(*S.getConditionVariable());
1267 BreakContinueStack.back().ContinueBlock = Continue;
1275 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1278 if (ForScope.requiresCleanups())
1287 llvm::MDNode *Weights =
1288 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1290 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1293 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1295 if (ExitBlock !=
LoopExit.getBlock()) {
1314 RunCleanupsScope BodyScope(*
this);
1326 BreakContinueStack.pop_back();
1328 ConditionScope.ForceCleanup();
1333 ForScope.ForceCleanup();
1354 LexicalScope ForScope(*
this, S.getSourceRange());
1379 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1380 if (ForScope.requiresCleanups())
1389 llvm::MDNode *Weights =
1390 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1392 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1394 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1396 if (ExitBlock !=
LoopExit.getBlock()) {
1411 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1415 LexicalScope BodyScope(*
this, S.getSourceRange());
1425 BreakContinueStack.pop_back();
1429 ForScope.ForceCleanup();
1445void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1461struct SaveRetExprRAII {
1463 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1466 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1467 const Expr *OldRetExpr;
1476 if (calleeQualType->isFunctionPointerType() ||
1477 calleeQualType->isFunctionReferenceType() ||
1478 calleeQualType->isBlockPointerType() ||
1479 calleeQualType->isMemberFunctionPointerType()) {
1481 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1483 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1484 if (
auto methodDecl = CMCE->getMethodDecl()) {
1500 if (requiresReturnValueCheck()) {
1503 new llvm::GlobalVariable(
CGM.
getModule(), SLoc->getType(),
false,
1504 llvm::GlobalVariable::PrivateLinkage, SLoc);
1505 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1507 assert(ReturnLocation.
isValid() &&
"No valid return location");
1514 Builder.ClearInsertionPoint();
1518 const Expr *RV = S.getRetValue();
1528 SaveRetExprRAII SaveRetExpr(RV, *
this);
1530 RunCleanupsScope cleanupScope(*
this);
1531 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1532 RV = EWC->getSubExpr();
1536 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1539 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1549 if (
getLangOpts().ElideConstructors && S.getNRVOCandidate() &&
1550 S.getNRVOCandidate()->isNRVOVariable() &&
1561 if (llvm::Value *NRVOFlag =
NRVOFlags[S.getNRVOCandidate()])
1604 ++NumSimpleReturnExprs;
1606 cleanupScope.ForceCleanup();
1616 for (
const auto *I : S.decls())
1621 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1633 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1649 assert(S.getRHS() &&
"Expected RHS value in CaseStmt");
1651 llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(
getContext());
1652 llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(
getContext());
1662 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1666 llvm::APInt
Range = RHS - LHS;
1668 if (
Range.ult(llvm::APInt(
Range.getBitWidth(), 64))) {
1671 unsigned NCases =
Range.getZExtValue() + 1;
1676 uint64_t Weight = Total / NCases,
Rem = Total % NCases;
1677 for (
unsigned I = 0; I != NCases; ++I) {
1679 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1680 else if (SwitchLikelihood)
1681 SwitchLikelihood->push_back(LH);
1685 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1693 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1698 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1702 Builder.SetInsertPoint(CaseRangeBlock);
1706 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1710 llvm::MDNode *Weights =
nullptr;
1711 if (SwitchWeights) {
1713 uint64_t DefaultCount = (*SwitchWeights)[0];
1714 Weights = createProfileWeights(ThisCount, DefaultCount);
1719 (*SwitchWeights)[0] += ThisCount;
1720 }
else if (SwitchLikelihood)
1721 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
1723 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
1727 Builder.SetInsertPoint(RestoreBB);
1729 Builder.ClearInsertionPoint();
1750 llvm::ConstantInt *CaseVal =
1755 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.getLHS()))
1756 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1758 CE = dyn_cast<ConstantExpr>(S.getLHS());
1760 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1763 Dbg->EmitGlobalVariable(DE->getDecl(),
1764 APValue(llvm::APSInt(CaseVal->getValue())));
1767 if (SwitchLikelihood)
1775 isa<BreakStmt>(S.getSubStmt())) {
1776 JumpDest
Block = BreakContinueStack.back().BreakBlock;
1782 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1786 if (
Builder.GetInsertBlock()) {
1788 Builder.ClearInsertionPoint();
1798 SwitchInsn->addCase(CaseVal, CaseDest);
1814 const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt());
1817 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1819 llvm::ConstantInt *CaseVal =
1830 if (SwitchLikelihood)
1833 SwitchInsn->addCase(CaseVal, CaseDest);
1834 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1857 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1858 assert(DefaultBlock->empty() &&
1859 "EmitDefaultStmt: Default block already defined?");
1861 if (SwitchLikelihood)
1903 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
1917 if (!Case && isa<BreakStmt>(S))
1922 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
1926 bool StartedInLiveCode = FoundCase;
1927 unsigned StartSize = ResultStmts.size();
1934 bool HadSkippedDecl =
false;
1938 for (; Case && I !=
E; ++I) {
1954 for (++I; I !=
E; ++I)
1964 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
1979 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
1984 bool AnyDecls =
false;
1985 for (; I !=
E; ++I) {
1998 for (++I; I !=
E; ++I)
2015 ResultStmts.resize(StartSize);
2016 ResultStmts.push_back(S);
2040 ResultStmts.push_back(S);
2049 const llvm::APSInt &ConstantCondValue,
2055 const SwitchCase *Case = S.getSwitchCaseList();
2061 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2067 const CaseStmt *CS = cast<CaseStmt>(Case);
2069 if (CS->
getRHS())
return false;
2094 bool FoundCase =
false;
2101static std::optional<SmallVector<uint64_t, 16>>
2104 if (Likelihoods.size() <= 1)
2105 return std::nullopt;
2107 uint64_t NumUnlikely = 0;
2108 uint64_t NumNone = 0;
2109 uint64_t NumLikely = 0;
2110 for (
const auto LH : Likelihoods) {
2125 if (NumUnlikely == 0 && NumLikely == 0)
2126 return std::nullopt;
2134 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2135 const uint64_t
None = Likely / (NumNone + 1);
2136 const uint64_t Unlikely = 0;
2139 Result.reserve(Likelihoods.size());
2140 for (
const auto LH : Likelihoods) {
2143 Result.push_back(Unlikely);
2149 Result.push_back(Likely);
2159 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2162 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2166 llvm::APSInt ConstantCondValue;
2174 RunCleanupsScope ExecutedScope(*
this);
2181 if (S.getConditionVariable())
2182 EmitDecl(*S.getConditionVariable());
2187 SwitchInsn =
nullptr;
2191 for (
unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
2197 SwitchInsn = SavedSwitchInsn;
2205 RunCleanupsScope ConditionScope(*
this);
2210 if (S.getConditionVariable())
2211 EmitDecl(*S.getConditionVariable());
2219 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2223 unsigned NumCases = 0;
2224 for (
const SwitchCase *Case = S.getSwitchCaseList();
2227 if (isa<DefaultStmt>(Case))
2232 SwitchWeights->reserve(NumCases);
2235 SwitchWeights->push_back(DefaultCount);
2242 CaseRangeBlock = DefaultBlock;
2245 Builder.ClearInsertionPoint();
2249 JumpDest OuterContinue;
2250 if (!BreakContinueStack.empty())
2251 OuterContinue = BreakContinueStack.back().ContinueBlock;
2253 BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue));
2258 BreakContinueStack.pop_back();
2262 SwitchInsn->setDefaultDest(CaseRangeBlock);
2265 if (!DefaultBlock->getParent()) {
2268 if (ConditionScope.requiresCleanups()) {
2273 DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock());
2274 delete DefaultBlock;
2278 ConditionScope.ForceCleanup();
2287 auto *
Call = dyn_cast<CallExpr>(S.getCond());
2289 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2290 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2292 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2293 MDHelper.createUnpredictable());
2297 if (SwitchWeights) {
2298 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2299 "switch weights do not match switch cases");
2301 if (SwitchWeights->size() > 1)
2302 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2303 createProfileWeights(*SwitchWeights));
2304 delete SwitchWeights;
2305 }
else if (SwitchLikelihood) {
2306 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2307 "switch likelihoods do not match switch cases");
2308 std::optional<SmallVector<uint64_t, 16>> LHW =
2312 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2313 createProfileWeights(*LHW));
2315 delete SwitchLikelihood;
2317 SwitchInsn = SavedSwitchInsn;
2318 SwitchWeights = SavedSwitchWeights;
2319 SwitchLikelihood = SavedSwitchLikelihood;
2320 CaseRangeBlock = SavedCRBlock;
2328 while (*Constraint) {
2329 switch (*Constraint) {
2341 while (Constraint[1] && Constraint[1] !=
',')
2347 while (Constraint[1] && Constraint[1] == *Constraint)
2358 "Must pass output names to constraints with a symbolic name");
2360 bool result =
Target.resolveSymbolicName(Constraint, *OutCons, Index);
2361 assert(result &&
"Could not resolve symbolic name"); (void)result;
2362 Result += llvm::utostr(Index);
2380 std::string *GCCReg =
nullptr) {
2381 const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
2393 StringRef Register =
Attr->getLabel();
2394 assert(
Target.isValidGCCRegisterName(Register));
2398 if (
Target.validateOutputConstraint(Info) &&
2404 Register =
Target.getNormalizedGCCRegisterName(Register);
2405 if (GCCReg !=
nullptr)
2406 *GCCReg = Register.str();
2407 return (EarlyClobber ?
"&{" :
"{") + Register.str() +
"}";
2410std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2419 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2429 ConstraintStr +=
'*';
2433std::pair<llvm::Value *, llvm::Type *>
2435 const Expr *InputExpr,
2436 std::string &ConstraintStr) {
2444 llvm::APSInt IntResult;
2447 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2459 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2463 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2475 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2478 if (!StrVal.empty()) {
2481 unsigned StartToken = 0;
2482 unsigned ByteOffset = 0;
2486 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2487 if (StrVal[i] !=
'\n')
continue;
2489 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2490 Locs.push_back(llvm::ConstantAsMetadata::get(
2499 bool HasUnwindClobber,
bool ReadOnly,
2500 bool ReadNone,
bool NoMerge,
bool NoConvergent,
2502 const std::vector<llvm::Type *> &ResultRegTypes,
2503 const std::vector<llvm::Type *> &ArgElemTypes,
2505 std::vector<llvm::Value *> &RegResults) {
2506 if (!HasUnwindClobber)
2507 Result.addFnAttr(llvm::Attribute::NoUnwind);
2510 Result.addFnAttr(llvm::Attribute::NoMerge);
2512 if (!HasSideEffect) {
2514 Result.setDoesNotAccessMemory();
2516 Result.setOnlyReadsMemory();
2520 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
2522 auto Attr = llvm::Attribute::get(
2523 CGF.
getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2530 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S))
2531 Result.setMetadata(
"srcloc",
2535 llvm::Constant *
Loc =
2536 llvm::ConstantInt::get(CGF.
Int64Ty, S.getAsmLoc().getRawEncoding());
2537 Result.setMetadata(
"srcloc",
2539 llvm::ConstantAsMetadata::get(
Loc)));
2547 Result.addFnAttr(llvm::Attribute::Convergent);
2549 if (ResultRegTypes.size() == 1) {
2550 RegResults.push_back(&
Result);
2552 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2553 llvm::Value *Tmp = CGF.
Builder.CreateExtractValue(&
Result, i,
"asmresult");
2554 RegResults.push_back(Tmp);
2566 const llvm::BitVector &ResultTypeRequiresCast,
2567 const llvm::BitVector &ResultRegIsFlagReg) {
2572 assert(RegResults.size() == ResultRegTypes.size());
2573 assert(RegResults.size() == ResultTruncRegTypes.size());
2574 assert(RegResults.size() == ResultRegDests.size());
2577 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2578 assert(ResultRegIsFlagReg.size() <= ResultRegDests.size());
2580 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2581 llvm::Value *Tmp = RegResults[i];
2582 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2584 if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
2587 llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2);
2588 llvm::Value *IsBooleanValue =
2589 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two);
2591 Builder.CreateCall(FnAssume, IsBooleanValue);
2596 if (ResultRegTypes[i] != TruncTy) {
2600 if (TruncTy->isFloatingPointTy())
2601 Tmp =
Builder.CreateFPTrunc(Tmp, TruncTy);
2602 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2605 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
2606 Tmp =
Builder.CreateIntToPtr(Tmp, TruncTy);
2607 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2611 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
2612 Tmp =
Builder.CreateTrunc(Tmp, TruncTy);
2613 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2614 Tmp =
Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2615 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2616 Tmp =
Builder.CreateBitCast(Tmp, TruncTy);
2620 LValue Dest = ResultRegDests[i];
2623 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2634 const Expr *OutExpr = S.getOutputExpr(i);
2636 diag::err_store_value_to_reg);
2647 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2650 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2651 Asm = GCCAsm->getAsmString()->getString();
2655 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2656 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2657 {StrTy->getType()},
false);
2658 auto UBF = CGF->
CGM.
getModule().getOrInsertFunction(Name, FnTy);
2660 CGF->
Builder.CreateCall(UBF, {StrTy});
2665 CodeGenFunction::RunCleanupsScope Cleanups(*
this);
2668 std::string AsmString = S.generateAsmString(
getContext());
2675 bool IsValidTargetAsm =
true;
2676 for (
unsigned i = 0, e = S.getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2678 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2679 Name = GAS->getOutputName(i);
2682 if (IsHipStdPar && !IsValid)
2683 IsValidTargetAsm =
false;
2685 assert(IsValid &&
"Failed to parse output constraint");
2686 OutputConstraintInfos.push_back(Info);
2689 for (
unsigned i = 0, e = S.getNumInputs(); i != e && IsValidTargetAsm; i++) {
2691 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2692 Name = GAS->getInputName(i);
2696 if (IsHipStdPar && !IsValid)
2697 IsValidTargetAsm =
false;
2699 assert(IsValid &&
"Failed to parse input constraint");
2700 InputConstraintInfos.push_back(Info);
2703 if (!IsValidTargetAsm)
2706 std::string Constraints;
2708 std::vector<LValue> ResultRegDests;
2709 std::vector<QualType> ResultRegQualTys;
2710 std::vector<llvm::Type *> ResultRegTypes;
2711 std::vector<llvm::Type *> ResultTruncRegTypes;
2712 std::vector<llvm::Type *> ArgTypes;
2713 std::vector<llvm::Type *> ArgElemTypes;
2714 std::vector<llvm::Value*> Args;
2715 llvm::BitVector ResultTypeRequiresCast;
2716 llvm::BitVector ResultRegIsFlagReg;
2719 std::string InOutConstraints;
2720 std::vector<llvm::Value*> InOutArgs;
2721 std::vector<llvm::Type*> InOutArgTypes;
2722 std::vector<llvm::Type*> InOutArgElemTypes;
2725 std::vector<std::string> OutputConstraints;
2728 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2736 bool ReadOnly =
true, ReadNone =
true;
2738 for (
unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
2742 std::string OutputConstraint(S.getOutputConstraint(i));
2746 const Expr *OutExpr = S.getOutputExpr(i);
2755 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2756 CGM.
Error(S.getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2758 OutputConstraints.push_back(OutputConstraint);
2760 if (!Constraints.empty())
2770 Constraints +=
"=" + OutputConstraint;
2771 ResultRegQualTys.push_back(QTy);
2772 ResultRegDests.push_back(Dest);
2774 bool IsFlagReg = llvm::StringRef(OutputConstraint).starts_with(
"{@cc");
2775 ResultRegIsFlagReg.push_back(IsFlagReg);
2780 Ty->isAggregateType());
2782 ResultTruncRegTypes.push_back(Ty);
2783 ResultTypeRequiresCast.push_back(RequiresCast);
2792 ResultRegTypes.push_back(Ty);
2798 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2803 assert(InputNo != S.getNumInputs() &&
"Didn't find matching input!");
2805 QualType InputTy = S.getInputExpr(InputNo)->getType();
2814 if (llvm::Type* AdjTy =
2816 ResultRegTypes.back()))
2817 ResultRegTypes.back() = AdjTy;
2820 diag::err_asm_invalid_type_in_input)
2821 << OutExpr->
getType() << OutputConstraint;
2825 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
2826 LargestVectorWidth =
2827 std::max((uint64_t)LargestVectorWidth,
2828 VT->getPrimitiveSizeInBits().getKnownMinValue());
2839 ArgTypes.push_back(DestAddr.
getType());
2842 Constraints +=
"=*";
2843 Constraints += OutputConstraint;
2844 ReadOnly = ReadNone =
false;
2848 InOutConstraints +=
',';
2850 const Expr *InputExpr = S.getOutputExpr(i);
2852 llvm::Type *ArgElemType;
2853 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
2854 Info, Dest, InputExpr->
getType(), InOutConstraints,
2857 if (llvm::Type* AdjTy =
2860 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2863 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2864 LargestVectorWidth =
2865 std::max((uint64_t)LargestVectorWidth,
2866 VT->getPrimitiveSizeInBits().getKnownMinValue());
2869 InOutConstraints += llvm::utostr(i);
2871 InOutConstraints += OutputConstraint;
2873 InOutArgTypes.push_back(Arg->getType());
2874 InOutArgElemTypes.push_back(ArgElemType);
2875 InOutArgs.push_back(Arg);
2881 if (isa<MSAsmStmt>(&S)) {
2887 *
this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
2888 ResultRegDests, AsmString, S.getNumOutputs());
2893 for (
unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
2894 const Expr *InputExpr = S.getInputExpr(i);
2901 if (!Constraints.empty())
2905 std::string InputConstraint(S.getInputConstraint(i));
2907 &OutputConstraintInfos);
2913 std::string ReplaceConstraint (InputConstraint);
2915 llvm::Type *ArgElemType;
2916 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
2925 QualType OutputType = S.getOutputExpr(Output)->getType();
2931 if (isa<llvm::PointerType>(Arg->getType()))
2934 if (isa<llvm::IntegerType>(OutputTy))
2935 Arg =
Builder.CreateZExt(Arg, OutputTy);
2936 else if (isa<llvm::PointerType>(OutputTy))
2938 else if (OutputTy->isFloatingPointTy())
2939 Arg =
Builder.CreateFPExt(Arg, OutputTy);
2942 ReplaceConstraint = OutputConstraints[Output];
2944 if (llvm::Type* AdjTy =
2947 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2950 << InputExpr->
getType() << InputConstraint;
2953 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2954 LargestVectorWidth =
2955 std::max((uint64_t)LargestVectorWidth,
2956 VT->getPrimitiveSizeInBits().getKnownMinValue());
2958 ArgTypes.push_back(Arg->getType());
2959 ArgElemTypes.push_back(ArgElemType);
2960 Args.push_back(Arg);
2961 Constraints += InputConstraint;
2965 for (
unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
2966 ArgTypes.push_back(InOutArgTypes[i]);
2967 ArgElemTypes.push_back(InOutArgElemTypes[i]);
2968 Args.push_back(InOutArgs[i]);
2970 Constraints += InOutConstraints;
2974 llvm::BasicBlock *Fallthrough =
nullptr;
2975 bool IsGCCAsmGoto =
false;
2976 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S)) {
2977 IsGCCAsmGoto = GS->isAsmGoto();
2979 for (
const auto *
E : GS->labels()) {
2981 Transfer.push_back(Dest.getBlock());
2982 if (!Constraints.empty())
2984 Constraints +=
"!i";
2990 bool HasUnwindClobber =
false;
2993 for (
unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
2994 StringRef Clobber = S.getClobber(i);
2996 if (Clobber ==
"memory")
2997 ReadOnly = ReadNone =
false;
2998 else if (Clobber ==
"unwind") {
2999 HasUnwindClobber =
true;
3001 }
else if (Clobber !=
"cc") {
3006 diag::warn_stack_clash_protection_inline_asm);
3010 if (isa<MSAsmStmt>(&S)) {
3011 if (Clobber ==
"eax" || Clobber ==
"edx") {
3012 if (Constraints.find(
"=&A") != std::string::npos)
3014 std::string::size_type position1 =
3015 Constraints.find(
"={" + Clobber.str() +
"}");
3016 if (position1 != std::string::npos) {
3017 Constraints.insert(position1 + 1,
"&");
3020 std::string::size_type position2 = Constraints.find(
"=A");
3021 if (position2 != std::string::npos) {
3022 Constraints.insert(position2 + 1,
"&");
3027 if (!Constraints.empty())
3030 Constraints +=
"~{";
3031 Constraints += Clobber;
3035 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
3036 "unwind clobber can't be used with asm goto");
3040 if (!MachineClobbers.empty()) {
3041 if (!Constraints.empty())
3043 Constraints += MachineClobbers;
3046 llvm::Type *ResultType;
3047 if (ResultRegTypes.empty())
3049 else if (ResultRegTypes.size() == 1)
3050 ResultType = ResultRegTypes[0];
3052 ResultType = llvm::StructType::get(
getLLVMContext(), ResultRegTypes);
3054 llvm::FunctionType *FTy =
3055 llvm::FunctionType::get(ResultType, ArgTypes,
false);
3057 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
3059 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3061 ? llvm::InlineAsm::AD_ATT
3062 : llvm::InlineAsm::AD_Intel;
3063 llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ?
3064 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3066 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3067 FTy, AsmString, Constraints, HasSideEffect,
3068 false, AsmDialect, HasUnwindClobber);
3069 std::vector<llvm::Value*> RegResults;
3070 llvm::CallBrInst *CBR;
3071 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3074 CBR =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3079 ArgElemTypes, *
this, RegResults);
3083 if (!RegResults.empty()) {
3085 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3086 llvm::Twine SynthName = Dest->getName() +
".split";
3088 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3089 Builder.SetInsertPoint(SynthBB);
3091 if (ResultRegTypes.size() == 1) {
3092 CBRRegResults[SynthBB].push_back(CBR);
3094 for (
unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3095 llvm::Value *Tmp =
Builder.CreateExtractValue(CBR, j,
"asmresult");
3096 CBRRegResults[SynthBB].push_back(Tmp);
3102 CBR->setIndirectDest(i++, SynthBB);
3105 }
else if (HasUnwindClobber) {
3110 ArgElemTypes, *
this, RegResults);
3117 ArgElemTypes, *
this, RegResults);
3120 EmitAsmStores(*
this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3121 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3122 ResultRegIsFlagReg);
3127 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3128 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3129 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3130 Builder.SetInsertPoint(Succ, --(Succ->end()));
3131 EmitAsmStores(*
this, S, CBRRegResults[Succ], ResultRegTypes,
3132 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3133 ResultTypeRequiresCast, ResultRegIsFlagReg);
3139 const RecordDecl *RD = S.getCapturedRecordDecl();
3148 E = S.capture_init_end();
3149 I !=
E; ++I, ++CurField) {
3151 if (CurField->hasCapturedVLAType()) {
3169 CGCapturedStmtRAII CapInfoRAII(CGF,
new CGCapturedStmtInfo(S, K));
3170 llvm::Function *F = CGF.GenerateCapturedStmtFunction(S);
3171 delete CGF.CapturedStmtInfo;
3188 "CapturedStmtInfo should be set when generating the captured function");
3190 const RecordDecl *RD = S.getCapturedRecordDecl();
3192 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3205 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3209 F->addFnAttr(llvm::Attribute::NoUnwind);
3221 for (
auto *FD : RD->
fields()) {
3222 if (FD->hasCapturedVLAType()) {
3226 auto VAT = FD->getCapturedVLAType();
3227 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3248 for (
auto &I : *BB) {
3249 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3256CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3258 assert(ParentToken);
3260 llvm::Value *bundleArgs[] = {ParentToken};
3261 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3262 auto *Output = llvm::CallBase::addOperandBundle(
3263 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3264 Input->replaceAllUsesWith(Output);
3265 Input->eraseFromParent();
3269llvm::ConvergenceControlInst *
3270CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
3271 CGBuilderTy::InsertPoint IP =
Builder.saveIP();
3275 Builder.SetInsertPoint(BB->getFirstInsertionPt());
3277 llvm::CallBase *CB =
Builder.CreateIntrinsic(
3278 llvm::Intrinsic::experimental_convergence_loop, {}, {});
3281 CB = addConvergenceControlToken(CB);
3282 return cast<llvm::ConvergenceControlInst>(CB);
3285llvm::ConvergenceControlInst *
3286CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3287 llvm::BasicBlock *BB = &F->getEntryBlock();
3296 CGBuilderTy::InsertPoint IP =
Builder.saveIP();
3297 Builder.SetInsertPoint(&BB->front());
3298 llvm::CallBase *I =
Builder.CreateIntrinsic(
3299 llvm::Intrinsic::experimental_convergence_entry, {}, {});
3300 assert(isa<llvm::IntrinsicInst>(I));
3303 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)
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 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 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)
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="")
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 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)
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 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