clang: lib/CodeGen/CGStmt.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
28#include "llvm/ADT/ArrayRef.h"
29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/SmallSet.h"
31#include "llvm/ADT/StringExtras.h"
32#include "llvm/IR/Assumptions.h"
33#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/InlineAsm.h"
35#include "llvm/IR/Intrinsics.h"
36#include "llvm/IR/MDBuilder.h"
37#include "llvm/Support/SaveAndRestore.h"
38#include
39
40using namespace clang;
42
43
44
45
46
47namespace llvm {
49}
50
55 DI->EmitLocation(Builder, Loc);
56
57 LastStopPoint = Loc;
58 }
59}
60
62 assert(S && "Null statement?");
63 PGO->setCurrentStmt(S);
64
65
67 return;
68
69
71
72
73
74
75
77
78
79 assert((*S) && "Unexpected DeclStmt!");
80 PGO->markStmtMaybeUsed(S);
81 return;
82 }
83
84
86 }
87
88
90
91
92
94 if (const auto *D = dyn_cast(S)) {
96 return;
97 }
98 }
99
102 case Stmt::CXXCatchStmtClass:
103 case Stmt::SEHExceptStmtClass:
104 case Stmt::SEHFinallyStmtClass:
105 case Stmt::MSDependentExistsStmtClass:
106 llvm_unreachable("invalid statement class to emit generically");
107 case Stmt::NullStmtClass:
108 case Stmt::CompoundStmtClass:
109 case Stmt::DeclStmtClass:
110 case Stmt::LabelStmtClass:
111 case Stmt::AttributedStmtClass:
112 case Stmt::GotoStmtClass:
113 case Stmt::BreakStmtClass:
114 case Stmt::ContinueStmtClass:
115 case Stmt::DefaultStmtClass:
116 case Stmt::CaseStmtClass:
117 case Stmt::DeferStmtClass:
118 case Stmt::SEHLeaveStmtClass:
119 case Stmt::SYCLKernelCallStmtClass:
120 llvm_unreachable("should have emitted these statements as simple");
121
122#define STMT(Type, Base)
123#define ABSTRACT_STMT(Op)
124#define EXPR(Type, Base) \
125 case Stmt::Type##Class:
126#include "clang/AST/StmtNodes.inc"
127 {
128
129 llvm::BasicBlock *incoming = Builder.GetInsertBlock();
130 assert(incoming && "expression emission must have an insertion point");
131
133
134 llvm::BasicBlock *outgoing = Builder.GetInsertBlock();
135 assert(outgoing && "expression emission cleared block!");
136
137
138
139
140
141
142
143
144
145
146
147
148
149 if (incoming != outgoing && outgoing->use_empty()) {
150 outgoing->eraseFromParent();
151 Builder.ClearInsertionPoint();
152 }
153 break;
154 }
155
156 case Stmt::IndirectGotoStmtClass:
158
163
165
167 case Stmt::GCCAsmStmtClass:
169 case Stmt::CoroutineBodyStmtClass:
171 break;
172 case Stmt::CoreturnStmtClass:
174 break;
175 case Stmt::CapturedStmtClass: {
178 }
179 break;
180 case Stmt::ObjCAtTryStmtClass:
182 break;
183 case Stmt::ObjCAtCatchStmtClass:
184 llvm_unreachable(
185 "@catch statements should be handled by EmitObjCAtTryStmt");
186 case Stmt::ObjCAtFinallyStmtClass:
187 llvm_unreachable(
188 "@finally statements should be handled by EmitObjCAtTryStmt");
189 case Stmt::ObjCAtThrowStmtClass:
191 break;
192 case Stmt::ObjCAtSynchronizedStmtClass:
194 break;
195 case Stmt::ObjCForCollectionStmtClass:
197 break;
198 case Stmt::ObjCAutoreleasePoolStmtClass:
200 break;
201
202 case Stmt::CXXTryStmtClass:
204 break;
205 case Stmt::CXXForRangeStmtClass:
207 break;
208 case Stmt::SEHTryStmtClass:
210 break;
211 case Stmt::OMPMetaDirectiveClass:
213 break;
214 case Stmt::OMPCanonicalLoopClass:
216 break;
217 case Stmt::OMPParallelDirectiveClass:
219 break;
220 case Stmt::OMPSimdDirectiveClass:
222 break;
223 case Stmt::OMPTileDirectiveClass:
225 break;
226 case Stmt::OMPStripeDirectiveClass:
228 break;
229 case Stmt::OMPUnrollDirectiveClass:
231 break;
232 case Stmt::OMPReverseDirectiveClass:
234 break;
235 case Stmt::OMPInterchangeDirectiveClass:
237 break;
238 case Stmt::OMPFuseDirectiveClass:
240 break;
241 case Stmt::OMPForDirectiveClass:
243 break;
244 case Stmt::OMPForSimdDirectiveClass:
246 break;
247 case Stmt::OMPSectionsDirectiveClass:
249 break;
250 case Stmt::OMPSectionDirectiveClass:
252 break;
253 case Stmt::OMPSingleDirectiveClass:
255 break;
256 case Stmt::OMPMasterDirectiveClass:
258 break;
259 case Stmt::OMPCriticalDirectiveClass:
261 break;
262 case Stmt::OMPParallelForDirectiveClass:
264 break;
265 case Stmt::OMPParallelForSimdDirectiveClass:
267 break;
268 case Stmt::OMPParallelMasterDirectiveClass:
270 break;
271 case Stmt::OMPParallelSectionsDirectiveClass:
273 break;
274 case Stmt::OMPTaskDirectiveClass:
276 break;
277 case Stmt::OMPTaskyieldDirectiveClass:
279 break;
280 case Stmt::OMPErrorDirectiveClass:
282 break;
283 case Stmt::OMPBarrierDirectiveClass:
285 break;
286 case Stmt::OMPTaskwaitDirectiveClass:
288 break;
289 case Stmt::OMPTaskgroupDirectiveClass:
291 break;
292 case Stmt::OMPFlushDirectiveClass:
294 break;
295 case Stmt::OMPDepobjDirectiveClass:
297 break;
298 case Stmt::OMPScanDirectiveClass:
300 break;
301 case Stmt::OMPOrderedDirectiveClass:
303 break;
304 case Stmt::OMPAtomicDirectiveClass:
306 break;
307 case Stmt::OMPTargetDirectiveClass:
309 break;
310 case Stmt::OMPTeamsDirectiveClass:
312 break;
313 case Stmt::OMPCancellationPointDirectiveClass:
315 break;
316 case Stmt::OMPCancelDirectiveClass:
318 break;
319 case Stmt::OMPTargetDataDirectiveClass:
321 break;
322 case Stmt::OMPTargetEnterDataDirectiveClass:
324 break;
325 case Stmt::OMPTargetExitDataDirectiveClass:
327 break;
328 case Stmt::OMPTargetParallelDirectiveClass:
330 break;
331 case Stmt::OMPTargetParallelForDirectiveClass:
333 break;
334 case Stmt::OMPTaskLoopDirectiveClass:
336 break;
337 case Stmt::OMPTaskLoopSimdDirectiveClass:
339 break;
340 case Stmt::OMPMasterTaskLoopDirectiveClass:
342 break;
343 case Stmt::OMPMaskedTaskLoopDirectiveClass:
345 break;
346 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
349 break;
350 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
353 break;
354 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
357 break;
358 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
361 break;
362 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
365 break;
366 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
369 break;
370 case Stmt::OMPDistributeDirectiveClass:
372 break;
373 case Stmt::OMPTargetUpdateDirectiveClass:
375 break;
376 case Stmt::OMPDistributeParallelForDirectiveClass:
379 break;
380 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
383 break;
384 case Stmt::OMPDistributeSimdDirectiveClass:
386 break;
387 case Stmt::OMPTargetParallelForSimdDirectiveClass:
390 break;
391 case Stmt::OMPTargetSimdDirectiveClass:
393 break;
394 case Stmt::OMPTeamsDistributeDirectiveClass:
396 break;
397 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
400 break;
401 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
404 break;
405 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
408 break;
409 case Stmt::OMPTargetTeamsDirectiveClass:
411 break;
412 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
415 break;
416 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
419 break;
420 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
423 break;
424 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
427 break;
428 case Stmt::OMPInteropDirectiveClass:
430 break;
431 case Stmt::OMPDispatchDirectiveClass:
432 CGM.ErrorUnsupported(S, "OpenMP dispatch directive");
433 break;
434 case Stmt::OMPScopeDirectiveClass:
436 break;
437 case Stmt::OMPMaskedDirectiveClass:
439 break;
440 case Stmt::OMPGenericLoopDirectiveClass:
442 break;
443 case Stmt::OMPTeamsGenericLoopDirectiveClass:
445 break;
446 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
449 break;
450 case Stmt::OMPParallelGenericLoopDirectiveClass:
453 break;
454 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
457 break;
458 case Stmt::OMPParallelMaskedDirectiveClass:
460 break;
461 case Stmt::OMPAssumeDirectiveClass:
463 break;
464 case Stmt::OpenACCComputeConstructClass:
466 break;
467 case Stmt::OpenACCLoopConstructClass:
469 break;
470 case Stmt::OpenACCCombinedConstructClass:
472 break;
473 case Stmt::OpenACCDataConstructClass:
475 break;
476 case Stmt::OpenACCEnterDataConstructClass:
478 break;
479 case Stmt::OpenACCExitDataConstructClass:
481 break;
482 case Stmt::OpenACCHostDataConstructClass:
484 break;
485 case Stmt::OpenACCWaitConstructClass:
487 break;
488 case Stmt::OpenACCInitConstructClass:
490 break;
491 case Stmt::OpenACCShutdownConstructClass:
493 break;
494 case Stmt::OpenACCSetConstructClass:
496 break;
497 case Stmt::OpenACCUpdateConstructClass:
499 break;
500 case Stmt::OpenACCAtomicConstructClass:
502 break;
503 case Stmt::OpenACCCacheConstructClass:
505 break;
506 }
507}
508
512 default:
513 return false;
514 case Stmt::NullStmtClass:
515 break;
516 case Stmt::CompoundStmtClass:
518 break;
519 case Stmt::DeclStmtClass:
521 break;
522 case Stmt::LabelStmtClass:
524 break;
525 case Stmt::AttributedStmtClass:
527 break;
528 case Stmt::GotoStmtClass:
530 break;
531 case Stmt::BreakStmtClass:
533 break;
534 case Stmt::ContinueStmtClass:
536 break;
537 case Stmt::DefaultStmtClass:
539 break;
540 case Stmt::CaseStmtClass:
542 break;
543 case Stmt::DeferStmtClass:
545 break;
546 case Stmt::SEHLeaveStmtClass:
548 break;
549 case Stmt::SYCLKernelCallStmtClass:
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565 break;
566 }
567 return true;
568}
569
570
571
572
576 "LLVM IR generation of compound statement ('{}')");
577
578
580
582}
583
586 bool GetLast,
588
591 I != E; ++I)
593
595 if (GetLast) {
596
597
598
599
600
603 if (const auto *LS = dyn_cast(LastStmt)) {
605 LastStmt = LS->getSubStmt();
606 } else if (const auto *AS = dyn_cast(LastStmt)) {
607
608
609 LastStmt = AS->getSubStmt();
610 } else {
611 llvm_unreachable("unknown value statement");
612 }
613 }
614
616
621 } else {
622
623
624
627 false);
628 }
629 }
630
631 return RetAlloca;
632}
633
635 llvm::BranchInst *BI = dyn_castllvm::BranchInst(BB->getTerminator());
636
637
638
639
641 return;
642
643
644 if (!BI || !BI->isUnconditional())
645 return;
646
647
648 if (BI->getIterator() != BB->begin())
649 return;
650
651 BB->replaceAllUsesWith(BI->getSuccessor(0));
652 BI->eraseFromParent();
653 BB->eraseFromParent();
654}
655
657 llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
658
659
661
662 if (IsFinished && BB->use_empty()) {
663 delete BB;
664 return;
665 }
666
667
668
669 if (CurBB && CurBB->getParent())
670 CurFn->insert(std::next(CurBB->getIterator()), BB);
671 else
673 Builder.SetInsertPoint(BB);
674}
675
677
678
679
680 llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
681
682 if (!CurBB || CurBB->getTerminator()) {
683
684
685 } else {
686
688 }
689
690 Builder.ClearInsertionPoint();
691}
692
694 bool inserted = false;
695 for (llvm::User *u : block->users()) {
696 if (llvm::Instruction *insn = dyn_castllvm::Instruction(u)) {
697 CurFn->insert(std::next(insn->getParent()->getIterator()), block);
698 inserted = true;
699 break;
700 }
701 }
702
703 if (!inserted)
705
706 Builder.SetInsertPoint(block);
707}
708
711 JumpDest &Dest = LabelMap[D];
712 if (Dest.isValid()) return Dest;
713
714
718 return Dest;
719}
720
722
723
724
725 if (EHStack.hasNormalCleanups() && CurLexicalScope)
726 CurLexicalScope->addLabel(D);
727
728 JumpDest &Dest = LabelMap[D];
729
730
731
734
735
736
737 } else {
741 }
742
744
745
747 if (CGM.getCodeGenOpts().hasReducedDebugInfo()) {
749 DI->EmitLabel(D, Builder);
750 }
751 }
752
754}
755
756
757
759 assert(!Labels.empty());
761 = CGF.EHStack.getInnermostNormalCleanup();
762
763
764 for (const LabelDecl *Label : Labels) {
765 assert(CGF.LabelMap.count(Label));
766 JumpDest &dest = CGF.LabelMap.find(Label)->second;
770 }
771
772
774 ParentScope->Labels.append(Labels.begin(), Labels.end());
775 }
776}
777
778
788
790 bool nomerge = false;
791 bool noinline = false;
792 bool alwaysinline = false;
793 bool noconvergent = false;
794 HLSLControlFlowHintAttr::Spelling flattenOrBranch =
795 HLSLControlFlowHintAttr::SpellingNotCalculated;
796 const CallExpr *musttail = nullptr;
797 const AtomicAttr *AA = nullptr;
798
799 for (const auto *A : S.getAttrs()) {
800 switch (A->getKind()) {
801 default:
802 break;
803 case attr::NoMerge:
804 nomerge = true;
805 break;
806 case attr::NoInline:
807 noinline = true;
808 break;
809 case attr::AlwaysInline:
810 alwaysinline = true;
811 break;
812 case attr::NoConvergent:
813 noconvergent = true;
814 break;
815 case attr::MustTail: {
819 } break;
820 case attr::CXXAssume: {
825 Builder.CreateAssumption(AssumptionVal);
826 }
827 } break;
828 case attr::Atomic:
830 break;
831 case attr::HLSLControlFlowHint: {
833 } break;
834 }
835 }
844}
845
856
857
862 return;
863 }
864
865
868 llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
869
870
872
873
874
876
878 if (CurBB && CurBB->getTerminator())
880}
881
884
885
886
889 if (Executed) {
892 }
893 return;
894 }
895
896
897
900
903
906
907
908
909 bool CondConstant;
912
914 const Stmt *Skipped = Else;
915 if (!CondConstant)
916 std::swap(Executed, Skipped);
917
918
919
921 if (CondConstant)
923 if (Executed) {
927 }
928 PGO->markStmtMaybeUsed(Skipped);
929 return;
930 }
931 }
932
933
934
937 llvm::BasicBlock *ElseBlock = ContBlock;
938 if (Else)
940
941
942
943
944
945
946
947
948
949
950
951
955 CGM.getCodeGenOpts().OptimizationLevel)
957
958
959
960
961
962
963
964 if (.getCodeGenOpts().MCDCCoverage) {
966 nullptr,
968 } else {
971 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
972 }
973
974
978 else
980 {
983 }
985
986
987 if (Else) {
988 {
989
992 }
993
996 {
999 }
1000 {
1001
1004 }
1005 }
1006
1007
1009
1010
1011
1014}
1015
1017 bool HasEmptyBody) {
1018 if (CGM.getCodeGenOpts().getFiniteLoops() ==
1020 return false;
1021
1022
1023
1024
1025
1026
1028 bool CondIsConstInt =
1029 !ControllingExpression ||
1031 Result.Val.isInt());
1032
1033 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
1034 Result.Val.getInt().getBoolValue());
1035
1036
1038 return true;
1039
1040
1041
1042
1043
1044
1045 if (CGM.getCodeGenOpts().getFiniteLoops() ==
1048 if (HasEmptyBody && CondIsTrue) {
1049 CurFn->removeFnAttr(llvm::Attribute::MustProgress);
1050 return false;
1051 }
1052 return true;
1053 }
1054 return false;
1055}
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066template static bool hasEmptyLoopBody(const LoopStmt &S) {
1067 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
1068 if (S.getInc())
1069 return false;
1070 }
1071 const Stmt *Body = S.getBody();
1073 return true;
1074 if (const CompoundStmt *Compound = dyn_cast(Body))
1075 return Compound->body_empty();
1076 return false;
1077}
1078
1081
1082
1085
1086 if (CGM.shouldEmitConvergenceTokens())
1088 emitConvergenceLoopToken(LoopHeader.getBlock()));
1089
1090
1091
1093
1094
1095 BreakContinueStack.push_back(BreakContinue(S, LoopExit, LoopHeader));
1096
1097
1098
1099
1100
1101
1102
1103
1105
1108
1109
1110
1111
1113
1115
1116
1117
1118 llvm::ConstantInt *C = dyn_castllvm::ConstantInt(BoolCondVal);
1119 bool EmitBoolCondBranch = ||
->isOne();
1125
1126
1129
1130
1131 llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
1132 if (EmitBoolCondBranch) {
1133 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
1136 llvm::MDNode *Weights =
1138 if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
1139 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1141 auto *I = Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
1142
1143
1144
1145
1146
1147 if (auto *CondI = dyn_castllvm::Instruction(BoolCondVal))
1150
1151 if (ExitBlock != LoopExit.getBlock()) {
1154 }
1156 CGM.getDiags().Report(A->getLocation(),
1157 diag::warn_attribute_has_no_effect_on_infinite_loop)
1158 << A << A->getRange();
1159 CGM.getDiags().Report(
1161 diag::note_attribute_has_no_effect_on_infinite_loop_here)
1163 }
1164
1165
1166
1167 {
1170
1173 else
1176 }
1177
1178 BreakContinueStack.pop_back();
1179
1180
1182
1184
1186
1188
1189
1191
1192
1193
1194 if (!EmitBoolCondBranch)
1196
1197
1198
1201
1202 if (CGM.shouldEmitConvergenceTokens())
1204}
1205
1210
1212
1213
1214 BreakContinueStack.push_back(BreakContinue(S, LoopExit, LoopCond));
1215
1216
1218
1221 else
1223
1224 if (CGM.shouldEmitConvergenceTokens())
1226
1227 {
1230 }
1231
1233
1236
1237
1238
1239
1240
1241
1242
1244
1245 BreakContinueStack.pop_back();
1246
1247
1248
1249 llvm::ConstantInt *C = dyn_castllvm::ConstantInt(BoolCondVal);
1250 bool EmitBoolCondBranch = ||
->isZero();
1251
1253 LoopStack.push(LoopBody, CGM.getContext(), CGM.getCodeGenOpts(), DoAttrs,
1257
1258
1259 if (EmitBoolCondBranch) {
1261 auto *I = Builder.CreateCondBr(
1262 BoolCondVal, LoopBody, LoopExit.getBlock(),
1263 createProfileWeightsForLoop(S.getCond(), BackedgeCount));
1264
1265
1266
1267
1268
1269
1270 if (auto *CondI = dyn_castllvm::Instruction(BoolCondVal))
1273 }
1274
1276
1277
1279
1280
1281
1282 if (!EmitBoolCondBranch)
1284
1285
1286
1289
1290 if (CGM.shouldEmitConvergenceTokens())
1292}
1293
1297
1298 std::optional ForScope;
1301
1302
1305
1306
1307
1308
1310 llvm::BasicBlock *CondBlock = CondDest.getBlock();
1312
1313 if (CGM.shouldEmitConvergenceTokens())
1315
1317 LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), ForAttrs,
1321
1322
1324
1325
1326
1327
1328
1329
1330
1331
1334 Continue = CondDest;
1337 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
1338
1340
1341
1344
1345
1346
1348 BreakContinueStack.back().ContinueBlock = Continue;
1349 }
1350
1351
1352
1355
1356 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
1357
1358
1359 if (ForScope && ForScope->requiresCleanups())
1361
1362
1364
1365
1366
1368
1370
1371 llvm::MDNode *Weights =
1373 if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
1374 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1376
1377 auto *I = Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1378
1379
1380
1381
1382 if (auto *CondI = dyn_castllvm::Instruction(BoolCondVal))
1385
1386 if (ExitBlock != LoopExit.getBlock()) {
1389 }
1390
1392 } else {
1393
1394
1395 }
1396
1397
1400 else
1402 {
1403
1404
1407 }
1408
1409
1410
1411 auto *FinalBodyBB = Builder.GetInsertBlock();
1412
1413
1419 }
1420
1421 BreakContinueStack.pop_back();
1422
1424
1427
1428 if (ForScope)
1429 ForScope->ForceCleanup();
1430
1432
1433
1435
1436
1437
1440
1441 if (CGM.shouldEmitConvergenceTokens())
1443
1444 if (FinalBodyBB) {
1445
1446
1448 }
1449}
1450
1451void
1455
1457
1458
1464
1465
1466
1467
1470
1471 if (CGM.shouldEmitConvergenceTokens())
1473
1475 LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), ForAttrs,
1478
1479
1480
1481 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
1484
1485
1487
1488
1489
1491 llvm::MDNode *Weights =
1493 if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
1494 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1496 auto *I = Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1497
1498
1499
1500
1501 if (auto *CondI = dyn_castllvm::Instruction(BoolCondVal))
1504
1505 if (ExitBlock != LoopExit.getBlock()) {
1508 }
1509
1513 else
1515
1516
1518
1519
1520 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
1521
1522 {
1523
1527 }
1528
1529
1530 auto *FinalBodyBB = Builder.GetInsertBlock();
1531
1533
1536
1537 BreakContinueStack.pop_back();
1538
1540
1542
1544
1545
1547
1548
1549
1552
1553 if (CGM.shouldEmitConvergenceTokens())
1555
1556 if (FinalBodyBB) {
1557
1558
1560 }
1561}
1562
1563void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
1570 } else {
1572 true);
1573 }
1575}
1576
1577namespace {
1578
1579struct SaveRetExprRAII {
1580 SaveRetExprRAII(const Expr *RetExpr, CodeGenFunction &CGF)
1581 : OldRetExpr(CGF.RetExpr), CGF(CGF) {
1583 }
1584 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1585 const Expr *OldRetExpr;
1586 CodeGenFunction &CGF;
1587};
1588}
1589
1590
1594 if (calleeQualType->isFunctionPointerType() ||
1595 calleeQualType->isFunctionReferenceType() ||
1596 calleeQualType->isBlockPointerType() ||
1597 calleeQualType->isMemberFunctionPointerType()) {
1599 } else if (auto *ty = dyn_cast(calleeQualType)) {
1600 calleeType = ty;
1601 } else if (auto CMCE = dyn_cast(CE)) {
1602 if (auto methodDecl = CMCE->getMethodDecl()) {
1603
1605 } else {
1606 return false;
1607 }
1608 } else {
1609 return false;
1610 }
1612}
1613
1614
1615
1616
1619 if (requiresReturnValueCheck()) {
1621 auto *SLocPtr =
1622 new llvm::GlobalVariable(CGM.getModule(), SLoc->getType(), false,
1623 llvm::GlobalVariable::PrivateLinkage, SLoc);
1624 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1625 CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
1626 assert(ReturnLocation.isValid() && "No valid return location");
1627 Builder.CreateStore(SLocPtr, ReturnLocation);
1628 }
1629
1630
1632 Builder.CreateUnreachable();
1633 Builder.ClearInsertionPoint();
1634 }
1635
1636
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647 SaveRetExprRAII SaveRetExpr(RV, *this);
1648
1650 if (const auto *EWC = dyn_cast_or_null(RV))
1651 RV = EWC->getSubExpr();
1652
1653
1654
1655 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;
1658 if (auto CE = dyn_cast(RV)) {
1661 }
1662 }
1663 }
1664
1665
1666
1667
1671 .getOpenMPRuntime()
1673 .isValid())) {
1674
1675
1676
1677
1678
1679
1681 Builder.CreateFlagStore(Builder.getTrue(), NRVOFlag);
1683
1684
1685 if (RV) {
1687 }
1688 } else if (!RV) {
1689
1690 } else if (FnRetTy->isReferenceType()) {
1691
1692
1696 } else {
1702 true);
1703 } else {
1706 }
1707 break;
1708 }
1711 true);
1712 break;
1720 break;
1721 }
1722 }
1723
1724 ++NumReturnExprs;
1726 ++NumSimpleReturnExprs;
1727
1730}
1731
1733
1734
1737
1738 for (const auto *I : S.decls())
1739 EmitDecl(*I, true);
1740}
1741
1743 -> const BreakContinue * {
1744 if (!S.hasLabelTarget())
1745 return &BreakContinueStack.back();
1746
1747 const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
1748 assert(LoopOrSwitch && "break/continue target not set?");
1749 for (const BreakContinue &BC : llvm::reverse(BreakContinueStack))
1750 if (BC.LoopOrSwitch == LoopOrSwitch)
1751 return &BC;
1752
1753 llvm_unreachable("break/continue target not found");
1754}
1755
1757 assert(!BreakContinueStack.empty() && "break stmt not in a loop or switch!");
1758
1759
1760
1761
1764
1767}
1768
1770 assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
1771
1772
1773
1774
1777
1780}
1781
1782
1783
1784
1787 assert(S.getRHS() && "Expected RHS value in CaseStmt");
1788
1791
1792
1793
1794
1798
1799
1800 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
1801 return;
1802
1804 llvm::APInt Range = RHS - LHS;
1805
1806 if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
1807
1809 unsigned NCases = Range.getZExtValue() + 1;
1810
1811
1812
1813
1814 uint64_t Weight = Total / NCases, Rem = Total % NCases;
1815 for (unsigned I = 0; I != NCases; ++I) {
1816 if (SwitchWeights)
1817 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
1818 else if (SwitchLikelihood)
1819 SwitchLikelihood->push_back(LH);
1820
1821 if (Rem)
1822 Rem--;
1823 SwitchInsn->addCase(Builder.getInt(LHS), CaseDest);
1824 ++LHS;
1825 }
1826 return;
1827 }
1828
1829
1830
1831 llvm::BasicBlock *RestoreBB = Builder.GetInsertBlock();
1832
1833
1834
1835
1836 llvm::BasicBlock *FalseDest = CaseRangeBlock;
1838
1839 CurFn->insert(CurFn->end(), CaseRangeBlock);
1840 Builder.SetInsertPoint(CaseRangeBlock);
1841
1842
1843 llvm::Value *Diff =
1844 Builder.CreateSub(SwitchInsn->getCondition(), Builder.getInt(LHS));
1845 llvm::Value *Cond =
1846 Builder.CreateICmpULE(Diff, Builder.getInt(Range), "inbounds");
1847
1848 llvm::MDNode *Weights = nullptr;
1849 if (SwitchWeights) {
1851 uint64_t DefaultCount = (*SwitchWeights)[0];
1852 Weights = createProfileWeights(ThisCount, DefaultCount);
1853
1854
1855
1856
1857 (*SwitchWeights)[0] += ThisCount;
1858 } else if (SwitchLikelihood)
1859 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
1860
1861 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
1862
1863
1864 if (RestoreBB)
1865 Builder.SetInsertPoint(RestoreBB);
1866 else
1867 Builder.ClearInsertionPoint();
1868}
1869
1872
1873
1874
1875
1876
1877 if (!SwitchInsn) {
1879 return;
1880 }
1881
1882
1885 return;
1886 }
1887
1888 llvm::ConstantInt *CaseVal =
1890
1891
1893 if (auto ICE = dyn_cast(S.getLHS()))
1894 CE = dyn_cast(ICE->getSubExpr());
1895 else
1896 CE = dyn_cast(S.getLHS());
1897 if (CE) {
1898 if (auto DE = dyn_cast(CE->getSubExpr()))
1900 if (CGM.getCodeGenOpts().hasReducedDebugInfo())
1901 Dbg->EmitGlobalVariable(DE->getDecl(),
1902 APValue(llvm::APSInt(CaseVal->getValue())));
1903 }
1904
1905 if (SwitchLikelihood)
1907
1908
1909
1910
1911 if (.getCodeGenOpts().hasProfileClangInstr() &&
1912 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1914 JumpDest Block = BreakContinueStack.back().BreakBlock;
1915
1916
1918 if (SwitchWeights)
1920 SwitchInsn->addCase(CaseVal, Block.getBlock());
1921
1922
1923
1924 if (Builder.GetInsertBlock()) {
1926 Builder.ClearInsertionPoint();
1927 }
1928 return;
1929 }
1930 }
1931
1934 if (SwitchWeights)
1936 SwitchInsn->addCase(CaseVal, CaseDest);
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951 const CaseStmt *CurCase = &S;
1953
1954
1955 while (NextCase && NextCase->getRHS() == nullptr) {
1956 CurCase = NextCase;
1957 llvm::ConstantInt *CaseVal =
1959
1960 if (SwitchWeights)
1962 if (CGM.getCodeGenOpts().hasProfileClangInstr()) {
1965 }
1966
1967
1968 if (SwitchLikelihood)
1970
1971 SwitchInsn->addCase(CaseVal, CaseDest);
1972 NextCase = dyn_cast(CurCase->getSubStmt());
1973 }
1974
1975
1976
1977
1980
1981
1983}
1984
1987
1988
1989
1990 if (!SwitchInsn) {
1992 return;
1993 }
1994
1995 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
1996 assert(DefaultBlock->empty() &&
1997 "EmitDefaultStmt: Default block already defined?");
1998
1999 if (SwitchLikelihood)
2001
2003
2005}
2006
2007namespace {
2008struct EmitDeferredStatement final : EHScopeStack::Cleanup {
2011
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068 llvm::Value *SavedCleanupDest = nullptr;
2070 SavedCleanupDest =
2072
2074
2077
2078
2080 }
2081};
2082}
2083
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2114 bool &FoundCase,
2116
2117 if (!S)
2119
2120
2121
2122 if (const SwitchCase *SC = dyn_cast(S)) {
2123 if (S == Case) {
2124 FoundCase = true;
2126 ResultStmts);
2127 }
2128
2129
2131 ResultStmts);
2132 }
2133
2134
2135
2138
2139
2140
2141 if (const CompoundStmt *CS = dyn_cast(S)) {
2142
2143
2145 bool StartedInLiveCode = FoundCase;
2146 unsigned StartSize = ResultStmts.size();
2147
2148
2149 if (Case) {
2150
2151
2152
2153 bool HadSkippedDecl = false;
2154
2155
2156
2157 for (; Case && I != E; ++I) {
2159
2163
2164
2165
2166
2167 if (FoundCase) {
2168
2169
2170 if (HadSkippedDecl)
2172
2173 for (++I; I != E; ++I)
2177 }
2178 break;
2180
2181
2182
2183 assert(FoundCase && "Didn't find case but returned fallthrough?");
2184
2185 Case = nullptr;
2186
2187
2188
2189 if (HadSkippedDecl)
2191 break;
2192 }
2193 }
2194
2195 if (!FoundCase)
2197
2198 assert(!HadSkippedDecl && "fallthrough after skipping decl");
2199 }
2200
2201
2202
2203 bool AnyDecls = false;
2204 for (; I != E; ++I) {
2206
2210
2211
2212 break;
2214
2215
2216
2217 for (++I; I != E; ++I)
2221 }
2222 }
2223
2224
2225
2226
2227 if (AnyDecls) {
2228
2229
2230
2231
2232
2234 ResultStmts.resize(StartSize);
2235 ResultStmts.push_back(S);
2236 } else {
2238 }
2239 }
2240
2242 }
2243
2244
2245
2246
2247 if (Case) {
2251 }
2252
2253
2254
2256
2257
2258
2259 ResultStmts.push_back(S);
2261}
2262
2263
2264
2265
2266
2268 const llvm::APSInt &ConstantCondValue,
2272
2273
2275 const DefaultStmt *DefaultCase = nullptr;
2276
2278
2279
2280 if (const DefaultStmt *DS = dyn_cast(Case)) {
2281 DefaultCase = DS;
2282 continue;
2283 }
2284
2285
2287
2288 if (CS->getRHS()) return false;
2289
2290
2292 break;
2293 }
2294
2295
2296
2297 if (!Case) {
2298
2299
2300 if (!DefaultCase)
2302 Case = DefaultCase;
2303 }
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313 bool FoundCase = false;
2314 ResultCase = Case;
2317 FoundCase;
2318}
2319
2320static std::optional<SmallVector<uint64_t, 16>>
2322
2323 if (Likelihoods.size() <= 1)
2324 return std::nullopt;
2325
2326 uint64_t NumUnlikely = 0;
2327 uint64_t NumNone = 0;
2328 uint64_t NumLikely = 0;
2329 for (const auto LH : Likelihoods) {
2330 switch (LH) {
2332 ++NumUnlikely;
2333 break;
2335 ++NumNone;
2336 break;
2338 ++NumLikely;
2339 break;
2340 }
2341 }
2342
2343
2344 if (NumUnlikely == 0 && NumLikely == 0)
2345 return std::nullopt;
2346
2347
2348
2349
2350
2351
2352
2353 const uint64_t Likely = INT32_MAX / (NumLikely + 2);
2354 const uint64_t None = Likely / (NumNone + 1);
2355 const uint64_t Unlikely = 0;
2356
2358 Result.reserve(Likelihoods.size());
2359 for (const auto LH : Likelihoods) {
2360 switch (LH) {
2362 Result.push_back(Unlikely);
2363 break;
2365 Result.push_back(None);
2366 break;
2368 Result.push_back(Likely);
2369 break;
2370 }
2371 }
2372
2373 return Result;
2374}
2375
2377
2378 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
2381 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
2382
2383
2384
2385 llvm::APSInt ConstantCondValue;
2391 if (Case)
2394
2397
2398
2399
2402
2403
2404
2405
2406 SwitchInsn = nullptr;
2407
2408
2409
2413 PGO->markStmtMaybeUsed(S.getBody());
2414
2415
2416
2417 SwitchInsn = SavedSwitchInsn;
2418
2419 return;
2420 }
2421 }
2422
2424
2426
2429
2434
2435
2436
2437
2438
2439 llvm::BasicBlock *DefaultBlock = createBasicBlock("sw.default");
2440 SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock);
2442
2443 if (HLSLControlFlowAttr != HLSLControlFlowHintAttr::SpellingNotCalculated) {
2444 llvm::MDBuilder MDHelper(CGM.getLLVMContext());
2445 llvm::ConstantInt *BranchHintConstant =
2447 HLSLControlFlowHintAttr::Spelling::Microsoft_branch
2448 ? llvm::ConstantInt::get(CGM.Int32Ty, 1)
2449 : llvm::ConstantInt::get(CGM.Int32Ty, 2);
2450 llvm::Metadata *Vals[] = {MDHelper.createString("hlsl.controlflow.hint"),
2451 MDHelper.createConstant(BranchHintConstant)};
2452 SwitchInsn->setMetadata("hlsl.controlflow.hint",
2453 llvm::MDNode::get(CGM.getLLVMContext(), Vals));
2454 }
2455
2456 if (PGO->haveRegionCounts()) {
2457
2458 uint64_t DefaultCount = 0;
2459 unsigned NumCases = 0;
2461 Case;
2465 NumCases += 1;
2466 }
2468 SwitchWeights->reserve(NumCases);
2469
2470
2471 SwitchWeights->push_back(DefaultCount);
2472 } else if (CGM.getCodeGenOpts().OptimizationLevel) {
2474
2476 }
2477
2478 CaseRangeBlock = DefaultBlock;
2479
2480
2481 Builder.ClearInsertionPoint();
2482
2483
2484
2486 if (!BreakContinueStack.empty())
2487 OuterContinue = BreakContinueStack.back().ContinueBlock;
2488
2489 BreakContinueStack.push_back(BreakContinue(S, SwitchExit, OuterContinue));
2490
2491
2493
2494 BreakContinueStack.pop_back();
2495
2496
2497
2498 SwitchInsn->setDefaultDest(CaseRangeBlock);
2499
2500
2501 if (!DefaultBlock->getParent()) {
2502
2503
2506
2507
2508 } else {
2509 DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock());
2510 delete DefaultBlock;
2511 }
2512 }
2513
2515
2516
2519
2520
2521
2522
2523 auto *Call = dyn_cast(S.getCond());
2524 if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) {
2525 auto *FD = dyn_cast_or_null(Call->getCalleeDecl());
2526 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
2528 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
2529 MDHelper.createUnpredictable());
2530 }
2531 }
2532
2533 if (SwitchWeights) {
2534 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
2535 "switch weights do not match switch cases");
2536
2537 if (SwitchWeights->size() > 1)
2538 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2539 createProfileWeights(*SwitchWeights));
2540 delete SwitchWeights;
2541 } else if (SwitchLikelihood) {
2542 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&
2543 "switch likelihoods do not match switch cases");
2544 std::optional<SmallVector<uint64_t, 16>> LHW =
2546 if (LHW) {
2547 llvm::MDBuilder MDHelper(CGM.getLLVMContext());
2548 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
2549 createProfileWeights(*LHW));
2550 }
2551 delete SwitchLikelihood;
2552 }
2553 SwitchInsn = SavedSwitchInsn;
2554 SwitchWeights = SavedSwitchWeights;
2555 SwitchLikelihood = SavedSwitchLikelihood;
2556 CaseRangeBlock = SavedCRBlock;
2557}
2558
2559
2560
2561
2562static std::string
2565 const AsmStmt &Stmt, const bool EarlyClobber,
2566 std::string *GCCReg = nullptr) {
2567 const DeclRefExpr *AsmDeclRef = dyn_cast(&AsmExpr);
2568 if (!AsmDeclRef)
2569 return Constraint;
2571 const VarDecl *Variable = dyn_cast(&Value);
2572 if (!Variable)
2573 return Constraint;
2574 if (Variable->getStorageClass() != SC_Register)
2575 return Constraint;
2576 AsmLabelAttr *Attr = Variable->getAttr();
2578 return Constraint;
2579 StringRef Register = Attr->getLabel();
2580 assert(Target.isValidGCCRegisterName(Register));
2581
2582
2584 if (Target.validateOutputConstraint(Info) &&
2587 return Constraint;
2588 }
2589
2590 Register = Target.getNormalizedGCCRegisterName(Register);
2591 if (GCCReg != nullptr)
2592 *GCCReg = Register.str();
2593 return (EarlyClobber ? "&{" : "{") + Register.str() + "}";
2594}
2595
2596std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(
2597 const TargetInfo::ConstraintInfo &Info, LValue InputValue,
2598 QualType InputType, std::string &ConstraintStr, SourceLocation Loc) {
2602
2603 llvm::Type *Ty = ConvertType(InputType);
2604 uint64_t Size = CGM.getDataLayout().getTypeSizeInBits(Ty);
2605 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
2606 getTargetHooks().isScalarizableAsmOperand(*this, Ty)) {
2607 Ty = llvm::IntegerType::get(getLLVMContext(), Size);
2608
2609 return {Builder.CreateLoad(InputValue.getAddress().withElementType(Ty)),
2610 nullptr};
2611 }
2612 }
2613
2614 Address Addr = InputValue.getAddress();
2615 ConstraintStr += '*';
2616 return {InputValue.getPointer(*this), Addr.getElementType()};
2617}
2618
2619std::pair<llvm::Value *, llvm::Type *>
2620CodeGenFunction::EmitAsmInput(const TargetInfo::ConstraintInfo &Info,
2621 const Expr *InputExpr,
2622 std::string &ConstraintStr) {
2623
2624
2627 Expr::EvalResult EVResult;
2629
2630 llvm::APSInt IntResult;
2633 return {llvm::ConstantInt::get(getLLVMContext(), IntResult), nullptr};
2634 }
2635
2636 Expr::EvalResult Result;
2639 nullptr};
2640 }
2641
2645 if (InputExpr->getStmtClass() == Expr::CXXThisExprClass)
2648 LValue Dest = EmitLValue(InputExpr);
2649 return EmitAsmInputLValue(Info, Dest, InputExpr->getType(), ConstraintStr,
2651}
2652
2653
2654
2655
2656
2660
2661 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2663 StringRef StrVal = Str->getString();
2664 if (!StrVal.empty()) {
2667 unsigned StartToken = 0;
2668 unsigned ByteOffset = 0;
2669
2670
2671
2672 for (unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
2673 if (StrVal[i] != '\n') continue;
2675 i + 1, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset);
2676 Locs.push_back(llvm::ConstantAsMetadata::get(
2678 }
2679 }
2680
2681 return llvm::MDNode::get(CGF.getLLVMContext(), Locs);
2682}
2683
2685 bool HasUnwindClobber, bool ReadOnly,
2686 bool ReadNone, bool NoMerge, bool NoConvergent,
2688 const std::vector<llvm::Type *> &ResultRegTypes,
2689 const std::vector<llvm::Type *> &ArgElemTypes,
2691 std::vector<llvm::Value *> &RegResults) {
2692 if (!HasUnwindClobber)
2693 Result.addFnAttr(llvm::Attribute::NoUnwind);
2694
2695 if (NoMerge)
2696 Result.addFnAttr(llvm::Attribute::NoMerge);
2697
2698 if (!HasSideEffect) {
2699 if (ReadNone)
2700 Result.setDoesNotAccessMemory();
2701 else if (ReadOnly)
2702 Result.setOnlyReadsMemory();
2703 }
2704
2705
2706 for (auto Pair : llvm::enumerate(ArgElemTypes)) {
2707 if (Pair.value()) {
2708 auto Attr = llvm::Attribute::get(
2709 CGF.getLLVMContext(), llvm::Attribute::ElementType, Pair.value());
2710 Result.addParamAttr(Pair.index(), Attr);
2711 }
2712 }
2713
2714
2715
2717 if (const auto *gccAsmStmt = dyn_cast(&S);
2718 gccAsmStmt &&
2719 (SL = dyn_cast(gccAsmStmt->getAsmStringExpr()))) {
2721 } else {
2722
2723
2724 llvm::Constant *Loc =
2726 Result.setMetadata("srcloc",
2728 llvm::ConstantAsMetadata::get(Loc)));
2729 }
2730
2731
2733
2735
2736
2737
2738
2739 Result.addFnAttr(llvm::Attribute::Convergent);
2740
2741 if (ResultRegTypes.size() == 1) {
2742 RegResults.push_back(&Result);
2743 } else {
2744 for (unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
2745 llvm::Value *Tmp = CGF.Builder.CreateExtractValue(&Result, i, "asmresult");
2746 RegResults.push_back(Tmp);
2747 }
2748 }
2749}
2750
2751static void
2758 const llvm::BitVector &ResultTypeRequiresCast,
2759 const std::vector<std::optional<std::pair<unsigned, unsigned>>>
2760 &ResultBounds) {
2764
2765 assert(RegResults.size() == ResultRegTypes.size());
2766 assert(RegResults.size() == ResultTruncRegTypes.size());
2767 assert(RegResults.size() == ResultRegDests.size());
2768
2769
2770 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
2771 assert(ResultBounds.size() <= ResultRegDests.size());
2772
2773 for (unsigned i = 0, e = RegResults.size(); i != e; ++i) {
2774 llvm::Value *Tmp = RegResults[i];
2775 llvm::Type *TruncTy = ResultTruncRegTypes[i];
2776
2777 if ((i < ResultBounds.size()) && ResultBounds[i].has_value()) {
2778 const auto [LowerBound, UpperBound] = ResultBounds[i].value();
2779
2780 assert(LowerBound == 0 && "Output operand lower bound is not zero.");
2781 llvm::Constant *UpperBoundConst =
2782 llvm::ConstantInt::get(Tmp->getType(), UpperBound);
2783 llvm::Value *IsBooleanValue =
2784 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, UpperBoundConst);
2785 llvm::Function *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume);
2786 Builder.CreateCall(FnAssume, IsBooleanValue);
2787 }
2788
2789
2790
2791 if (ResultRegTypes[i] != TruncTy) {
2792
2793
2794
2795 if (TruncTy->isFloatingPointTy())
2796 Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
2797 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
2798 uint64_t ResSize = CGM.getDataLayout().getTypeSizeInBits(TruncTy);
2799 Tmp = Builder.CreateTrunc(
2800 Tmp, llvm::IntegerType::get(CTX, (unsigned)ResSize));
2801 Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
2802 } else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
2803 uint64_t TmpSize =
2805 Tmp = Builder.CreatePtrToInt(
2806 Tmp, llvm::IntegerType::get(CTX, (unsigned)TmpSize));
2807 Tmp = Builder.CreateTrunc(Tmp, TruncTy);
2808 } else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
2809 Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
2810 } else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
2811 Tmp = Builder.CreateBitCast(Tmp, TruncTy);
2812 }
2813 }
2814
2816 LValue Dest = ResultRegDests[i];
2817
2818
2819 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {
2821 Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
2823 llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
2825 continue;
2826 }
2827
2833 diag::err_store_value_to_reg);
2834 return;
2835 }
2837 }
2839 }
2840}
2841
2844 constexpr auto Name = "__ASM__hipstdpar_unsupported";
2845
2846 std::string Asm;
2847 if (auto GCCAsm = dyn_cast(&S))
2848 Asm = GCCAsm->getAsmString();
2849
2851
2852 auto StrTy = llvm::ConstantDataArray::getString(Ctx, Asm);
2853 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
2854 {StrTy->getType()}, false);
2855 auto UBF = CGF->CGM.getModule().getOrInsertFunction(Name, FnTy);
2856
2857 CGF->Builder.CreateCall(UBF, {StrTy});
2858}
2859
2861
2863
2864
2866
2867
2870
2872 bool IsValidTargetAsm = true;
2873 for (unsigned i = 0, e = S.getNumOutputs(); i != e && IsValidTargetAsm; i++) {
2874 StringRef Name;
2875 if (const GCCAsmStmt *GAS = dyn_cast(&S))
2876 Name = GAS->getOutputName(i);
2879 if (IsHipStdPar && !IsValid)
2880 IsValidTargetAsm = false;
2881 else
2882 assert(IsValid && "Failed to parse output constraint");
2883 OutputConstraintInfos.push_back(Info);
2884 }
2885
2886 for (unsigned i = 0, e = S.getNumInputs(); i != e && IsValidTargetAsm; i++) {
2887 StringRef Name;
2888 if (const GCCAsmStmt *GAS = dyn_cast(&S))
2889 Name = GAS->getInputName(i);
2891 bool IsValid =
2893 if (IsHipStdPar && !IsValid)
2894 IsValidTargetAsm = false;
2895 else
2896 assert(IsValid && "Failed to parse input constraint");
2897 InputConstraintInfos.push_back(Info);
2898 }
2899
2900 if (!IsValidTargetAsm)
2902
2903 std::string Constraints;
2904
2905 std::vector ResultRegDests;
2906 std::vector ResultRegQualTys;
2907 std::vector<llvm::Type *> ResultRegTypes;
2908 std::vector<llvm::Type *> ResultTruncRegTypes;
2909 std::vector<llvm::Type *> ArgTypes;
2910 std::vector<llvm::Type *> ArgElemTypes;
2911 std::vectorllvm::Value\* Args;
2912 llvm::BitVector ResultTypeRequiresCast;
2913 std::vector<std::optional<std::pair<unsigned, unsigned>>> ResultBounds;
2914
2915
2916 std::string InOutConstraints;
2917 std::vectorllvm::Value\* InOutArgs;
2918 std::vectorllvm::Type\* InOutArgTypes;
2919 std::vectorllvm::Type\* InOutArgElemTypes;
2920
2921
2922 std::vectorstd::string OutputConstraints;
2923
2924
2925 llvm::SmallSet<std::string, 8> PhysRegOutputs;
2926
2927
2928
2929
2930
2931
2932
2933 bool ReadOnly = true, ReadNone = true;
2934
2935 for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
2937
2938
2941 StringRef(OutputConstraint).substr(1), &OutputConstraintInfos);
2942
2945
2946 std::string GCCReg;
2950 &GCCReg);
2951
2952 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)
2953 CGM.Error(S.getAsmLoc(), "multiple outputs to hard register: " + GCCReg);
2954
2955 OutputConstraints.push_back(OutputConstraint);
2957 if (!Constraints.empty())
2958 Constraints += ',';
2959
2960
2961
2965 if (!Info.allowsMemory() && IsScalarOrAggregate) {
2966
2967 Constraints += "=" + OutputConstraint;
2968 ResultRegQualTys.push_back(QTy);
2969 ResultRegDests.push_back(Dest);
2970
2972
2976 Ty->isAggregateType());
2977
2978 ResultTruncRegTypes.push_back(Ty);
2979 ResultTypeRequiresCast.push_back(RequiresCast);
2980
2981 if (RequiresCast) {
2983 if (Size)
2984 Ty = llvm::IntegerType::get(getLLVMContext(), Size);
2985 else
2986 CGM.Error(OutExpr->getExprLoc(), "output size should not be zero");
2987 }
2988 ResultRegTypes.push_back(Ty);
2989
2990
2991
2993 unsigned InputNo;
2994 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
2997 break;
2998 }
2999 assert(InputNo != S.getNumInputs() && "Didn't find matching input!");
3000
3003
3006
3007 ResultRegTypes.back() = ConvertType(InputTy);
3008 }
3009 }
3010 if (llvm::Type* AdjTy =
3011 getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,
3012 ResultRegTypes.back()))
3013 ResultRegTypes.back() = AdjTy;
3014 else {
3016 diag::err_asm_invalid_type_in_input)
3017 << OutExpr->getType() << OutputConstraint;
3018 }
3019
3020
3021 if (auto *VT = dyn_castllvm::VectorType(ResultRegTypes.back()))
3022 LargestVectorWidth =
3023 std::max((uint64_t)LargestVectorWidth,
3024 VT->getPrimitiveSizeInBits().getKnownMinValue());
3025 } else {
3027
3028
3029
3030
3031
3034
3035 ArgTypes.push_back(DestAddr.getType());
3038 Constraints += "=*";
3039 Constraints += OutputConstraint;
3040 ReadOnly = ReadNone = false;
3041 }
3042
3044 InOutConstraints += ',';
3045
3047 llvm::Value *Arg;
3048 llvm::Type *ArgElemType;
3049 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(
3050 Info, Dest, InputExpr->getType(), InOutConstraints,
3052
3053 if (llvm::Type* AdjTy =
3054 getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,
3055 Arg->getType()))
3056 Arg = Builder.CreateBitCast(Arg, AdjTy);
3057
3058
3059 if (auto *VT = dyn_castllvm::VectorType(Arg->getType()))
3060 LargestVectorWidth =
3061 std::max((uint64_t)LargestVectorWidth,
3062 VT->getPrimitiveSizeInBits().getKnownMinValue());
3063
3065 InOutConstraints += llvm::utostr(i);
3066 else
3067 InOutConstraints += OutputConstraint;
3068
3069 InOutArgTypes.push_back(Arg->getType());
3070 InOutArgElemTypes.push_back(ArgElemType);
3071 InOutArgs.push_back(Arg);
3072 }
3073 }
3074
3075
3076
3080
3082 CGM.getTargetCodeGenInfo().addReturnRegisterOutputs(
3083 *this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
3086 }
3087 }
3088
3089 for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
3091
3093
3095 ReadNone = false;
3096
3097 if (!Constraints.empty())
3098 Constraints += ',';
3099
3100
3102 InputConstraint =
3104
3107 getTarget(), CGM, S, false );
3108
3109 std::string ReplaceConstraint (InputConstraint);
3110 llvm::Value *Arg;
3111 llvm::Type *ArgElemType;
3112 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);
3113
3114
3115
3116
3117
3118
3123
3126
3129 llvm::Type *OutputTy = ConvertType(OutputType);
3131 Arg = Builder.CreateZExt(Arg, OutputTy);
3134 else if (OutputTy->isFloatingPointTy())
3135 Arg = Builder.CreateFPExt(Arg, OutputTy);
3136 }
3137
3138 ReplaceConstraint = OutputConstraints[Output];
3139 }
3140 if (llvm::Type* AdjTy =
3141 getTargetHooks().adjustInlineAsmType(*this, ReplaceConstraint,
3142 Arg->getType()))
3143 Arg = Builder.CreateBitCast(Arg, AdjTy);
3144 else
3145 CGM.getDiags().Report(S.getAsmLoc(), diag::err_asm_invalid_type_in_input)
3146 << InputExpr->getType() << InputConstraint;
3147
3148
3149 if (auto *VT = dyn_castllvm::VectorType(Arg->getType()))
3150 LargestVectorWidth =
3151 std::max((uint64_t)LargestVectorWidth,
3152 VT->getPrimitiveSizeInBits().getKnownMinValue());
3153
3154 ArgTypes.push_back(Arg->getType());
3155 ArgElemTypes.push_back(ArgElemType);
3156 Args.push_back(Arg);
3157 Constraints += InputConstraint;
3158 }
3159
3160
3161 for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
3162 ArgTypes.push_back(InOutArgTypes[i]);
3163 ArgElemTypes.push_back(InOutArgElemTypes[i]);
3164 Args.push_back(InOutArgs[i]);
3165 }
3166 Constraints += InOutConstraints;
3167
3168
3170 llvm::BasicBlock *Fallthrough = nullptr;
3171 bool IsGCCAsmGoto = false;
3172 if (const auto *GS = dyn_cast(&S)) {
3173 IsGCCAsmGoto = GS->isAsmGoto();
3174 if (IsGCCAsmGoto) {
3175 for (const auto *E : GS->labels()) {
3177 Transfer.push_back(Dest.getBlock());
3178 if (!Constraints.empty())
3179 Constraints += ',';
3180 Constraints += "!i";
3181 }
3183 }
3184 }
3185
3186 bool HasUnwindClobber = false;
3187
3188
3189 for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
3190 std::string Clobber = S.getClobber(i);
3191
3192 if (Clobber == "memory")
3193 ReadOnly = ReadNone = false;
3194 else if (Clobber == "unwind") {
3195 HasUnwindClobber = true;
3196 continue;
3197 } else if (Clobber != "cc") {
3199 if (CGM.getCodeGenOpts().StackClashProtector &&
3200 getTarget().isSPRegName(Clobber)) {
3202 diag::warn_stack_clash_protection_inline_asm);
3203 }
3204 }
3205
3207 if (Clobber == "eax" || Clobber == "edx") {
3208 if (Constraints.find("=&A") != std:🧵:npos)
3209 continue;
3210 std:🧵:size_type position1 =
3211 Constraints.find("={" + Clobber + "}");
3212 if (position1 != std:🧵:npos) {
3213 Constraints.insert(position1 + 1, "&");
3214 continue;
3215 }
3216 std:🧵:size_type position2 = Constraints.find("=A");
3217 if (position2 != std:🧵:npos) {
3218 Constraints.insert(position2 + 1, "&");
3219 continue;
3220 }
3221 }
3222 }
3223 if (!Constraints.empty())
3224 Constraints += ',';
3225
3226 Constraints += "~{";
3227 Constraints += Clobber;
3228 Constraints += '}';
3229 }
3230
3231 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
3232 "unwind clobber can't be used with asm goto");
3233
3234
3236 if (!MachineClobbers.empty()) {
3237 if (!Constraints.empty())
3238 Constraints += ',';
3239 Constraints += MachineClobbers;
3240 }
3241
3242 llvm::Type *ResultType;
3243 if (ResultRegTypes.empty())
3244 ResultType = VoidTy;
3245 else if (ResultRegTypes.size() == 1)
3246 ResultType = ResultRegTypes[0];
3247 else
3248 ResultType = llvm::StructType::get(getLLVMContext(), ResultRegTypes);
3249
3250 llvm::FunctionType *FTy =
3251 llvm::FunctionType::get(ResultType, ArgTypes, false);
3252
3254
3255 llvm::InlineAsm::AsmDialect GnuAsmDialect =
3257 ? llvm::InlineAsm::AD_ATT
3258 : llvm::InlineAsm::AD_Intel;
3259 llvm::InlineAsm::AsmDialect AsmDialect = isa(&S) ?
3260 llvm::InlineAsm::AD_Intel : GnuAsmDialect;
3261
3262 llvm::InlineAsm *IA = llvm::InlineAsm::get(
3263 FTy, AsmString, Constraints, HasSideEffect,
3264 false, AsmDialect, HasUnwindClobber);
3265 std::vectorllvm::Value\* RegResults;
3266 llvm::CallBrInst *CBR;
3267 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>
3268 CBRRegResults;
3269 if (IsGCCAsmGoto) {
3270 CBR = Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
3272 UpdateAsmCallInst(*CBR, HasSideEffect, false, ReadOnly,
3275 ArgElemTypes, *this, RegResults);
3276
3277
3278
3279 if (!RegResults.empty()) {
3280 unsigned i = 0;
3281 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {
3282 llvm::Twine SynthName = Dest->getName() + ".split";
3284 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
3285 Builder.SetInsertPoint(SynthBB);
3286
3287 if (ResultRegTypes.size() == 1) {
3288 CBRRegResults[SynthBB].push_back(CBR);
3289 } else {
3290 for (unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {
3291 llvm::Value *Tmp = Builder.CreateExtractValue(CBR, j, "asmresult");
3292 CBRRegResults[SynthBB].push_back(Tmp);
3293 }
3294 }
3295
3298 CBR->setIndirectDest(i++, SynthBB);
3299 }
3300 }
3301 } else if (HasUnwindClobber) {
3306 ArgElemTypes, *this, RegResults);
3307 } else {
3308 llvm::CallInst *Result =
3313 ArgElemTypes, *this, RegResults);
3314 }
3315
3316 EmitAsmStores(*this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
3317 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3318 ResultBounds);
3319
3320
3321
3322
3323 if (IsGCCAsmGoto && !CBRRegResults.empty()) {
3324 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {
3325 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
3326 Builder.SetInsertPoint(Succ, --(Succ->end()));
3327 EmitAsmStores(*this, S, CBRRegResults[Succ], ResultRegTypes,
3328 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3329 ResultTypeRequiresCast, ResultBounds);
3330 }
3331 }
3332}
3333
3337
3338
3341
3345 I != E; ++I, ++CurField) {
3347 if (CurField->hasCapturedVLAType()) {
3349 } else {
3351 }
3352 }
3353
3354 return SlotLV;
3355}
3356
3357
3358
3359llvm::Function *
3362
3363
3364 CodeGenFunction CGF(CGM, true);
3368
3369
3371
3372 return F;
3373}
3374
3379
3380
3381llvm::Function *
3384 "CapturedStmtInfo should be set when generating the captured function");
3388 assert(CD->hasBody() && "missing CapturedDecl body");
3389
3390
3394
3395
3397 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
3398 llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
3399
3400 llvm::Function *F =
3401 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
3403 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
3405 F->addFnAttr(llvm::Attribute::NoUnwind);
3406
3407
3410
3413
3414
3417 for (auto *FD : RD->fields()) {
3418 if (FD->hasCapturedVLAType()) {
3419 auto *ExprArg =
3422 auto VAT = FD->getCapturedVLAType();
3423 VLASizeMap[VAT->getSizeExpr()] = ExprArg;
3424 }
3425 }
3426
3427
3432 }
3433
3434 PGO->assignRegionCounters(GlobalDecl(CD), F);
3437
3438 return F;
3439}
3440
3441
3442
3444 for (auto &I : *BB) {
3445 if (auto *CI = dyn_castllvm::ConvergenceControlInst(&I))
3446 return CI;
3447 }
3448 return nullptr;
3449}
3450
3451llvm::CallBase *
3452CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
3454 assert(ParentToken);
3455
3456 llvm::Value *bundleArgs[] = {ParentToken};
3457 llvm::OperandBundleDef OB("convergencectrl", bundleArgs);
3458 auto *Output = llvm::CallBase::addOperandBundle(
3459 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());
3460 Input->replaceAllUsesWith(Output);
3461 Input->eraseFromParent();
3462 return Output;
3463}
3464
3465llvm::ConvergenceControlInst *
3466CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
3468 assert(ParentToken);
3469 return llvm::ConvergenceControlInst::CreateLoop(*BB, ParentToken);
3470}
3471
3472llvm::ConvergenceControlInst *
3473CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
3474 llvm::BasicBlock *BB = &F->getEntryBlock();
3476 if (Token)
3477 return Token;
3478
3479
3480
3481 F->setConvergent();
3482 return llvm::ConvergenceControlInst::CreateEntry(*BB);
3483}
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...
Definition CGStmt.cpp:2563
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...
Definition CGStmt.cpp:2267
static llvm::ConvergenceControlInst * getConvergenceToken(llvm::BasicBlock *BB)
Definition CGStmt.cpp:3443
static void EmitHipStdParUnsupportedAsm(CodeGenFunction *CGF, const AsmStmt &S)
Definition CGStmt.cpp:2842
static std::optional< SmallVector< uint64_t, 16 > > getLikelihoodWeights(ArrayRef< Stmt::Likelihood > Likelihoods)
Definition CGStmt.cpp:2321
static llvm::MDNode * getAsmSrcLocInfo(const StringLiteral *Str, CodeGenFunction &CGF)
getAsmSrcLocInfo - Return the !srcloc metadata node to attach to an inline asm call instruction.
Definition CGStmt.cpp:2657
static bool isSwiftAsyncCallee(const CallExpr *CE)
Determine if the given call uses the swiftasync calling convention.
Definition CGStmt.cpp:1591
static CSFC_Result CollectStatementsForCase(const Stmt *S, const SwitchCase *Case, bool &FoundCase, SmallVectorImpl< const Stmt * > &ResultStmts)
Definition CGStmt.cpp:2112
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 std::vector< std::optional< std::pair< unsigned, unsigned > > > &ResultBounds)
Definition CGStmt.cpp:2752
static bool hasEmptyLoopBody(const LoopStmt &S)
Definition CGStmt.cpp:1066
CSFC_Result
CollectStatementsForCase - Given the body of a 'switch' statement and a constant value that is being ...
Definition CGStmt.cpp:2111
@ CSFC_Failure
Definition CGStmt.cpp:2111
@ CSFC_Success
Definition CGStmt.cpp:2111
@ CSFC_FallThrough
Definition CGStmt.cpp:2111
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)
Definition CGStmt.cpp:2684
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 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.
CanQualType getCanonicalTagType(const TagDecl *TD) const
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
std::string getInputConstraint(unsigned i) const
getInputConstraint - Return the specified input constraint.
std::string getOutputConstraint(unsigned i) const
getOutputConstraint - Return the constraint string for the specified output operand.
SourceLocation getAsmLoc() const
const Expr * getInputExpr(unsigned i) const
unsigned getNumClobbers() const
const Expr * getOutputExpr(unsigned i) const
unsigned getNumOutputs() const
std::string generateAsmString(const ASTContext &C) const
Assemble final IR asm string.
unsigned getNumInputs() const
std::string getClobber(unsigned i) const
Attr - This represents one attribute.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
BreakStmt - This represents a break.
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
DeclStmt * getBeginStmt()
DeclStmt * getLoopVarStmt()
DeclStmt * getRangeStmt()
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.
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument.
SourceLocation getBeginLoc() const LLVM_READONLY
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument.
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.
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 source atom group for CGDebugInfo::addInstToCurrentSourceAtom.
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 * 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.
API for captured statement code generation.
RAII for correct setting/restoring of CapturedStmtInfo.
void rescopeLabels()
Change the cleanup scope of the labels in this lexical scope to match the scope of the enclosing cont...
Definition CGStmt.cpp:758
void ForceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
bool requiresCleanups() const
Determine whether this scope requires any cleanups.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitCXXTryStmt(const CXXTryStmt &S)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void EmitSehCppScopeBegin()
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...
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 EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
static bool ContainsLabel(const Stmt *S, bool IgnoreCaseStmts=false)
ContainsLabel - Return true if the statement contains a label in it.
void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef< const Attr * > Attrs={})
Definition CGStmt.cpp:1452
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit)
EmitComplexExprIntoLValue - Emit the given expression of complex type and place its result into the s...
static bool hasScalarEvaluationKind(QualType T)
llvm::Type * ConvertType(QualType T)
void EmitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &S)
LValue InitCapturedStruct(const CapturedStmt &S)
Definition CGStmt.cpp:3334
void addInstToNewSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)
Add KeyInstruction and an optional Backup instruction to a new atom group (See ApplyAtomGroup for mor...
CGCapturedStmtInfo * CapturedStmtInfo
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
void EmitOMPParallelForDirective(const OMPParallelForDirective &S)
llvm::CallBase * EmitCallOrInvoke(llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const Twine &Name="")
Emits a call or invoke instruction to the given function, depending on the current state of the EH st...
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOpenACCInitConstruct(const OpenACCInitConstruct &S)
void EmitOMPFlushDirective(const OMPFlushDirective &S)
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
JumpDest getJumpDestForLabel(const LabelDecl *S)
getBasicBlockForLabel - Return the LLVM basicblock that the specified label maps to.
Definition CGStmt.cpp:710
void EmitCoreturnStmt(const CoreturnStmt &S)
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
SmallVector< llvm::ConvergenceControlInst *, 4 > ConvergenceTokenStack
Stack to track the controlled convergence tokens.
void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S)
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)
Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...
bool EmitSimpleStmt(const Stmt *S, ArrayRef< const Attr * > Attrs)
EmitSimpleStmt - Try to emit a "simple" statement which does not necessarily require an insertion poi...
Definition CGStmt.cpp:509
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)
See CGDebugInfo::addInstToCurrentSourceAtom.
const LangOptions & getLangOpts() const
RValue EmitReferenceBindingToExpr(const Expr *E)
Emits a reference binding to the passed in expression.
void EmitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &S)
bool InNoConvergentAttributedStmt
True if the current statement has noconvergent attribute.
void EmitOpenACCWaitConstruct(const OpenACCWaitConstruct &S)
void EmitBlockAfterUses(llvm::BasicBlock *BB)
EmitBlockAfterUses - Emit the given block somewhere hopefully near its uses, and leave the insertion ...
Definition CGStmt.cpp:693
void SimplifyForwardingBlocks(llvm::BasicBlock *BB)
SimplifyForwardingBlocks - If the given basic block is only a branch to another basic block,...
Definition CGStmt.cpp:634
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
bool InNoMergeAttributedStmt
True if the current statement has nomerge attribute.
void EmitOMPScopeDirective(const OMPScopeDirective &S)
LValue MakeAddrLValueWithoutTBAA(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
const TargetInfo & getTarget() const
Address EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
Definition CGStmt.cpp:585
void EmitGotoStmt(const GotoStmt &S)
Definition CGStmt.cpp:846
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPCancelDirective(const OMPCancelDirective &S)
const Expr * RetExpr
If a return statement is being visited, this holds the return statment's result expression.
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
void EmitForStmt(const ForStmt &S, ArrayRef< const Attr * > Attrs={})
Definition CGStmt.cpp:1294
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S)
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 EmitOMPInteropDirective(const OMPInteropDirective &S)
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
void EmitWhileStmt(const WhileStmt &S, ArrayRef< const Attr * > Attrs={})
Definition CGStmt.cpp:1079
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
Emit combined directive 'target parallel loop' as if its constituent constructs are 'target',...
void EmitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &S)
void ResolveBranchFixups(llvm::BasicBlock *Target)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
bool checkIfLoopMustProgress(const Expr *, bool HasEmptyBody)
Returns true if a loop must make progress, which means the mustprogress attribute can be added.
Definition CGStmt.cpp:1016
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
CGDebugInfo * getDebugInfo()
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPReverseDirective(const OMPReverseDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EmitOpenACCDataConstruct(const OpenACCDataConstruct &S)
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)
void EmitObjCAtTryStmt(const ObjCAtTryStmt &S)
const TargetCodeGenInfo & getTargetHooks() const
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void EmitSEHLeaveStmt(const SEHLeaveStmt &S)
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
bool InNoInlineAttributedStmt
True if the current statement has noinline attribute.
SmallVector< llvm::OperandBundleDef, 1 > getBundlesForFunclet(llvm::Value *Callee)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
void EmitCoroutineBody(const CoroutineBodyStmt &S)
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
ASTContext & getContext() const
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
Definition CGStmt.cpp:51
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitIfStmt(const IfStmt &S)
Definition CGStmt.cpp:882
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
void EmitDeferStmt(const DeferStmt &S)
Definition CGStmt.cpp:2084
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
void EmitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &S)
void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S)
Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
EmitCompoundStmt - Emit a compound statement {..} node.
Definition CGStmt.cpp:573
void EmitOpenACCCacheConstruct(const OpenACCCacheConstruct &S)
void EmitOpenACCLoopConstruct(const OpenACCLoopConstruct &S)
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
void EmitOMPFuseDirective(const OMPFuseDirective &S)
void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init)
void EmitAsmStmt(const AsmStmt &S)
Definition CGStmt.cpp:2860
void EmitDefaultStmt(const DefaultStmt &S, ArrayRef< const Attr * > Attrs)
Definition CGStmt.cpp:1985
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitSwitchStmt(const SwitchStmt &S)
Definition CGStmt.cpp:2376
static bool mightAddDeclToScope(const Stmt *S)
Determine if the given statement might introduce a declaration into the current scope,...
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...
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 EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
Definition CGStmt.cpp:61
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
uint64_t getCurrentProfileCount()
Get the profiler's current count.
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
void EmitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &S)
llvm::Function * EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K)
Generate an outlined function for the body of a CapturedStmt, store any captured variables into the c...
Definition CGStmt.cpp:3360
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
static bool containsBreak(const Stmt *S)
containsBreak - Return true if the statement contains a break out of it.
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
HLSLControlFlowHintAttr::Spelling HLSLControlFlowAttr
HLSL Branch attribute.
bool InAlwaysInlineAttributedStmt
True if the current statement has always_inline attribute.
void EmitCaseStmt(const CaseStmt &S, ArrayRef< const Attr * > Attrs)
Definition CGStmt.cpp:1870
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitBreakStmt(const BreakStmt &S)
Definition CGStmt.cpp:1756
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void EmitOpenACCComputeConstruct(const OpenACCComputeConstruct &S)
void EmitDoStmt(const DoStmt &S, ArrayRef< const Attr * > Attrs={})
Definition CGStmt.cpp:1206
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
const TargetInfo & Target
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
Definition CGStmt.cpp:3375
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
Definition CGStmt.cpp:676
void EmitOMPSimdDirective(const OMPSimdDirective &S)
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 EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
RawAddress NormalCleanupDest
i32s containing the indexes of the cleanup destinations.
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
unsigned NextCleanupDestIndex
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
const BreakContinue * GetDestForLoopControlStmt(const LoopControlStmt &S)
Definition CGStmt.cpp:1742
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
llvm::BasicBlock * GetIndirectGotoBlock()
void EmitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &S)
void EmitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &S)
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
static bool hasAggregateEvaluationKind(QualType T)
void EmitCaseStmtRange(const CaseStmt &S, ArrayRef< const Attr * > Attrs)
EmitCaseStmtRange - If case statement range is not too big then add multiple cases to switch instruct...
Definition CGStmt.cpp:1785
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void EmitReturnStmt(const ReturnStmt &S)
EmitReturnStmt - Note that due to GCC extensions, this can have an operand if the function returns vo...
Definition CGStmt.cpp:1617
void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::Value * EmitCheckedArgForAssume(const Expr *E)
Emits an argument for a call to a __builtin_assume.
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
Definition CGStmt.cpp:3382
const CallExpr * MustTailCall
const CGFunctionInfo * CurFnInfo
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
void EmitDeclStmt(const DeclStmt &S)
Definition CGStmt.cpp:1732
void EmitLabelStmt(const LabelStmt &S)
Definition CGStmt.cpp:779
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
void EmitOMPTileDirective(const OMPTileDirective &S)
void EmitDecl(const Decl &D, bool EvaluateConditionDecl=false)
EmitDecl - Emit a declaration.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
void EmitOpenACCSetConstruct(const OpenACCSetConstruct &S)
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitAttributedStmt(const AttributedStmt &S)
Definition CGStmt.cpp:789
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
llvm::LLVMContext & getLLVMContext()
bool SawAsmBlock
Whether we processed a Microsoft-style asm block during CodeGen.
void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)
void EmitIndirectGotoStmt(const IndirectGotoStmt &S)
Definition CGStmt.cpp:858
void MaybeEmitDeferredVarDeclInit(const VarDecl *var)
bool isObviouslyBranchWithoutCleanups(JumpDest Dest) const
isObviouslyBranchWithoutCleanups - Return true if a branch to the specified destination obviously has...
void EmitSEHTryStmt(const SEHTryStmt &S)
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S)
When instrumenting to collect profile data, the counts for some blocks such as switch cases need to n...
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 EmitOMPForDirective(const OMPForDirective &S)
void EmitLabel(const LabelDecl *D)
EmitLabel - Emit the block for the given label.
Definition CGStmt.cpp:721
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
Definition CGStmt.cpp:656
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
void EmitContinueStmt(const ContinueStmt &S)
Definition CGStmt.cpp:1769
This class organizes the cross-function state that is used while generating LLVM code.
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
const llvm::DataLayout & getDataLayout() const
ASTContext & getContext() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
A saved depth on the scope stack.
bool encloses(stable_iterator I) const
Returns true if this scope encloses I.
static stable_iterator invalid()
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
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 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
SourceLocation getLBracLoc() const
body_iterator body_begin()
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
ContinueStmt - This represents a continue.
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
DeferStmt - This represents a deferred statement.
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) 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.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
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.
LabelDecl * getLabel() const
IfStmt - This represents an if/then/else.
bool isNegatedConsteval() const
VarDecl * getConditionVariable()
Retrieve the variable declared in this "if" statement, if any.
IndirectGotoStmt - This represents an indirect goto.
LabelDecl * getConstantTarget()
getConstantTarget - Returns the fixed target of this indirect goto, if one exists.
Represents the declaration of a label.
LabelStmt * getStmt() const
LabelStmt - Represents a label, which has a substatement.
LabelDecl * getDecl() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool assumeFunctionsAreConvergent() const
Base class for BreakStmt and ContinueStmt.
Represents a point when we exit a loop.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
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
specific_decl_iterator< FieldDecl > field_iterator
field_iterator field_begin() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
SourceLocation getBeginLoc() const
const VarDecl * getNRVOCandidate() const
Retrieve the variable that might be used for the named return value optimization.
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
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
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.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "switch" statement, if any.
SwitchCase * getSwitchCaseList()
Exposes information about the current target.
bool validateInputConstraint(MutableArrayRef< ConstraintInfo > OutputConstraints, ConstraintInfo &info) const
std::string simplifyConstraint(StringRef Constraint, SmallVectorImpl< ConstraintInfo > *OutCons=nullptr) 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.
const T * castAs() const
Member-template castAs.
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.
bool isNRVOVariable() const
Determine whether this local variable can be used with the named return value optimization (NRVO).
WhileStmt - This represents a 'while' stmt.
SourceLocation getWhileLoc() const
SourceLocation getRParenLoc() const
VarDecl * getConditionVariable()
Retrieve the variable declared in this "while" statement, if any.
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
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.
U cast(CodeGen::Address addr)
@ None
The alignment was not explicit in code.
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)
llvm::BasicBlock * getBlock() const
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
std::optional< std::pair< unsigned, unsigned > > getOutputOperandBounds() 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