clang: lib/CodeGen/CGStmt.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
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"
37#include
38
39using namespace clang;
40using namespace CodeGen;
41
42
43
44
45
46namespace llvm {
48}
49
50void CodeGenFunction::EmitStopPoint(const Stmt *S) {
53 Loc = S->getBeginLoc();
55
56 LastStopPoint = Loc;
57 }
58}
59
61 assert(S && "Null statement?");
63
64
66 return;
67
68
70
71
72
73
74
76
77
78 assert(!isa(*S) && "Unexpected DeclStmt!");
80 return;
81 }
82
83
85 }
86
87
89
90
91
93 if (const auto *D = dyn_cast(S)) {
95 return;
96 }
97 }
98
99 switch (S->getStmtClass()) {
101 case Stmt::CXXCatchStmtClass:
102 case Stmt::SEHExceptStmtClass:
103 case Stmt::SEHFinallyStmtClass:
104 case Stmt::MSDependentExistsStmtClass:
105 llvm_unreachable("invalid statement class to emit generically");
106 case Stmt::NullStmtClass:
107 case Stmt::CompoundStmtClass:
108 case Stmt::DeclStmtClass:
109 case Stmt::LabelStmtClass:
110 case Stmt::AttributedStmtClass:
111 case Stmt::GotoStmtClass:
112 case Stmt::BreakStmtClass:
113 case Stmt::ContinueStmtClass:
114 case Stmt::DefaultStmtClass:
115 case Stmt::CaseStmtClass:
116 case Stmt::SEHLeaveStmtClass:
117 llvm_unreachable("should have emitted these statements as simple");
118
119#define STMT(Type, Base)
120#define ABSTRACT_STMT(Op)
121#define EXPR(Type, Base) \
122 case Stmt::Type##Class:
123#include "clang/AST/StmtNodes.inc"
124 {
125
126 llvm::BasicBlock *incoming = Builder.GetInsertBlock();
127 assert(incoming && "expression emission must have an insertion point");
128
130
131 llvm::BasicBlock *outgoing = Builder.GetInsertBlock();
132 assert(outgoing && "expression emission cleared block!");
133
134
135
136
137
138
139
140
141
142
143
144
145
146 if (incoming != outgoing && outgoing->use_empty()) {
147 outgoing->eraseFromParent();
148 Builder.ClearInsertionPoint();
149 }
150 break;
151 }
152
153 case Stmt::IndirectGotoStmtClass:
155
156 case Stmt::IfStmtClass: EmitIfStmt(cast(*S)); break;
157 case Stmt::WhileStmtClass: EmitWhileStmt(cast(*S), Attrs); break;
158 case Stmt::DoStmtClass: EmitDoStmt(cast(*S), Attrs); break;
159 case Stmt::ForStmtClass: EmitForStmt(cast(*S), Attrs); break;
160
161 case Stmt::ReturnStmtClass: EmitReturnStmt(cast(*S)); break;
162
163 case Stmt::SwitchStmtClass: EmitSwitchStmt(cast(*S)); break;
164 case Stmt::GCCAsmStmtClass:
165 case Stmt::MSAsmStmtClass: EmitAsmStmt(cast(*S)); break;
166 case Stmt::CoroutineBodyStmtClass:
168 break;
169 case Stmt::CoreturnStmtClass:
171 break;
172 case Stmt::CapturedStmtClass: {
173 const CapturedStmt *CS = cast(S);
175 }
176 break;
177 case Stmt::ObjCAtTryStmtClass:
179 break;
180 case Stmt::ObjCAtCatchStmtClass:
181 llvm_unreachable(
182 "@catch statements should be handled by EmitObjCAtTryStmt");
183 case Stmt::ObjCAtFinallyStmtClass:
184 llvm_unreachable(
185 "@finally statements should be handled by EmitObjCAtTryStmt");
186 case Stmt::ObjCAtThrowStmtClass:
188 break;
189 case Stmt::ObjCAtSynchronizedStmtClass:
191 break;
192 case Stmt::ObjCForCollectionStmtClass:
194 break;
195 case Stmt::ObjCAutoreleasePoolStmtClass:
197 break;
198
199 case Stmt::CXXTryStmtClass:
201 break;
202 case Stmt::CXXForRangeStmtClass:
204 break;
205 case Stmt::SEHTryStmtClass:
207 break;
208 case Stmt::OMPMetaDirectiveClass:
210 break;
211 case Stmt::OMPCanonicalLoopClass:
213 break;
214 case Stmt::OMPParallelDirectiveClass:
216 break;
217 case Stmt::OMPSimdDirectiveClass:
219 break;
220 case Stmt::OMPTileDirectiveClass:
222 break;
223 case Stmt::OMPUnrollDirectiveClass:
225 break;
226 case Stmt::OMPReverseDirectiveClass:
228 break;
229 case Stmt::OMPInterchangeDirectiveClass:
231 break;
232 case Stmt::OMPForDirectiveClass:
234 break;
235 case Stmt::OMPForSimdDirectiveClass:
237 break;
238 case Stmt::OMPSectionsDirectiveClass:
240 break;
241 case Stmt::OMPSectionDirectiveClass:
243 break;
244 case Stmt::OMPSingleDirectiveClass:
246 break;
247 case Stmt::OMPMasterDirectiveClass:
249 break;
250 case Stmt::OMPCriticalDirectiveClass:
252 break;
253 case Stmt::OMPParallelForDirectiveClass:
255 break;
256 case Stmt::OMPParallelForSimdDirectiveClass:
258 break;
259 case Stmt::OMPParallelMasterDirectiveClass:
261 break;
262 case Stmt::OMPParallelSectionsDirectiveClass:
264 break;
265 case Stmt::OMPTaskDirectiveClass:
267 break;
268 case Stmt::OMPTaskyieldDirectiveClass:
270 break;
271 case Stmt::OMPErrorDirectiveClass:
273 break;
274 case Stmt::OMPBarrierDirectiveClass:
276 break;
277 case Stmt::OMPTaskwaitDirectiveClass:
279 break;
280 case Stmt::OMPTaskgroupDirectiveClass:
282 break;
283 case Stmt::OMPFlushDirectiveClass:
285 break;
286 case Stmt::OMPDepobjDirectiveClass:
288 break;
289 case Stmt::OMPScanDirectiveClass:
291 break;
292 case Stmt::OMPOrderedDirectiveClass:
294 break;
295 case Stmt::OMPAtomicDirectiveClass:
297 break;
298 case Stmt::OMPTargetDirectiveClass:
300 break;
301 case Stmt::OMPTeamsDirectiveClass:
303 break;
304 case Stmt::OMPCancellationPointDirectiveClass:
306 break;
307 case Stmt::OMPCancelDirectiveClass:
309 break;
310 case Stmt::OMPTargetDataDirectiveClass:
312 break;
313 case Stmt::OMPTargetEnterDataDirectiveClass:
315 break;
316 case Stmt::OMPTargetExitDataDirectiveClass:
318 break;
319 case Stmt::OMPTargetParallelDirectiveClass:
321 break;
322 case Stmt::OMPTargetParallelForDirectiveClass:
324 break;
325 case Stmt::OMPTaskLoopDirectiveClass:
327 break;
328 case Stmt::OMPTaskLoopSimdDirectiveClass:
330 break;
331 case Stmt::OMPMasterTaskLoopDirectiveClass:
333 break;
334 case Stmt::OMPMaskedTaskLoopDirectiveClass:
336 break;
337 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
339 cast(*S));
340 break;
341 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
343 cast(*S));
344 break;
345 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
347 cast(*S));
348 break;
349 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
351 cast(*S));
352 break;
353 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
355 cast(*S));
356 break;
357 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
359 cast(*S));
360 break;
361 case Stmt::OMPDistributeDirectiveClass:
363 break;
364 case Stmt::OMPTargetUpdateDirectiveClass:
366 break;
367 case Stmt::OMPDistributeParallelForDirectiveClass:
369 cast(*S));
370 break;
371 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
373 cast(*S));
374 break;
375 case Stmt::OMPDistributeSimdDirectiveClass:
377 break;
378 case Stmt::OMPTargetParallelForSimdDirectiveClass:
380 cast(*S));
381 break;
382 case Stmt::OMPTargetSimdDirectiveClass:
384 break;
385 case Stmt::OMPTeamsDistributeDirectiveClass:
387 break;
388 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
390 cast(*S));
391 break;
392 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
394 cast(*S));
395 break;
396 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
398 cast(*S));
399 break;
400 case Stmt::OMPTargetTeamsDirectiveClass:
402 break;
403 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
405 cast(*S));
406 break;
407 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
409 cast(*S));
410 break;
411 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
413 cast(*S));
414 break;
415 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
417 cast(*S));
418 break;
419 case Stmt::OMPInteropDirectiveClass:
421 break;
422 case Stmt::OMPDispatchDirectiveClass:
424 break;
425 case Stmt::OMPScopeDirectiveClass:
427 break;
428 case Stmt::OMPMaskedDirectiveClass:
430 break;
431 case Stmt::OMPGenericLoopDirectiveClass:
433 break;
434 case Stmt::OMPTeamsGenericLoopDirectiveClass:
436 break;
437 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
439 cast(*S));
440 break;
441 case Stmt::OMPParallelGenericLoopDirectiveClass:
443 cast(*S));
444 break;
445 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
447 cast(*S));
448 break;
449 case Stmt::OMPParallelMaskedDirectiveClass:
451 break;
452 case Stmt::OMPAssumeDirectiveClass:
454 break;
455 case Stmt::OpenACCComputeConstructClass:
457 break;
458 case Stmt::OpenACCLoopConstructClass:
460 break;
461 case Stmt::OpenACCCombinedConstructClass:
463 break;
464 case Stmt::OpenACCDataConstructClass:
466 break;
467 case Stmt::OpenACCEnterDataConstructClass:
469 break;
470 case Stmt::OpenACCExitDataConstructClass:
472 break;
473 case Stmt::OpenACCHostDataConstructClass:
475 break;
476 case Stmt::OpenACCWaitConstructClass:
478 break;
479 case Stmt::OpenACCInitConstructClass:
481 break;
482 case Stmt::OpenACCShutdownConstructClass:
484 break;
485 case Stmt::OpenACCSetConstructClass:
487 break;
488 case Stmt::OpenACCUpdateConstructClass:
490 break;
491 }
492}
493
496 switch (S->getStmtClass()) {
497 default:
498 return false;
499 case Stmt::NullStmtClass:
500 break;
501 case Stmt::CompoundStmtClass:
503 break;
504 case Stmt::DeclStmtClass:
506 break;
507 case Stmt::LabelStmtClass:
509 break;
510 case Stmt::AttributedStmtClass:
512 break;
513 case Stmt::GotoStmtClass:
515 break;
516 case Stmt::BreakStmtClass:
518 break;
519 case Stmt::ContinueStmtClass:
521 break;
522 case Stmt::DefaultStmtClass:
524 break;
525 case Stmt::CaseStmtClass:
527 break;
528 case Stmt::SEHLeaveStmtClass:
530 break;
531 }
532 return true;
533}
534
535
536
537
541 "LLVM IR generation of compound statement ('{}')");
542
543
544 LexicalScope Scope(*this, S.getSourceRange());
545
547}
548
551 bool GetLast,
553
555 assert((!GetLast || (GetLast && ExprResult)) &&
556 "If GetLast is true then the CompoundStmt must have a StmtExprResult");
557
559
560 for (auto *CurStmt : S.body()) {
561 if (GetLast && ExprResult == CurStmt) {
562
563
564
565
566
568 if (const auto *LS = dyn_cast(ExprResult)) {
571 } else if (const auto *AS = dyn_cast(ExprResult)) {
572
573
575 } else {
576 llvm_unreachable("unknown value statement");
577 }
578 }
579
581
586 } else {
587
588
589
592 false);
593 }
594 } else {
596 }
597 }
598
599 return RetAlloca;
600}
601
603 llvm::BranchInst *BI = dyn_castllvm::BranchInst(BB->getTerminator());
604
605
606
607
609 return;
610
611
612 if (!BI || !BI->isUnconditional())
613 return;
614
615
616 if (BI->getIterator() != BB->begin())
617 return;
618
619 BB->replaceAllUsesWith(BI->getSuccessor(0));
620 BI->eraseFromParent();
621 BB->eraseFromParent();
622}
623
625 llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
626
627
629
630 if (IsFinished && BB->use_empty()) {
631 delete BB;
632 return;
633 }
634
635
636
637 if (CurBB && CurBB->getParent())
638 CurFn->insert(std::next(CurBB->getIterator()), BB);
639 else
641 Builder.SetInsertPoint(BB);
642}
643
645
646
647
648 llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
649
650 if (!CurBB || CurBB->getTerminator()) {
651
652
653 } else {
654
656 }
657
658 Builder.ClearInsertionPoint();
659}
660
662 bool inserted = false;
663 for (llvm::User *u : block->users()) {
664 if (llvm::Instruction *insn = dyn_castllvm::Instruction(u)) {
665 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
666 inserted = true;
667 break;
668 }
669 }
670
671 if (!inserted)
673
674 Builder.SetInsertPoint(block);
675}
676
677CodeGenFunction::JumpDest
679 JumpDest &Dest = LabelMap[D];
680 if (Dest.isValid()) return Dest;
681
682
686 return Dest;
687}
688
690
691
692
695
696 JumpDest &Dest = LabelMap[D];
697
698
699
700 if (!Dest.isValid()) {
702
703
704
705 } else {
706 assert(!Dest.getScopeDepth().isValid() && "already emitted label!");
709 }
710
712
713
718 }
719 }
720
722}
723
724
725
727 assert(!Labels.empty());
730
731
733 i = Labels.begin(), e = Labels.end(); i != e; ++i) {
734 assert(CGF.LabelMap.count(*i));
735 JumpDest &dest = CGF.LabelMap.find(*i)->second;
739 }
740
741
743 ParentScope->Labels.append(Labels.begin(), Labels.end());
744 }
745}
746
747
750
751
752 if (getLangOpts().EHAsynch && S.isSideEntry())
754
756}
757
759 bool nomerge = false;
760 bool noinline = false;
761 bool alwaysinline = false;
762 bool noconvergent = false;
763 HLSLControlFlowHintAttr::Spelling flattenOrBranch =
764 HLSLControlFlowHintAttr::SpellingNotCalculated;
765 const CallExpr *musttail = nullptr;
766
767 for (const auto *A : S.getAttrs()) {
768 switch (A->getKind()) {
769 default:
770 break;
771 case attr::NoMerge:
772 nomerge = true;
773 break;
774 case attr::NoInline:
775 noinline = true;
776 break;
777 case attr::AlwaysInline:
778 alwaysinline = true;
779 break;
780 case attr::NoConvergent:
781 noconvergent = true;
782 break;
783 case attr::MustTail: {
784 const Stmt *Sub = S.getSubStmt();
785 const ReturnStmt *R = cast(Sub);
787 } break;
788 case attr::CXXAssume: {
789 const Expr *Assumption = cast(A)->getAssumption();
793 Builder.CreateAssumption(AssumptionVal);
794 }
795 } break;
796 case attr::HLSLControlFlowHint: {
797 flattenOrBranch = cast(A)->getSemanticSpelling();
798 } break;
799 }
800 }
807 EmitStmt(S.getSubStmt(), S.getAttrs());
808}
809
811
812
813
816
818}
819
820
824 return;
825 }
826
827
830 llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
831
832
834
835
836
837 castllvm::PHINode(IndGotoBB->begin())->addIncoming(V, CurBB);
838
840}
841
843 const Stmt *Else = S.getElse();
844
845
846
847 if (S.isConsteval()) {
848 const Stmt *Executed = S.isNegatedConsteval() ? S.getThen() : Else;
849 if (Executed) {
850 RunCleanupsScope ExecutedScope(*this);
852 }
853 return;
854 }
855
856
857
858 LexicalScope ConditionScope(*this, S.getCond()->getSourceRange());
860
861 if (S.getInit())
863
864 if (S.getConditionVariable())
865 EmitDecl(*S.getConditionVariable());
866
867
868
869 bool CondConstant;
871 S.isConstexpr())) {
872
873 const Stmt *Executed = S.getThen();
874 const Stmt *Skipped = Else;
875 if (!CondConstant)
876 std::swap(Executed, Skipped);
877
878
879
880 if (S.isConstexpr() || (Skipped)) {
881 if (CondConstant)
883 if (Executed) {
884 RunCleanupsScope ExecutedScope(*this);
886 }
888 return;
889 }
890 }
891
892
893
896 llvm::BasicBlock *ElseBlock = ContBlock;
897 if (Else)
899
900
901
902
903
904
905
906
907
908
909
910
916
917
918
919
920
921
922
925 else {
927 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
928 }
929
930
934 else
936 {
937 RunCleanupsScope ThenScope(*this);
939 }
941
942
943 if (Else) {
944 {
945
948 }
949
952 {
953 RunCleanupsScope ElseScope(*this);
955 }
956 {
957
960 }
961 }
962
963
965
966
967
970}
971
973 bool HasEmptyBody) {
976 return false;
977
978
979
980
981
982
984 bool CondIsConstInt =
985 !ControllingExpression ||
988
989 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
990 Result.Val.getInt().getBoolValue());
991
992
993 if (getLangOpts().C11 && !CondIsConstInt)
994 return true;
995
996
997
998
999
1000
1004 if (HasEmptyBody && CondIsTrue) {
1005 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1006 return false;
1007 }
1008 return true;
1009 }
1010 return false;
1011}
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022template static bool hasEmptyLoopBody(const LoopStmt &S) {
1023 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1024 if (S.getInc())
1025 return false;
1026 }
1027 const Stmt *Body = S.getBody();
1028 if (!Body || isa(Body))
1029 return true;
1030 if (const CompoundStmt *Compound = dyn_cast(Body))
1031 return Compound->body_empty();
1032 return false;
1033}
1034
1037
1038
1040 EmitBlock(LoopHeader.getBlock());
1041
1044 emitConvergenceLoopToken(LoopHeader.getBlock()));
1045
1046
1047
1049
1050
1051 BreakContinueStack.push_back(BreakContinue(LoopExit, LoopHeader));
1052
1053
1054
1055
1056
1057
1058
1059
1060 RunCleanupsScope ConditionScope(*this);
1061
1062 if (S.getConditionVariable())
1063 EmitDecl(*S.getConditionVariable());
1064
1065
1066
1067
1069
1070
1071
1072 llvm::ConstantInt *C = dyn_castllvm::ConstantInt(BoolCondVal);
1073 bool EmitBoolCondBranch = ||
->isOne();
1074 const SourceRange &R = S.getSourceRange();
1079
1080
1083
1084
1085 llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
1086 if (EmitBoolCondBranch) {
1087 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
1088 if (ConditionScope.requiresCleanups())
1090 llvm::MDNode *Weights =
1091 createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));
1093 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1095 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1096
1097 if (ExitBlock != LoopExit.getBlock()) {
1100 }
1103 diag::warn_attribute_has_no_effect_on_infinite_loop)
1104 << A << A->getRange();
1106 S.getWhileLoc(),
1107 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1108 << SourceRange(S.getWhileLoc(), S.getRParenLoc());
1109 }
1110
1111
1112
1113 {
1114 RunCleanupsScope BodyScope(*this);
1116
1119 else
1122 }
1123
1124 BreakContinueStack.pop_back();
1125
1126
1127 ConditionScope.ForceCleanup();
1128
1130
1132
1134
1135
1137
1138
1139
1140 if (!EmitBoolCondBranch)
1142
1143
1144
1147
1150}
1151
1156
1158
1159
1160 BreakContinueStack.push_back(BreakContinue(LoopExit, LoopCond));
1161
1162
1164
1167 else
1169
1172
1173 {
1174 RunCleanupsScope BodyScope(*this);
1176 }
1177
1179
1182
1183
1184
1185
1186
1187
1188
1190
1191 BreakContinueStack.pop_back();
1192
1193
1194
1195 llvm::ConstantInt *C = dyn_castllvm::ConstantInt(BoolCondVal);
1196 bool EmitBoolCondBranch = ||
->isZero();
1197
1198 const SourceRange &R = S.getSourceRange();
1203
1204
1205 if (EmitBoolCondBranch) {
1208 BoolCondVal, LoopBody, LoopExit.getBlock(),
1209 createProfileWeightsForLoop(S.getCond(), BackedgeCount));
1210 }
1211
1213
1214
1216
1217
1218
1219 if (!EmitBoolCondBranch)
1221
1222
1223
1226
1229}
1230
1234
1235 LexicalScope ForScope(*this, S.getSourceRange());
1236
1237
1238 if (S.getInit())
1240
1241
1242
1243
1245 llvm::BasicBlock *CondBlock = CondDest.getBlock();
1247
1250
1251 const SourceRange &R = S.getSourceRange();
1256
1257
1258 LexicalScope ConditionScope(*this, S.getSourceRange());
1259
1260
1261
1262
1263
1264
1265
1266
1267 JumpDest Continue;
1268 if (!S.getInc())
1269 Continue = CondDest;
1270 else if (!S.getConditionVariable())
1272 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
1273
1274 if (S.getCond()) {
1275
1276
1277 if (S.getConditionVariable()) {
1278 EmitDecl(*S.getConditionVariable());
1279
1280
1281
1283 BreakContinueStack.back().ContinueBlock = Continue;
1284 }
1285
1286
1287
1290
1291 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
1292
1293
1294 if (ForScope.requiresCleanups())
1296
1297
1299
1300
1301
1303 llvm::MDNode *Weights =
1304 createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));
1306 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1308
1309 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1310
1311 if (ExitBlock != LoopExit.getBlock()) {
1314 }
1315
1317 } else {
1318
1319
1320 }
1321
1322
1325 else
1327 {
1328
1329
1330 RunCleanupsScope BodyScope(*this);
1332 }
1333
1334
1335 if (S.getInc()) {
1340 }
1341
1342 BreakContinueStack.pop_back();
1343
1344 ConditionScope.ForceCleanup();
1345
1348
1349 ForScope.ForceCleanup();
1350
1352
1353
1355
1356
1357
1360
1363}
1364
1365void
1369
1370 LexicalScope ForScope(*this, S.getSourceRange());
1371
1372
1373 if (S.getInit())
1378
1379
1380
1381
1384
1387
1388 const SourceRange &R = S.getSourceRange();
1392
1393
1394
1395 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
1396 if (ForScope.requiresCleanups())
1398
1399
1401
1402
1403
1405 llvm::MDNode *Weights =
1406 createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));
1408 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1410 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1411
1412 if (ExitBlock != LoopExit.getBlock()) {
1415 }
1416
1420 else
1422
1423
1425
1426
1427 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
1428
1429 {
1430
1431 LexicalScope BodyScope(*this, S.getSourceRange());
1432 EmitStmt(S.getLoopVarStmt());
1434 }
1435
1437
1440
1441 BreakContinueStack.pop_back();
1442
1444
1445 ForScope.ForceCleanup();
1446
1448
1449
1451
1452
1453
1456
1459}
1460
1461void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
1468 } else {
1470 true);
1471 }
1473}
1474
1475namespace {
1476
1477struct SaveRetExprRAII {
1479 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1481 }
1482 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1483 const Expr *OldRetExpr;
1485};
1486}
1487
1488
1492 if (calleeQualType->isFunctionPointerType() ||
1493 calleeQualType->isFunctionReferenceType() ||
1494 calleeQualType->isBlockPointerType() ||
1495 calleeQualType->isMemberFunctionPointerType()) {
1497 } else if (auto *ty = dyn_cast(calleeQualType)) {
1498 calleeType = ty;
1499 } else if (auto CMCE = dyn_cast(CE)) {
1500 if (auto methodDecl = CMCE->getMethodDecl()) {
1501
1503 } else {
1504 return false;
1505 }
1506 } else {
1507 return false;
1508 }
1510}
1511
1512
1513
1514
1516 if (requiresReturnValueCheck()) {
1518 auto *SLocPtr =
1519 new llvm::GlobalVariable(CGM.getModule(), SLoc->getType(), false,
1520 llvm::GlobalVariable::PrivateLinkage, SLoc);
1521 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1523 assert(ReturnLocation.isValid() && "No valid return location");
1525 }
1526
1527
1529 Builder.CreateUnreachable();
1530 Builder.ClearInsertionPoint();
1531 }
1532
1533
1534 const Expr *RV = S.getRetValue();
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544 SaveRetExprRAII SaveRetExpr(RV, *this);
1545
1546 RunCleanupsScope cleanupScope(*this);
1547 if (const auto *EWC = dyn_cast_or_null(RV))
1548 RV = EWC->getSubExpr();
1549
1550
1551
1552 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1555 if (auto CE = dyn_cast(RV)) {
1558 }
1559 }
1560 }
1561
1562
1563
1564
1565 if (getLangOpts().ElideConstructors && S.getNRVOCandidate() &&
1566 S.getNRVOCandidate()->isNRVOVariable() &&
1571
1572
1573
1574
1575
1576
1577 if (llvm::Value *NRVOFlag = NRVOFlags[S.getNRVOCandidate()])
1580
1581
1582 if (RV) {
1584 }
1585 } else if (!RV) {
1586
1588
1589
1592 } else {
1598 true);
1599 else
1601 break;
1602 }
1605 true);
1606 break;
1614 break;
1615 }
1616 }
1617
1618 ++NumReturnExprs;
1620 ++NumSimpleReturnExprs;
1621
1622 cleanupScope.ForceCleanup();
1624}
1625
1627
1628
1631
1632 for (const auto *I : S.decls())
1634}
1635
1637 assert(!BreakContinueStack.empty() && "break stmt not in a loop or switch!");
1638
1639
1640
1641
1644
1646}
1647
1649 assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
1650
1651
1652
1653
1656
1658}
1659
1660
1661
1662
1665 assert(S.getRHS() && "Expected RHS value in CaseStmt");
1666
1667 llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(getContext());
1668 llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(getContext());
1669
1670
1671
1672
1676
1677
1678 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1679 return;
1680
1682 llvm::APInt Range = RHS - LHS;
1683
1684 if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
1685
1687 unsigned NCases = Range.getZExtValue() + 1;
1688
1689
1690
1691
1692 uint64_t Weight = Total / NCases, Rem = Total % NCases;
1693 for (unsigned I = 0; I != NCases; ++I) {
1694 if (SwitchWeights)
1695 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1696 else if (SwitchLikelihood)
1697 SwitchLikelihood->push_back(LH);
1698
1699 if (Rem)
1701 SwitchInsn->addCase(Builder.getInt(LHS), CaseDest);
1702 ++LHS;
1703 }
1704 return;
1705 }
1706
1707
1708
1709 llvm::BasicBlock *RestoreBB = Builder.GetInsertBlock();
1710
1711
1712
1713
1714 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1716
1717 CurFn->insert(CurFn->end(), CaseRangeBlock);
1718 Builder.SetInsertPoint(CaseRangeBlock);
1719
1720
1721 llvm::Value *Diff =
1722 Builder.CreateSub(SwitchInsn->getCondition(), Builder.getInt(LHS));
1723 llvm::Value *Cond =
1725
1726 llvm::MDNode *Weights = nullptr;
1727 if (SwitchWeights) {
1729 uint64_t DefaultCount = (*SwitchWeights)[0];
1730 Weights = createProfileWeights(ThisCount, DefaultCount);
1731
1732
1733
1734
1735 (*SwitchWeights)[0] += ThisCount;
1736 } else if (SwitchLikelihood)
1737 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
1738
1739 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
1740
1741
1742 if (RestoreBB)
1743 Builder.SetInsertPoint(RestoreBB);
1744 else
1745 Builder.ClearInsertionPoint();
1746}
1747
1750
1751
1752
1753
1754
1755 if (!SwitchInsn) {
1757 return;
1758 }
1759
1760
1761 if (S.getRHS()) {
1763 return;
1764 }
1765
1766 llvm::ConstantInt *CaseVal =
1767 Builder.getInt(S.getLHS()->EvaluateKnownConstInt(getContext()));
1768
1769
1771 if (auto ICE = dyn_cast(S.getLHS()))
1772 CE = dyn_cast(ICE->getSubExpr());
1773 else
1774 CE = dyn_cast(S.getLHS());
1775 if (CE) {
1776 if (auto DE = dyn_cast(CE->getSubExpr()))
1779 Dbg->EmitGlobalVariable(DE->getDecl(),
1780 APValue(llvm::APSInt(CaseVal->getValue())));
1781 }
1782
1783 if (SwitchLikelihood)
1785
1786
1787
1788
1791 isa(S.getSubStmt())) {
1792 JumpDest Block = BreakContinueStack.back().BreakBlock;
1793
1794
1796 if (SwitchWeights)
1798 SwitchInsn->addCase(CaseVal, Block.getBlock());
1799
1800
1801
1802 if (Builder.GetInsertBlock()) {
1804 Builder.ClearInsertionPoint();
1805 }
1806 return;
1807 }
1808 }
1809
1812 if (SwitchWeights)
1814 SwitchInsn->addCase(CaseVal, CaseDest);
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829 const CaseStmt *CurCase = &S;
1830 const CaseStmt *NextCase = dyn_cast(S.getSubStmt());
1831
1832
1833 while (NextCase && NextCase->getRHS() == nullptr) {
1834 CurCase = NextCase;
1835 llvm::ConstantInt *CaseVal =
1837
1838 if (SwitchWeights)
1843 }
1844
1845
1846 if (SwitchLikelihood)
1848
1849 SwitchInsn->addCase(CaseVal, CaseDest);
1850 NextCase = dyn_cast(CurCase->getSubStmt());
1851 }
1852
1853
1854
1855
1858
1859
1861}
1862
1865
1866
1867
1868 if (!SwitchInsn) {
1870 return;
1871 }
1872
1873 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1874 assert(DefaultBlock->empty() &&
1875 "EmitDefaultStmt: Default block already defined?");
1876
1877 if (SwitchLikelihood)
1879
1881
1883}
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1911 bool &FoundCase,
1913
1914 if (!S)
1916
1917
1918
1919 if (const SwitchCase *SC = dyn_cast(S)) {
1920 if (S == Case) {
1921 FoundCase = true;
1923 ResultStmts);
1924 }
1925
1926
1928 ResultStmts);
1929 }
1930
1931
1932
1933 if (!Case && isa(S))
1935
1936
1937
1938 if (const CompoundStmt *CS = dyn_cast(S)) {
1939
1940
1942 bool StartedInLiveCode = FoundCase;
1943 unsigned StartSize = ResultStmts.size();
1944
1945
1946 if (Case) {
1947
1948
1949
1950 bool HadSkippedDecl = false;
1951
1952
1953
1954 for (; Case && I != E; ++I) {
1956
1960
1961
1962
1963
1964 if (FoundCase) {
1965
1966
1967 if (HadSkippedDecl)
1969
1970 for (++I; I != E; ++I)
1974 }
1975 break;
1977
1978
1979
1980 assert(FoundCase && "Didn't find case but returned fallthrough?");
1981
1982 Case = nullptr;
1983
1984
1985
1986 if (HadSkippedDecl)
1988 break;
1989 }
1990 }
1991
1992 if (!FoundCase)
1994
1995 assert(!HadSkippedDecl && "fallthrough after skipping decl");
1996 }
1997
1998
1999
2000 bool AnyDecls = false;
2001 for (; I != E; ++I) {
2003
2007
2008
2009 break;
2011
2012
2013
2014 for (++I; I != E; ++I)
2018 }
2019 }
2020
2021
2022
2023
2024 if (AnyDecls) {
2025
2026
2027
2028
2029
2031 ResultStmts.resize(StartSize);
2032 ResultStmts.push_back(S);
2033 } else {
2035 }
2036 }
2037
2039 }
2040
2041
2042
2043
2044 if (Case) {
2048 }
2049
2050
2051
2053
2054
2055
2056 ResultStmts.push_back(S);
2058}
2059
2060
2061
2062
2063
2065 const llvm::APSInt &ConstantCondValue,
2069
2070
2071 const SwitchCase *Case = S.getSwitchCaseList();
2072 const DefaultStmt *DefaultCase = nullptr;
2073
2075
2076
2077 if (const DefaultStmt *DS = dyn_cast(Case)) {
2078 DefaultCase = DS;
2079 continue;
2080 }
2081
2082
2083 const CaseStmt *CS = cast(Case);
2084
2085 if (CS->getRHS()) return false;
2086
2087
2089 break;
2090 }
2091
2092
2093
2094 if (!Case) {
2095
2096
2097 if (!DefaultCase)
2099 Case = DefaultCase;
2100 }
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110 bool FoundCase = false;
2111 ResultCase = Case;
2114 FoundCase;
2115}
2116
2117static std::optional<SmallVector<uint64_t, 16>>
2119
2120 if (Likelihoods.size() <= 1)
2121 return std::nullopt;
2122
2123 uint64_t NumUnlikely = 0;
2124 uint64_t NumNone = 0;
2125 uint64_t NumLikely = 0;
2126 for (const auto LH : Likelihoods) {
2127 switch (LH) {
2129 ++NumUnlikely;
2130 break;
2132 ++NumNone;
2133 break;
2135 ++NumLikely;
2136 break;
2137 }
2138 }
2139
2140
2141 if (NumUnlikely == 0 && NumLikely == 0)
2142 return std::nullopt;
2143
2144
2145
2146
2147
2148
2149
2150 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2151 const uint64_t None = Likely / (NumNone + 1);
2152 const uint64_t Unlikely = 0;
2153
2155 Result.reserve(Likelihoods.size());
2156 for (const auto LH : Likelihoods) {
2157 switch (LH) {
2159 Result.push_back(Unlikely);
2160 break;
2163 break;
2165 Result.push_back(Likely);
2166 break;
2167 }
2168 }
2169
2171}
2172
2174
2175 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2178 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2179
2180
2181
2182 llvm::APSInt ConstantCondValue;
2188 if (Case)
2190 RunCleanupsScope ExecutedScope(*this);
2191
2192 if (S.getInit())
2194
2195
2196
2197 if (S.getConditionVariable())
2198 EmitDecl(*S.getConditionVariable());
2199
2200
2201
2202
2203 SwitchInsn = nullptr;
2204
2205
2206
2207 for (unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
2211
2212
2213
2214 SwitchInsn = SavedSwitchInsn;
2215
2216 return;
2217 }
2218 }
2219
2221
2222 RunCleanupsScope ConditionScope(*this);
2223
2224 if (S.getInit())
2226
2227 if (S.getConditionVariable())
2228 EmitDecl(*S.getConditionVariable());
2230
2231
2232
2233
2234
2235 llvm::BasicBlock *DefaultBlock = createBasicBlock("sw.default");
2236 SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock);
2238
2240 unsigned NumCases = 0;
2241 for (const SwitchCase *Case = S.getSwitchCaseList();
2242 Case;
2244 if (isa(Case))
2246 NumCases += 1;
2247 }
2249 SwitchWeights->reserve(NumCases);
2250
2251
2252 SwitchWeights->push_back(DefaultCount);
2255
2257 }
2258
2259 CaseRangeBlock = DefaultBlock;
2260
2261
2262 Builder.ClearInsertionPoint();
2263
2264
2265
2266 JumpDest OuterContinue;
2267 if (!BreakContinueStack.empty())
2268 OuterContinue = BreakContinueStack.back().ContinueBlock;
2269
2270 BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue));
2271
2272
2274
2275 BreakContinueStack.pop_back();
2276
2277
2278
2279 SwitchInsn->setDefaultDest(CaseRangeBlock);
2280
2281
2282 if (!DefaultBlock->getParent()) {
2283
2284
2285 if (ConditionScope.requiresCleanups()) {
2287
2288
2289 } else {
2290 DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock());
2291 delete DefaultBlock;
2292 }
2293 }
2294
2295 ConditionScope.ForceCleanup();
2296
2297
2298 EmitBlock(SwitchExit.getBlock(), true);
2300
2301
2302
2303
2304 auto *Call = dyn_cast(S.getCond());
2306 auto *FD = dyn_cast_or_null(Call->getCalleeDecl());
2307 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2309 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2310 MDHelper.createUnpredictable());
2311 }
2312 }
2313
2314 if (SwitchWeights) {
2315 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2316 "switch weights do not match switch cases");
2317
2318 if (SwitchWeights->size() > 1)
2319 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2320 createProfileWeights(*SwitchWeights));
2321 delete SwitchWeights;
2322 } else if (SwitchLikelihood) {
2323 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2324 "switch likelihoods do not match switch cases");
2325 std::optional<SmallVector<uint64_t, 16>> LHW =
2327 if (LHW) {
2329 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2330 createProfileWeights(*LHW));
2331 }
2332 delete SwitchLikelihood;
2333 }
2334 SwitchInsn = SavedSwitchInsn;
2335 SwitchWeights = SavedSwitchWeights;
2336 SwitchLikelihood = SavedSwitchLikelihood;
2337 CaseRangeBlock = SavedCRBlock;
2338}
2339
2340static std::string
2344
2345 while (*Constraint) {
2346 switch (*Constraint) {
2347 default:
2348 Result += Target.convertConstraint(Constraint);
2349 break;
2350
2351 case '*':
2352 case '?':
2353 case '!':
2354 case '=':
2355 case '+':
2356 break;
2357 case '#':
2358 while (Constraint[1] && Constraint[1] != ',')
2359 Constraint++;
2360 break;
2361 case '&':
2362 case '%':
2363 Result += *Constraint;
2364 while (Constraint[1] && Constraint[1] == *Constraint)
2365 Constraint++;
2366 break;
2367 case ',':
2369 break;
2370 case 'g':
2372 break;
2373 case '[': {
2374 assert(OutCons &&
2375 "Must pass output names to constraints with a symbolic name");
2376 unsigned Index;
2377 bool result = Target.resolveSymbolicName(Constraint, *OutCons, Index);
2378 assert(result && "Could not resolve symbolic name"); (void)result;
2379 Result += llvm::utostr(Index);
2380 break;
2381 }
2382 }
2383
2384 Constraint++;
2385 }
2386
2388}
2389
2390
2391
2392
2393static std::string
2396 const AsmStmt &Stmt, const bool EarlyClobber,
2397 std::string *GCCReg = nullptr) {
2398 const DeclRefExpr *AsmDeclRef = dyn_cast(&AsmExpr);
2399 if (!AsmDeclRef)
2400 return Constraint;
2404 return Constraint;
2406 return Constraint;
2409 return Constraint;
2410 StringRef Register = Attr->getLabel();
2411 assert(Target.isValidGCCRegisterName(Register));
2412
2413
2415 if (Target.validateOutputConstraint(Info) &&
2418 return Constraint;
2419 }
2420
2421 Register = Target.getNormalizedGCCRegisterName(Register);
2422 if (GCCReg != nullptr)
2423 *GCCReg = Register.str();
2424 return (EarlyClobber ? "&{" : "{") + Register.str() + "}";
2425}
2426
2427std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2433
2434 llvm::Type *Ty = ConvertType(InputType);
2436 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2437 getTargetHooks().isScalarizableAsmOperand(*this, Ty)) {
2438 Ty = llvm::IntegerType::get(getLLVMContext(), Size);
2439
2441 nullptr};
2442 }
2443 }
2444
2446 ConstraintStr += '*';
2448}
2449
2450std::pair<llvm::Value *, llvm::Type *>
2452 const Expr *InputExpr,
2453 std::string &ConstraintStr) {
2454
2455
2460
2461 llvm::APSInt IntResult;
2464 return {llvm::ConstantInt::get(getLLVMContext(), IntResult), nullptr};
2465 }
2466
2470 nullptr};
2471 }
2472
2476 if (InputExpr->getStmtClass() == Expr::CXXThisExprClass)
2480 return EmitAsmInputLValue(Info, Dest, InputExpr->getType(), ConstraintStr,
2482}
2483
2484
2485
2486
2487
2491
2492 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2494 StringRef StrVal = Str->getString();
2495 if (!StrVal.empty()) {
2498 unsigned StartToken = 0;
2499 unsigned ByteOffset = 0;
2500
2501
2502
2503 for (unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2504 if (StrVal[i] != '\n') continue;
2506 i + 1, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset);
2507 Locs.push_back(llvm::ConstantAsMetadata::get(
2509 }
2510 }
2511
2512 return llvm::MDNode::get(CGF.getLLVMContext(), Locs);
2513}
2514
2516 bool HasUnwindClobber, bool ReadOnly,
2517 bool ReadNone, bool NoMerge, bool NoConvergent,
2519 const std::vector<llvm::Type *> &ResultRegTypes,
2520 const std::vector<llvm::Type *> &ArgElemTypes,
2522 std::vector<llvm::Value *> &RegResults) {
2523 if (!HasUnwindClobber)
2524 Result.addFnAttr(llvm::Attribute::NoUnwind);
2525
2526 if (NoMerge)
2527 Result.addFnAttr(llvm::Attribute::NoMerge);
2528
2529 if (!HasSideEffect) {
2530 if (ReadNone)
2531 Result.setDoesNotAccessMemory();
2532 else if (ReadOnly)
2533 Result.setOnlyReadsMemory();
2534 }
2535
2536
2537 for (auto Pair : llvm::enumerate(ArgElemTypes)) {
2538 if (Pair.value()) {
2539 auto Attr = llvm::Attribute::get(
2540 CGF.getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2541 Result.addParamAttr(Pair.index(), Attr);
2542 }
2543 }
2544
2545
2546
2547 if (const auto *gccAsmStmt = dyn_cast(&S))
2548 Result.setMetadata("srcloc",
2550 else {
2551
2552 llvm::Constant *Loc =
2553 llvm::ConstantInt::get(CGF.Int64Ty, S.getAsmLoc().getRawEncoding());
2554 Result.setMetadata("srcloc",
2556 llvm::ConstantAsMetadata::get(Loc)));
2557 }
2558
2560
2561
2562
2563
2564 Result.addFnAttr(llvm::Attribute::Convergent);
2565
2566 if (ResultRegTypes.size() == 1) {
2567 RegResults.push_back(&Result);
2568 } else {
2569 for (unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2570 llvm::Value *Tmp = CGF.Builder.CreateExtractValue(&Result, i, "asmresult");
2571 RegResults.push_back(Tmp);
2572 }
2573 }
2574}
2575
2576static void
2583 const llvm::BitVector &ResultTypeRequiresCast,
2584 const llvm::BitVector &ResultRegIsFlagReg) {
2588
2589 assert(RegResults.size() == ResultRegTypes.size());
2590 assert(RegResults.size() == ResultTruncRegTypes.size());
2591 assert(RegResults.size() == ResultRegDests.size());
2592
2593
2594 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2595 assert(ResultRegIsFlagReg.size() <= ResultRegDests.size());
2596
2597 for (unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2598 llvm::Value *Tmp = RegResults[i];
2599 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2600
2601 if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
2602
2603
2604 llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2);
2605 llvm::Value *IsBooleanValue =
2606 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two);
2607 llvm::Function *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume);
2608 Builder.CreateCall(FnAssume, IsBooleanValue);
2609 }
2610
2611
2612
2613 if (ResultRegTypes[i] != TruncTy) {
2614
2615
2616
2617 if (TruncTy->isFloatingPointTy())
2618 Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
2619 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2620 uint64_t ResSize = CGM.getDataLayout().getTypeSizeInBits(TruncTy);
2621 Tmp = Builder.CreateTrunc(
2622 Tmp, llvm::IntegerType::get(CTX, (unsigned)ResSize));
2623 Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
2624 } else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2625 uint64_t TmpSize =
2627 Tmp = Builder.CreatePtrToInt(
2628 Tmp, llvm::IntegerType::get(CTX, (unsigned)TmpSize));
2629 Tmp = Builder.CreateTrunc(Tmp, TruncTy);
2630 } else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2631 Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2632 } else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2633 Tmp = Builder.CreateBitCast(Tmp, TruncTy);
2634 }
2635 }
2636
2637 LValue Dest = ResultRegDests[i];
2638
2639
2640 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2645 continue;
2646 }
2647
2651 const Expr *OutExpr = S.getOutputExpr(i);
2653 diag::err_store_value_to_reg);
2654 return;
2655 }
2657 }
2659 }
2660}
2661
2664 constexpr auto Name = "__ASM__hipstdpar_unsupported";
2665
2666 StringRef Asm;
2667 if (auto GCCAsm = dyn_cast(&S))
2668 Asm = GCCAsm->getAsmString()->getString();
2669
2671
2672 auto StrTy = llvm::ConstantDataArray::getString(Ctx, Asm);
2673 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2674 {StrTy->getType()}, false);
2675 auto UBF = CGF->CGM.getModule().getOrInsertFunction(Name, FnTy);
2676
2677 CGF->Builder.CreateCall(UBF, {StrTy});
2678}
2679
2681
2682 CodeGenFunction::RunCleanupsScope Cleanups(*this);
2683
2684
2685 std::string AsmString = S.generateAsmString(getContext());
2686
2687
2690
2692 bool IsValidTargetAsm = true;
2693 for (unsigned i = 0, e = S.getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2694 StringRef Name;
2695 if (const GCCAsmStmt *GAS = dyn_cast(&S))
2696 Name = GAS->getOutputName(i);
2699 if (IsHipStdPar && !IsValid)
2700 IsValidTargetAsm = false;
2701 else
2702 assert(IsValid && "Failed to parse output constraint");
2703 OutputConstraintInfos.push_back(Info);
2704 }
2705
2706 for (unsigned i = 0, e = S.getNumInputs(); i != e && IsValidTargetAsm; i++) {
2707 StringRef Name;
2708 if (const GCCAsmStmt *GAS = dyn_cast(&S))
2709 Name = GAS->getInputName(i);
2711 bool IsValid =
2713 if (IsHipStdPar && !IsValid)
2714 IsValidTargetAsm = false;
2715 else
2716 assert(IsValid && "Failed to parse input constraint");
2717 InputConstraintInfos.push_back(Info);
2718 }
2719
2720 if (!IsValidTargetAsm)
2722
2723 std::string Constraints;
2724
2725 std::vector ResultRegDests;
2726 std::vector ResultRegQualTys;
2727 std::vector<llvm::Type *> ResultRegTypes;
2728 std::vector<llvm::Type *> ResultTruncRegTypes;
2729 std::vector<llvm::Type *> ArgTypes;
2730 std::vector<llvm::Type *> ArgElemTypes;
2731 std::vectorllvm::Value\* Args;
2732 llvm::BitVector ResultTypeRequiresCast;
2733 llvm::BitVector ResultRegIsFlagReg;
2734
2735
2736 std::string InOutConstraints;
2737 std::vectorllvm::Value\* InOutArgs;
2738 std::vectorllvm::Type\* InOutArgTypes;
2739 std::vectorllvm::Type\* InOutArgElemTypes;
2740
2741
2742 std::vectorstd::string OutputConstraints;
2743
2744
2745 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2746
2747
2748
2749
2750
2751
2752
2753 bool ReadOnly = true, ReadNone = true;
2754
2755 for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
2757
2758
2759 std::string OutputConstraint(S.getOutputConstraint(i));
2761 getTarget(), &OutputConstraintInfos);
2762
2763 const Expr *OutExpr = S.getOutputExpr(i);
2765
2766 std::string GCCReg;
2770 &GCCReg);
2771
2772 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2773 CGM.Error(S.getAsmLoc(), "multiple outputs to hard register: " + GCCReg);
2774
2775 OutputConstraints.push_back(OutputConstraint);
2777 if (!Constraints.empty())
2778 Constraints += ',';
2779
2780
2781
2785 if (!Info.allowsMemory() && IsScalarOrAggregate) {
2786
2787 Constraints += "=" + OutputConstraint;
2788 ResultRegQualTys.push_back(QTy);
2789 ResultRegDests.push_back(Dest);
2790
2791 bool IsFlagReg = llvm::StringRef(OutputConstraint).starts_with("{@cc");
2792 ResultRegIsFlagReg.push_back(IsFlagReg);
2793
2797 Ty->isAggregateType());
2798
2799 ResultTruncRegTypes.push_back(Ty);
2800 ResultTypeRequiresCast.push_back(RequiresCast);
2801
2802 if (RequiresCast) {
2804 if (Size)
2805 Ty = llvm::IntegerType::get(getLLVMContext(), Size);
2806 else
2808 }
2809 ResultRegTypes.push_back(Ty);
2810
2811
2812
2814 unsigned InputNo;
2815 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2818 break;
2819 }
2820 assert(InputNo != S.getNumInputs() && "Didn't find matching input!");
2821
2822 QualType InputTy = S.getInputExpr(InputNo)->getType();
2824
2827
2828 ResultRegTypes.back() = ConvertType(InputTy);
2829 }
2830 }
2831 if (llvm::Type* AdjTy =
2832 getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,
2833 ResultRegTypes.back()))
2834 ResultRegTypes.back() = AdjTy;
2835 else {
2837 diag::err_asm_invalid_type_in_input)
2838 << OutExpr->getType() << OutputConstraint;
2839 }
2840
2841
2842 if (auto *VT = dyn_castllvm::VectorType(ResultRegTypes.back()))
2843 LargestVectorWidth =
2844 std::max((uint64_t)LargestVectorWidth,
2845 VT->getPrimitiveSizeInBits().getKnownMinValue());
2846 } else {
2848
2849
2850
2851
2852
2855
2856 ArgTypes.push_back(DestAddr.getType());
2859 Constraints += "=*";
2860 Constraints += OutputConstraint;
2861 ReadOnly = ReadNone = false;
2862 }
2863
2865 InOutConstraints += ',';
2866
2867 const Expr *InputExpr = S.getOutputExpr(i);
2868 llvm::Value *Arg;
2869 llvm::Type *ArgElemType;
2870 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
2871 Info, Dest, InputExpr->getType(), InOutConstraints,
2873
2874 if (llvm::Type* AdjTy =
2875 getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,
2876 Arg->getType()))
2877 Arg = Builder.CreateBitCast(Arg, AdjTy);
2878
2879
2880 if (auto *VT = dyn_castllvm::VectorType(Arg->getType()))
2881 LargestVectorWidth =
2882 std::max((uint64_t)LargestVectorWidth,
2883 VT->getPrimitiveSizeInBits().getKnownMinValue());
2884
2886 InOutConstraints += llvm::utostr(i);
2887 else
2888 InOutConstraints += OutputConstraint;
2889
2890 InOutArgTypes.push_back(Arg->getType());
2891 InOutArgElemTypes.push_back(ArgElemType);
2892 InOutArgs.push_back(Arg);
2893 }
2894 }
2895
2896
2897
2898 if (isa(&S)) {
2901
2904 *this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
2905 ResultRegDests, AsmString, S.getNumOutputs());
2907 }
2908 }
2909
2910 for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
2911 const Expr *InputExpr = S.getInputExpr(i);
2912
2914
2916 ReadNone = false;
2917
2918 if (!Constraints.empty())
2919 Constraints += ',';
2920
2921
2922 std::string InputConstraint(S.getInputConstraint(i));
2924 &OutputConstraintInfos);
2925
2928 getTarget(), CGM, S, false );
2929
2930 std::string ReplaceConstraint (InputConstraint);
2931 llvm::Value *Arg;
2932 llvm::Type *ArgElemType;
2933 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
2934
2935
2936
2937
2938
2939
2942 QualType OutputType = S.getOutputExpr(Output)->getType();
2944
2947
2948 if (isallvm::PointerType(Arg->getType()))
2950 llvm::Type *OutputTy = ConvertType(OutputType);
2951 if (isallvm::IntegerType(OutputTy))
2952 Arg = Builder.CreateZExt(Arg, OutputTy);
2953 else if (isallvm::PointerType(OutputTy))
2955 else if (OutputTy->isFloatingPointTy())
2956 Arg = Builder.CreateFPExt(Arg, OutputTy);
2957 }
2958
2959 ReplaceConstraint = OutputConstraints[Output];
2960 }
2961 if (llvm::Type* AdjTy =
2962 getTargetHooks().adjustInlineAsmType(*this, ReplaceConstraint,
2963 Arg->getType()))
2964 Arg = Builder.CreateBitCast(Arg, AdjTy);
2965 else
2966 CGM.getDiags().Report(S.getAsmLoc(), diag::err_asm_invalid_type_in_input)
2967 << InputExpr->getType() << InputConstraint;
2968
2969
2970 if (auto *VT = dyn_castllvm::VectorType(Arg->getType()))
2971 LargestVectorWidth =
2972 std::max((uint64_t)LargestVectorWidth,
2973 VT->getPrimitiveSizeInBits().getKnownMinValue());
2974
2975 ArgTypes.push_back(Arg->getType());
2976 ArgElemTypes.push_back(ArgElemType);
2977 Args.push_back(Arg);
2978 Constraints += InputConstraint;
2979 }
2980
2981
2982 for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
2983 ArgTypes.push_back(InOutArgTypes[i]);
2984 ArgElemTypes.push_back(InOutArgElemTypes[i]);
2985 Args.push_back(InOutArgs[i]);
2986 }
2987 Constraints += InOutConstraints;
2988
2989
2991 llvm::BasicBlock *Fallthrough = nullptr;
2992 bool IsGCCAsmGoto = false;
2993 if (const auto *GS = dyn_cast(&S)) {
2994 IsGCCAsmGoto = GS->isAsmGoto();
2995 if (IsGCCAsmGoto) {
2996 for (const auto *E : GS->labels()) {
2998 Transfer.push_back(Dest.getBlock());
2999 if (!Constraints.empty())
3000 Constraints += ',';
3001 Constraints += "!i";
3002 }
3004 }
3005 }
3006
3007 bool HasUnwindClobber = false;
3008
3009
3010 for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
3011 StringRef Clobber = S.getClobber(i);
3012
3013 if (Clobber == "memory")
3014 ReadOnly = ReadNone = false;
3015 else if (Clobber == "unwind") {
3016 HasUnwindClobber = true;
3017 continue;
3018 } else if (Clobber != "cc") {
3021 getTarget().isSPRegName(Clobber)) {
3023 diag::warn_stack_clash_protection_inline_asm);
3024 }
3025 }
3026
3027 if (isa(&S)) {
3028 if (Clobber == "eax" || Clobber == "edx") {
3029 if (Constraints.find("=&A") != std:🧵:npos)
3030 continue;
3031 std:🧵:size_type position1 =
3032 Constraints.find("={" + Clobber.str() + "}");
3033 if (position1 != std:🧵:npos) {
3034 Constraints.insert(position1 + 1, "&");
3035 continue;
3036 }
3037 std:🧵:size_type position2 = Constraints.find("=A");
3038 if (position2 != std:🧵:npos) {
3039 Constraints.insert(position2 + 1, "&");
3040 continue;
3041 }
3042 }
3043 }
3044 if (!Constraints.empty())
3045 Constraints += ',';
3046
3047 Constraints += "~{";
3048 Constraints += Clobber;
3049 Constraints += '}';
3050 }
3051
3052 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
3053 "unwind clobber can't be used with asm goto");
3054
3055
3057 if (!MachineClobbers.empty()) {
3058 if (!Constraints.empty())
3059 Constraints += ',';
3060 Constraints += MachineClobbers;
3061 }
3062
3063 llvm::Type *ResultType;
3064 if (ResultRegTypes.empty())
3065 ResultType = VoidTy;
3066 else if (ResultRegTypes.size() == 1)
3067 ResultType = ResultRegTypes[0];
3068 else
3069 ResultType = llvm::StructType::get(getLLVMContext(), ResultRegTypes);
3070
3071 llvm::FunctionType *FTy =
3072 llvm::FunctionType::get(ResultType, ArgTypes, false);
3073
3074 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
3075
3076 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3078 ? llvm::InlineAsm::AD_ATT
3079 : llvm::InlineAsm::AD_Intel;
3080 llvm::InlineAsm::AsmDialect AsmDialect = isa(&S) ?
3081 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3082
3083 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3084 FTy, AsmString, Constraints, HasSideEffect,
3085 false, AsmDialect, HasUnwindClobber);
3086 std::vectorllvm::Value\* RegResults;
3087 llvm::CallBrInst *CBR;
3088 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3089 CBRRegResults;
3090 if (IsGCCAsmGoto) {
3091 CBR = Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3093 UpdateAsmCallInst(*CBR, HasSideEffect, false, ReadOnly,
3096 ArgElemTypes, *this, RegResults);
3097
3098
3099
3100 if (!RegResults.empty()) {
3101 unsigned i = 0;
3102 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3103 llvm::Twine SynthName = Dest->getName() + ".split";
3105 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
3106 Builder.SetInsertPoint(SynthBB);
3107
3108 if (ResultRegTypes.size() == 1) {
3109 CBRRegResults[SynthBB].push_back(CBR);
3110 } else {
3111 for (unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3112 llvm::Value *Tmp = Builder.CreateExtractValue(CBR, j, "asmresult");
3113 CBRRegResults[SynthBB].push_back(Tmp);
3114 }
3115 }
3116
3119 CBR->setIndirectDest(i++, SynthBB);
3120 }
3121 }
3122 } else if (HasUnwindClobber) {
3127 ArgElemTypes, *this, RegResults);
3128 } else {
3129 llvm::CallInst *Result =
3134 ArgElemTypes, *this, RegResults);
3135 }
3136
3137 EmitAsmStores(*this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3138 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3139 ResultRegIsFlagReg);
3140
3141
3142
3143
3144 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3145 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3146 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
3147 Builder.SetInsertPoint(Succ, --(Succ->end()));
3148 EmitAsmStores(*this, S, CBRRegResults[Succ], ResultRegTypes,
3149 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3150 ResultTypeRequiresCast, ResultRegIsFlagReg);
3151 }
3152 }
3153}
3154
3156 const RecordDecl *RD = S.getCapturedRecordDecl();
3158
3159
3162
3165 E = S.capture_init_end();
3166 I != E; ++I, ++CurField) {
3168 if (CurField->hasCapturedVLAType()) {
3170 } else {
3172 }
3173 }
3174
3175 return SlotLV;
3176}
3177
3178
3179
3180llvm::Function *
3183
3184
3186 CGCapturedStmtRAII CapInfoRAII(CGF, new CGCapturedStmtInfo(S, K));
3187 llvm::Function *F = CGF.GenerateCapturedStmtFunction(S);
3188 delete CGF.CapturedStmtInfo;
3189
3190
3192
3193 return F;
3194}
3195
3199}
3200
3201
3202llvm::Function *
3205 "CapturedStmtInfo should be set when generating the captured function");
3206 const CapturedDecl *CD = S.getCapturedDecl();
3207 const RecordDecl *RD = S.getCapturedRecordDecl();
3209 assert(CD->hasBody() && "missing CapturedDecl body");
3210
3211
3215
3216
3220
3221 llvm::Function *F =
3222 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3226 F->addFnAttr(llvm::Attribute::NoUnwind);
3227
3228
3231
3234
3235
3238 for (auto *FD : RD->fields()) {
3239 if (FD->hasCapturedVLAType()) {
3240 auto *ExprArg =
3243 auto VAT = FD->getCapturedVLAType();
3244 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3245 }
3246 }
3247
3248
3253 }
3254
3258
3259 return F;
3260}
3261
3262
3263
3265 for (auto &I : *BB) {
3266 if (auto *CI = dyn_castllvm::ConvergenceControlInst(&I))
3267 return CI;
3268 }
3269 return nullptr;
3270}
3271
3272llvm::CallBase *
3273CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3275 assert(ParentToken);
3276
3277 llvm::Value *bundleArgs[] = {ParentToken};
3278 llvm::OperandBundleDef OB("convergencectrl", bundleArgs);
3279 auto *Output = llvm::CallBase::addOperandBundle(
3280 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3281 Input->replaceAllUsesWith(Output);
3282 Input->eraseFromParent();
3283 return Output;
3284}
3285
3286llvm::ConvergenceControlInst *
3287CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
3288 CGBuilderTy::InsertPoint IP = Builder.saveIP();
3289 if (BB->empty())
3290 Builder.SetInsertPoint(BB);
3291 else
3292 Builder.SetInsertPoint(BB->getFirstInsertionPt());
3293
3294 llvm::CallBase *CB = Builder.CreateIntrinsic(
3295 llvm::Intrinsic::experimental_convergence_loop, {}, {});
3297
3298 CB = addConvergenceControlToken(CB);
3299 return castllvm::ConvergenceControlInst(CB);
3300}
3301
3302llvm::ConvergenceControlInst *
3303CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3304 llvm::BasicBlock *BB = &F->getEntryBlock();
3308
3309
3310
3311 F->setConvergent();
3312
3313 CGBuilderTy::InsertPoint IP = Builder.saveIP();
3314 Builder.SetInsertPoint(&BB->front());
3315 llvm::CallBase *I = Builder.CreateIntrinsic(
3316 llvm::Intrinsic::experimental_convergence_entry, {}, {});
3317 assert(isallvm::IntrinsicInst(I));
3319
3320 return castllvm::ConvergenceControlInst(I);
3321}
Defines enum values for all the target-independent builtin functions.
static std::string AddVariableConstraints(const std::string &Constraint, const Expr &AsmExpr, const TargetInfo &Target, CodeGenModule &CGM, const AsmStmt &Stmt, const bool EarlyClobber, std::string *GCCReg=nullptr)
AddVariableConstraints - Look at AsmExpr and if it is a variable declared as using a particular regis...
static bool FindCaseStatementsForValue(const SwitchStmt &S, const llvm::APSInt &ConstantCondValue, SmallVectorImpl< const Stmt * > &ResultStmts, ASTContext &C, const SwitchCase *&ResultCase)
FindCaseStatementsForValue - Find the case statement being jumped to and then invoke CollectStatement...
static llvm::ConvergenceControlInst * getConvergenceToken(llvm::BasicBlock *BB)
static void EmitHipStdParUnsupportedAsm(CodeGenFunction *CGF, const AsmStmt &S)
static std::optional< SmallVector< uint64_t, 16 > > getLikelihoodWeights(ArrayRef< Stmt::Likelihood > Likelihoods)
static llvm::MDNode * getAsmSrcLocInfo(const StringLiteral *Str, CodeGenFunction &CGF)
getAsmSrcLocInfo - Return the !srcloc metadata node to attach to an inline asm call instruction.
static std::string SimplifyConstraint(const char *Constraint, const TargetInfo &Target, SmallVectorImpl< TargetInfo::ConstraintInfo > *OutCons=nullptr)
static bool isSwiftAsyncCallee(const CallExpr *CE)
Determine if the given call uses the swiftasync calling convention.
static CSFC_Result CollectStatementsForCase(const Stmt *S, const SwitchCase *Case, bool &FoundCase, SmallVectorImpl< const Stmt * > &ResultStmts)
static void EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S, const llvm::ArrayRef< llvm::Value * > RegResults, const llvm::ArrayRef< llvm::Type * > ResultRegTypes, const llvm::ArrayRef< llvm::Type * > ResultTruncRegTypes, const llvm::ArrayRef< LValue > ResultRegDests, const llvm::ArrayRef< QualType > ResultRegQualTys, const llvm::BitVector &ResultTypeRequiresCast, const llvm::BitVector &ResultRegIsFlagReg)
static bool hasEmptyLoopBody(const LoopStmt &S)
CSFC_Result
CollectStatementsForCase - Given the body of a 'switch' statement and a constant value that is being ...
static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, bool HasUnwindClobber, bool ReadOnly, bool ReadNone, bool NoMerge, bool NoConvergent, const AsmStmt &S, const std::vector< llvm::Type * > &ResultRegTypes, const std::vector< llvm::Type * > &ArgElemTypes, CodeGenFunction &CGF, std::vector< llvm::Value * > &RegResults)
llvm::MachO::Target Target
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Defines the SourceManager interface.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
bool toIntegralConstant(APSInt &Result, QualType SrcTy, const ASTContext &Ctx) const
Try to convert this value to an integral constant.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
QualType getTagDeclType(const TagDecl *Decl) const
Return the unique reference to the type for the specified TagDecl (struct/union/class/enum) decl.
QualType getRecordType(const RecordDecl *Decl) const
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
Attr - This represents one attribute.
Represents an attribute applied to a statement.
BreakStmt - This represents a break.
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Represents the body of a CapturedStmt, and serves as its DeclContext.
ImplicitParamDecl * getContextParam() const
Retrieve the parameter containing captured variables.
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
This captures a statement into a function.
Expr *const * const_capture_init_iterator
Const iterator that walks over the capture initialization arguments.
CapturedRegionKind getCapturedRegionKind() const
Retrieve the captured region kind.
CaseStmt - Represent a case statement.
bool hasProfileClangInstr() const
Check if Clang profile instrumenation is on.
bool hasReducedDebugInfo() const
Check if type and variable info should be emitted.
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::PointerType * getType() const
Return the type of the pointer value.
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
A scoped helper to set the current debug location to the specified location or preferred location of ...
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateFlagStore(bool Value, llvm::Value *Addr)
Emit a store to an i1 flag variable.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
CGFunctionInfo - Class to encapsulate the information about a function definition.
ABIArgInfo & getReturnInfo()
CallingConv getASTCallingConvention() const
getASTCallingConvention() - Return the AST-specified calling convention.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual llvm::Value * getContextValue() const
virtual void setContextValue(llvm::Value *V)
bool isCXXThisExprCaptured() const
virtual FieldDecl * getThisFieldDecl() const
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual StringRef getHelperName() const
Get the name of the capture helper.
void rescopeLabels()
Change the cleanup scope of the labels in this lexical scope to match the scope of the enclosing cont...
void addLabel(const LabelDecl *label)
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitGotoStmt(const GotoStmt &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
bool checkIfLoopMustProgress(const Expr *, bool HasEmptyBody)
Returns true if a loop must make progress, which means the mustprogress attribute can be added.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
static bool ContainsLabel(const Stmt *S, bool IgnoreCaseStmts=false)
ContainsLabel - Return true if the statement contains a label in it.
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
void EmitSehCppScopeBegin()
void EmitIfStmt(const IfStmt &S)
void EmitWhileStmt(const WhileStmt &S, ArrayRef< const Attr * > Attrs={})
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
llvm::DenseMap< const VarDecl *, llvm::Value * > NRVOFlags
A mapping from NRVO variables to the flags used to indicate when the NRVO has been applied to this va...
bool IsOutlinedSEHHelper
True if the current function is an outlined SEH helper.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
Address EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
void EmitOMPReverseDirective(const OMPReverseDirective &S)
static bool hasScalarEvaluationKind(QualType T)
void EmitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &S)
CGCapturedStmtInfo * CapturedStmtInfo
void EmitIndirectGotoStmt(const IndirectGotoStmt &S)
void EmitDecl(const Decl &D)
EmitDecl - Emit a declaration.
void EmitCXXTryStmt(const CXXTryStmt &S)
bool EmitSimpleStmt(const Stmt *S, ArrayRef< const Attr * > Attrs)
EmitSimpleStmt - Try to emit a "simple" statement which does not necessarily require an insertion poi...
void EmitLabel(const LabelDecl *D)
EmitLabel - Emit the block for the given label.
void EmitOpenACCInitConstruct(const OpenACCInitConstruct &S)
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
SmallVector< llvm::ConvergenceControlInst *, 4 > ConvergenceTokenStack
Stack to track the controlled convergence tokens.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitCaseStmt(const CaseStmt &S, ArrayRef< const Attr * > Attrs)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitDefaultStmt(const DefaultStmt &S, ArrayRef< const Attr * > Attrs)
const LangOptions & getLangOpts() const
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
void EmitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &S)
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
bool InNoConvergentAttributedStmt
True if the current statement has noconvergent attribute.
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
SmallVector< llvm::OperandBundleDef, 1 > getBundlesForFunclet(llvm::Value *Callee)
void EmitOpenACCWaitConstruct(const OpenACCWaitConstruct &S)
llvm::Value * EmitCheckedArgForAssume(const Expr *E)
Emits an argument for a call to a __builtin_assume.
void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
void SimplifyForwardingBlocks(llvm::BasicBlock *BB)
SimplifyForwardingBlocks - If the given basic block is only a branch to another basic block,...
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
void EmitBlockAfterUses(llvm::BasicBlock *BB)
EmitBlockAfterUses - Emit the given block somewhere hopefully near its uses, and leave the insertion ...
void EmitContinueStmt(const ContinueStmt &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
bool InNoMergeAttributedStmt
True if the current statement has nomerge attribute.
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
LValue MakeAddrLValueWithoutTBAA(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
JumpDest ReturnBlock
ReturnBlock - Unified return block.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitOMPFlushDirective(const OMPFlushDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)
void EmitSEHLeaveStmt(const SEHLeaveStmt &S)
void EmitAttributedStmt(const AttributedStmt &S)
void EmitOMPCancelDirective(const OMPCancelDirective &S)
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitCaseStmtRange(const CaseStmt &S, ArrayRef< const Attr * > Attrs)
const TargetInfo & getTarget() const
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef< const Attr * > Attrs={})
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitLabelStmt(const LabelStmt &S)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
const Expr * RetExpr
If a return statement is being visited, this holds the return statment's result expression.
void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init)
void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit)
EmitComplexExprIntoLValue - Emit the given expression of complex type and place its result into the s...
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S)
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
void EmitForStmt(const ForStmt &S, ArrayRef< const Attr * > Attrs={})
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
void EmitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &S)
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
void EmitOMPParallelForDirective(const OMPParallelForDirective &S)
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
uint64_t getCurrentProfileCount()
Get the profiler's current count.
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)
Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...
void EmitSwitchStmt(const SwitchStmt &S)
CGDebugInfo * getDebugInfo()
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
void EmitOpenACCDataConstruct(const OpenACCDataConstruct &S)
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
void EmitSEHTryStmt(const SEHTryStmt &S)
void EmitOMPInteropDirective(const OMPInteropDirective &S)
const TargetCodeGenInfo & getTargetHooks() const
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
RValue EmitReferenceBindingToExpr(const Expr *E)
Emits a reference binding to the passed in expression.
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
void EmitDeclStmt(const DeclStmt &S)
void EmitOMPScopeDirective(const OMPScopeDirective &S)
bool InNoInlineAttributedStmt
True if the current statement has noinline attribute.
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitCoroutineBody(const CoroutineBodyStmt &S)
Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
ASTContext & getContext() const
void EmitOpenACCLoopConstruct(const OpenACCLoopConstruct &S)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
void EmitOMPTileDirective(const OMPTileDirective &S)
JumpDest getJumpDestForLabel(const LabelDecl *S)
getBasicBlockForLabel - Return the LLVM basicblock that the specified label maps to.
void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S)
llvm::Function * EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K)
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
llvm::Type * ConvertType(QualType T)
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
void EmitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &S)
llvm::CallBase * EmitCallOrInvoke(llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const Twine &Name="")
HLSLControlFlowHintAttr::Spelling HLSLControlFlowAttr
HLSL Branch attribute.
void EmitDoStmt(const DoStmt &S, ArrayRef< const Attr * > Attrs={})
bool InAlwaysInlineAttributedStmt
True if the current statement has always_inline attribute.
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitOpenACCComputeConstruct(const OpenACCComputeConstruct &S)
void EmitOMPSimdDirective(const OMPSimdDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S)
void EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
LValue InitCapturedStruct(const CapturedStmt &S)
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitReturnStmt(const ReturnStmt &S)
unsigned NextCleanupDestIndex
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &S)
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
static bool mightAddDeclToScope(const Stmt *S)
Determine if the given statement might introduce a declaration into the current scope,...
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
static bool hasAggregateEvaluationKind(QualType T)
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
void EmitBreakStmt(const BreakStmt &S)
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV)
const CallExpr * MustTailCall
const CGFunctionInfo * CurFnInfo
bool isObviouslyBranchWithoutCleanups(JumpDest Dest) const
isObviouslyBranchWithoutCleanups - Return true if a branch to the specified destination obviously has...
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
void EmitCoreturnStmt(const CoreturnStmt &S)
void EmitOpenACCSetConstruct(const OpenACCSetConstruct &S)
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)
llvm::LLVMContext & getLLVMContext()
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
bool SawAsmBlock
Whether we processed a Microsoft-style asm block during CodeGen.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
void ResolveBranchFixups(llvm::BasicBlock *Target)
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
llvm::BasicBlock * GetIndirectGotoBlock()
void EmitAsmStmt(const AsmStmt &S)
void EmitObjCAtTryStmt(const ObjCAtTryStmt &S)
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
static bool containsBreak(const Stmt *S)
containsBreak - Return true if the statement contains a break out of it.
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
void ErrorUnsupported(const Stmt *S, const char *Type)
Print out an error that codegen doesn't support the specified stmt yet.
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
void Error(SourceLocation loc, StringRef error)
Emit a general error that something can't be done.
bool shouldEmitConvergenceTokens() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
SanitizerMetadata * getSanitizerMetadata()
ASTContext & getContext() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn)
Assign counters to regions and configure them for PGO of a given function.
void markStmtMaybeUsed(const Stmt *S)
void setCurrentStmt(const Stmt *S)
If the execution count for the current statement is known, record that as the current count.
bool haveRegionCounts() const
Whether or not we have PGO region data for the current function.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
A saved depth on the scope stack.
bool encloses(stable_iterator I) const
Returns true if this scope encloses I.
static stable_iterator invalid()
stable_iterator getInnermostNormalCleanup() const
Returns the innermost normal cleanup on the stack, or stable_end() if there are no normal cleanups.
stable_iterator stable_begin() const
Create a stable reference to the top of the EH stack.
bool empty() const
Determines whether the exception-scopes stack is empty.
bool hasNormalCleanups() const
Determines whether there are any normal cleanups on the stack.
static stable_iterator stable_end()
Create a stable reference to the bottom of the EH stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
llvm::Value * getPointer(CodeGenFunction &CGF) const
Address getAddress() const
void pop()
End the current loop.
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
virtual void addReturnRegisterOutputs(CodeGen::CodeGenFunction &CGF, CodeGen::LValue ReturnValue, std::string &Constraints, std::vector< llvm::Type * > &ResultRegTypes, std::vector< llvm::Type * > &ResultTruncRegTypes, std::vector< CodeGen::LValue > &ResultRegDests, std::string &AsmString, unsigned NumOutputs) const
Adds constraints and types for result registers.
virtual bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, llvm::Type *Ty) const
Target hook to decide whether an inline asm operand can be passed by value.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Stmt *const * const_body_iterator
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
ContinueStmt - This represents a continue.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
DoStmt - This represents a 'do/while' stmt.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
ForStmt - This represents a 'for (init;cond;inc)' stmt.
const Expr * getSubExpr() const
FunctionType - C99 6.7.5.3 - Function Declarators.
CallingConv getCallConv() const
This represents a GCC inline-assembly statement extension.
GlobalDecl - represents a global declaration.
GotoStmt - This represents a direct goto.
IfStmt - This represents an if/then/else.
IndirectGotoStmt - This represents an indirect goto.
Represents the declaration of a label.
LabelStmt - Represents a label, which has a substatement.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool assumeFunctionsAreConvergent() const
Represents a point when we exit a loop.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType getCanonicalType() const
The collection of all-type qualifiers we support.
Represents a struct/union/class.
field_range fields() const
field_iterator field_begin() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
StmtClass getStmtClass() const
Likelihood
The likelihood of a branch being taken.
@ LH_Unlikely
Branch has the [[unlikely]] attribute.
@ LH_None
No attribute set or branches of the IfStmt have the same attribute.
@ LH_Likely
Branch has the [[likely]] attribute.
static const Attr * getLikelihoodAttr(const Stmt *S)
SourceLocation getBeginLoc() const LLVM_READONLY
static Likelihood getLikelihood(ArrayRef< const Attr * > Attrs)
StringLiteral - This represents a string literal expression, e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target, unsigned *StartToken=nullptr, unsigned *StartTokenByteOffset=nullptr) const
getLocationOfByte - Return a source location that points to the specified byte of this string literal...
StringRef getString() const
const SwitchCase * getNextSwitchCase() const
SwitchStmt - This represents a 'switch' stmt.
Exposes information about the current target.
bool validateInputConstraint(MutableArrayRef< ConstraintInfo > OutputConstraints, ConstraintInfo &info) const
StringRef getNormalizedGCCRegisterName(StringRef Name, bool ReturnCanonical=false) const
Returns the "normalized" GCC register name.
bool validateOutputConstraint(ConstraintInfo &Info) const
virtual std::string_view getClobbers() const =0
Returns a string of target-specific clobbers, in LLVM format.
Token - This structure provides full information about a lexed token.
const T * castAs() const
Member-template castAs.
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)
- 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