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:
482 case Stmt::OpenACCSetConstructClass:
490 switch (S->getStmtClass()) {
493 case Stmt::NullStmtClass:
495 case Stmt::CompoundStmtClass:
498 case Stmt::DeclStmtClass:
501 case Stmt::LabelStmtClass:
504 case Stmt::AttributedStmtClass:
507 case Stmt::GotoStmtClass:
510 case Stmt::BreakStmtClass:
513 case Stmt::ContinueStmtClass:
516 case Stmt::DefaultStmtClass:
519 case Stmt::CaseStmtClass:
522 case Stmt::SEHLeaveStmtClass:
535 "LLVM IR generation of compound statement ('{}')");
538 LexicalScope
Scope(*
this, S.getSourceRange());
549 assert((!GetLast || (GetLast &&
ExprResult)) &&
550 "If GetLast is true then the CompoundStmt must have a StmtExprResult");
554 for (
auto *CurStmt : S.body()) {
562 if (
const auto *LS = dyn_cast<LabelStmt>(
ExprResult)) {
565 }
else if (
const auto *AS = dyn_cast<AttributedStmt>(
ExprResult)) {
570 llvm_unreachable(
"unknown value statement");
597 llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
606 if (!BI || !BI->isUnconditional())
610 if (BI->getIterator() != BB->begin())
613 BB->replaceAllUsesWith(BI->getSuccessor(0));
614 BI->eraseFromParent();
615 BB->eraseFromParent();
619 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
624 if (IsFinished && BB->use_empty()) {
631 if (CurBB && CurBB->getParent())
632 CurFn->insert(std::next(CurBB->getIterator()), BB);
642 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
644 if (!CurBB || CurBB->getTerminator()) {
656 bool inserted =
false;
657 for (llvm::User *u : block->users()) {
658 if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
659 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
671CodeGenFunction::JumpDest
673 JumpDest &Dest = LabelMap[
D];
674 if (Dest.isValid())
return Dest;
690 JumpDest &Dest = LabelMap[
D];
694 if (!Dest.isValid()) {
700 assert(!Dest.getScopeDepth().isValid() &&
"already emitted label!");
721 assert(!Labels.empty());
727 i = Labels.begin(), e = Labels.end(); i != e; ++i) {
728 assert(
CGF.LabelMap.count(*i));
737 ParentScope->Labels.append(Labels.begin(), Labels.end());
753 bool nomerge =
false;
754 bool noinline =
false;
755 bool alwaysinline =
false;
756 bool noconvergent =
false;
757 HLSLControlFlowHintAttr::Spelling flattenOrBranch =
758 HLSLControlFlowHintAttr::SpellingNotCalculated;
761 for (
const auto *A : S.getAttrs()) {
762 switch (A->getKind()) {
771 case attr::AlwaysInline:
774 case attr::NoConvergent:
777 case attr::MustTail: {
778 const Stmt *Sub = S.getSubStmt();
782 case attr::CXXAssume: {
783 const Expr *Assumption = cast<CXXAssumeAttr>(A)->getAssumption();
787 Builder.CreateAssumption(AssumptionVal);
790 case attr::HLSLControlFlowHint: {
791 flattenOrBranch = cast<HLSLControlFlowHintAttr>(A)->getSemanticSpelling();
801 EmitStmt(S.getSubStmt(), S.getAttrs());
824 llvm::BasicBlock *CurBB =
Builder.GetInsertBlock();
831 cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(
V, CurBB);
837 const Stmt *Else = S.getElse();
841 if (S.isConsteval()) {
842 const Stmt *Executed = S.isNegatedConsteval() ? S.getThen() : Else;
844 RunCleanupsScope ExecutedScope(*
this);
852 LexicalScope ConditionScope(*
this, S.getCond()->getSourceRange());
858 if (S.getConditionVariable())
859 EmitDecl(*S.getConditionVariable());
867 const Stmt *Executed = S.getThen();
868 const Stmt *Skipped = Else;
870 std::swap(Executed, Skipped);
878 RunCleanupsScope ExecutedScope(*
this);
889 llvm::BasicBlock *ElseBlock = ContBlock;
920 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
930 RunCleanupsScope ThenScope(*
this);
946 RunCleanupsScope ElseScope(*
this);
977 bool CondIsConstInt =
978 !ControllingExpression ||
982 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
983 Result.Val.getInt().getBoolValue());
997 if (HasEmptyBody && CondIsTrue) {
998 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1016 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1020 const Stmt *Body = S.getBody();
1021 if (!Body || isa<NullStmt>(Body))
1023 if (
const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
1024 return Compound->body_empty();
1037 emitConvergenceLoopToken(LoopHeader.getBlock()));
1044 BreakContinueStack.push_back(BreakContinue(
LoopExit, LoopHeader));
1053 RunCleanupsScope ConditionScope(*
this);
1055 if (S.getConditionVariable())
1056 EmitDecl(*S.getConditionVariable());
1065 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1066 bool EmitBoolCondBranch = !
C || !
C->isOne();
1079 if (EmitBoolCondBranch) {
1080 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1081 if (ConditionScope.requiresCleanups())
1083 llvm::MDNode *Weights =
1084 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1086 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1088 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1090 if (ExitBlock !=
LoopExit.getBlock()) {
1096 diag::warn_attribute_has_no_effect_on_infinite_loop)
1097 << A << A->getRange();
1100 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1101 <<
SourceRange(S.getWhileLoc(), S.getRParenLoc());
1107 RunCleanupsScope BodyScope(*
this);
1117 BreakContinueStack.pop_back();
1120 ConditionScope.ForceCleanup();
1133 if (!EmitBoolCondBranch)
1153 BreakContinueStack.push_back(BreakContinue(
LoopExit, LoopCond));
1167 RunCleanupsScope BodyScope(*
this);
1184 BreakContinueStack.pop_back();
1188 llvm::ConstantInt *
C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
1189 bool EmitBoolCondBranch = !
C || !
C->isZero();
1198 if (EmitBoolCondBranch) {
1201 BoolCondVal, LoopBody,
LoopExit.getBlock(),
1202 createProfileWeightsForLoop(S.getCond(), BackedgeCount));
1212 if (!EmitBoolCondBranch)
1228 LexicalScope ForScope(*
this, S.getSourceRange());
1238 llvm::BasicBlock *CondBlock = CondDest.getBlock();
1251 LexicalScope ConditionScope(*
this, S.getSourceRange());
1262 Continue = CondDest;
1263 else if (!S.getConditionVariable())
1265 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1270 if (S.getConditionVariable()) {
1271 EmitDecl(*S.getConditionVariable());
1276 BreakContinueStack.back().ContinueBlock = Continue;
1284 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1287 if (ForScope.requiresCleanups())
1296 llvm::MDNode *Weights =
1297 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1299 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1302 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1304 if (ExitBlock !=
LoopExit.getBlock()) {
1323 RunCleanupsScope BodyScope(*
this);
1335 BreakContinueStack.pop_back();
1337 ConditionScope.ForceCleanup();
1342 ForScope.ForceCleanup();
1363 LexicalScope ForScope(*
this, S.getSourceRange());
1388 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1389 if (ForScope.requiresCleanups())
1398 llvm::MDNode *Weights =
1399 createProfileWeightsForLoop(S.getCond(),
getProfileCount(S.getBody()));
1401 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1403 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1405 if (ExitBlock !=
LoopExit.getBlock()) {
1420 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1424 LexicalScope BodyScope(*
this, S.getSourceRange());
1434 BreakContinueStack.pop_back();
1438 ForScope.ForceCleanup();
1454void CodeGenFunction::EmitReturnOfRValue(
RValue RV,
QualType Ty) {
1470struct SaveRetExprRAII {
1472 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1475 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1476 const Expr *OldRetExpr;
1485 if (calleeQualType->isFunctionPointerType() ||
1486 calleeQualType->isFunctionReferenceType() ||
1487 calleeQualType->isBlockPointerType() ||
1488 calleeQualType->isMemberFunctionPointerType()) {
1490 }
else if (
auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1492 }
else if (
auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1493 if (
auto methodDecl = CMCE->getMethodDecl()) {
1509 if (requiresReturnValueCheck()) {
1512 new llvm::GlobalVariable(
CGM.
getModule(), SLoc->getType(),
false,
1513 llvm::GlobalVariable::PrivateLinkage, SLoc);
1514 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1516 assert(ReturnLocation.
isValid() &&
"No valid return location");
1523 Builder.ClearInsertionPoint();
1527 const Expr *RV = S.getRetValue();
1537 SaveRetExprRAII SaveRetExpr(RV, *
this);
1539 RunCleanupsScope cleanupScope(*
this);
1540 if (
const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV))
1541 RV = EWC->getSubExpr();
1545 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1548 if (
auto CE = dyn_cast<CallExpr>(RV)) {
1558 if (
getLangOpts().ElideConstructors && S.getNRVOCandidate() &&
1559 S.getNRVOCandidate()->isNRVOVariable() &&
1570 if (llvm::Value *NRVOFlag =
NRVOFlags[S.getNRVOCandidate()])
1613 ++NumSimpleReturnExprs;
1615 cleanupScope.ForceCleanup();
1625 for (
const auto *I : S.decls())
1630 assert(!BreakContinueStack.empty() &&
"break stmt not in a loop or switch!");
1642 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
1658 assert(S.getRHS() &&
"Expected RHS value in CaseStmt");
1660 llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(
getContext());
1661 llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(
getContext());
1671 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1675 llvm::APInt
Range = RHS - LHS;
1677 if (
Range.ult(llvm::APInt(
Range.getBitWidth(), 64))) {
1680 unsigned NCases =
Range.getZExtValue() + 1;
1685 uint64_t Weight = Total / NCases,
Rem = Total % NCases;
1686 for (
unsigned I = 0; I != NCases; ++I) {
1688 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1689 else if (SwitchLikelihood)
1690 SwitchLikelihood->push_back(LH);
1694 SwitchInsn->addCase(
Builder.getInt(LHS), CaseDest);
1702 llvm::BasicBlock *RestoreBB =
Builder.GetInsertBlock();
1707 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1711 Builder.SetInsertPoint(CaseRangeBlock);
1715 Builder.CreateSub(SwitchInsn->getCondition(),
Builder.getInt(LHS));
1719 llvm::MDNode *Weights =
nullptr;
1720 if (SwitchWeights) {
1722 uint64_t DefaultCount = (*SwitchWeights)[0];
1723 Weights = createProfileWeights(ThisCount, DefaultCount);
1728 (*SwitchWeights)[0] += ThisCount;
1729 }
else if (SwitchLikelihood)
1730 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
1732 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
1736 Builder.SetInsertPoint(RestoreBB);
1738 Builder.ClearInsertionPoint();
1759 llvm::ConstantInt *CaseVal =
1764 if (
auto ICE = dyn_cast<ImplicitCastExpr>(S.getLHS()))
1765 CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
1767 CE = dyn_cast<ConstantExpr>(S.getLHS());
1769 if (
auto DE = dyn_cast<DeclRefExpr>(CE->
getSubExpr()))
1772 Dbg->EmitGlobalVariable(DE->getDecl(),
1773 APValue(llvm::APSInt(CaseVal->getValue())));
1776 if (SwitchLikelihood)
1784 isa<BreakStmt>(S.getSubStmt())) {
1785 JumpDest
Block = BreakContinueStack.back().BreakBlock;
1791 SwitchInsn->addCase(CaseVal,
Block.getBlock());
1795 if (
Builder.GetInsertBlock()) {
1797 Builder.ClearInsertionPoint();
1807 SwitchInsn->addCase(CaseVal, CaseDest);
1823 const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt());
1826 while (NextCase && NextCase->
getRHS() ==
nullptr) {
1828 llvm::ConstantInt *CaseVal =
1839 if (SwitchLikelihood)
1842 SwitchInsn->addCase(CaseVal, CaseDest);
1843 NextCase = dyn_cast<CaseStmt>(CurCase->
getSubStmt());
1866 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1867 assert(DefaultBlock->empty() &&
1868 "EmitDefaultStmt: Default block already defined?");
1870 if (SwitchLikelihood)
1912 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
1926 if (!Case && isa<BreakStmt>(S))
1931 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
1935 bool StartedInLiveCode = FoundCase;
1936 unsigned StartSize = ResultStmts.size();
1943 bool HadSkippedDecl =
false;
1947 for (; Case && I !=
E; ++I) {
1963 for (++I; I !=
E; ++I)
1973 assert(FoundCase &&
"Didn't find case but returned fallthrough?");
1988 assert(!HadSkippedDecl &&
"fallthrough after skipping decl");
1993 bool AnyDecls =
false;
1994 for (; I !=
E; ++I) {
2007 for (++I; I !=
E; ++I)
2024 ResultStmts.resize(StartSize);
2025 ResultStmts.push_back(S);
2049 ResultStmts.push_back(S);
2058 const llvm::APSInt &ConstantCondValue,
2064 const SwitchCase *Case = S.getSwitchCaseList();
2070 if (
const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
2076 const CaseStmt *CS = cast<CaseStmt>(Case);
2078 if (CS->
getRHS())
return false;
2103 bool FoundCase =
false;
2110static std::optional<SmallVector<uint64_t, 16>>
2113 if (Likelihoods.size() <= 1)
2114 return std::nullopt;
2116 uint64_t NumUnlikely = 0;
2117 uint64_t NumNone = 0;
2118 uint64_t NumLikely = 0;
2119 for (
const auto LH : Likelihoods) {
2134 if (NumUnlikely == 0 && NumLikely == 0)
2135 return std::nullopt;
2143 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2144 const uint64_t
None = Likely / (NumNone + 1);
2145 const uint64_t Unlikely = 0;
2148 Result.reserve(Likelihoods.size());
2149 for (
const auto LH : Likelihoods) {
2152 Result.push_back(Unlikely);
2158 Result.push_back(Likely);
2168 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2171 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2175 llvm::APSInt ConstantCondValue;
2183 RunCleanupsScope ExecutedScope(*
this);
2190 if (S.getConditionVariable())
2191 EmitDecl(*S.getConditionVariable());
2196 SwitchInsn =
nullptr;
2200 for (
unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
2206 SwitchInsn = SavedSwitchInsn;
2214 RunCleanupsScope ConditionScope(*
this);
2219 if (S.getConditionVariable())
2220 EmitDecl(*S.getConditionVariable());
2228 SwitchInsn =
Builder.CreateSwitch(CondV, DefaultBlock);
2232 unsigned NumCases = 0;
2233 for (
const SwitchCase *Case = S.getSwitchCaseList();
2236 if (isa<DefaultStmt>(Case))
2241 SwitchWeights->reserve(NumCases);
2244 SwitchWeights->push_back(DefaultCount);
2251 CaseRangeBlock = DefaultBlock;
2254 Builder.ClearInsertionPoint();
2258 JumpDest OuterContinue;
2259 if (!BreakContinueStack.empty())
2260 OuterContinue = BreakContinueStack.back().ContinueBlock;
2262 BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue));
2267 BreakContinueStack.pop_back();
2271 SwitchInsn->setDefaultDest(CaseRangeBlock);
2274 if (!DefaultBlock->getParent()) {
2277 if (ConditionScope.requiresCleanups()) {
2282 DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock());
2283 delete DefaultBlock;
2287 ConditionScope.ForceCleanup();
2296 auto *
Call = dyn_cast<CallExpr>(S.getCond());
2298 auto *FD = dyn_cast_or_null<FunctionDecl>(
Call->getCalleeDecl());
2299 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2301 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2302 MDHelper.createUnpredictable());
2306 if (SwitchWeights) {
2307 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2308 "switch weights do not match switch cases");
2310 if (SwitchWeights->size() > 1)
2311 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2312 createProfileWeights(*SwitchWeights));
2313 delete SwitchWeights;
2314 }
else if (SwitchLikelihood) {
2315 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2316 "switch likelihoods do not match switch cases");
2317 std::optional<SmallVector<uint64_t, 16>> LHW =
2321 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2322 createProfileWeights(*LHW));
2324 delete SwitchLikelihood;
2326 SwitchInsn = SavedSwitchInsn;
2327 SwitchWeights = SavedSwitchWeights;
2328 SwitchLikelihood = SavedSwitchLikelihood;
2329 CaseRangeBlock = SavedCRBlock;
2337 while (*Constraint) {
2338 switch (*Constraint) {
2350 while (Constraint[1] && Constraint[1] !=
',')
2356 while (Constraint[1] && Constraint[1] == *Constraint)
2367 "Must pass output names to constraints with a symbolic name");
2369 bool result =
Target.resolveSymbolicName(Constraint, *OutCons, Index);
2370 assert(result &&
"Could not resolve symbolic name"); (void)result;
2371 Result += llvm::utostr(Index);
2389 std::string *GCCReg =
nullptr) {
2390 const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
2402 StringRef Register =
Attr->getLabel();
2403 assert(
Target.isValidGCCRegisterName(Register));
2407 if (
Target.validateOutputConstraint(Info) &&
2413 Register =
Target.getNormalizedGCCRegisterName(Register);
2414 if (GCCReg !=
nullptr)
2415 *GCCReg = Register.str();
2416 return (EarlyClobber ?
"&{" :
"{") + Register.str() +
"}";
2419std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2428 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2438 ConstraintStr +=
'*';
2442std::pair<llvm::Value *, llvm::Type *>
2444 const Expr *InputExpr,
2445 std::string &ConstraintStr) {
2453 llvm::APSInt IntResult;
2456 return {llvm::ConstantInt::get(
getLLVMContext(), IntResult),
nullptr};
2468 if (InputExpr->
getStmtClass() == Expr::CXXThisExprClass)
2472 return EmitAsmInputLValue(Info, Dest, InputExpr->
getType(), ConstraintStr,
2484 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2487 if (!StrVal.empty()) {
2490 unsigned StartToken = 0;
2491 unsigned ByteOffset = 0;
2495 for (
unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2496 if (StrVal[i] !=
'\n')
continue;
2498 i + 1,
SM, LangOpts, CGF.
getTarget(), &StartToken, &ByteOffset);
2499 Locs.push_back(llvm::ConstantAsMetadata::get(
2508 bool HasUnwindClobber,
bool ReadOnly,
2509 bool ReadNone,
bool NoMerge,
bool NoConvergent,
2511 const std::vector<llvm::Type *> &ResultRegTypes,
2512 const std::vector<llvm::Type *> &ArgElemTypes,
2514 std::vector<llvm::Value *> &RegResults) {
2515 if (!HasUnwindClobber)
2516 Result.addFnAttr(llvm::Attribute::NoUnwind);
2519 Result.addFnAttr(llvm::Attribute::NoMerge);
2521 if (!HasSideEffect) {
2523 Result.setDoesNotAccessMemory();
2525 Result.setOnlyReadsMemory();
2529 for (
auto Pair : llvm::enumerate(ArgElemTypes)) {
2531 auto Attr = llvm::Attribute::get(
2532 CGF.
getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2539 if (
const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S))
2540 Result.setMetadata(
"srcloc",
2544 llvm::Constant *
Loc =
2545 llvm::ConstantInt::get(CGF.
Int64Ty, S.getAsmLoc().getRawEncoding());
2546 Result.setMetadata(
"srcloc",
2548 llvm::ConstantAsMetadata::get(
Loc)));
2556 Result.addFnAttr(llvm::Attribute::Convergent);
2558 if (ResultRegTypes.size() == 1) {
2559 RegResults.push_back(&
Result);
2561 for (
unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2562 llvm::Value *Tmp = CGF.
Builder.CreateExtractValue(&
Result, i,
"asmresult");
2563 RegResults.push_back(Tmp);
2575 const llvm::BitVector &ResultTypeRequiresCast,
2576 const llvm::BitVector &ResultRegIsFlagReg) {
2581 assert(RegResults.size() == ResultRegTypes.size());
2582 assert(RegResults.size() == ResultTruncRegTypes.size());
2583 assert(RegResults.size() == ResultRegDests.size());
2586 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2587 assert(ResultRegIsFlagReg.size() <= ResultRegDests.size());
2589 for (
unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2590 llvm::Value *Tmp = RegResults[i];
2591 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2593 if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
2596 llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2);
2597 llvm::Value *IsBooleanValue =
2598 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two);
2600 Builder.CreateCall(FnAssume, IsBooleanValue);
2605 if (ResultRegTypes[i] != TruncTy) {
2609 if (TruncTy->isFloatingPointTy())
2610 Tmp =
Builder.CreateFPTrunc(Tmp, TruncTy);
2611 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2614 Tmp, llvm::IntegerType::get(CTX, (
unsigned)ResSize));
2615 Tmp =
Builder.CreateIntToPtr(Tmp, TruncTy);
2616 }
else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2620 Tmp, llvm::IntegerType::get(CTX, (
unsigned)TmpSize));
2621 Tmp =
Builder.CreateTrunc(Tmp, TruncTy);
2622 }
else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2623 Tmp =
Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2624 }
else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2625 Tmp =
Builder.CreateBitCast(Tmp, TruncTy);
2629 LValue Dest = ResultRegDests[i];
2632 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2643 const Expr *OutExpr = S.getOutputExpr(i);
2645 diag::err_store_value_to_reg);
2656 constexpr auto Name =
"__ASM__hipstdpar_unsupported";
2659 if (
auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
2660 Asm = GCCAsm->getAsmString()->getString();
2664 auto StrTy = llvm::ConstantDataArray::getString(Ctx,
Asm);
2665 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2666 {StrTy->getType()},
false);
2667 auto UBF = CGF->
CGM.
getModule().getOrInsertFunction(Name, FnTy);
2669 CGF->
Builder.CreateCall(UBF, {StrTy});
2674 CodeGenFunction::RunCleanupsScope Cleanups(*
this);
2677 std::string AsmString = S.generateAsmString(
getContext());
2684 bool IsValidTargetAsm =
true;
2685 for (
unsigned i = 0, e = S.getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2687 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2688 Name = GAS->getOutputName(i);
2691 if (IsHipStdPar && !IsValid)
2692 IsValidTargetAsm =
false;
2694 assert(IsValid &&
"Failed to parse output constraint");
2695 OutputConstraintInfos.push_back(Info);
2698 for (
unsigned i = 0, e = S.getNumInputs(); i != e && IsValidTargetAsm; i++) {
2700 if (
const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
2701 Name = GAS->getInputName(i);
2705 if (IsHipStdPar && !IsValid)
2706 IsValidTargetAsm =
false;
2708 assert(IsValid &&
"Failed to parse input constraint");
2709 InputConstraintInfos.push_back(Info);
2712 if (!IsValidTargetAsm)
2715 std::string Constraints;
2717 std::vector<LValue> ResultRegDests;
2718 std::vector<QualType> ResultRegQualTys;
2719 std::vector<llvm::Type *> ResultRegTypes;
2720 std::vector<llvm::Type *> ResultTruncRegTypes;
2721 std::vector<llvm::Type *> ArgTypes;
2722 std::vector<llvm::Type *> ArgElemTypes;
2723 std::vector<llvm::Value*> Args;
2724 llvm::BitVector ResultTypeRequiresCast;
2725 llvm::BitVector ResultRegIsFlagReg;
2728 std::string InOutConstraints;
2729 std::vector<llvm::Value*> InOutArgs;
2730 std::vector<llvm::Type*> InOutArgTypes;
2731 std::vector<llvm::Type*> InOutArgElemTypes;
2734 std::vector<std::string> OutputConstraints;
2737 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2745 bool ReadOnly =
true, ReadNone =
true;
2747 for (
unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
2751 std::string OutputConstraint(S.getOutputConstraint(i));
2755 const Expr *OutExpr = S.getOutputExpr(i);
2764 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2765 CGM.
Error(S.getAsmLoc(),
"multiple outputs to hard register: " + GCCReg);
2767 OutputConstraints.push_back(OutputConstraint);
2769 if (!Constraints.empty())
2779 Constraints +=
"=" + OutputConstraint;
2780 ResultRegQualTys.push_back(QTy);
2781 ResultRegDests.push_back(Dest);
2783 bool IsFlagReg = llvm::StringRef(OutputConstraint).starts_with(
"{@cc");
2784 ResultRegIsFlagReg.push_back(IsFlagReg);
2789 Ty->isAggregateType());
2791 ResultTruncRegTypes.push_back(Ty);
2792 ResultTypeRequiresCast.push_back(RequiresCast);
2801 ResultRegTypes.push_back(Ty);
2807 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2812 assert(InputNo != S.getNumInputs() &&
"Didn't find matching input!");
2814 QualType InputTy = S.getInputExpr(InputNo)->getType();
2823 if (llvm::Type* AdjTy =
2825 ResultRegTypes.back()))
2826 ResultRegTypes.back() = AdjTy;
2829 diag::err_asm_invalid_type_in_input)
2830 << OutExpr->
getType() << OutputConstraint;
2834 if (
auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
2835 LargestVectorWidth =
2836 std::max((uint64_t)LargestVectorWidth,
2837 VT->getPrimitiveSizeInBits().getKnownMinValue());
2848 ArgTypes.push_back(DestAddr.
getType());
2851 Constraints +=
"=*";
2852 Constraints += OutputConstraint;
2853 ReadOnly = ReadNone =
false;
2857 InOutConstraints +=
',';
2859 const Expr *InputExpr = S.getOutputExpr(i);
2861 llvm::Type *ArgElemType;
2862 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
2863 Info, Dest, InputExpr->
getType(), InOutConstraints,
2866 if (llvm::Type* AdjTy =
2869 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2872 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2873 LargestVectorWidth =
2874 std::max((uint64_t)LargestVectorWidth,
2875 VT->getPrimitiveSizeInBits().getKnownMinValue());
2878 InOutConstraints += llvm::utostr(i);
2880 InOutConstraints += OutputConstraint;
2882 InOutArgTypes.push_back(Arg->getType());
2883 InOutArgElemTypes.push_back(ArgElemType);
2884 InOutArgs.push_back(Arg);
2890 if (isa<MSAsmStmt>(&S)) {
2896 *
this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
2897 ResultRegDests, AsmString, S.getNumOutputs());
2902 for (
unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
2903 const Expr *InputExpr = S.getInputExpr(i);
2910 if (!Constraints.empty())
2914 std::string InputConstraint(S.getInputConstraint(i));
2916 &OutputConstraintInfos);
2922 std::string ReplaceConstraint (InputConstraint);
2924 llvm::Type *ArgElemType;
2925 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
2934 QualType OutputType = S.getOutputExpr(Output)->getType();
2940 if (isa<llvm::PointerType>(Arg->getType()))
2943 if (isa<llvm::IntegerType>(OutputTy))
2944 Arg =
Builder.CreateZExt(Arg, OutputTy);
2945 else if (isa<llvm::PointerType>(OutputTy))
2947 else if (OutputTy->isFloatingPointTy())
2948 Arg =
Builder.CreateFPExt(Arg, OutputTy);
2951 ReplaceConstraint = OutputConstraints[Output];
2953 if (llvm::Type* AdjTy =
2956 Arg =
Builder.CreateBitCast(Arg, AdjTy);
2959 << InputExpr->
getType() << InputConstraint;
2962 if (
auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
2963 LargestVectorWidth =
2964 std::max((uint64_t)LargestVectorWidth,
2965 VT->getPrimitiveSizeInBits().getKnownMinValue());
2967 ArgTypes.push_back(Arg->getType());
2968 ArgElemTypes.push_back(ArgElemType);
2969 Args.push_back(Arg);
2970 Constraints += InputConstraint;
2974 for (
unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
2975 ArgTypes.push_back(InOutArgTypes[i]);
2976 ArgElemTypes.push_back(InOutArgElemTypes[i]);
2977 Args.push_back(InOutArgs[i]);
2979 Constraints += InOutConstraints;
2983 llvm::BasicBlock *Fallthrough =
nullptr;
2984 bool IsGCCAsmGoto =
false;
2985 if (
const auto *GS = dyn_cast<GCCAsmStmt>(&S)) {
2986 IsGCCAsmGoto = GS->isAsmGoto();
2988 for (
const auto *
E : GS->labels()) {
2990 Transfer.push_back(Dest.getBlock());
2991 if (!Constraints.empty())
2993 Constraints +=
"!i";
2999 bool HasUnwindClobber =
false;
3002 for (
unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
3003 StringRef Clobber = S.getClobber(i);
3005 if (Clobber ==
"memory")
3006 ReadOnly = ReadNone =
false;
3007 else if (Clobber ==
"unwind") {
3008 HasUnwindClobber =
true;
3010 }
else if (Clobber !=
"cc") {
3015 diag::warn_stack_clash_protection_inline_asm);
3019 if (isa<MSAsmStmt>(&S)) {
3020 if (Clobber ==
"eax" || Clobber ==
"edx") {
3021 if (Constraints.find(
"=&A") != std::string::npos)
3023 std::string::size_type position1 =
3024 Constraints.find(
"={" + Clobber.str() +
"}");
3025 if (position1 != std::string::npos) {
3026 Constraints.insert(position1 + 1,
"&");
3029 std::string::size_type position2 = Constraints.find(
"=A");
3030 if (position2 != std::string::npos) {
3031 Constraints.insert(position2 + 1,
"&");
3036 if (!Constraints.empty())
3039 Constraints +=
"~{";
3040 Constraints += Clobber;
3044 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
3045 "unwind clobber can't be used with asm goto");
3049 if (!MachineClobbers.empty()) {
3050 if (!Constraints.empty())
3052 Constraints += MachineClobbers;
3055 llvm::Type *ResultType;
3056 if (ResultRegTypes.empty())
3058 else if (ResultRegTypes.size() == 1)
3059 ResultType = ResultRegTypes[0];
3061 ResultType = llvm::StructType::get(
getLLVMContext(), ResultRegTypes);
3063 llvm::FunctionType *FTy =
3064 llvm::FunctionType::get(ResultType, ArgTypes,
false);
3066 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
3068 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3070 ? llvm::InlineAsm::AD_ATT
3071 : llvm::InlineAsm::AD_Intel;
3072 llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ?
3073 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3075 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3076 FTy, AsmString, Constraints, HasSideEffect,
3077 false, AsmDialect, HasUnwindClobber);
3078 std::vector<llvm::Value*> RegResults;
3079 llvm::CallBrInst *CBR;
3080 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3083 CBR =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3088 ArgElemTypes, *
this, RegResults);
3092 if (!RegResults.empty()) {
3094 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3095 llvm::Twine SynthName = Dest->getName() +
".split";
3097 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3098 Builder.SetInsertPoint(SynthBB);
3100 if (ResultRegTypes.size() == 1) {
3101 CBRRegResults[SynthBB].push_back(CBR);
3103 for (
unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3104 llvm::Value *Tmp =
Builder.CreateExtractValue(CBR, j,
"asmresult");
3105 CBRRegResults[SynthBB].push_back(Tmp);
3111 CBR->setIndirectDest(i++, SynthBB);
3114 }
else if (HasUnwindClobber) {
3119 ArgElemTypes, *
this, RegResults);
3126 ArgElemTypes, *
this, RegResults);
3129 EmitAsmStores(*
this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3130 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3131 ResultRegIsFlagReg);
3136 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3137 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3138 llvm::IRBuilderBase::InsertPointGuard IPG(
Builder);
3139 Builder.SetInsertPoint(Succ, --(Succ->end()));
3140 EmitAsmStores(*
this, S, CBRRegResults[Succ], ResultRegTypes,
3141 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3142 ResultTypeRequiresCast, ResultRegIsFlagReg);
3148 const RecordDecl *RD = S.getCapturedRecordDecl();
3157 E = S.capture_init_end();
3158 I !=
E; ++I, ++CurField) {
3160 if (CurField->hasCapturedVLAType()) {
3178 CGCapturedStmtRAII CapInfoRAII(CGF,
new CGCapturedStmtInfo(S, K));
3179 llvm::Function *F = CGF.GenerateCapturedStmtFunction(S);
3180 delete CGF.CapturedStmtInfo;
3197 "CapturedStmtInfo should be set when generating the captured function");
3199 const RecordDecl *RD = S.getCapturedRecordDecl();
3201 assert(CD->
hasBody() &&
"missing CapturedDecl body");
3214 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3218 F->addFnAttr(llvm::Attribute::NoUnwind);
3230 for (
auto *FD : RD->
fields()) {
3231 if (FD->hasCapturedVLAType()) {
3235 auto VAT = FD->getCapturedVLAType();
3236 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3257 for (
auto &I : *BB) {
3258 if (
auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
3265CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3267 assert(ParentToken);
3269 llvm::Value *bundleArgs[] = {ParentToken};
3270 llvm::OperandBundleDef OB(
"convergencectrl", bundleArgs);
3271 auto *Output = llvm::CallBase::addOperandBundle(
3272 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3273 Input->replaceAllUsesWith(Output);
3274 Input->eraseFromParent();
3278llvm::ConvergenceControlInst *
3279CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
3280 CGBuilderTy::InsertPoint IP =
Builder.saveIP();
3284 Builder.SetInsertPoint(BB->getFirstInsertionPt());
3286 llvm::CallBase *CB =
Builder.CreateIntrinsic(
3287 llvm::Intrinsic::experimental_convergence_loop, {}, {});
3290 CB = addConvergenceControlToken(CB);
3291 return cast<llvm::ConvergenceControlInst>(CB);
3294llvm::ConvergenceControlInst *
3295CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3296 llvm::BasicBlock *BB = &F->getEntryBlock();
3305 CGBuilderTy::InsertPoint IP =
Builder.saveIP();
3306 Builder.SetInsertPoint(&BB->front());
3307 llvm::CallBase *I =
Builder.CreateIntrinsic(
3308 llvm::Intrinsic::experimental_convergence_entry, {}, {});
3309 assert(isa<llvm::IntrinsicInst>(I));
3312 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="")
HLSLControlFlowHintAttr::Spelling HLSLControlFlowAttr
HLSL Branch attribute.
void EmitDoStmt(const DoStmt &S, ArrayRef< const Attr * > Attrs={})
bool InAlwaysInlineAttributedStmt
True if the current statement has always_inline attribute.
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitOpenACCComputeConstruct(const OpenACCComputeConstruct &S)
void EmitOMPSimdDirective(const OMPSimdDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S)
void EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
LValue InitCapturedStruct(const CapturedStmt &S)
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitReturnStmt(const ReturnStmt &S)
unsigned NextCleanupDestIndex
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &S)
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
static bool mightAddDeclToScope(const Stmt *S)
Determine if the given statement might introduce a declaration into the current scope,...
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
static bool hasAggregateEvaluationKind(QualType T)
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
void EmitBreakStmt(const BreakStmt &S)
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV)
const CallExpr * MustTailCall
const CGFunctionInfo * CurFnInfo
bool isObviouslyBranchWithoutCleanups(JumpDest Dest) const
isObviouslyBranchWithoutCleanups - Return true if a branch to the specified destination obviously has...
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
void EmitCoreturnStmt(const CoreturnStmt &S)
void EmitOpenACCSetConstruct(const OpenACCSetConstruct &S)
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)
llvm::LLVMContext & getLLVMContext()
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
bool SawAsmBlock
Whether we processed a Microsoft-style asm block during CodeGen.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
void ResolveBranchFixups(llvm::BasicBlock *Target)
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
llvm::BasicBlock * GetIndirectGotoBlock()
void EmitAsmStmt(const AsmStmt &S)
void EmitObjCAtTryStmt(const ObjCAtTryStmt &S)
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
static bool containsBreak(const Stmt *S)
containsBreak - Return true if the statement contains a break out of it.
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
void ErrorUnsupported(const Stmt *S, const char *Type)
Print out an error that codegen doesn't support the specified stmt yet.
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
void Error(SourceLocation loc, StringRef error)
Emit a general error that something can't be done.
bool shouldEmitConvergenceTokens() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
SanitizerMetadata * getSanitizerMetadata()
ASTContext & getContext() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn)
Assign counters to regions and configure them for PGO of a given function.
void 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