clang: lib/CodeGen/CGException.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
24#include "llvm/IR/IntrinsicInst.h"
25#include "llvm/IR/Intrinsics.h"
26#include "llvm/IR/IntrinsicsWebAssembly.h"
27#include "llvm/Support/SaveAndRestore.h"
28
29using namespace clang;
30using namespace CodeGen;
31
33
34
35 llvm::FunctionType *FTy =
36 llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, false);
37
39}
40
42 llvm::FunctionType *FTy =
43 llvm::FunctionType::get(CGM.VoidTy, false);
45}
46
48 llvm::FunctionType *FTy =
49 llvm::FunctionType::get(CGM.VoidTy, false);
51}
52
54
55
56 llvm::FunctionType *FTy =
57 llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, false);
58
60}
61
63
64
65 llvm::FunctionType *FTy =
66 llvm::FunctionType::get(VoidTy, false);
67
68 StringRef name;
69
70
73 name = "_ZSt9terminatev";
77 name = "__std_terminate";
78 else
79 name = "?terminate@@YAXXZ";
82 name = "objc_terminate";
83 else
84 name = "abort";
86}
87
89 StringRef Name) {
90 llvm::FunctionType *FTy =
91 llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, false);
92
94}
95
128 nullptr};
130 nullptr};
131
134 const llvm::Triple &T = Target.getTriple();
135 if (T.isWindowsMSVCEnvironment())
144}
145
148 const llvm::Triple &T = Target.getTriple();
149 if (T.isWindowsMSVCEnvironment())
151
160 if (T.isOSCygMing())
164 [[fallthrough]];
172 }
173 llvm_unreachable("bad runtime kind");
174}
175
178 const llvm::Triple &T = Target.getTriple();
179 if (T.isWindowsMSVCEnvironment())
181 if (T.isOSAIX())
191 if (T.isOSzOS())
194}
195
196
197
200 if (Target.getTriple().isWindowsMSVCEnvironment())
202
204
205
208
209
210
211
216
220
221
222
226 }
227 llvm_unreachable("bad runtime kind");
228}
229
231 if (T.getArch() == llvm::Triple::x86)
234}
235
241
242
245
246 if (L.ObjC)
251}
252
255
256
257
259 return get(CGF.CGM, dyn_cast_or_null(FD));
260}
261
266 llvm::AttributeList(), true);
267}
268
271 llvm::FunctionCallee Fn = getPersonalityFn(CGM, Personality);
272 return castllvm::Constant(Fn.getCallee());
273}
274
275
277 for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) {
278
279
280 llvm::Value *Val = LPI->getClause(I)->stripPointerCasts();
281 if (LPI->isCatch(I)) {
282
283 if (llvm::GlobalVariable *GV = dyn_castllvm::GlobalVariable(Val))
284
285
286 if (GV->getName().starts_with("OBJC_EHTYPE"))
287 return false;
288 } else {
289
290 llvm::Constant *CVal = castllvm::Constant(Val);
291 for (llvm::User::op_iterator
292 II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) {
293 if (llvm::GlobalVariable *GV =
294 castllvm::GlobalVariable((*II)->stripPointerCasts()))
295
296
297 if (GV->getName().starts_with("OBJC_EHTYPE"))
298 return false;
299 }
300 }
301 }
302 return true;
303}
304
305
306
308 for (llvm::User *U : Fn->users()) {
309
310 if (llvm::ConstantExpr *CE = dyn_castllvm::ConstantExpr(U)) {
311 if (CE->getOpcode() != llvm::Instruction::BitCast) return false;
313 return false;
314 continue;
315 }
316
317
318 llvm::Function *F = dyn_castllvm::Function(U);
319 if (!F) return false;
320
321 for (auto BB = F->begin(), E = F->end(); BB != E; ++BB) {
322 if (BB->isLandingPad())
324 return false;
325 }
326 }
327
328 return true;
329}
330
331
332
333
334
335void CodeGenModule::SimplifyPersonality() {
336
337 if (!LangOpts.CPlusPlus || !LangOpts.ObjC || !LangOpts.Exceptions)
338 return;
339
340
341
343 return;
344
348 return;
349
350 assert(std::strcmp(ObjCXX.PersonalityFn, CXX.PersonalityFn) != 0 &&
351 "Different EHPersonalities using the same personality function.");
352
353 llvm::Function *Fn = getModule().getFunction(ObjCXX.PersonalityFn);
354
355
356 if (!Fn || Fn->use_empty()) return;
357
358
360
361
362
364
365
366 if (Fn->getType() != CXXFn.getCallee()->getType())
367 return;
368
369 Fn->replaceAllUsesWith(CXXFn.getCallee());
370 Fn->eraseFromParent();
371}
372
373
374
376
377 return llvm::ConstantPointerNull::get(CGF.Int8PtrTy);
378}
379
380namespace {
381
382
384 llvm::Value *exn;
385 FreeException(llvm::Value *exn) : exn(exn) {}
388 }
389 };
390}
391
392
393
394
395
397
398
401
402
403
406
407
408
409
410
411
412
413
415 true);
416
417
419 cleanup, castllvm::Instruction(typedAddr.emitRawPointer(*this)));
420}
421
426}
427
432}
433
436}
437
440}
441
443 bool KeepInsertionPoint) {
444
445
446
447
448 const llvm::Triple &T = Target.getTriple();
449 if (CGM.getLangOpts().OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN())) {
451 return;
452 }
453 if (const Expr *SubExpr = E->getSubExpr()) {
454 QualType ThrowType = SubExpr->getType();
456 const Stmt *ThrowStmt = E->getSubExpr();
459 } else {
461 }
462 } else {
464 }
465
466
467
468 if (KeepInsertionPoint)
470}
471
474 return;
475
476 const FunctionDecl* FD = dyn_cast_or_null(D);
477 if (!FD) {
478
479 if (const CapturedDecl* CD = dyn_cast_or_null(D)) {
480 if (CD->isNothrow())
482 }
483 return;
484 }
486 if (!Proto)
487 return;
488
490
491
492
495
496
498 return;
499
500
501
505 else
507 diag::warn_wasm_dynamic_exception_spec_ignored)
509 return;
510 }
511
512
513
514
515
521 diag::warn_wasm_dynamic_exception_spec_ignored)
523
526
527 for (unsigned I = 0; I != NumExceptions; ++I) {
531 true);
532 Filter->setFilter(I, EHType);
533 }
535
536 if (().EHAsynch)
538 }
539}
540
541
545 if (!dispatchBlock) return;
546 if (dispatchBlock->use_empty()) {
547 delete dispatchBlock;
548 return;
549 }
550
552
553
554
556
558 llvm::BasicBlock *unexpectedBB = CGF.createBasicBlock("ehspec.unexpected");
559
560 llvm::Value *zero = CGF.Builder.getInt32(0);
561 llvm::Value *failsFilter =
562 CGF.Builder.CreateICmpSLT(selector, zero, "ehspec.fails");
563 CGF.Builder.CreateCondBr(failsFilter, unexpectedBB,
565
567 }
568
569
570
571
572
575 ->setDoesNotReturn();
576 CGF.Builder.CreateUnreachable();
577}
578
581 return;
582
583 const FunctionDecl* FD = dyn_cast_or_null(D);
584 if (!FD) {
585
586 if (const CapturedDecl* CD = dyn_cast_or_null(D)) {
589 }
590 return;
591 }
593 if (!Proto)
594 return;
595
599
600
602 return;
603
604
605
609 return;
610 }
615
618 }
619}
620
622 const llvm::Triple &T = Target.getTriple();
623
624
625 const bool IsTargetDevice =
626 (CGM.getLangOpts().OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN()));
627 if (!IsTargetDevice)
630 if (!IsTargetDevice)
632}
633
635 unsigned NumHandlers = S.getNumHandlers();
637
638 for (unsigned I = 0; I != NumHandlers; ++I) {
640
642 if (C->getExceptionDecl()) {
643
644
645
646
647
648
651 C->getCaughtType().getNonReferenceType(), CaughtTypeQuals);
652
656 else
658 CaughtType, C->getCaughtType());
660 } else {
661
663
664
667 }
668 }
669}
670
671llvm::BasicBlock *
675
676
677
680
681
683
685 if (!dispatchBlock) {
686 switch (scope.getKind()) {
688
689 EHCatchScope &catchScope = cast(scope);
693
694
695 } else {
697 }
698 break;
699 }
700
703 break;
704
707 break;
708
711 break;
712 }
714 }
715 return dispatchBlock;
716}
717
718llvm::BasicBlock *
720
721
723 return nullptr;
724
725
727
729 if (DispatchBlock)
730 return DispatchBlock;
731
734 else
737
740 DispatchBlock->setName("catch.dispatch");
741 break;
742
744 DispatchBlock->setName("ehcleanup");
745 break;
746
748 llvm_unreachable("exception specifications not handled yet!");
749
751 DispatchBlock->setName("terminate");
752 break;
753 }
755 return DispatchBlock;
756}
757
758
759
760
762 switch (S.getKind()) {
764 return !cast(S).isEHCleanup();
768 return false;
769 }
770
771 llvm_unreachable("Invalid EHScope Kind!");
772}
773
777
778
779
780
781
783 if (!LO.Exceptions || LO.IgnoreExceptions) {
784 if (!LO.Borland && !LO.MicrosoftExt)
785 return nullptr;
787 return nullptr;
788 }
789
790
791 if (LO.CUDA && LO.CUDAIsDevice)
792 return nullptr;
793
794
795
797 if (LP) return LP;
798
800
801 if (->hasPersonalityFn())
803
805
807 } else {
808
810 }
811
812 assert(LP);
813
814
815
817 ir->setCachedLandingPad(LP);
819 }
820
821 return LP;
822}
823
827 "LandingPad should not be emitted when -fignore-exceptions are in "
828 "effect.");
830 switch (innermostEHScope.getKind()) {
833
838 return lpad;
839 }
840
841
842 CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP();
844
845
848
849 llvm::LandingPadInst *LPadInst =
851
852 llvm::Value *LPadExn = Builder.CreateExtractValue(LPadInst, 0);
854 llvm::Value *LPadSel = Builder.CreateExtractValue(LPadInst, 1);
856
857
858
859
860
861
862
863 bool hasCatchAll = false;
864 bool hasCleanup = false;
865 bool hasFilter = false;
869 ++I) {
870
871 switch (I->getKind()) {
873
874 hasCleanup = (hasCleanup || cast(*I).isEHCleanup());
875 continue;
876
878 assert(I.next() == EHStack.end() && "EH filter is not end of EH stack");
879 assert(!hasCatchAll && "EH filter reached after catch-all");
880
881
883 hasFilter = true;
884
885
886 for (unsigned i = 0, e = filter.getNumFilters(); i != e; ++i)
887 filterTypes.push_back(filter.getFilter(i));
888 goto done;
889 }
890
892
893 assert(!hasCatchAll);
894 hasCatchAll = true;
895 goto done;
896
898 break;
899 }
900
901 EHCatchScope &catchScope = cast(*I);
902 for (unsigned hi = 0, he = catchScope.getNumHandlers(); hi != he; ++hi) {
904 assert(handler.Type.Flags == 0 &&
905 "landingpads do not support catch handler flags");
906
907
909 assert(!hasCatchAll);
910 hasCatchAll = true;
911 goto done;
912 }
913
914
915 if (catchTypes.insert(handler.Type.RTTI).second)
916
917 LPadInst->addClause(handler.Type.RTTI);
918 }
919 }
920
921 done:
922
923 assert(!(hasCatchAll && hasFilter));
924 if (hasCatchAll) {
926
927
928
929 } else if (hasFilter) {
930
931
932
934 llvm::ArrayType *AType =
935 llvm::ArrayType::get(!filterTypes.empty() ?
936 filterTypes[0]->getType() : Int8PtrTy,
937 filterTypes.size());
938
939 for (unsigned i = 0, e = filterTypes.size(); i != e; ++i)
940 Filters.push_back(castllvm::Constant(filterTypes[i]));
941 llvm::Constant *FilterArray = llvm::ConstantArray::get(AType, Filters);
942 LPadInst->addClause(FilterArray);
943
944
945 if (hasCleanup)
946 LPadInst->setCleanup(true);
947
948
949 } else if (hasCleanup) {
950 LPadInst->setCleanup(true);
951 }
952
953 assert((LPadInst->getNumClauses() > 0 || LPadInst->isCleanup()) &&
954 "landingpad instruction has no clauses!");
955
956
958
959
960 Builder.restoreIP(savedIP);
961
962 return lpad;
963}
964
967 assert(DispatchBlock);
968
969 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP();
971
973 if (!ParentPad)
974 ParentPad = llvm::ConstantTokenNone::get(CGF.getLLVMContext());
975 llvm::BasicBlock *UnwindBB =
977
979 llvm::CatchSwitchInst *CatchSwitch =
980 CGF.Builder.CreateCatchSwitch(ParentPad, UnwindBB, NumHandlers);
981
982
983 for (unsigned I = 0; I < NumHandlers; ++I) {
985
989
991
993 CGF.Builder.CreateCatchPad(
995 llvm::Constant::getNullValue(CGF.VoidPtrTy)});
996 } else {
997 CGF.Builder.CreateCatchPad(CatchSwitch, {TypeInfo.RTTI});
998 }
999
1000 CatchSwitch->addHandler(Handler.Block);
1001 }
1002 CGF.Builder.restoreIP(SavedIP);
1003}
1004
1005
1006
1007
1011 assert(DispatchBlock);
1012
1013 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP();
1015
1017 if (!ParentPad)
1018 ParentPad = llvm::ConstantTokenNone::get(CGF.getLLVMContext());
1019 llvm::BasicBlock *UnwindBB =
1021
1023 llvm::CatchSwitchInst *CatchSwitch =
1024 CGF.Builder.CreateCatchSwitch(ParentPad, UnwindBB, NumHandlers);
1025
1026
1027
1028 llvm::BasicBlock *WasmCatchStartBlock = CGF.createBasicBlock("catch.start");
1029 CatchSwitch->addHandler(WasmCatchStartBlock);
1031
1032
1034 for (unsigned I = 0, E = NumHandlers; I < E; ++I) {
1039 CatchTypes.push_back(TypeInfo.RTTI);
1040 }
1041 auto *CPI = CGF.Builder.CreateCatchPad(CatchSwitch, CatchTypes);
1042
1043
1044
1045
1046 llvm::Function *GetExnFn =
1047 CGF.CGM.getIntrinsic(llvm::Intrinsic::wasm_get_exception);
1048 llvm::Function *GetSelectorFn =
1049 CGF.CGM.getIntrinsic(llvm::Intrinsic::wasm_get_ehselector);
1050 llvm::CallInst *Exn = CGF.Builder.CreateCall(GetExnFn, CPI);
1052 llvm::CallInst *Selector = CGF.Builder.CreateCall(GetSelectorFn, CPI);
1053
1054 llvm::Function *TypeIDFn =
1056
1057
1061 CGF.Builder.restoreIP(SavedIP);
1062 return;
1063 }
1064
1065
1066 for (unsigned I = 0, E = NumHandlers;; ++I) {
1067 assert(I < E && "ran off end of handlers!");
1072
1073
1074 llvm::BasicBlock *NextBlock;
1075
1076 bool EmitNextBlock = false, NextIsEnd = false;
1077
1078
1079
1080
1081 if (I + 1 == E) {
1083 EmitNextBlock = true;
1084 NextIsEnd = true;
1085
1086
1087
1090 NextIsEnd = true;
1091
1092
1093 } else {
1095 EmitNextBlock = true;
1096 }
1097
1098
1099 llvm::CallInst *TypeIndex = CGF.Builder.CreateCall(TypeIDFn, TypeInfo.RTTI);
1100 TypeIndex->setDoesNotThrow();
1101
1102 llvm::Value *MatchesTypeIndex =
1103 CGF.Builder.CreateICmpEQ(Selector, TypeIndex, "matches");
1104 CGF.Builder.CreateCondBr(MatchesTypeIndex, Handler.Block, NextBlock);
1105
1106 if (EmitNextBlock)
1108 if (NextIsEnd)
1109 break;
1110 }
1111
1112 CGF.Builder.restoreIP(SavedIP);
1113}
1114
1115
1116
1123
1125 assert(dispatchBlock);
1126
1127
1128
1131 assert(dispatchBlock == catchScope.getHandler(0).Block);
1132 return;
1133 }
1134
1135 CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP();
1137
1138
1139 llvm::Function *llvm_eh_typeid_for =
1141 llvm::Type *argTy = llvm_eh_typeid_for->getArg(0)->getType();
1143
1144
1146
1147
1148 for (unsigned i = 0, e = catchScope.getNumHandlers(); ; ++i) {
1149 assert(i < e && "ran off end of handlers!");
1151
1152 llvm::Value *typeValue = handler.Type.RTTI;
1153 assert(handler.Type.Flags == 0 &&
1154 "landingpads do not support catch handler flags");
1155 assert(typeValue && "fell into catch-all case!");
1156
1157 if (typeValue->getType() != argTy)
1158 typeValue =
1161
1162
1163 bool nextIsEnd;
1164 llvm::BasicBlock *nextBlock;
1165
1166
1167
1168 if (i + 1 == e) {
1170 nextIsEnd = true;
1171
1172
1173
1176 nextIsEnd = true;
1177
1178
1179 } else {
1181 nextIsEnd = false;
1182 }
1183
1184
1185 llvm::CallInst *typeIndex =
1186 CGF.Builder.CreateCall(llvm_eh_typeid_for, typeValue);
1187 typeIndex->setDoesNotThrow();
1188
1189 llvm::Value *matchesTypeIndex =
1190 CGF.Builder.CreateICmpEQ(selector, typeIndex, "matches");
1191 CGF.Builder.CreateCondBr(matchesTypeIndex, handler.Block, nextBlock);
1192
1193
1194 if (nextIsEnd) {
1195 CGF.Builder.restoreIP(savedIP);
1196 return;
1197 }
1198
1200 }
1201}
1202
1208}
1209
1211 unsigned NumHandlers = S.getNumHandlers();
1215
1216
1220 return;
1221 }
1222
1223
1225
1226
1227
1229 CatchScope.begin(), CatchScope.begin() + NumHandlers);
1230
1232
1233
1235
1236
1238 Builder.CreateBr(ContBB);
1239
1240
1241
1242 bool doImplicitRethrow = false;
1243 if (IsFnTryBlock)
1244 doImplicitRethrow = isa(CurCodeDecl) ||
1246
1247
1248
1249
1251 llvm::BasicBlock *WasmCatchStartBlock = nullptr;
1253 auto *CatchSwitch =
1254 castllvm::CatchSwitchInst(DispatchBlock->getFirstNonPHI());
1255 WasmCatchStartBlock = CatchSwitch->hasUnwindDest()
1256 ? CatchSwitch->getSuccessor(1)
1257 : CatchSwitch->getSuccessor(0);
1258 auto *CPI = castllvm::CatchPadInst(WasmCatchStartBlock->getFirstNonPHI());
1260 }
1261
1262
1263
1264
1265
1266
1267
1268
1269 bool HasCatchAll = false;
1270 for (unsigned I = NumHandlers; I != 0; --I) {
1271 HasCatchAll |= Handlers[I - 1].isCatchAll();
1272 llvm::BasicBlock *CatchBlock = Handlers[I-1].Block;
1274
1275
1277
1278
1279
1280 RunCleanupsScope CatchScope(*this);
1281
1282
1285
1286
1288
1289
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1303 Builder.CreateUnreachable();
1304 Builder.ClearInsertionPoint();
1305 }
1306
1307
1308 CatchScope.ForceCleanup();
1309
1310
1312 Builder.CreateBr(ContBB);
1313 }
1314
1315
1316
1317
1318
1320 assert(WasmCatchStartBlock);
1321
1322
1323
1324
1325 llvm::BasicBlock *RethrowBlock = WasmCatchStartBlock;
1326 while (llvm::Instruction *TI = RethrowBlock->getTerminator()) {
1327 auto *BI = castllvm::BranchInst(TI);
1328 assert(BI->isConditional());
1329 RethrowBlock = BI->getSuccessor(1);
1330 }
1331 assert(RethrowBlock != WasmCatchStartBlock && RethrowBlock->empty());
1332 Builder.SetInsertPoint(RethrowBlock);
1333 llvm::Function *RethrowInCatchFn =
1336 }
1337
1340}
1341
1342namespace {
1344 llvm::Value *ForEHVar;
1345 llvm::FunctionCallee EndCatchFn;
1346 CallEndCatchForFinally(llvm::Value *ForEHVar,
1347 llvm::FunctionCallee EndCatchFn)
1348 : ForEHVar(ForEHVar), EndCatchFn(EndCatchFn) {}
1349
1351 llvm::BasicBlock *EndCatchBB = CGF.createBasicBlock("finally.endcatch");
1352 llvm::BasicBlock *CleanupContBB =
1354
1355 llvm::Value *ShouldEndCatch =
1357 CGF.Builder.CreateCondBr(ShouldEndCatch, EndCatchBB, CleanupContBB);
1361 }
1362 };
1363
1365 const Stmt *Body;
1366 llvm::Value *ForEHVar;
1367 llvm::FunctionCallee EndCatchFn;
1368 llvm::FunctionCallee RethrowFn;
1369 llvm::Value *SavedExnVar;
1370
1371 PerformFinally(const Stmt *Body, llvm::Value *ForEHVar,
1372 llvm::FunctionCallee EndCatchFn,
1373 llvm::FunctionCallee RethrowFn, llvm::Value *SavedExnVar)
1374 : Body(Body), ForEHVar(ForEHVar), EndCatchFn(EndCatchFn),
1375 RethrowFn(RethrowFn), SavedExnVar(SavedExnVar) {}
1376
1378
1379 if (EndCatchFn)
1381 ForEHVar, EndCatchFn);
1382
1383
1384
1385 llvm::Value *SavedCleanupDest =
1387 "cleanup.dest.saved");
1388
1389
1391
1392
1393
1395 llvm::BasicBlock *RethrowBB = CGF.createBasicBlock("finally.rethrow");
1396 llvm::BasicBlock *ContBB = CGF.createBasicBlock("finally.cont");
1397
1398 llvm::Value *ShouldRethrow =
1400 CGF.Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB);
1401
1403 if (SavedExnVar) {
1407 } else {
1409 }
1410 CGF.Builder.CreateUnreachable();
1411
1413
1414
1417 }
1418
1419
1420
1421
1422 if (EndCatchFn) {
1423 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
1425 CGF.Builder.restoreIP(SavedIP);
1426 }
1427
1428
1429
1431 }
1432 };
1433}
1434
1435
1436
1437
1439 llvm::FunctionCallee beginCatchFn,
1440 llvm::FunctionCallee endCatchFn,
1441 llvm::FunctionCallee rethrowFn) {
1442 assert((!!beginCatchFn) == (!!endCatchFn) &&
1443 "begin/end catch functions not paired");
1444 assert(rethrowFn && "rethrow function is required");
1445
1446 BeginCatchFn = beginCatchFn;
1447
1448
1449
1450
1451
1452
1453
1454 llvm::FunctionType *rethrowFnTy = rethrowFn.getFunctionType();
1455 SavedExnVar = nullptr;
1456 if (rethrowFnTy->getNumParams())
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1475
1476
1479
1480
1482 ForEHVar, endCatchFn,
1483 rethrowFn, SavedExnVar);
1484
1485
1486 llvm::BasicBlock *catchBB = CGF.createBasicBlock("finally.catchall");
1489}
1490
1492
1494 llvm::BasicBlock *catchBB = catchScope.getHandler(0).Block;
1495
1497
1498
1499 if (catchBB->use_empty()) {
1500 delete catchBB;
1501 } else {
1502 CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveAndClearIP();
1504
1505 llvm::Value *exn = nullptr;
1506
1507
1508 if (BeginCatchFn) {
1511 }
1512
1513
1514 if (SavedExnVar) {
1517 }
1518
1519
1521
1522
1524
1525 CGF.Builder.restoreIP(savedIP);
1526 }
1527
1528
1530}
1531
1533 if (TerminateLandingPad)
1534 return TerminateLandingPad;
1535
1536 CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
1537
1538
1540 Builder.SetInsertPoint(TerminateLandingPad);
1541
1542
1544
1545 if (->hasPersonalityFn())
1547
1548 llvm::LandingPadInst *LPadInst =
1551
1552 llvm::Value *Exn = nullptr;
1554 Exn = Builder.CreateExtractValue(LPadInst, 0);
1555 llvm::CallInst *terminateCall =
1557 terminateCall->setDoesNotReturn();
1558 Builder.CreateUnreachable();
1559
1560
1561 Builder.restoreIP(SavedIP);
1562
1563 return TerminateLandingPad;
1564}
1565
1567 if (TerminateHandler)
1568 return TerminateHandler;
1569
1570
1571
1573 CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
1574 Builder.SetInsertPoint(TerminateHandler);
1575
1576 llvm::Value *Exn = nullptr;
1579 llvm::CallInst *terminateCall =
1581 terminateCall->setDoesNotReturn();
1582 Builder.CreateUnreachable();
1583
1584
1585 Builder.restoreIP(SavedIP);
1586
1587 return TerminateHandler;
1588}
1589
1592 "use getTerminateLandingPad for non-funclet EH");
1593
1594 llvm::BasicBlock *&TerminateFunclet = TerminateFunclets[CurrentFuncletPad];
1595 if (TerminateFunclet)
1596 return TerminateFunclet;
1597
1598 CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
1599
1600
1601
1603 Builder.SetInsertPoint(TerminateFunclet);
1604
1605
1606
1609 if (!ParentPad)
1612
1613
1614 llvm::CallInst *terminateCall =
1616 terminateCall->setDoesNotReturn();
1617 Builder.CreateUnreachable();
1618
1619
1620 Builder.restoreIP(SavedIP);
1621
1622 return TerminateFunclet;
1623}
1624
1627
1628 CGBuilderTy::InsertPoint SavedIP = Builder.saveIP();
1629
1630
1633
1635
1636
1637
1639 if (RethrowName != nullptr && !isCleanup) {
1642 Builder.CreateUnreachable();
1643 Builder.restoreIP(SavedIP);
1645 }
1646
1647
1650
1651 llvm::Type *LPadType = llvm::StructType::get(Exn->getType(), Sel->getType());
1652 llvm::Value *LPadVal = llvm::PoisonValue::get(LPadType);
1653 LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val");
1654 LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val");
1655
1656 Builder.CreateResume(LPadVal);
1657 Builder.restoreIP(SavedIP);
1659}
1660
1663 {
1665
1667
1668 llvm::BasicBlock *TryBB = nullptr;
1669
1673 TryBB = Builder.GetInsertBlock();
1674 }
1675
1677
1678
1679 if (TryBB) {
1682 }
1683
1685
1686 if (!TryExit.getBlock()->use_empty())
1687 EmitBlock(TryExit.getBlock(), true);
1688 else
1689 delete TryExit.getBlock();
1690 }
1692}
1693
1694
1695
1699 .insert(BB).second ||
1700 !BB->getParent() || BB->empty())
1701 return;
1702
1703 if (!BB->isEHPad()) {
1704 for (llvm::BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE;
1705 ++J) {
1706 if (auto LI = dyn_castllvm::LoadInst(J)) {
1707 LI->setVolatile(true);
1708 } else if (auto SI = dyn_castllvm::StoreInst(J)) {
1709 SI->setVolatile(true);
1710 } else if (auto* MCI = dyn_castllvm::MemIntrinsic(J)) {
1711 MCI->setVolatile(llvm::ConstantInt::get(Builder.getInt1Ty(), 1));
1712 }
1713 }
1714 }
1715 const llvm::Instruction *TI = BB->getTerminator();
1716 if (TI) {
1717 unsigned N = TI->getNumSuccessors();
1718 for (unsigned I = 0; I < N; I++)
1720 }
1721}
1722
1723namespace {
1725 llvm::Function *OutlinedFinally;
1726 PerformSEHFinally(llvm::Function *OutlinedFinally)
1727 : OutlinedFinally(OutlinedFinally) {}
1728
1732
1734
1735
1737 llvm::Value *FP = nullptr;
1738
1740 FP = &CGF.CurFn->arg_begin()[1];
1741 } else {
1742 llvm::Function *LocalAddrFn =
1743 CGM.getIntrinsic(llvm::Intrinsic::localaddress);
1744 FP = CGF.Builder.CreateCall(LocalAddrFn);
1745 }
1746
1747 llvm::Value *IsForEH =
1748 llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup());
1749
1750
1751
1752
1753
1754
1755 if (!F.isForEHCleanup() && F.hasExitSwitch()) {
1758 llvm::Value *Zero = llvm::Constant::getNullValue(CGM.Int32Ty);
1759 IsForEH = CGF.Builder.CreateICmpNE(Load, Zero);
1760 }
1761
1764
1765
1768
1771 }
1772};
1773}
1774
1775namespace {
1776
1779 const VarDecl *ParentThis;
1783 : ParentCGF(ParentCGF), ParentThis(ParentThis) {}
1784
1785
1786 bool foundCaptures() {
1787 return !Captures.empty() || SEHCodeSlot.isValid();
1788 }
1789
1790 void Visit(const Stmt *S) {
1791
1793 for (const Stmt *Child : S->children())
1794 if (Child)
1795 Visit(Child);
1796 }
1797
1798 void VisitDeclRefExpr(const DeclRefExpr *E) {
1799
1800 if (E->refersToEnclosingVariableOrCapture())
1801 Captures.insert(ParentThis);
1802
1803 const auto *D = dyn_cast(E->getDecl());
1804 if (D && D->isLocalVarDeclOrParm() && D->hasLocalStorage())
1805 Captures.insert(D);
1806 }
1807
1808 void VisitCXXThisExpr(const CXXThisExpr *E) {
1809 Captures.insert(ParentThis);
1810 }
1811
1812 void VisitCallExpr(const CallExpr *E) {
1813
1814 if (ParentCGF.getTarget().getTriple().getArch() != llvm::Triple::x86)
1815 return;
1816
1817 unsigned ID = E->getBuiltinCallee();
1818 switch (ID) {
1819 case Builtin::BI__exception_code:
1820 case Builtin::BI_exception_code:
1821
1822
1823
1824 if (!SEHCodeSlot.isValid())
1826 break;
1827 }
1828 }
1829};
1830}
1831
1834 llvm::Value *ParentFP) {
1835 llvm::CallInst *RecoverCall = nullptr;
1837 if (auto *ParentAlloca =
1838 dyn_cast_or_nullllvm::AllocaInst(ParentVar.getBasePointer())) {
1839
1840
1841 auto InsertPair = ParentCGF.EscapedLocals.insert(
1842 std::make_pair(ParentAlloca, ParentCGF.EscapedLocals.size()));
1843 int FrameEscapeIdx = InsertPair.first->second;
1844
1845 llvm::Function *FrameRecoverFn = llvm::Intrinsic::getOrInsertDeclaration(
1846 &CGM.getModule(), llvm::Intrinsic::localrecover);
1847 RecoverCall = Builder.CreateCall(
1849 llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)});
1850
1851 } else {
1852
1853
1854
1855 auto *ParentRecover = castllvm::IntrinsicInst(
1856 ParentVar.emitRawPointer(*this)->stripPointerCasts());
1857 assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover &&
1858 "expected alloca or localrecover in parent LocalDeclMap");
1859 RecoverCall = castllvm::CallInst(ParentRecover->clone());
1860 RecoverCall->setArgOperand(1, ParentFP);
1862 }
1863
1864
1865 llvm::Value *ChildVar =
1866 Builder.CreateBitCast(RecoverCall, ParentVar.getType());
1867 ChildVar->setName(ParentVar.getName());
1869}
1870
1872 const Stmt *OutlinedStmt,
1873 bool IsFilter) {
1874
1876 Finder.Visit(OutlinedStmt);
1877
1878
1879
1880 if (!Finder.foundCaptures() &&
1882 if (IsFilter)
1884 return;
1885 }
1886
1887 llvm::Value *EntryFP = nullptr;
1890
1891
1892
1893 EntryFP = Builder.CreateCall(
1895 {Builder.getInt32(1)});
1896 } else {
1897
1898
1899 auto AI = CurFn->arg_begin();
1900 ++AI;
1901 EntryFP = &*AI;
1902 }
1903
1904 llvm::Value *ParentFP = EntryFP;
1905 if (IsFilter) {
1906
1907
1908
1909 llvm::Function *RecoverFPIntrin =
1912
1913
1914
1915
1916
1917
1918
1920
1921
1922
1923 llvm::AllocaInst *FramePtrAddrAlloca = nullptr;
1924 for (auto &I : ParentCGF.LocalDeclMap) {
1925 const VarDecl *D = cast(I.first);
1926 if (isa(D) &&
1928 assert(D->getName().starts_with("frame_pointer"));
1929 FramePtrAddrAlloca =
1930 castllvm::AllocaInst(I.second.getBasePointer());
1931 break;
1932 }
1933 }
1934 assert(FramePtrAddrAlloca);
1935 auto InsertPair = ParentCGF.EscapedLocals.insert(
1936 std::make_pair(FramePtrAddrAlloca, ParentCGF.EscapedLocals.size()));
1937 int FrameEscapeIdx = InsertPair.first->second;
1938
1939
1940
1941
1942
1943
1944 llvm::Function *FrameRecoverFn = llvm::Intrinsic::getOrInsertDeclaration(
1945 &CGM.getModule(), llvm::Intrinsic::localrecover);
1946 ParentFP = Builder.CreateCall(
1948 llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)});
1951 }
1952 }
1953
1954
1955 for (const VarDecl *VD : Finder.Captures) {
1958 continue;
1959 }
1961 "captured non-local variable");
1962
1966 continue;
1967 }
1968
1969
1970
1971 auto I = ParentCGF.LocalDeclMap.find(VD);
1972 if (I == ParentCGF.LocalDeclMap.end())
1973 continue;
1974
1975 Address ParentVar = I->second;
1978 setAddrOfLocalVar(VD, Recovered);
1979
1980 if (isa(VD)) {
1981 CXXABIThisAlignment = ParentCGF.CXXABIThisAlignment;
1982 CXXThisAlignment = ParentCGF.CXXThisAlignment;
1986
1987
1988 LValue ThisFieldLValue =
1992 } else {
1995 }
1996 } else {
1997 CXXThisValue = CXXABIThisValue;
1998 }
1999 }
2000 }
2001
2002 if (Finder.SEHCodeSlot.isValid()) {
2005 }
2006
2007 if (IsFilter)
2009}
2010
2011
2012
2013
2015 bool IsFilter,
2016 const Stmt *OutlinedStmt) {
2018
2019
2021 {
2022 llvm::raw_svector_ostream OS(Name);
2024 assert(ParentSEHFn && "No CurSEHParent!");
2026 if (IsFilter)
2028 else
2030 }
2031
2034
2035
2036 if (IsFilter) {
2038 getContext(), nullptr, StartLoc,
2039 &getContext().Idents.get("exception_pointers"),
2041 } else {
2043 getContext(), nullptr, StartLoc,
2044 &getContext().Idents.get("abnormal_termination"),
2046 }
2048 getContext(), nullptr, StartLoc,
2051 }
2052
2054
2057
2059 llvm::Function *Fn = llvm::Function::Create(
2060 FnTy, llvm::GlobalValue::InternalLinkage, Name.str(), &CGM.getModule());
2061
2063
2067
2070}
2071
2072
2073
2074
2075llvm::Function *
2080
2081
2086
2088
2090}
2091
2092llvm::Function *
2095 const Stmt *FinallyBlock = Finally.getBlock();
2097
2098
2100
2102
2104}
2105
2107 llvm::Value *ParentFP,
2108 llvm::Value *EntryFP) {
2109
2110
2112
2116 } else {
2117
2118
2119
2120
2125 }
2126
2127
2128
2129
2130
2131
2132
2133
2134 llvm::Type *RecordTy = llvm::PointerType::getUnqual(getLLVMContext());
2135 llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy);
2139 assert(.empty() && "emitting EH code outside of __except");
2141}
2142
2144
2145
2147 return llvm::UndefValue::get(Int8PtrTy);
2150}
2151
2153 assert(.empty() && "emitting EH code outside of __except");
2155}
2156
2158
2159
2160 auto AI = CurFn->arg_begin();
2162}
2163
2165 llvm::Function *FinallyFunc) {
2166 EHStack.pushCleanup(Kind, FinallyFunc);
2167}
2168
2171 HelperCGF.ParentCGF = this;
2172 if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
2173
2174 llvm::Function *FinallyFunc =
2175 HelperCGF.GenerateSEHFinallyFunction(*this, *Finally);
2176
2177
2179 return;
2180 }
2181
2182
2183 const SEHExceptStmt *Except = S.getExceptHandler();
2184 assert(Except);
2188
2189
2190
2191
2192 llvm::Constant *C =
2196 C->isOneValue()) {
2198 return;
2199 }
2200
2201
2202
2203 llvm::Function *FilterFunc =
2204 HelperCGF.GenerateSEHFilterFunction(*this, *Except);
2206}
2207
2209
2210 if (S.getFinallyHandler()) {
2212 return;
2213 }
2214
2215
2219 }
2220
2221
2222 const SEHExceptStmt *Except = S.getExceptHandler();
2223 assert(Except && "__try must have __finally xor __except");
2225
2226
2227
2228
2233 return;
2234 }
2235
2236
2238
2239
2241 Builder.CreateBr(ContBB);
2242
2243
2245
2246
2247 llvm::BasicBlock *CatchPadBB = CatchScope.getHandler(0).Block;
2249
2251
2252
2253
2254 llvm::CatchPadInst *CPI =
2255 castllvm::CatchPadInst(CatchPadBB->getFirstNonPHI());
2257 Builder.CreateCatchRet(CPI, ExceptBB);
2259
2260
2262 llvm::Function *SEHCodeIntrin =
2264 llvm::Value *Code = Builder.CreateCall(SEHCodeIntrin, {CPI});
2266 }
2267
2268
2270
2271
2273
2275 Builder.CreateBr(ContBB);
2276
2278}
2279
2281
2282
2283
2286
2287
2288
2290 Builder.CreateUnreachable();
2291 Builder.ClearInsertionPoint();
2292 return;
2293 }
2294
2296}
static llvm::FunctionCallee getUnexpectedFn(CodeGenModule &CGM)
static const EHPersonality & getObjCPersonality(const TargetInfo &Target, const LangOptions &L)
static const EHPersonality & getSEHPersonalityMSVC(const llvm::Triple &T)
static const EHPersonality & getCXXPersonality(const TargetInfo &Target, const LangOptions &L)
static llvm::FunctionCallee getPersonalityFn(CodeGenModule &CGM, const EHPersonality &Personality)
static void emitFilterDispatchBlock(CodeGenFunction &CGF, EHFilterScope &filterScope)
Emit the dispatch block for a filter scope if necessary.
static void emitCatchPadBlock(CodeGenFunction &CGF, EHCatchScope &CatchScope)
static llvm::FunctionCallee getFreeExceptionFn(CodeGenModule &CGM)
static llvm::FunctionCallee getSehTryEndFn(CodeGenModule &CGM)
static bool LandingPadHasOnlyCXXUses(llvm::LandingPadInst *LPI)
Check whether a landingpad instruction only uses C++ features.
static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn)
Check whether a personality function could reasonably be swapped for a C++ personality function.
static void emitCatchDispatchBlock(CodeGenFunction &CGF, EHCatchScope &catchScope)
Emit the structure of the dispatch block for the given catch scope.
static llvm::Constant * getOpaquePersonalityFn(CodeGenModule &CGM, const EHPersonality &Personality)
static bool isNonEHScope(const EHScope &S)
Check whether this is a non-EH scope, i.e.
static llvm::FunctionCallee getCatchallRethrowFn(CodeGenModule &CGM, StringRef Name)
static llvm::FunctionCallee getSehTryBeginFn(CodeGenModule &CGM)
static llvm::Constant * getCatchAllValue(CodeGenFunction &CGF)
Returns the value to inject into a selector to indicate the presence of a catch-all.
static const EHPersonality & getObjCXXPersonality(const TargetInfo &Target, const LangOptions &L)
Determines the personality function to use when both C++ and Objective-C exceptions are being caught.
static void emitWasmCatchPadBlock(CodeGenFunction &CGF, EHCatchScope &CatchScope)
static const EHPersonality & getCPersonality(const TargetInfo &Target, const LangOptions &L)
llvm::DenseSet< const void * > Visited
llvm::MachO::Target Target
Defines the Objective-C statement AST node classes.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CanQualType UnsignedCharTy
QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals) const
Return this type as a completely-unqualified array type, capturing the qualifiers in Quals.
CXXCatchStmt - This represents a C++ catch block.
Represents the this expression in C++.
A C++ throw-expression (C++ [except.throw]).
CXXTryStmt - A C++ try block, including all handlers.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Represents the body of a CapturedStmt, and serves as its DeclContext.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * getBasePointer() const
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Address withPointer(llvm::Value *NewPointer, KnownNonNull_t IsKnownNonNull) const
Return address with different pointer, but same element type and alignment.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::StringRef getName() const
Return the IR name of the pointer value.
llvm::PointerType * getType() const
Return the type of the pointer value.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
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::StoreInst * CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, CharUnits Align, bool IsVolatile=false)
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::LoadInst * CreateFlagLoad(llvm::Value *Addr, const llvm::Twine &Name="")
Emit a load from an i1 flag variable.
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C)=0
virtual void emitRethrow(CodeGenFunction &CGF, bool isNoReturn)=0
virtual llvm::CallInst * emitTerminateForUnexpectedException(CodeGenFunction &CGF, llvm::Value *Exn)
virtual CatchTypeInfo getCatchAllTypeInfo()
virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E)=0
virtual CatchTypeInfo getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType)=0
MangleContext & getMangleContext()
Gets the mangle context.
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
CGFunctionInfo - Class to encapsulate the information about a function definition.
virtual llvm::Constant * GetEHType(QualType T)=0
Get the type constant to catch for the given ObjC pointer type.
virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S, bool ClearInsertionPoint=true)=0
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
void exit(CodeGenFunction &CGF)
void enter(CodeGenFunction &CGF, const Stmt *Finally, llvm::FunctionCallee beginCatchFn, llvm::FunctionCallee endCatchFn, llvm::FunctionCallee rethrowFn)
Enters a finally block for an implementation using zero-cost exceptions.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::BasicBlock * getEHDispatchBlock(EHScopeStack::stable_iterator scope)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void DeactivateCleanupBlock(EHScopeStack::stable_iterator Cleanup, llvm::Instruction *DominatingIP)
DeactivateCleanupBlock - Deactivates the given cleanup block.
void EnterSEHTryStmt(const SEHTryStmt &S)
Address getExceptionSlot()
Returns a pointer to the function's exception object and selector slot, which is assigned in every la...
void VolatilizeTryBlocks(llvm::BasicBlock *BB, llvm::SmallPtrSet< llvm::BasicBlock *, 10 > &V)
llvm::Function * GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF, const SEHFinallyStmt &Finally)
llvm::CallInst * EmitTrapCall(llvm::Intrinsic::ID IntrID)
Emit a call to trap or debugtrap and attach function attribute "trap-func-name" if specified.
llvm::Function * GenerateSEHFilterFunction(CodeGenFunction &ParentCGF, const SEHExceptStmt &Except)
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::BasicBlock * getInvokeDestImpl()
bool IsOutlinedSEHHelper
True if the current function is an outlined SEH helper.
void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter, const Stmt *OutlinedStmt)
SmallVector< Address, 1 > SEHCodeSlotStack
A stack of exception code slots.
FieldDecl * LambdaThisCaptureField
void EmitCXXTryStmt(const CXXTryStmt &S)
void popCatchScope()
popCatchScope - Pops the catch scope at the top of the EHScope stack, emitting any required code (oth...
void EmitEndEHSpec(const Decl *D)
EmitEndEHSpec - Emit the end of the exception spec.
void EmitAnyExprToExn(const Expr *E, Address Addr)
bool isSEHTryScope() const
Returns true inside SEH __try blocks.
void EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF, llvm::Value *ParentFP, llvm::Value *EntryEBP)
llvm::BasicBlock * getEHResumeBlock(bool isCleanup)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
llvm::Value * EmitSEHExceptionInfo()
const LangOptions & getLangOpts() const
llvm::BasicBlock * EHResumeBlock
EHResumeBlock - Unified block containing a call to llvm.eh.resume.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
llvm::AllocaInst * EHSelectorSlot
The selector slot.
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
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 ...
RawAddress getNormalCleanupDestSlot()
llvm::BasicBlock * getTerminateFunclet()
getTerminateLandingPad - Return a cleanup funclet that just calls terminate.
llvm::Type * ConvertTypeForMem(QualType T)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
llvm::BasicBlock * getUnreachableBlock()
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
bool currentFunctionUsesSEHTry() const
llvm::SmallVector< const JumpDest *, 2 > SEHTryEpilogueStack
CodeGenFunction * ParentCGF
llvm::Value * ExceptionSlot
The exception slot.
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 EmitSEHLeaveStmt(const SEHLeaveStmt &S)
const TargetInfo & getTarget() const
llvm::Value * EmitSEHExceptionCode()
void pushSEHCleanup(CleanupKind kind, llvm::Function *FinallyFunc)
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 EmitSehTryScopeBegin()
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
Address recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, Address ParentVar, llvm::Value *ParentFP)
Recovers the address of a local in a parent function.
void EmitSEHTryStmt(const SEHTryStmt &S)
void ExitSEHTryStmt(const SEHTryStmt &S)
llvm::BasicBlock * getTerminateLandingPad()
getTerminateLandingPad - Return a landing pad that just calls terminate.
llvm::BasicBlock * getTerminateHandler()
getTerminateHandler - Return a handler (not a landing pad, just a catch handler) that just calls term...
const TargetCodeGenInfo & getTargetHooks() const
void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)
void EmitStartEHSpec(const Decl *D)
EmitStartEHSpec - Emit the start of the exception spec.
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
void EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint=true)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
llvm::Value * SEHInfo
Value returned by __exception_info intrinsic.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
llvm::BasicBlock * EmitLandingPad()
Emits a landing pad for the current EH stack.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Type * ConvertType(QualType T)
void EmitNoreturnRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args)
llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args, const Twine &name="")
void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt, bool IsFilter)
Scan the outlined statement for captures from the parent function.
llvm::BasicBlock * getFuncletEHDispatchBlock(EHScopeStack::stable_iterator scope)
llvm::Value * EmitSEHAbnormalTermination()
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)
llvm::Instruction * CurrentFuncletPad
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
llvm::LLVMContext & getLLVMContext()
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
llvm::Value * getSelectorFromSlot()
llvm::Value * getExceptionFromSlot()
Returns the contents of the function's exception object and selector slots.
Address getEHSelectorSlot()
LValue EmitLValueForLambdaField(const FieldDecl *Field)
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
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)
Get the address of the RTTI descriptor for the given type.
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 TargetInfo & getTarget() const
CGCXXABI & getCXXABI() const
ASTContext & getContext() const
llvm::FunctionCallee getTerminateFn()
Get the declaration of std::terminate for the platform.
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
CGObjCRuntime & getObjCRuntime()
Return a reference to the configured Objective-C runtime.
LangAS GetGlobalVarAddressSpace(const VarDecl *D)
Return the AST address space of the underlying global variable for D, as determined by its declaratio...
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.
const CGFunctionInfo & arrangeBuiltinFunctionCall(QualType resultType, const CallArgList &args)
llvm::Constant * tryEmitAbstract(const Expr *E, QualType T)
Try to emit the result of the given expression as an abstract constant.
A scope which attempts to handle some, possibly all, types of exceptions.
const Handler & getHandler(unsigned I) const
void setHandler(unsigned I, llvm::Constant *Type, llvm::BasicBlock *Block)
void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block)
void clearHandlerBlocks()
unsigned getNumHandlers() const
An exceptions scope which filters exceptions thrown through it.
llvm::Value * getFilter(unsigned i) const
unsigned getNumFilters() const
Information for lazily generating a cleanup.
A non-stable pointer into the scope stack.
A saved depth on the scope stack.
class EHFilterScope * pushFilter(unsigned NumFilters)
Push an exceptions filter on the stack.
stable_iterator stable_begin() const
Create a stable reference to the top of the EH stack.
stable_iterator getInnermostEHScope() const
bool requiresLandingPad() const
bool empty() const
Determines whether the exception-scopes stack is empty.
iterator end() const
Returns an iterator pointing to the outermost EH scope.
void popFilter()
Pops an exceptions filter off the stack.
iterator begin() const
Returns an iterator pointing to the innermost EH scope.
void popCatch()
Pops a catch scope off the stack. This is private to CGException.cpp.
class EHCatchScope * pushCatch(unsigned NumHandlers)
Push a set of catch handlers on the stack.
iterator find(stable_iterator save) const
Turn a stable reference to a scope depth into a unstable pointer to the EH stack.
static stable_iterator stable_end()
Create a stable reference to the bottom of the EH stack.
void popTerminate()
Pops a terminate handler off the stack.
void pushTerminate()
Push a terminate handler on the stack.
A protected scope for zero-cost EH handling.
llvm::BasicBlock * getCachedLandingPad() const
EHScopeStack::stable_iterator getEnclosingEHScope() const
llvm::BasicBlock * getCachedEHDispatchBlock() const
void setCachedEHDispatchBlock(llvm::BasicBlock *block)
bool hasEHBranches() const
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
Address getAddress() const
static RValue get(llvm::Value *V)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Address performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, Address Addr, LangAS SrcAddr, LangAS DestAddr, llvm::Type *DestTy, bool IsNonNull=false) const
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getLocation() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a function declaration or definition.
bool usesSEHTry() const
Indicates the function uses __try.
SourceRange getExceptionSpecSourceRange() const
Attempt to compute an informative source range covering the function exception specification,...
Represents a prototype with parameter type info, e.g.
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
QualType getExceptionType(unsigned i) const
Return the ith exception type, where 0 <= i < getNumExceptions().
unsigned getNumExceptions() const
Return the number of types in the exception specification.
CanThrowResult canThrow() const
Determine whether this function type has a non-throwing exception specification.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool hasWasmExceptions() const
clang::ObjCRuntime ObjCRuntime
bool hasSjLjExceptions() const
bool hasDWARFExceptions() const
bool hasSEHExceptions() const
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
virtual void mangleSEHFilterExpression(GlobalDecl EnclosingDecl, raw_ostream &Out)=0
virtual void mangleSEHFinallyBlock(GlobalDecl EnclosingDecl, raw_ostream &Out)=0
Represents Objective-C's @throw statement.
The basic abstraction for the target Objective-C runtime.
bool hasTerminate() const
Does this runtime provide an objc_terminate function?
bool isNeXTFamily() const
Is this runtime basically of the NeXT family of runtimes?
const VersionTuple & getVersion() const
@ MacOSX
'macosx' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the non-fragile AB...
@ FragileMacOSX
'macosx-fragile' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the fragil...
@ GNUstep
'gnustep' is the modern non-fragile GNUstep runtime.
@ ObjFW
'objfw' is the Objective-C runtime included in ObjFW
@ iOS
'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS simulator; it is always non-fragil...
@ GCC
'gcc' is the Objective-C runtime shipped with GCC, implementing a fragile Objective-C ABI
@ WatchOS
'watchos' is a variant of iOS for Apple's watchOS.
A (possibly-)qualified type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
The collection of all-type qualifiers we support.
CompoundStmt * getBlock() const
Expr * getFilterExpr() const
CompoundStmt * getBlock() const
Represents a __leave statement.
Smart pointer class that efficiently represents Objective-C method names.
Encodes a location in the source.
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const LLVM_READONLY
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
Exposes information about the current target.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
bool isPointerType() const
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isObjCObjectPointerType() const
const T * getAs() const
Member-template getAs'.
Represents a variable declaration or definition.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
@ NormalCleanup
Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...
@ EHCleanup
Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName="")
Clean up any erroneous/redundant code in the given Ranges in Code.
bool Zero(InterpState &S, CodePtr OpPC)
bool Load(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
LangAS
Defines the address space values used by the address space qualifier of QualType.
const FunctionProtoType * T
@ Other
Other implicit parameter.
ExceptionSpecificationType
The various types of exception specifications that exist in C++11.
@ EST_Dynamic
throw(T1, T2)
The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the type of a catch handler,...
llvm::PointerType * VoidPtrTy
CharUnits getIntAlign() const
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntTy
int
llvm::PointerType * Int8PtrTy
CharUnits getPointerAlign() const
llvm::PointerType * AllocaInt8PtrTy
CatchTypeInfo Type
A type info value, or null (C++ null, not an LLVM null pointer) for a catch-all.
llvm::BasicBlock * Block
The catch handler for this type.
The exceptions personality for a function.
static const EHPersonality & get(CodeGenModule &CGM, const FunctionDecl *FD)
static const EHPersonality XL_CPlusPlus
static const EHPersonality GNU_ObjC_SJLJ
bool isWasmPersonality() const
static const EHPersonality ZOS_CPlusPlus
static const EHPersonality GNUstep_ObjC
static const EHPersonality MSVC_CxxFrameHandler3
bool usesFuncletPads() const
Does this personality use landingpads or the family of pad instructions designed to form funclets?
static const EHPersonality MSVC_C_specific_handler
static const EHPersonality GNU_CPlusPlus_SEH
static const EHPersonality GNU_ObjC
static const EHPersonality GNU_CPlusPlus_SJLJ
static const EHPersonality GNU_C_SJLJ
static const EHPersonality GNU_C
static const EHPersonality NeXT_ObjC
const char * CatchallRethrowFn
static const EHPersonality GNU_CPlusPlus
static const EHPersonality GNU_ObjCXX
static const EHPersonality GNU_C_SEH
static const EHPersonality MSVC_except_handler
static const EHPersonality GNU_ObjC_SEH
const char * PersonalityFn
static const EHPersonality GNU_Wasm_CPlusPlus