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();
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));
1159 RunCleanupsScope BodyScope(*
this);
1176 BreakContinueStack.pop_back();
1180 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1181 bool EmitBoolCondBranch = !
C || !
C->isZero();
1190 if (EmitBoolCondBranch) {
1193 BoolCondVal, LoopBody,
LoopExit.getBlock(),
1194 createProfileWeightsForLoop(S.getCond(), BackedgeCount));
1204 if (!EmitBoolCondBranch)
1220 LexicalScope ForScope(*
this, S.getSourceRange());
1230 llvm::BasicBlock *CondBlock = CondDest.getBlock();
1244 LexicalScope ConditionScope(*
this, S.getSourceRange());
1255 Continue = CondDest;
1256 else if (!S.getConditionVariable())
1258 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1263 if (S.getConditionVariable()) {
1264 EmitDecl(*S.getConditionVariable());
1269 BreakContinueStack.back().ContinueBlock = Continue;
1277 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1280 if (ForScope.requiresCleanups())
1289 llvm::MDNode *Weights =
1290 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1292 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1295 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1297 if (ExitBlock !=
LoopExit.getBlock()) {
1316 RunCleanupsScope BodyScope(*
this);
1328 BreakContinueStack.pop_back();
1330 ConditionScope.ForceCleanup();
1335 ForScope.ForceCleanup();
1356 LexicalScope ForScope(*
this, S.getSourceRange());
1382 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1383 if (ForScope.requiresCleanups())
1392 llvm::MDNode *Weights =
1393 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1395 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1397 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1399 if (ExitBlock !=
LoopExit.getBlock()) {
1414 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1418 LexicalScope BodyScope(*
this, S.getSourceRange());
1428 BreakContinueStack.pop_back();
1432 ForScope.ForceCleanup();
1448void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1464struct SaveRetExprRAII {
1466 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1469 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1470 const Expr *OldRetExpr;
1479 if (calleeQualType->isFunctionPointerType() ||
1480 calleeQualType->isFunctionReferenceType() ||
1481 calleeQualType->isBlockPointerType() ||
1482 calleeQualType->isMemberFunctionPointerType()) {
1484 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1486 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1487 if (
auto methodDecl = CMCE->getMethodDecl()) {
1503 if (requiresReturnValueCheck()) {
1506 new llvm::GlobalVariable(
CGM.
getModule(), SLoc->getType(),
false,
1507 llvm::GlobalVariable::PrivateLinkage, SLoc);
1508 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1510 assert(ReturnLocation.
isValid() &&
"No valid return location");
1517 Builder.ClearInsertionPoint();
1521 const Expr *RV = S.getRetValue();
1531 SaveRetExprRAII SaveRetExpr(RV, *
this);
1533 RunCleanupsScope cleanupScope(*
this);
1534 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1535 RV = EWC->getSubExpr();
1539 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1542 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1552 if (
getLangOpts().ElideConstructors && S.getNRVOCandidate() &&
1553 S.getNRVOCandidate()->isNRVOVariable() &&
1564 if (llvm::Value *NRVOFlag =
NRVOFlags[S.getNRVOCandidate()])
1607 ++NumSimpleReturnExprs;
1609 cleanupScope.ForceCleanup();
1619 for (
const auto *I : S.decls())
1624 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1636 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1652 assert(S.getRHS() &&
"Expected RHS value in CaseStmt");
1654 llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(
getContext());
1655 llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(
getContext());
1665 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1669 llvm::APInt
Range = RHS - LHS;
1671 if (
Range.ult(llvm::APInt(
Range.getBitWidth(), 64))) {
1674 unsigned NCases =
Range.getZExtValue() + 1;
1679 uint64_t Weight = Total / NCases,
Rem = Total % NCases;
1680 for (
unsigned I = 0; I != NCases; ++I) {
1682 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1683 else if (SwitchLikelihood)
1684 SwitchLikelihood->push_back(LH);
1688 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1696 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1701 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1705 Builder.SetInsertPoint(CaseRangeBlock);
1709 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1713 llvm::MDNode *Weights =
nullptr;
1714 if (SwitchWeights) {
1716 uint64_t DefaultCount = (*SwitchWeights)[0];
1717 Weights = createProfileWeights(ThisCount, DefaultCount);
1722 (*SwitchWeights)[0] += ThisCount;
1723 }
else if (SwitchLikelihood)
1724 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
1726 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
1730 Builder.SetInsertPoint(RestoreBB);
1732 Builder.ClearInsertionPoint();
1753 llvm::ConstantInt *CaseVal =
1758 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.getLHS()))
1759 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1761 CE = dyn_cast<ConstantExpr>(S.getLHS());
1763 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1766 Dbg->EmitGlobalVariable(DE->getDecl(),
1767 APValue(llvm::APSInt(CaseVal->getValue())));
1770 if (SwitchLikelihood)
1778 isa<BreakStmt>(S.getSubStmt())) {
1779 JumpDest
Block = BreakContinueStack.back().BreakBlock;
1785 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1789 if (
Builder.GetInsertBlock()) {
1791 Builder.ClearInsertionPoint();
1801 SwitchInsn->addCase(CaseVal, CaseDest);
1817 const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt());
1820 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1822 llvm::ConstantInt *CaseVal =
1833 if (SwitchLikelihood)
1836 SwitchInsn->addCase(CaseVal, CaseDest);
1837 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1860 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1861 assert(DefaultBlock->empty() &&
1862 "EmitDefaultStmt: Default block already defined?");
1864 if (SwitchLikelihood)
1906 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
1920 if (!Case && isa<BreakStmt>(S))
1925 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
1929 bool StartedInLiveCode = FoundCase;
1930 unsigned StartSize = ResultStmts.size();
1937 bool HadSkippedDecl =
false;
1941 for (; Case && I !=
E; ++I) {
1957 for (++I; I !=
E; ++I)
1967 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
1982 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
1987 bool AnyDecls =
false;
1988 for (; I !=
E; ++I) {
2001 for (++I; I !=
E; ++I)
2018 ResultStmts.resize(StartSize);
2019 ResultStmts.push_back(S);
2043 ResultStmts.push_back(S);
2052 const llvm::APSInt &ConstantCondValue,
2058 const SwitchCase *Case = S.getSwitchCaseList();
2064 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2070 const CaseStmt *CS = cast<CaseStmt>(Case);
2072 if (CS->
getRHS())
return false;
2097 bool FoundCase =
false;
2104static std::optional<SmallVector<uint64_t, 16>>
2107 if (Likelihoods.size() <= 1)
2108 return std::nullopt;
2110 uint64_t NumUnlikely = 0;
2111 uint64_t NumNone = 0;
2112 uint64_t NumLikely = 0;
2113 for (
const auto LH : Likelihoods) {
2128 if (NumUnlikely == 0 && NumLikely == 0)
2129 return std::nullopt;
2137 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2138 const uint64_t
None = Likely / (NumNone + 1);
2139 const uint64_t Unlikely = 0;
2142 Result.reserve(Likelihoods.size());
2143 for (
const auto LH : Likelihoods) {
2146 Result.push_back(Unlikely);
2152 Result.push_back(Likely);
2162 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2165 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2169 llvm::APSInt ConstantCondValue;
2177 RunCleanupsScope ExecutedScope(*
this);
2184 if (S.getConditionVariable())
2185 EmitDecl(*S.getConditionVariable());
2190 SwitchInsn =
nullptr;
2194 for (
unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
2200 SwitchInsn = SavedSwitchInsn;
2208 RunCleanupsScope ConditionScope(*
this);
2213 if (S.getConditionVariable())
2214 EmitDecl(*S.getConditionVariable());
2222 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2226 unsigned NumCases = 0;
2227 for (
const SwitchCase *Case = S.getSwitchCaseList();
2230 if (isa<DefaultStmt>(Case))
2235 SwitchWeights->reserve(NumCases);
2238 SwitchWeights->push_back(DefaultCount);
2245 CaseRangeBlock = DefaultBlock;
2248 Builder.ClearInsertionPoint();
2252 JumpDest OuterContinue;
2253 if (!BreakContinueStack.empty())
2254 OuterContinue = BreakContinueStack.back().ContinueBlock;
2256 BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue));
2261 BreakContinueStack.pop_back();
2265 SwitchInsn->setDefaultDest(CaseRangeBlock);
2268 if (!DefaultBlock->getParent()) {
2271 if (ConditionScope.requiresCleanups()) {
2276 DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock());
2277 delete DefaultBlock;
2281 ConditionScope.ForceCleanup();
2290 auto *
Call = dyn_cast<CallExpr>(S.getCond());
2292 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2293 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2295 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2296 MDHelper.createUnpredictable());
2300 if (SwitchWeights) {
2301 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2302 "switch weights do not match switch cases");
2304 if (SwitchWeights->size() > 1)
2305 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2306 createProfileWeights(*SwitchWeights));
2307 delete SwitchWeights;
2308 }
else if (SwitchLikelihood) {
2309 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2310 "switch likelihoods do not match switch cases");
2311 std::optional<SmallVector<uint64_t, 16>> LHW =
2315 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2316 createProfileWeights(*LHW));
2318 delete SwitchLikelihood;
2320 SwitchInsn = SavedSwitchInsn;
2321 SwitchWeights = SavedSwitchWeights;
2322 SwitchLikelihood = SavedSwitchLikelihood;
2323 CaseRangeBlock = SavedCRBlock;
2331 while (*Constraint) {
2332 switch (*Constraint) {
2344 while (Constraint[1] && Constraint[1] !=
',')
2350 while (Constraint[1] && Constraint[1] == *Constraint)
2361 "Must pass output names to constraints with a symbolic name");
2363 bool result =
Target.resolveSymbolicName(Constraint, *OutCons, Index);
2364 assert(result &&
"Could not resolve symbolic name"); (void)result;
2365 Result += llvm::utostr(Index);
2383 std::string *GCCReg =
nullptr) {
2384 const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
2396 StringRef Register =
Attr->getLabel();
2397 assert(
Target.isValidGCCRegisterName(Register));
2401 if (
Target.validateOutputConstraint(Info) &&
2407 Register =
Target.getNormalizedGCCRegisterName(Register);
2408 if (GCCReg !=
nullptr)
2409 *GCCReg = Register.str();
2410 return (EarlyClobber ?
"&{" :
"{") + Register.str() +
"}";
2413std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2422 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2432 ConstraintStr +=
'*';
2436std::pair<llvm::Value *, llvm::Type *>
2438 const Expr *InputExpr,
2439 std::string &ConstraintStr) {
2447 llvm::APSInt IntResult;
2450 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2462 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2466 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2478 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2481 if (!StrVal.empty()) {
2484 unsigned StartToken = 0;
2485 unsigned ByteOffset = 0;
2489 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2490 if (StrVal[i] !=
'\n')
continue;
2492 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2493 Locs.push_back(llvm::ConstantAsMetadata::get(
2502 bool HasUnwindClobber,
bool ReadOnly,
2503 bool ReadNone,
bool NoMerge,
bool NoConvergent,
2505 const std::vector<llvm::Type *> &ResultRegTypes,
2506 const std::vector<llvm::Type *> &ArgElemTypes,
2508 std::vector<llvm::Value *> &RegResults) {
2509 if (!HasUnwindClobber)
2510 Result.addFnAttr(llvm::Attribute::NoUnwind);
2513 Result.addFnAttr(llvm::Attribute::NoMerge);
2515 if (!HasSideEffect) {
2517 Result.setDoesNotAccessMemory();
2519 Result.setOnlyReadsMemory();
2523 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
2525 auto Attr = llvm::Attribute::get(
2526 CGF.
getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2533 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S))
2534 Result.setMetadata(
"srcloc",
2538 llvm::Constant *
Loc =
2539 llvm::ConstantInt::get(CGF.
Int64Ty, S.getAsmLoc().getRawEncoding());
2540 Result.setMetadata(
"srcloc",
2542 llvm::ConstantAsMetadata::get(
Loc)));
2550 Result.addFnAttr(llvm::Attribute::Convergent);
2552 if (ResultRegTypes.size() == 1) {
2553 RegResults.push_back(&
Result);
2555 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2556 llvm::Value *Tmp = CGF.
Builder.CreateExtractValue(&
Result, i,
"asmresult");
2557 RegResults.push_back(Tmp);
2569 const llvm::BitVector &ResultTypeRequiresCast,
2570 const llvm::BitVector &ResultRegIsFlagReg) {
2575 assert(RegResults.size() == ResultRegTypes.size());
2576 assert(RegResults.size() == ResultTruncRegTypes.size());
2577 assert(RegResults.size() == ResultRegDests.size());
2580 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2581 assert(ResultRegIsFlagReg.size() <= ResultRegDests.size());
2583 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2584 llvm::Value *Tmp = RegResults[i];
2585 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2587 if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
2590 llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2);
2591 llvm::Value *IsBooleanValue =
2592 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two);
2594 Builder.CreateCall(FnAssume, IsBooleanValue);
2599 if (ResultRegTypes[i] != TruncTy) {
2603 if (TruncTy->isFloatingPointTy())
2604 Tmp =
Builder.CreateFPTrunc(Tmp, TruncTy);
2605 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2608 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
2609 Tmp =
Builder.CreateIntToPtr(Tmp, TruncTy);
2610 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2614 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
2615 Tmp =
Builder.CreateTrunc(Tmp, TruncTy);
2616 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2617 Tmp =
Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2618 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2619 Tmp =
Builder.CreateBitCast(Tmp, TruncTy);
2623 LValue Dest = ResultRegDests[i];
2626 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2637 const Expr *OutExpr = S.getOutputExpr(i);
2639 diag::err_store_value_to_reg);
2650 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2653 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2654 Asm = GCCAsm->getAsmString()->getString();
2658 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2659 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2660 {StrTy->getType()},
false);
2661 auto UBF = CGF->
CGM.
getModule().getOrInsertFunction(Name, FnTy);
2663 CGF->
Builder.CreateCall(UBF, {StrTy});
2668 CodeGenFunction::RunCleanupsScope Cleanups(*
this);
2671 std::string AsmString = S.generateAsmString(
getContext());
2678 bool IsValidTargetAsm =
true;
2679 for (
unsigned i = 0, e = S.getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2681 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2682 Name = GAS->getOutputName(i);
2685 if (IsHipStdPar && !IsValid)
2686 IsValidTargetAsm =
false;
2688 assert(IsValid &&
"Failed to parse output constraint");
2689 OutputConstraintInfos.push_back(Info);
2692 for (
unsigned i = 0, e = S.getNumInputs(); i != e && IsValidTargetAsm; i++) {
2694 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2695 Name = GAS->getInputName(i);
2699 if (IsHipStdPar && !IsValid)
2700 IsValidTargetAsm =
false;
2702 assert(IsValid &&
"Failed to parse input constraint");
2703 InputConstraintInfos.push_back(Info);
2706 if (!IsValidTargetAsm)
2709 std::string Constraints;
2711 std::vector<LValue> ResultRegDests;
2712 std::vector<QualType> ResultRegQualTys;
2713 std::vector<llvm::Type *> ResultRegTypes;
2714 std::vector<llvm::Type *> ResultTruncRegTypes;
2715 std::vector<llvm::Type *> ArgTypes;
2716 std::vector<llvm::Type *> ArgElemTypes;
2717 std::vector<llvm::Value*> Args;
2718 llvm::BitVector ResultTypeRequiresCast;
2719 llvm::BitVector ResultRegIsFlagReg;
2722 std::string InOutConstraints;
2723 std::vector<llvm::Value*> InOutArgs;
2724 std::vector<llvm::Type*> InOutArgTypes;
2725 std::vector<llvm::Type*> InOutArgElemTypes;
2728 std::vector<std::string> OutputConstraints;
2731 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2739 bool ReadOnly =
true, ReadNone =
true;
2741 for (
unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
2745 std::string OutputConstraint(S.getOutputConstraint(i));
2749 const Expr *OutExpr = S.getOutputExpr(i);
2758 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2759 CGM.
Error(S.getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2761 OutputConstraints.push_back(OutputConstraint);
2763 if (!Constraints.empty())
2773 Constraints +=
"=" + OutputConstraint;
2774 ResultRegQualTys.push_back(QTy);
2775 ResultRegDests.push_back(Dest);
2777 bool IsFlagReg = llvm::StringRef(OutputConstraint).starts_with(
"{@cc");
2778 ResultRegIsFlagReg.push_back(IsFlagReg);
2783 Ty->isAggregateType());
2785 ResultTruncRegTypes.push_back(Ty);
2786 ResultTypeRequiresCast.push_back(RequiresCast);
2795 ResultRegTypes.push_back(Ty);
2801 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2806 assert(InputNo != S.getNumInputs() &&
"Didn't find matching input!");
2808 QualType InputTy = S.getInputExpr(InputNo)->getType();
2817 if (llvm::Type* AdjTy =
2819 ResultRegTypes.back()))
2820 ResultRegTypes.back() = AdjTy;
2823 diag::err_asm_invalid_type_in_input)
2824 << OutExpr->
getType() << OutputConstraint;
2828 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
2829 LargestVectorWidth =
2830 std::max((uint64_t)LargestVectorWidth,
2831 VT->getPrimitiveSizeInBits().getKnownMinValue());
2842 ArgTypes.push_back(DestAddr.
getType());
2845 Constraints +=
"=*";
2846 Constraints += OutputConstraint;
2847 ReadOnly = ReadNone =
false;
2851 InOutConstraints +=
',';
2853 const Expr *InputExpr = S.getOutputExpr(i);
2855 llvm::Type *ArgElemType;
2856 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
2857 Info, Dest, InputExpr->
getType(), InOutConstraints,
2860 if (llvm::Type* AdjTy =
2863 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2866 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2867 LargestVectorWidth =
2868 std::max((uint64_t)LargestVectorWidth,
2869 VT->getPrimitiveSizeInBits().getKnownMinValue());
2872 InOutConstraints += llvm::utostr(i);
2874 InOutConstraints += OutputConstraint;
2876 InOutArgTypes.push_back(Arg->getType());
2877 InOutArgElemTypes.push_back(ArgElemType);
2878 InOutArgs.push_back(Arg);
2884 if (isa<MSAsmStmt>(&S)) {
2890 *
this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
2891 ResultRegDests, AsmString, S.getNumOutputs());
2896 for (
unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
2897 const Expr *InputExpr = S.getInputExpr(i);
2904 if (!Constraints.empty())
2908 std::string InputConstraint(S.getInputConstraint(i));
2910 &OutputConstraintInfos);
2916 std::string ReplaceConstraint (InputConstraint);
2918 llvm::Type *ArgElemType;
2919 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
2928 QualType OutputType = S.getOutputExpr(Output)->getType();
2934 if (isa<llvm::PointerType>(Arg->getType()))
2937 if (isa<llvm::IntegerType>(OutputTy))
2938 Arg =
Builder.CreateZExt(Arg, OutputTy);
2939 else if (isa<llvm::PointerType>(OutputTy))
2941 else if (OutputTy->isFloatingPointTy())
2942 Arg =
Builder.CreateFPExt(Arg, OutputTy);
2945 ReplaceConstraint = OutputConstraints[Output];
2947 if (llvm::Type* AdjTy =
2950 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2953 << InputExpr->
getType() << InputConstraint;
2956 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2957 LargestVectorWidth =
2958 std::max((uint64_t)LargestVectorWidth,
2959 VT->getPrimitiveSizeInBits().getKnownMinValue());
2961 ArgTypes.push_back(Arg->getType());
2962 ArgElemTypes.push_back(ArgElemType);
2963 Args.push_back(Arg);
2964 Constraints += InputConstraint;
2968 for (
unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
2969 ArgTypes.push_back(InOutArgTypes[i]);
2970 ArgElemTypes.push_back(InOutArgElemTypes[i]);
2971 Args.push_back(InOutArgs[i]);
2973 Constraints += InOutConstraints;
2977 llvm::BasicBlock *Fallthrough =
nullptr;
2978 bool IsGCCAsmGoto =
false;
2979 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S)) {
2980 IsGCCAsmGoto = GS->isAsmGoto();
2982 for (
const auto *
E : GS->labels()) {
2984 Transfer.push_back(Dest.getBlock());
2985 if (!Constraints.empty())
2987 Constraints +=
"!i";
2993 bool HasUnwindClobber =
false;
2996 for (
unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
2997 StringRef Clobber = S.getClobber(i);
2999 if (Clobber ==
"memory")
3000 ReadOnly = ReadNone =
false;
3001 else if (Clobber ==
"unwind") {
3002 HasUnwindClobber =
true;
3004 }
else if (Clobber !=
"cc") {
3009 diag::warn_stack_clash_protection_inline_asm);
3013 if (isa<MSAsmStmt>(&S)) {
3014 if (Clobber ==
"eax" || Clobber ==
"edx") {
3015 if (Constraints.find(
"=&A") != std::string::npos)
3017 std::string::size_type position1 =
3018 Constraints.find(
"={" + Clobber.str() +
"}");
3019 if (position1 != std::string::npos) {
3020 Constraints.insert(position1 + 1,
"&");
3023 std::string::size_type position2 = Constraints.find(
"=A");
3024 if (position2 != std::string::npos) {
3025 Constraints.insert(position2 + 1,
"&");
3030 if (!Constraints.empty())
3033 Constraints +=
"~{";
3034 Constraints += Clobber;
3038 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
3039 "unwind clobber can't be used with asm goto");
3043 if (!MachineClobbers.empty()) {
3044 if (!Constraints.empty())
3046 Constraints += MachineClobbers;
3049 llvm::Type *ResultType;
3050 if (ResultRegTypes.empty())
3052 else if (ResultRegTypes.size() == 1)
3053 ResultType = ResultRegTypes[0];
3055 ResultType = llvm::StructType::get(
getLLVMContext(), ResultRegTypes);
3057 llvm::FunctionType *FTy =
3058 llvm::FunctionType::get(ResultType, ArgTypes,
false);
3060 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
3062 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3064 ? llvm::InlineAsm::AD_ATT
3065 : llvm::InlineAsm::AD_Intel;
3066 llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ?
3067 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3069 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3070 FTy, AsmString, Constraints, HasSideEffect,
3071 false, AsmDialect, HasUnwindClobber);
3072 std::vector<llvm::Value*> RegResults;
3073 llvm::CallBrInst *CBR;
3074 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3077 CBR =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3082 ArgElemTypes, *
this, RegResults);
3086 if (!RegResults.empty()) {
3088 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3089 llvm::Twine SynthName = Dest->getName() +
".split";
3091 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3092 Builder.SetInsertPoint(SynthBB);
3094 if (ResultRegTypes.size() == 1) {
3095 CBRRegResults[SynthBB].push_back(CBR);
3097 for (
unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3098 llvm::Value *Tmp =
Builder.CreateExtractValue(CBR, j,
"asmresult");
3099 CBRRegResults[SynthBB].push_back(Tmp);
3105 CBR->setIndirectDest(i++, SynthBB);
3108 }
else if (HasUnwindClobber) {
3113 ArgElemTypes, *
this, RegResults);
3120 ArgElemTypes, *
this, RegResults);
3123 EmitAsmStores(*
this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3124 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3125 ResultRegIsFlagReg);
3130 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3131 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3132 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3133 Builder.SetInsertPoint(Succ, --(Succ->end()));
3134 EmitAsmStores(*
this, S, CBRRegResults[Succ], ResultRegTypes,
3135 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3136 ResultTypeRequiresCast, ResultRegIsFlagReg);
3142 const RecordDecl *RD = S.getCapturedRecordDecl();
3151 E = S.capture_init_end();
3152 I !=
E; ++I, ++CurField) {
3154 if (CurField->hasCapturedVLAType()) {
3172 CGCapturedStmtRAII CapInfoRAII(CGF,
new CGCapturedStmtInfo(S, K));
3173 llvm::Function *F = CGF.GenerateCapturedStmtFunction(S);
3174 delete CGF.CapturedStmtInfo;
3191 "CapturedStmtInfo should be set when generating the captured function");
3193 const RecordDecl *RD = S.getCapturedRecordDecl();
3195 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3208 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3212 F->addFnAttr(llvm::Attribute::NoUnwind);
3224 for (
auto *FD : RD->
fields()) {
3225 if (FD->hasCapturedVLAType()) {
3229 auto VAT = FD->getCapturedVLAType();
3230 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3251llvm::IntrinsicInst *getConvergenceToken(llvm::BasicBlock *BB) {
3252 for (
auto &I : *BB) {
3253 auto *II = dyn_cast<llvm::IntrinsicInst>(&I);
3254 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID()))
3263CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input,
3264 llvm::Value *ParentToken) {
3265 llvm::Value *bundleArgs[] = {ParentToken};
3266 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3267 auto Output = llvm::CallBase::addOperandBundle(
3268 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3269 Input->replaceAllUsesWith(Output);
3270 Input->eraseFromParent();
3274llvm::IntrinsicInst *
3275CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB,
3276 llvm::Value *ParentToken) {
3277 CGBuilderTy::InsertPoint IP =
Builder.saveIP();
3281 Builder.SetInsertPoint(BB->getFirstInsertionPt());
3283 llvm::CallBase *CB =
Builder.CreateIntrinsic(
3284 llvm::Intrinsic::experimental_convergence_loop, {}, {});
3287 llvm::CallBase *I = addConvergenceControlToken(CB, ParentToken);
3288 return cast<llvm::IntrinsicInst>(I);
3291llvm::IntrinsicInst *
3292CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3293 llvm::BasicBlock *BB = &F->getEntryBlock();
3294 llvm::IntrinsicInst *
Token = getConvergenceToken(BB);
3302 CGBuilderTy::InsertPoint IP =
Builder.saveIP();
3303 Builder.SetInsertPoint(&BB->front());
3304 llvm::CallBase *I =
Builder.CreateIntrinsic(
3305 llvm::Intrinsic::experimental_convergence_entry, {}, {});
3306 assert(isa<llvm::IntrinsicInst>(I));
3309 return cast<llvm::IntrinsicInst>(I);
Defines enum values for all the target-independent builtin functions.
static std::string AddVariableConstraints(const std::string &Constraint, const Expr &AsmExpr, const TargetInfo &Target, CodeGenModule &CGM, const AsmStmt &Stmt, const bool EarlyClobber, std::string *GCCReg=nullptr)
AddVariableConstraints - Look at AsmExpr and if it is a variable declared as using a particular regis...
static bool FindCaseStatementsForValue(const SwitchStmt &S, const llvm::APSInt &ConstantCondValue, SmallVectorImpl< const Stmt * > &ResultStmts, ASTContext &C, const SwitchCase *&ResultCase)
FindCaseStatementsForValue - Find the case statement being jumped to and then invoke CollectStatement...
static void EmitHipStdParUnsupportedAsm(CodeGenFunction *CGF, const AsmStmt &S)
static std::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)
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)
SmallVector< llvm::IntrinsicInst *, 4 > ConvergenceTokenStack
Stack to track the controlled convergence tokens.
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