clang: lib/CodeGen/CGStmt.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

27#include "llvm/ADT/ArrayRef.h"

28#include "llvm/ADT/DenseMap.h"

29#include "llvm/ADT/SmallSet.h"

30#include "llvm/ADT/StringExtras.h"

31#include "llvm/IR/Assumptions.h"

32#include "llvm/IR/DataLayout.h"

33#include "llvm/IR/InlineAsm.h"

34#include "llvm/IR/Intrinsics.h"

35#include "llvm/IR/MDBuilder.h"

36#include "llvm/Support/SaveAndRestore.h"

37#include

38

39using namespace clang;

40using namespace CodeGen;

41

42

43

44

45

46namespace llvm {

48}

49

50void CodeGenFunction::EmitStopPoint(const Stmt *S) {

53 Loc = S->getBeginLoc();

55

56 LastStopPoint = Loc;

57 }

58}

59

61 assert(S && "Null statement?");

63

64

66 return;

67

68

70

71

72

73

74

76

77

78 assert(!isa(*S) && "Unexpected DeclStmt!");

80 return;

81 }

82

83

85 }

86

87

89

90

91

93 if (const auto *D = dyn_cast(S)) {

95 return;

96 }

97 }

98

99 switch (S->getStmtClass()) {

101 case Stmt::CXXCatchStmtClass:

102 case Stmt::SEHExceptStmtClass:

103 case Stmt::SEHFinallyStmtClass:

104 case Stmt::MSDependentExistsStmtClass:

105 llvm_unreachable("invalid statement class to emit generically");

106 case Stmt::NullStmtClass:

107 case Stmt::CompoundStmtClass:

108 case Stmt::DeclStmtClass:

109 case Stmt::LabelStmtClass:

110 case Stmt::AttributedStmtClass:

111 case Stmt::GotoStmtClass:

112 case Stmt::BreakStmtClass:

113 case Stmt::ContinueStmtClass:

114 case Stmt::DefaultStmtClass:

115 case Stmt::CaseStmtClass:

116 case Stmt::SEHLeaveStmtClass:

117 llvm_unreachable("should have emitted these statements as simple");

118

119#define STMT(Type, Base)

120#define ABSTRACT_STMT(Op)

121#define EXPR(Type, Base) \

122 case Stmt::Type##Class:

123#include "clang/AST/StmtNodes.inc"

124 {

125

126 llvm::BasicBlock *incoming = Builder.GetInsertBlock();

127 assert(incoming && "expression emission must have an insertion point");

128

130

131 llvm::BasicBlock *outgoing = Builder.GetInsertBlock();

132 assert(outgoing && "expression emission cleared block!");

133

134

135

136

137

138

139

140

141

142

143

144

145

146 if (incoming != outgoing && outgoing->use_empty()) {

147 outgoing->eraseFromParent();

148 Builder.ClearInsertionPoint();

149 }

150 break;

151 }

152

153 case Stmt::IndirectGotoStmtClass:

155

156 case Stmt::IfStmtClass: EmitIfStmt(cast(*S)); break;

157 case Stmt::WhileStmtClass: EmitWhileStmt(cast(*S), Attrs); break;

158 case Stmt::DoStmtClass: EmitDoStmt(cast(*S), Attrs); break;

159 case Stmt::ForStmtClass: EmitForStmt(cast(*S), Attrs); break;

160

161 case Stmt::ReturnStmtClass: EmitReturnStmt(cast(*S)); break;

162

163 case Stmt::SwitchStmtClass: EmitSwitchStmt(cast(*S)); break;

164 case Stmt::GCCAsmStmtClass:

165 case Stmt::MSAsmStmtClass: EmitAsmStmt(cast(*S)); break;

166 case Stmt::CoroutineBodyStmtClass:

168 break;

169 case Stmt::CoreturnStmtClass:

171 break;

172 case Stmt::CapturedStmtClass: {

173 const CapturedStmt *CS = cast(S);

175 }

176 break;

177 case Stmt::ObjCAtTryStmtClass:

179 break;

180 case Stmt::ObjCAtCatchStmtClass:

181 llvm_unreachable(

182 "@catch statements should be handled by EmitObjCAtTryStmt");

183 case Stmt::ObjCAtFinallyStmtClass:

184 llvm_unreachable(

185 "@finally statements should be handled by EmitObjCAtTryStmt");

186 case Stmt::ObjCAtThrowStmtClass:

188 break;

189 case Stmt::ObjCAtSynchronizedStmtClass:

191 break;

192 case Stmt::ObjCForCollectionStmtClass:

194 break;

195 case Stmt::ObjCAutoreleasePoolStmtClass:

197 break;

198

199 case Stmt::CXXTryStmtClass:

201 break;

202 case Stmt::CXXForRangeStmtClass:

204 break;

205 case Stmt::SEHTryStmtClass:

207 break;

208 case Stmt::OMPMetaDirectiveClass:

210 break;

211 case Stmt::OMPCanonicalLoopClass:

213 break;

214 case Stmt::OMPParallelDirectiveClass:

216 break;

217 case Stmt::OMPSimdDirectiveClass:

219 break;

220 case Stmt::OMPTileDirectiveClass:

222 break;

223 case Stmt::OMPUnrollDirectiveClass:

225 break;

226 case Stmt::OMPReverseDirectiveClass:

228 break;

229 case Stmt::OMPInterchangeDirectiveClass:

231 break;

232 case Stmt::OMPForDirectiveClass:

234 break;

235 case Stmt::OMPForSimdDirectiveClass:

237 break;

238 case Stmt::OMPSectionsDirectiveClass:

240 break;

241 case Stmt::OMPSectionDirectiveClass:

243 break;

244 case Stmt::OMPSingleDirectiveClass:

246 break;

247 case Stmt::OMPMasterDirectiveClass:

249 break;

250 case Stmt::OMPCriticalDirectiveClass:

252 break;

253 case Stmt::OMPParallelForDirectiveClass:

255 break;

256 case Stmt::OMPParallelForSimdDirectiveClass:

258 break;

259 case Stmt::OMPParallelMasterDirectiveClass:

261 break;

262 case Stmt::OMPParallelSectionsDirectiveClass:

264 break;

265 case Stmt::OMPTaskDirectiveClass:

267 break;

268 case Stmt::OMPTaskyieldDirectiveClass:

270 break;

271 case Stmt::OMPErrorDirectiveClass:

273 break;

274 case Stmt::OMPBarrierDirectiveClass:

276 break;

277 case Stmt::OMPTaskwaitDirectiveClass:

279 break;

280 case Stmt::OMPTaskgroupDirectiveClass:

282 break;

283 case Stmt::OMPFlushDirectiveClass:

285 break;

286 case Stmt::OMPDepobjDirectiveClass:

288 break;

289 case Stmt::OMPScanDirectiveClass:

291 break;

292 case Stmt::OMPOrderedDirectiveClass:

294 break;

295 case Stmt::OMPAtomicDirectiveClass:

297 break;

298 case Stmt::OMPTargetDirectiveClass:

300 break;

301 case Stmt::OMPTeamsDirectiveClass:

303 break;

304 case Stmt::OMPCancellationPointDirectiveClass:

306 break;

307 case Stmt::OMPCancelDirectiveClass:

309 break;

310 case Stmt::OMPTargetDataDirectiveClass:

312 break;

313 case Stmt::OMPTargetEnterDataDirectiveClass:

315 break;

316 case Stmt::OMPTargetExitDataDirectiveClass:

318 break;

319 case Stmt::OMPTargetParallelDirectiveClass:

321 break;

322 case Stmt::OMPTargetParallelForDirectiveClass:

324 break;

325 case Stmt::OMPTaskLoopDirectiveClass:

327 break;

328 case Stmt::OMPTaskLoopSimdDirectiveClass:

330 break;

331 case Stmt::OMPMasterTaskLoopDirectiveClass:

333 break;

334 case Stmt::OMPMaskedTaskLoopDirectiveClass:

336 break;

337 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:

339 cast(*S));

340 break;

341 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:

343 cast(*S));

344 break;

345 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:

347 cast(*S));

348 break;

349 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:

351 cast(*S));

352 break;

353 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:

355 cast(*S));

356 break;

357 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:

359 cast(*S));

360 break;

361 case Stmt::OMPDistributeDirectiveClass:

363 break;

364 case Stmt::OMPTargetUpdateDirectiveClass:

366 break;

367 case Stmt::OMPDistributeParallelForDirectiveClass:

369 cast(*S));

370 break;

371 case Stmt::OMPDistributeParallelForSimdDirectiveClass:

373 cast(*S));

374 break;

375 case Stmt::OMPDistributeSimdDirectiveClass:

377 break;

378 case Stmt::OMPTargetParallelForSimdDirectiveClass:

380 cast(*S));

381 break;

382 case Stmt::OMPTargetSimdDirectiveClass:

384 break;

385 case Stmt::OMPTeamsDistributeDirectiveClass:

387 break;

388 case Stmt::OMPTeamsDistributeSimdDirectiveClass:

390 cast(*S));

391 break;

392 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:

394 cast(*S));

395 break;

396 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:

398 cast(*S));

399 break;

400 case Stmt::OMPTargetTeamsDirectiveClass:

402 break;

403 case Stmt::OMPTargetTeamsDistributeDirectiveClass:

405 cast(*S));

406 break;

407 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:

409 cast(*S));

410 break;

411 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:

413 cast(*S));

414 break;

415 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:

417 cast(*S));

418 break;

419 case Stmt::OMPInteropDirectiveClass:

421 break;

422 case Stmt::OMPDispatchDirectiveClass:

424 break;

425 case Stmt::OMPScopeDirectiveClass:

427 break;

428 case Stmt::OMPMaskedDirectiveClass:

430 break;

431 case Stmt::OMPGenericLoopDirectiveClass:

433 break;

434 case Stmt::OMPTeamsGenericLoopDirectiveClass:

436 break;

437 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:

439 cast(*S));

440 break;

441 case Stmt::OMPParallelGenericLoopDirectiveClass:

443 cast(*S));

444 break;

445 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:

447 cast(*S));

448 break;

449 case Stmt::OMPParallelMaskedDirectiveClass:

451 break;

452 case Stmt::OMPAssumeDirectiveClass:

454 break;

455 case Stmt::OpenACCComputeConstructClass:

457 break;

458 case Stmt::OpenACCLoopConstructClass:

460 break;

461 case Stmt::OpenACCCombinedConstructClass:

463 break;

464 case Stmt::OpenACCDataConstructClass:

466 break;

467 case Stmt::OpenACCEnterDataConstructClass:

469 break;

470 case Stmt::OpenACCExitDataConstructClass:

472 break;

473 case Stmt::OpenACCHostDataConstructClass:

475 break;

476 case Stmt::OpenACCWaitConstructClass:

478 break;

479 case Stmt::OpenACCInitConstructClass:

481 break;

482 case Stmt::OpenACCShutdownConstructClass:

484 break;

485 case Stmt::OpenACCSetConstructClass:

487 break;

488 case Stmt::OpenACCUpdateConstructClass:

490 break;

491 }

492}

493

496 switch (S->getStmtClass()) {

497 default:

498 return false;

499 case Stmt::NullStmtClass:

500 break;

501 case Stmt::CompoundStmtClass:

503 break;

504 case Stmt::DeclStmtClass:

506 break;

507 case Stmt::LabelStmtClass:

509 break;

510 case Stmt::AttributedStmtClass:

512 break;

513 case Stmt::GotoStmtClass:

515 break;

516 case Stmt::BreakStmtClass:

518 break;

519 case Stmt::ContinueStmtClass:

521 break;

522 case Stmt::DefaultStmtClass:

524 break;

525 case Stmt::CaseStmtClass:

527 break;

528 case Stmt::SEHLeaveStmtClass:

530 break;

531 }

532 return true;

533}

534

535

536

537

541 "LLVM IR generation of compound statement ('{}')");

542

543

544 LexicalScope Scope(*this, S.getSourceRange());

545

547}

548

551 bool GetLast,

553

555 assert((!GetLast || (GetLast && ExprResult)) &&

556 "If GetLast is true then the CompoundStmt must have a StmtExprResult");

557

559

560 for (auto *CurStmt : S.body()) {

561 if (GetLast && ExprResult == CurStmt) {

562

563

564

565

566

568 if (const auto *LS = dyn_cast(ExprResult)) {

571 } else if (const auto *AS = dyn_cast(ExprResult)) {

572

573

575 } else {

576 llvm_unreachable("unknown value statement");

577 }

578 }

579

581

586 } else {

587

588

589

592 false);

593 }

594 } else {

596 }

597 }

598

599 return RetAlloca;

600}

601

603 llvm::BranchInst *BI = dyn_castllvm::BranchInst(BB->getTerminator());

604

605

606

607

609 return;

610

611

612 if (!BI || !BI->isUnconditional())

613 return;

614

615

616 if (BI->getIterator() != BB->begin())

617 return;

618

619 BB->replaceAllUsesWith(BI->getSuccessor(0));

620 BI->eraseFromParent();

621 BB->eraseFromParent();

622}

623

625 llvm::BasicBlock *CurBB = Builder.GetInsertBlock();

626

627

629

630 if (IsFinished && BB->use_empty()) {

631 delete BB;

632 return;

633 }

634

635

636

637 if (CurBB && CurBB->getParent())

638 CurFn->insert(std::next(CurBB->getIterator()), BB);

639 else

641 Builder.SetInsertPoint(BB);

642}

643

645

646

647

648 llvm::BasicBlock *CurBB = Builder.GetInsertBlock();

649

650 if (!CurBB || CurBB->getTerminator()) {

651

652

653 } else {

654

656 }

657

658 Builder.ClearInsertionPoint();

659}

660

662 bool inserted = false;

663 for (llvm::User *u : block->users()) {

664 if (llvm::Instruction *insn = dyn_castllvm::Instruction(u)) {

665 CurFn->insert(std::next(insn->getParent()->getIterator()), block);

666 inserted = true;

667 break;

668 }

669 }

670

671 if (!inserted)

673

674 Builder.SetInsertPoint(block);

675}

676

677CodeGenFunction::JumpDest

679 JumpDest &Dest = LabelMap[D];

680 if (Dest.isValid()) return Dest;

681

682

686 return Dest;

687}

688

690

691

692

695

696 JumpDest &Dest = LabelMap[D];

697

698

699

700 if (!Dest.isValid()) {

702

703

704

705 } else {

706 assert(!Dest.getScopeDepth().isValid() && "already emitted label!");

709 }

710

712

713

718 }

719 }

720

722}

723

724

725

727 assert(!Labels.empty());

730

731

733 i = Labels.begin(), e = Labels.end(); i != e; ++i) {

734 assert(CGF.LabelMap.count(*i));

735 JumpDest &dest = CGF.LabelMap.find(*i)->second;

739 }

740

741

743 ParentScope->Labels.append(Labels.begin(), Labels.end());

744 }

745}

746

747

750

751

752 if (getLangOpts().EHAsynch && S.isSideEntry())

754

756}

757

759 bool nomerge = false;

760 bool noinline = false;

761 bool alwaysinline = false;

762 bool noconvergent = false;

763 HLSLControlFlowHintAttr::Spelling flattenOrBranch =

764 HLSLControlFlowHintAttr::SpellingNotCalculated;

765 const CallExpr *musttail = nullptr;

766

767 for (const auto *A : S.getAttrs()) {

768 switch (A->getKind()) {

769 default:

770 break;

771 case attr::NoMerge:

772 nomerge = true;

773 break;

774 case attr::NoInline:

775 noinline = true;

776 break;

777 case attr::AlwaysInline:

778 alwaysinline = true;

779 break;

780 case attr::NoConvergent:

781 noconvergent = true;

782 break;

783 case attr::MustTail: {

784 const Stmt *Sub = S.getSubStmt();

785 const ReturnStmt *R = cast(Sub);

787 } break;

788 case attr::CXXAssume: {

789 const Expr *Assumption = cast(A)->getAssumption();

793 Builder.CreateAssumption(AssumptionVal);

794 }

795 } break;

796 case attr::HLSLControlFlowHint: {

797 flattenOrBranch = cast(A)->getSemanticSpelling();

798 } break;

799 }

800 }

807 EmitStmt(S.getSubStmt(), S.getAttrs());

808}

809

811

812

813

816

818}

819

820

824 return;

825 }

826

827

830 llvm::BasicBlock *CurBB = Builder.GetInsertBlock();

831

832

834

835

836

837 castllvm::PHINode(IndGotoBB->begin())->addIncoming(V, CurBB);

838

840}

841

843 const Stmt *Else = S.getElse();

844

845

846

847 if (S.isConsteval()) {

848 const Stmt *Executed = S.isNegatedConsteval() ? S.getThen() : Else;

849 if (Executed) {

850 RunCleanupsScope ExecutedScope(*this);

852 }

853 return;

854 }

855

856

857

858 LexicalScope ConditionScope(*this, S.getCond()->getSourceRange());

860

861 if (S.getInit())

863

864 if (S.getConditionVariable())

865 EmitDecl(*S.getConditionVariable());

866

867

868

869 bool CondConstant;

871 S.isConstexpr())) {

872

873 const Stmt *Executed = S.getThen();

874 const Stmt *Skipped = Else;

875 if (!CondConstant)

876 std::swap(Executed, Skipped);

877

878

879

880 if (S.isConstexpr() || ContainsLabel(Skipped)) {

881 if (CondConstant)

883 if (Executed) {

884 RunCleanupsScope ExecutedScope(*this);

886 }

888 return;

889 }

890 }

891

892

893

896 llvm::BasicBlock *ElseBlock = ContBlock;

897 if (Else)

899

900

901

902

903

904

905

906

907

908

909

910

916

917

918

919

920

921

922

925 else {

927 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);

928 }

929

930

934 else

936 {

937 RunCleanupsScope ThenScope(*this);

939 }

941

942

943 if (Else) {

944 {

945

948 }

949

952 {

953 RunCleanupsScope ElseScope(*this);

955 }

956 {

957

960 }

961 }

962

963

965

966

967

970}

971

973 bool HasEmptyBody) {

976 return false;

977

978

979

980

981

982

984 bool CondIsConstInt =

985 !ControllingExpression ||

988

989 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||

990 Result.Val.getInt().getBoolValue());

991

992

993 if (getLangOpts().C11 && !CondIsConstInt)

994 return true;

995

996

997

998

999

1000

1004 if (HasEmptyBody && CondIsTrue) {

1005 CurFn->removeFnAttr(llvm::Attribute::MustProgress);

1006 return false;

1007 }

1008 return true;

1009 }

1010 return false;

1011}

1012

1013

1014

1015

1016

1017

1018

1019

1020

1021

1022template static bool hasEmptyLoopBody(const LoopStmt &S) {

1023 if constexpr (std::is_same_v<LoopStmt, ForStmt>) {

1024 if (S.getInc())

1025 return false;

1026 }

1027 const Stmt *Body = S.getBody();

1028 if (!Body || isa(Body))

1029 return true;

1030 if (const CompoundStmt *Compound = dyn_cast(Body))

1031 return Compound->body_empty();

1032 return false;

1033}

1034

1037

1038

1040 EmitBlock(LoopHeader.getBlock());

1041

1044 emitConvergenceLoopToken(LoopHeader.getBlock()));

1045

1046

1047

1049

1050

1051 BreakContinueStack.push_back(BreakContinue(LoopExit, LoopHeader));

1052

1053

1054

1055

1056

1057

1058

1059

1060 RunCleanupsScope ConditionScope(*this);

1061

1062 if (S.getConditionVariable())

1063 EmitDecl(*S.getConditionVariable());

1064

1065

1066

1067

1069

1070

1071

1072 llvm::ConstantInt *C = dyn_castllvm::ConstantInt(BoolCondVal);

1073 bool EmitBoolCondBranch = C || C->isOne();

1074 const SourceRange &R = S.getSourceRange();

1079

1080

1083

1084

1085 llvm::BasicBlock *LoopBody = createBasicBlock("while.body");

1086 if (EmitBoolCondBranch) {

1087 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();

1088 if (ConditionScope.requiresCleanups())

1090 llvm::MDNode *Weights =

1091 createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));

1093 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(

1095 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);

1096

1097 if (ExitBlock != LoopExit.getBlock()) {

1100 }

1103 diag::warn_attribute_has_no_effect_on_infinite_loop)

1104 << A << A->getRange();

1106 S.getWhileLoc(),

1107 diag::note_attribute_has_no_effect_on_infinite_loop_here)

1108 << SourceRange(S.getWhileLoc(), S.getRParenLoc());

1109 }

1110

1111

1112

1113 {

1114 RunCleanupsScope BodyScope(*this);

1116

1119 else

1122 }

1123

1124 BreakContinueStack.pop_back();

1125

1126

1127 ConditionScope.ForceCleanup();

1128

1130

1132

1134

1135

1137

1138

1139

1140 if (!EmitBoolCondBranch)

1142

1143

1144

1147

1150}

1151

1156

1158

1159

1160 BreakContinueStack.push_back(BreakContinue(LoopExit, LoopCond));

1161

1162

1164

1167 else

1169

1172

1173 {

1174 RunCleanupsScope BodyScope(*this);

1176 }

1177

1179

1182

1183

1184

1185

1186

1187

1188

1190

1191 BreakContinueStack.pop_back();

1192

1193

1194

1195 llvm::ConstantInt *C = dyn_castllvm::ConstantInt(BoolCondVal);

1196 bool EmitBoolCondBranch = C || C->isZero();

1197

1198 const SourceRange &R = S.getSourceRange();

1203

1204

1205 if (EmitBoolCondBranch) {

1208 BoolCondVal, LoopBody, LoopExit.getBlock(),

1209 createProfileWeightsForLoop(S.getCond(), BackedgeCount));

1210 }

1211

1213

1214

1216

1217

1218

1219 if (!EmitBoolCondBranch)

1221

1222

1223

1226

1229}

1230

1234

1235 LexicalScope ForScope(*this, S.getSourceRange());

1236

1237

1238 if (S.getInit())

1240

1241

1242

1243

1245 llvm::BasicBlock *CondBlock = CondDest.getBlock();

1247

1250

1251 const SourceRange &R = S.getSourceRange();

1256

1257

1258 LexicalScope ConditionScope(*this, S.getSourceRange());

1259

1260

1261

1262

1263

1264

1265

1266

1267 JumpDest Continue;

1268 if (!S.getInc())

1269 Continue = CondDest;

1270 else if (!S.getConditionVariable())

1272 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));

1273

1274 if (S.getCond()) {

1275

1276

1277 if (S.getConditionVariable()) {

1278 EmitDecl(*S.getConditionVariable());

1279

1280

1281

1283 BreakContinueStack.back().ContinueBlock = Continue;

1284 }

1285

1286

1287

1290

1291 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();

1292

1293

1294 if (ForScope.requiresCleanups())

1296

1297

1299

1300

1301

1303 llvm::MDNode *Weights =

1304 createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));

1306 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(

1308

1309 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);

1310

1311 if (ExitBlock != LoopExit.getBlock()) {

1314 }

1315

1317 } else {

1318

1319

1320 }

1321

1322

1325 else

1327 {

1328

1329

1330 RunCleanupsScope BodyScope(*this);

1332 }

1333

1334

1335 if (S.getInc()) {

1340 }

1341

1342 BreakContinueStack.pop_back();

1343

1344 ConditionScope.ForceCleanup();

1345

1348

1349 ForScope.ForceCleanup();

1350

1352

1353

1355

1356

1357

1360

1363}

1364

1365void

1369

1370 LexicalScope ForScope(*this, S.getSourceRange());

1371

1372

1373 if (S.getInit())

1378

1379

1380

1381

1384

1387

1388 const SourceRange &R = S.getSourceRange();

1392

1393

1394

1395 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();

1396 if (ForScope.requiresCleanups())

1398

1399

1401

1402

1403

1405 llvm::MDNode *Weights =

1406 createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));

1408 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(

1410 Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);

1411

1412 if (ExitBlock != LoopExit.getBlock()) {

1415 }

1416

1420 else

1422

1423

1425

1426

1427 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));

1428

1429 {

1430

1431 LexicalScope BodyScope(*this, S.getSourceRange());

1432 EmitStmt(S.getLoopVarStmt());

1434 }

1435

1437

1440

1441 BreakContinueStack.pop_back();

1442

1444

1445 ForScope.ForceCleanup();

1446

1448

1449

1451

1452

1453

1456

1459}

1460

1461void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {

1468 } else {

1470 true);

1471 }

1473}

1474

1475namespace {

1476

1477struct SaveRetExprRAII {

1479 : OldRetExpr(CGF.RetExpr), CGF(CGF) {

1481 }

1482 ~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }

1483 const Expr *OldRetExpr;

1485};

1486}

1487

1488

1492 if (calleeQualType->isFunctionPointerType() ||

1493 calleeQualType->isFunctionReferenceType() ||

1494 calleeQualType->isBlockPointerType() ||

1495 calleeQualType->isMemberFunctionPointerType()) {

1497 } else if (auto *ty = dyn_cast(calleeQualType)) {

1498 calleeType = ty;

1499 } else if (auto CMCE = dyn_cast(CE)) {

1500 if (auto methodDecl = CMCE->getMethodDecl()) {

1501

1503 } else {

1504 return false;

1505 }

1506 } else {

1507 return false;

1508 }

1510}

1511

1512

1513

1514

1516 if (requiresReturnValueCheck()) {

1518 auto *SLocPtr =

1519 new llvm::GlobalVariable(CGM.getModule(), SLoc->getType(), false,

1520 llvm::GlobalVariable::PrivateLinkage, SLoc);

1521 SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

1523 assert(ReturnLocation.isValid() && "No valid return location");

1525 }

1526

1527

1529 Builder.CreateUnreachable();

1530 Builder.ClearInsertionPoint();

1531 }

1532

1533

1534 const Expr *RV = S.getRetValue();

1535

1536

1537

1538

1539

1540

1541

1542

1543

1544 SaveRetExprRAII SaveRetExpr(RV, *this);

1545

1546 RunCleanupsScope cleanupScope(*this);

1547 if (const auto *EWC = dyn_cast_or_null(RV))

1548 RV = EWC->getSubExpr();

1549

1550

1551

1552 std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail;

1555 if (auto CE = dyn_cast(RV)) {

1558 }

1559 }

1560 }

1561

1562

1563

1564

1565 if (getLangOpts().ElideConstructors && S.getNRVOCandidate() &&

1566 S.getNRVOCandidate()->isNRVOVariable() &&

1571

1572

1573

1574

1575

1576

1577 if (llvm::Value *NRVOFlag = NRVOFlags[S.getNRVOCandidate()])

1580

1581

1582 if (RV) {

1584 }

1585 } else if (!RV) {

1586

1588

1589

1592 } else {

1598 true);

1599 else

1601 break;

1602 }

1605 true);

1606 break;

1614 break;

1615 }

1616 }

1617

1618 ++NumReturnExprs;

1620 ++NumSimpleReturnExprs;

1621

1622 cleanupScope.ForceCleanup();

1624}

1625

1627

1628

1631

1632 for (const auto *I : S.decls())

1634}

1635

1637 assert(!BreakContinueStack.empty() && "break stmt not in a loop or switch!");

1638

1639

1640

1641

1644

1646}

1647

1649 assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");

1650

1651

1652

1653

1656

1658}

1659

1660

1661

1662

1665 assert(S.getRHS() && "Expected RHS value in CaseStmt");

1666

1667 llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(getContext());

1668 llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(getContext());

1669

1670

1671

1672

1676

1677

1678 if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))

1679 return;

1680

1682 llvm::APInt Range = RHS - LHS;

1683

1684 if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {

1685

1687 unsigned NCases = Range.getZExtValue() + 1;

1688

1689

1690

1691

1692 uint64_t Weight = Total / NCases, Rem = Total % NCases;

1693 for (unsigned I = 0; I != NCases; ++I) {

1694 if (SwitchWeights)

1695 SwitchWeights->push_back(Weight + (Rem ? 1 : 0));

1696 else if (SwitchLikelihood)

1697 SwitchLikelihood->push_back(LH);

1698

1699 if (Rem)

1701 SwitchInsn->addCase(Builder.getInt(LHS), CaseDest);

1702 ++LHS;

1703 }

1704 return;

1705 }

1706

1707

1708

1709 llvm::BasicBlock *RestoreBB = Builder.GetInsertBlock();

1710

1711

1712

1713

1714 llvm::BasicBlock *FalseDest = CaseRangeBlock;

1716

1717 CurFn->insert(CurFn->end(), CaseRangeBlock);

1718 Builder.SetInsertPoint(CaseRangeBlock);

1719

1720

1721 llvm::Value *Diff =

1722 Builder.CreateSub(SwitchInsn->getCondition(), Builder.getInt(LHS));

1723 llvm::Value *Cond =

1725

1726 llvm::MDNode *Weights = nullptr;

1727 if (SwitchWeights) {

1729 uint64_t DefaultCount = (*SwitchWeights)[0];

1730 Weights = createProfileWeights(ThisCount, DefaultCount);

1731

1732

1733

1734

1735 (*SwitchWeights)[0] += ThisCount;

1736 } else if (SwitchLikelihood)

1737 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);

1738

1739 Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);

1740

1741

1742 if (RestoreBB)

1743 Builder.SetInsertPoint(RestoreBB);

1744 else

1745 Builder.ClearInsertionPoint();

1746}

1747

1750

1751

1752

1753

1754

1755 if (!SwitchInsn) {

1757 return;

1758 }

1759

1760

1761 if (S.getRHS()) {

1763 return;

1764 }

1765

1766 llvm::ConstantInt *CaseVal =

1767 Builder.getInt(S.getLHS()->EvaluateKnownConstInt(getContext()));

1768

1769

1771 if (auto ICE = dyn_cast(S.getLHS()))

1772 CE = dyn_cast(ICE->getSubExpr());

1773 else

1774 CE = dyn_cast(S.getLHS());

1775 if (CE) {

1776 if (auto DE = dyn_cast(CE->getSubExpr()))

1779 Dbg->EmitGlobalVariable(DE->getDecl(),

1780 APValue(llvm::APSInt(CaseVal->getValue())));

1781 }

1782

1783 if (SwitchLikelihood)

1785

1786

1787

1788

1791 isa(S.getSubStmt())) {

1792 JumpDest Block = BreakContinueStack.back().BreakBlock;

1793

1794

1796 if (SwitchWeights)

1798 SwitchInsn->addCase(CaseVal, Block.getBlock());

1799

1800

1801

1802 if (Builder.GetInsertBlock()) {

1804 Builder.ClearInsertionPoint();

1805 }

1806 return;

1807 }

1808 }

1809

1812 if (SwitchWeights)

1814 SwitchInsn->addCase(CaseVal, CaseDest);

1815

1816

1817

1818

1819

1820

1821

1822

1823

1824

1825

1826

1827

1828

1829 const CaseStmt *CurCase = &S;

1830 const CaseStmt *NextCase = dyn_cast(S.getSubStmt());

1831

1832

1833 while (NextCase && NextCase->getRHS() == nullptr) {

1834 CurCase = NextCase;

1835 llvm::ConstantInt *CaseVal =

1837

1838 if (SwitchWeights)

1843 }

1844

1845

1846 if (SwitchLikelihood)

1848

1849 SwitchInsn->addCase(CaseVal, CaseDest);

1850 NextCase = dyn_cast(CurCase->getSubStmt());

1851 }

1852

1853

1854

1855

1858

1859

1861}

1862

1865

1866

1867

1868 if (!SwitchInsn) {

1870 return;

1871 }

1872

1873 llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();

1874 assert(DefaultBlock->empty() &&

1875 "EmitDefaultStmt: Default block already defined?");

1876

1877 if (SwitchLikelihood)

1879

1881

1883}

1884

1885

1886

1887

1888

1889

1890

1891

1892

1893

1894

1895

1896

1897

1898

1899

1900

1901

1902

1903

1904

1905

1906

1907

1911 bool &FoundCase,

1913

1914 if (!S)

1916

1917

1918

1919 if (const SwitchCase *SC = dyn_cast(S)) {

1920 if (S == Case) {

1921 FoundCase = true;

1923 ResultStmts);

1924 }

1925

1926

1928 ResultStmts);

1929 }

1930

1931

1932

1933 if (!Case && isa(S))

1935

1936

1937

1938 if (const CompoundStmt *CS = dyn_cast(S)) {

1939

1940

1942 bool StartedInLiveCode = FoundCase;

1943 unsigned StartSize = ResultStmts.size();

1944

1945

1946 if (Case) {

1947

1948

1949

1950 bool HadSkippedDecl = false;

1951

1952

1953

1954 for (; Case && I != E; ++I) {

1956

1960

1961

1962

1963

1964 if (FoundCase) {

1965

1966

1967 if (HadSkippedDecl)

1969

1970 for (++I; I != E; ++I)

1974 }

1975 break;

1977

1978

1979

1980 assert(FoundCase && "Didn't find case but returned fallthrough?");

1981

1982 Case = nullptr;

1983

1984

1985

1986 if (HadSkippedDecl)

1988 break;

1989 }

1990 }

1991

1992 if (!FoundCase)

1994

1995 assert(!HadSkippedDecl && "fallthrough after skipping decl");

1996 }

1997

1998

1999

2000 bool AnyDecls = false;

2001 for (; I != E; ++I) {

2003

2007

2008

2009 break;

2011

2012

2013

2014 for (++I; I != E; ++I)

2018 }

2019 }

2020

2021

2022

2023

2024 if (AnyDecls) {

2025

2026

2027

2028

2029

2031 ResultStmts.resize(StartSize);

2032 ResultStmts.push_back(S);

2033 } else {

2035 }

2036 }

2037

2039 }

2040

2041

2042

2043

2044 if (Case) {

2048 }

2049

2050

2051

2053

2054

2055

2056 ResultStmts.push_back(S);

2058}

2059

2060

2061

2062

2063

2065 const llvm::APSInt &ConstantCondValue,

2069

2070

2071 const SwitchCase *Case = S.getSwitchCaseList();

2072 const DefaultStmt *DefaultCase = nullptr;

2073

2075

2076

2077 if (const DefaultStmt *DS = dyn_cast(Case)) {

2078 DefaultCase = DS;

2079 continue;

2080 }

2081

2082

2083 const CaseStmt *CS = cast(Case);

2084

2085 if (CS->getRHS()) return false;

2086

2087

2089 break;

2090 }

2091

2092

2093

2094 if (!Case) {

2095

2096

2097 if (!DefaultCase)

2099 Case = DefaultCase;

2100 }

2101

2102

2103

2104

2105

2106

2107

2108

2109

2110 bool FoundCase = false;

2111 ResultCase = Case;

2114 FoundCase;

2115}

2116

2117static std::optional<SmallVector<uint64_t, 16>>

2119

2120 if (Likelihoods.size() <= 1)

2121 return std::nullopt;

2122

2123 uint64_t NumUnlikely = 0;

2124 uint64_t NumNone = 0;

2125 uint64_t NumLikely = 0;

2126 for (const auto LH : Likelihoods) {

2127 switch (LH) {

2129 ++NumUnlikely;

2130 break;

2132 ++NumNone;

2133 break;

2135 ++NumLikely;

2136 break;

2137 }

2138 }

2139

2140

2141 if (NumUnlikely == 0 && NumLikely == 0)

2142 return std::nullopt;

2143

2144

2145

2146

2147

2148

2149

2150 const uint64_t Likely = INT32_MAX / (NumLikely + 2);

2151 const uint64_t None = Likely / (NumNone + 1);

2152 const uint64_t Unlikely = 0;

2153

2155 Result.reserve(Likelihoods.size());

2156 for (const auto LH : Likelihoods) {

2157 switch (LH) {

2159 Result.push_back(Unlikely);

2160 break;

2163 break;

2165 Result.push_back(Likely);

2166 break;

2167 }

2168 }

2169

2171}

2172

2174

2175 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;

2178 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;

2179

2180

2181

2182 llvm::APSInt ConstantCondValue;

2188 if (Case)

2190 RunCleanupsScope ExecutedScope(*this);

2191

2192 if (S.getInit())

2194

2195

2196

2197 if (S.getConditionVariable())

2198 EmitDecl(*S.getConditionVariable());

2199

2200

2201

2202

2203 SwitchInsn = nullptr;

2204

2205

2206

2207 for (unsigned i = 0, e = CaseStmts.size(); i != e; ++i)

2211

2212

2213

2214 SwitchInsn = SavedSwitchInsn;

2215

2216 return;

2217 }

2218 }

2219

2221

2222 RunCleanupsScope ConditionScope(*this);

2223

2224 if (S.getInit())

2226

2227 if (S.getConditionVariable())

2228 EmitDecl(*S.getConditionVariable());

2230

2231

2232

2233

2234

2235 llvm::BasicBlock *DefaultBlock = createBasicBlock("sw.default");

2236 SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock);

2238

2240 unsigned NumCases = 0;

2241 for (const SwitchCase *Case = S.getSwitchCaseList();

2242 Case;

2244 if (isa(Case))

2246 NumCases += 1;

2247 }

2249 SwitchWeights->reserve(NumCases);

2250

2251

2252 SwitchWeights->push_back(DefaultCount);

2255

2257 }

2258

2259 CaseRangeBlock = DefaultBlock;

2260

2261

2262 Builder.ClearInsertionPoint();

2263

2264

2265

2266 JumpDest OuterContinue;

2267 if (!BreakContinueStack.empty())

2268 OuterContinue = BreakContinueStack.back().ContinueBlock;

2269

2270 BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue));

2271

2272

2274

2275 BreakContinueStack.pop_back();

2276

2277

2278

2279 SwitchInsn->setDefaultDest(CaseRangeBlock);

2280

2281

2282 if (!DefaultBlock->getParent()) {

2283

2284

2285 if (ConditionScope.requiresCleanups()) {

2287

2288

2289 } else {

2290 DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock());

2291 delete DefaultBlock;

2292 }

2293 }

2294

2295 ConditionScope.ForceCleanup();

2296

2297

2298 EmitBlock(SwitchExit.getBlock(), true);

2300

2301

2302

2303

2304 auto *Call = dyn_cast(S.getCond());

2306 auto *FD = dyn_cast_or_null(Call->getCalleeDecl());

2307 if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {

2309 SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,

2310 MDHelper.createUnpredictable());

2311 }

2312 }

2313

2314 if (SwitchWeights) {

2315 assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&

2316 "switch weights do not match switch cases");

2317

2318 if (SwitchWeights->size() > 1)

2319 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,

2320 createProfileWeights(*SwitchWeights));

2321 delete SwitchWeights;

2322 } else if (SwitchLikelihood) {

2323 assert(SwitchLikelihood->size() == 1 + SwitchInsn->getNumCases() &&

2324 "switch likelihoods do not match switch cases");

2325 std::optional<SmallVector<uint64_t, 16>> LHW =

2327 if (LHW) {

2329 SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,

2330 createProfileWeights(*LHW));

2331 }

2332 delete SwitchLikelihood;

2333 }

2334 SwitchInsn = SavedSwitchInsn;

2335 SwitchWeights = SavedSwitchWeights;

2336 SwitchLikelihood = SavedSwitchLikelihood;

2337 CaseRangeBlock = SavedCRBlock;

2338}

2339

2340static std::string

2344

2345 while (*Constraint) {

2346 switch (*Constraint) {

2347 default:

2348 Result += Target.convertConstraint(Constraint);

2349 break;

2350

2351 case '*':

2352 case '?':

2353 case '!':

2354 case '=':

2355 case '+':

2356 break;

2357 case '#':

2358 while (Constraint[1] && Constraint[1] != ',')

2359 Constraint++;

2360 break;

2361 case '&':

2362 case '%':

2363 Result += *Constraint;

2364 while (Constraint[1] && Constraint[1] == *Constraint)

2365 Constraint++;

2366 break;

2367 case ',':

2369 break;

2370 case 'g':

2372 break;

2373 case '[': {

2374 assert(OutCons &&

2375 "Must pass output names to constraints with a symbolic name");

2376 unsigned Index;

2377 bool result = Target.resolveSymbolicName(Constraint, *OutCons, Index);

2378 assert(result && "Could not resolve symbolic name"); (void)result;

2379 Result += llvm::utostr(Index);

2380 break;

2381 }

2382 }

2383

2384 Constraint++;

2385 }

2386

2388}

2389

2390

2391

2392

2393static std::string

2396 const AsmStmt &Stmt, const bool EarlyClobber,

2397 std::string *GCCReg = nullptr) {

2398 const DeclRefExpr *AsmDeclRef = dyn_cast(&AsmExpr);

2399 if (!AsmDeclRef)

2400 return Constraint;

2404 return Constraint;

2406 return Constraint;

2409 return Constraint;

2410 StringRef Register = Attr->getLabel();

2411 assert(Target.isValidGCCRegisterName(Register));

2412

2413

2415 if (Target.validateOutputConstraint(Info) &&

2418 return Constraint;

2419 }

2420

2421 Register = Target.getNormalizedGCCRegisterName(Register);

2422 if (GCCReg != nullptr)

2423 *GCCReg = Register.str();

2424 return (EarlyClobber ? "&{" : "{") + Register.str() + "}";

2425}

2426

2427std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue(

2433

2434 llvm::Type *Ty = ConvertType(InputType);

2436 if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||

2437 getTargetHooks().isScalarizableAsmOperand(*this, Ty)) {

2438 Ty = llvm::IntegerType::get(getLLVMContext(), Size);

2439

2441 nullptr};

2442 }

2443 }

2444

2446 ConstraintStr += '*';

2448}

2449

2450std::pair<llvm::Value *, llvm::Type *>

2452 const Expr *InputExpr,

2453 std::string &ConstraintStr) {

2454

2455

2460

2461 llvm::APSInt IntResult;

2464 return {llvm::ConstantInt::get(getLLVMContext(), IntResult), nullptr};

2465 }

2466

2470 nullptr};

2471 }

2472

2476 if (InputExpr->getStmtClass() == Expr::CXXThisExprClass)

2480 return EmitAsmInputLValue(Info, Dest, InputExpr->getType(), ConstraintStr,

2482}

2483

2484

2485

2486

2487

2491

2492 Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(

2494 StringRef StrVal = Str->getString();

2495 if (!StrVal.empty()) {

2498 unsigned StartToken = 0;

2499 unsigned ByteOffset = 0;

2500

2501

2502

2503 for (unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {

2504 if (StrVal[i] != '\n') continue;

2506 i + 1, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset);

2507 Locs.push_back(llvm::ConstantAsMetadata::get(

2509 }

2510 }

2511

2512 return llvm::MDNode::get(CGF.getLLVMContext(), Locs);

2513}

2514

2516 bool HasUnwindClobber, bool ReadOnly,

2517 bool ReadNone, bool NoMerge, bool NoConvergent,

2519 const std::vector<llvm::Type *> &ResultRegTypes,

2520 const std::vector<llvm::Type *> &ArgElemTypes,

2522 std::vector<llvm::Value *> &RegResults) {

2523 if (!HasUnwindClobber)

2524 Result.addFnAttr(llvm::Attribute::NoUnwind);

2525

2526 if (NoMerge)

2527 Result.addFnAttr(llvm::Attribute::NoMerge);

2528

2529 if (!HasSideEffect) {

2530 if (ReadNone)

2531 Result.setDoesNotAccessMemory();

2532 else if (ReadOnly)

2533 Result.setOnlyReadsMemory();

2534 }

2535

2536

2537 for (auto Pair : llvm::enumerate(ArgElemTypes)) {

2538 if (Pair.value()) {

2539 auto Attr = llvm::Attribute::get(

2540 CGF.getLLVMContext(), llvm::Attribute::ElementType, Pair.value());

2541 Result.addParamAttr(Pair.index(), Attr);

2542 }

2543 }

2544

2545

2546

2547 if (const auto *gccAsmStmt = dyn_cast(&S))

2548 Result.setMetadata("srcloc",

2550 else {

2551

2552 llvm::Constant *Loc =

2553 llvm::ConstantInt::get(CGF.Int64Ty, S.getAsmLoc().getRawEncoding());

2554 Result.setMetadata("srcloc",

2556 llvm::ConstantAsMetadata::get(Loc)));

2557 }

2558

2560

2561

2562

2563

2564 Result.addFnAttr(llvm::Attribute::Convergent);

2565

2566 if (ResultRegTypes.size() == 1) {

2567 RegResults.push_back(&Result);

2568 } else {

2569 for (unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {

2570 llvm::Value *Tmp = CGF.Builder.CreateExtractValue(&Result, i, "asmresult");

2571 RegResults.push_back(Tmp);

2572 }

2573 }

2574}

2575

2576static void

2583 const llvm::BitVector &ResultTypeRequiresCast,

2584 const llvm::BitVector &ResultRegIsFlagReg) {

2588

2589 assert(RegResults.size() == ResultRegTypes.size());

2590 assert(RegResults.size() == ResultTruncRegTypes.size());

2591 assert(RegResults.size() == ResultRegDests.size());

2592

2593

2594 assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());

2595 assert(ResultRegIsFlagReg.size() <= ResultRegDests.size());

2596

2597 for (unsigned i = 0, e = RegResults.size(); i != e; ++i) {

2598 llvm::Value *Tmp = RegResults[i];

2599 llvm::Type *TruncTy = ResultTruncRegTypes[i];

2600

2601 if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {

2602

2603

2604 llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2);

2605 llvm::Value *IsBooleanValue =

2606 Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two);

2607 llvm::Function *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume);

2608 Builder.CreateCall(FnAssume, IsBooleanValue);

2609 }

2610

2611

2612

2613 if (ResultRegTypes[i] != TruncTy) {

2614

2615

2616

2617 if (TruncTy->isFloatingPointTy())

2618 Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);

2619 else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {

2620 uint64_t ResSize = CGM.getDataLayout().getTypeSizeInBits(TruncTy);

2621 Tmp = Builder.CreateTrunc(

2622 Tmp, llvm::IntegerType::get(CTX, (unsigned)ResSize));

2623 Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);

2624 } else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {

2625 uint64_t TmpSize =

2627 Tmp = Builder.CreatePtrToInt(

2628 Tmp, llvm::IntegerType::get(CTX, (unsigned)TmpSize));

2629 Tmp = Builder.CreateTrunc(Tmp, TruncTy);

2630 } else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {

2631 Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);

2632 } else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {

2633 Tmp = Builder.CreateBitCast(Tmp, TruncTy);

2634 }

2635 }

2636

2637 LValue Dest = ResultRegDests[i];

2638

2639

2640 if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) {

2645 continue;

2646 }

2647

2651 const Expr *OutExpr = S.getOutputExpr(i);

2653 diag::err_store_value_to_reg);

2654 return;

2655 }

2657 }

2659 }

2660}

2661

2664 constexpr auto Name = "__ASM__hipstdpar_unsupported";

2665

2666 StringRef Asm;

2667 if (auto GCCAsm = dyn_cast(&S))

2668 Asm = GCCAsm->getAsmString()->getString();

2669

2671

2672 auto StrTy = llvm::ConstantDataArray::getString(Ctx, Asm);

2673 auto FnTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),

2674 {StrTy->getType()}, false);

2675 auto UBF = CGF->CGM.getModule().getOrInsertFunction(Name, FnTy);

2676

2677 CGF->Builder.CreateCall(UBF, {StrTy});

2678}

2679

2681

2682 CodeGenFunction::RunCleanupsScope Cleanups(*this);

2683

2684

2685 std::string AsmString = S.generateAsmString(getContext());

2686

2687

2690

2692 bool IsValidTargetAsm = true;

2693 for (unsigned i = 0, e = S.getNumOutputs(); i != e && IsValidTargetAsm; i++) {

2694 StringRef Name;

2695 if (const GCCAsmStmt *GAS = dyn_cast(&S))

2696 Name = GAS->getOutputName(i);

2699 if (IsHipStdPar && !IsValid)

2700 IsValidTargetAsm = false;

2701 else

2702 assert(IsValid && "Failed to parse output constraint");

2703 OutputConstraintInfos.push_back(Info);

2704 }

2705

2706 for (unsigned i = 0, e = S.getNumInputs(); i != e && IsValidTargetAsm; i++) {

2707 StringRef Name;

2708 if (const GCCAsmStmt *GAS = dyn_cast(&S))

2709 Name = GAS->getInputName(i);

2711 bool IsValid =

2713 if (IsHipStdPar && !IsValid)

2714 IsValidTargetAsm = false;

2715 else

2716 assert(IsValid && "Failed to parse input constraint");

2717 InputConstraintInfos.push_back(Info);

2718 }

2719

2720 if (!IsValidTargetAsm)

2722

2723 std::string Constraints;

2724

2725 std::vector ResultRegDests;

2726 std::vector ResultRegQualTys;

2727 std::vector<llvm::Type *> ResultRegTypes;

2728 std::vector<llvm::Type *> ResultTruncRegTypes;

2729 std::vector<llvm::Type *> ArgTypes;

2730 std::vector<llvm::Type *> ArgElemTypes;

2731 std::vectorllvm::Value\* Args;

2732 llvm::BitVector ResultTypeRequiresCast;

2733 llvm::BitVector ResultRegIsFlagReg;

2734

2735

2736 std::string InOutConstraints;

2737 std::vectorllvm::Value\* InOutArgs;

2738 std::vectorllvm::Type\* InOutArgTypes;

2739 std::vectorllvm::Type\* InOutArgElemTypes;

2740

2741

2742 std::vectorstd::string OutputConstraints;

2743

2744

2745 llvm::SmallSet<std::string, 8> PhysRegOutputs;

2746

2747

2748

2749

2750

2751

2752

2753 bool ReadOnly = true, ReadNone = true;

2754

2755 for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {

2757

2758

2759 std::string OutputConstraint(S.getOutputConstraint(i));

2761 getTarget(), &OutputConstraintInfos);

2762

2763 const Expr *OutExpr = S.getOutputExpr(i);

2765

2766 std::string GCCReg;

2770 &GCCReg);

2771

2772 if (!GCCReg.empty() && !PhysRegOutputs.insert(GCCReg).second)

2773 CGM.Error(S.getAsmLoc(), "multiple outputs to hard register: " + GCCReg);

2774

2775 OutputConstraints.push_back(OutputConstraint);

2777 if (!Constraints.empty())

2778 Constraints += ',';

2779

2780

2781

2785 if (!Info.allowsMemory() && IsScalarOrAggregate) {

2786

2787 Constraints += "=" + OutputConstraint;

2788 ResultRegQualTys.push_back(QTy);

2789 ResultRegDests.push_back(Dest);

2790

2791 bool IsFlagReg = llvm::StringRef(OutputConstraint).starts_with("{@cc");

2792 ResultRegIsFlagReg.push_back(IsFlagReg);

2793

2797 Ty->isAggregateType());

2798

2799 ResultTruncRegTypes.push_back(Ty);

2800 ResultTypeRequiresCast.push_back(RequiresCast);

2801

2802 if (RequiresCast) {

2804 if (Size)

2805 Ty = llvm::IntegerType::get(getLLVMContext(), Size);

2806 else

2808 }

2809 ResultRegTypes.push_back(Ty);

2810

2811

2812

2814 unsigned InputNo;

2815 for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {

2818 break;

2819 }

2820 assert(InputNo != S.getNumInputs() && "Didn't find matching input!");

2821

2822 QualType InputTy = S.getInputExpr(InputNo)->getType();

2824

2827

2828 ResultRegTypes.back() = ConvertType(InputTy);

2829 }

2830 }

2831 if (llvm::Type* AdjTy =

2832 getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,

2833 ResultRegTypes.back()))

2834 ResultRegTypes.back() = AdjTy;

2835 else {

2837 diag::err_asm_invalid_type_in_input)

2838 << OutExpr->getType() << OutputConstraint;

2839 }

2840

2841

2842 if (auto *VT = dyn_castllvm::VectorType(ResultRegTypes.back()))

2843 LargestVectorWidth =

2844 std::max((uint64_t)LargestVectorWidth,

2845 VT->getPrimitiveSizeInBits().getKnownMinValue());

2846 } else {

2848

2849

2850

2851

2852

2855

2856 ArgTypes.push_back(DestAddr.getType());

2859 Constraints += "=*";

2860 Constraints += OutputConstraint;

2861 ReadOnly = ReadNone = false;

2862 }

2863

2865 InOutConstraints += ',';

2866

2867 const Expr *InputExpr = S.getOutputExpr(i);

2868 llvm::Value *Arg;

2869 llvm::Type *ArgElemType;

2870 std::tie(Arg, ArgElemType) = EmitAsmInputLValue(

2871 Info, Dest, InputExpr->getType(), InOutConstraints,

2873

2874 if (llvm::Type* AdjTy =

2875 getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,

2876 Arg->getType()))

2877 Arg = Builder.CreateBitCast(Arg, AdjTy);

2878

2879

2880 if (auto *VT = dyn_castllvm::VectorType(Arg->getType()))

2881 LargestVectorWidth =

2882 std::max((uint64_t)LargestVectorWidth,

2883 VT->getPrimitiveSizeInBits().getKnownMinValue());

2884

2886 InOutConstraints += llvm::utostr(i);

2887 else

2888 InOutConstraints += OutputConstraint;

2889

2890 InOutArgTypes.push_back(Arg->getType());

2891 InOutArgElemTypes.push_back(ArgElemType);

2892 InOutArgs.push_back(Arg);

2893 }

2894 }

2895

2896

2897

2898 if (isa(&S)) {

2901

2904 *this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,

2905 ResultRegDests, AsmString, S.getNumOutputs());

2907 }

2908 }

2909

2910 for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) {

2911 const Expr *InputExpr = S.getInputExpr(i);

2912

2914

2916 ReadNone = false;

2917

2918 if (!Constraints.empty())

2919 Constraints += ',';

2920

2921

2922 std::string InputConstraint(S.getInputConstraint(i));

2924 &OutputConstraintInfos);

2925

2928 getTarget(), CGM, S, false );

2929

2930 std::string ReplaceConstraint (InputConstraint);

2931 llvm::Value *Arg;

2932 llvm::Type *ArgElemType;

2933 std::tie(Arg, ArgElemType) = EmitAsmInput(Info, InputExpr, Constraints);

2934

2935

2936

2937

2938

2939

2942 QualType OutputType = S.getOutputExpr(Output)->getType();

2944

2947

2948 if (isallvm::PointerType(Arg->getType()))

2950 llvm::Type *OutputTy = ConvertType(OutputType);

2951 if (isallvm::IntegerType(OutputTy))

2952 Arg = Builder.CreateZExt(Arg, OutputTy);

2953 else if (isallvm::PointerType(OutputTy))

2955 else if (OutputTy->isFloatingPointTy())

2956 Arg = Builder.CreateFPExt(Arg, OutputTy);

2957 }

2958

2959 ReplaceConstraint = OutputConstraints[Output];

2960 }

2961 if (llvm::Type* AdjTy =

2962 getTargetHooks().adjustInlineAsmType(*this, ReplaceConstraint,

2963 Arg->getType()))

2964 Arg = Builder.CreateBitCast(Arg, AdjTy);

2965 else

2966 CGM.getDiags().Report(S.getAsmLoc(), diag::err_asm_invalid_type_in_input)

2967 << InputExpr->getType() << InputConstraint;

2968

2969

2970 if (auto *VT = dyn_castllvm::VectorType(Arg->getType()))

2971 LargestVectorWidth =

2972 std::max((uint64_t)LargestVectorWidth,

2973 VT->getPrimitiveSizeInBits().getKnownMinValue());

2974

2975 ArgTypes.push_back(Arg->getType());

2976 ArgElemTypes.push_back(ArgElemType);

2977 Args.push_back(Arg);

2978 Constraints += InputConstraint;

2979 }

2980

2981

2982 for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) {

2983 ArgTypes.push_back(InOutArgTypes[i]);

2984 ArgElemTypes.push_back(InOutArgElemTypes[i]);

2985 Args.push_back(InOutArgs[i]);

2986 }

2987 Constraints += InOutConstraints;

2988

2989

2991 llvm::BasicBlock *Fallthrough = nullptr;

2992 bool IsGCCAsmGoto = false;

2993 if (const auto *GS = dyn_cast(&S)) {

2994 IsGCCAsmGoto = GS->isAsmGoto();

2995 if (IsGCCAsmGoto) {

2996 for (const auto *E : GS->labels()) {

2998 Transfer.push_back(Dest.getBlock());

2999 if (!Constraints.empty())

3000 Constraints += ',';

3001 Constraints += "!i";

3002 }

3004 }

3005 }

3006

3007 bool HasUnwindClobber = false;

3008

3009

3010 for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {

3011 StringRef Clobber = S.getClobber(i);

3012

3013 if (Clobber == "memory")

3014 ReadOnly = ReadNone = false;

3015 else if (Clobber == "unwind") {

3016 HasUnwindClobber = true;

3017 continue;

3018 } else if (Clobber != "cc") {

3021 getTarget().isSPRegName(Clobber)) {

3023 diag::warn_stack_clash_protection_inline_asm);

3024 }

3025 }

3026

3027 if (isa(&S)) {

3028 if (Clobber == "eax" || Clobber == "edx") {

3029 if (Constraints.find("=&A") != std:🧵:npos)

3030 continue;

3031 std:🧵:size_type position1 =

3032 Constraints.find("={" + Clobber.str() + "}");

3033 if (position1 != std:🧵:npos) {

3034 Constraints.insert(position1 + 1, "&");

3035 continue;

3036 }

3037 std:🧵:size_type position2 = Constraints.find("=A");

3038 if (position2 != std:🧵:npos) {

3039 Constraints.insert(position2 + 1, "&");

3040 continue;

3041 }

3042 }

3043 }

3044 if (!Constraints.empty())

3045 Constraints += ',';

3046

3047 Constraints += "~{";

3048 Constraints += Clobber;

3049 Constraints += '}';

3050 }

3051

3052 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&

3053 "unwind clobber can't be used with asm goto");

3054

3055

3057 if (!MachineClobbers.empty()) {

3058 if (!Constraints.empty())

3059 Constraints += ',';

3060 Constraints += MachineClobbers;

3061 }

3062

3063 llvm::Type *ResultType;

3064 if (ResultRegTypes.empty())

3065 ResultType = VoidTy;

3066 else if (ResultRegTypes.size() == 1)

3067 ResultType = ResultRegTypes[0];

3068 else

3069 ResultType = llvm::StructType::get(getLLVMContext(), ResultRegTypes);

3070

3071 llvm::FunctionType *FTy =

3072 llvm::FunctionType::get(ResultType, ArgTypes, false);

3073

3074 bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;

3075

3076 llvm::InlineAsm::AsmDialect GnuAsmDialect =

3078 ? llvm::InlineAsm::AD_ATT

3079 : llvm::InlineAsm::AD_Intel;

3080 llvm::InlineAsm::AsmDialect AsmDialect = isa(&S) ?

3081 llvm::InlineAsm::AD_Intel : GnuAsmDialect;

3082

3083 llvm::InlineAsm *IA = llvm::InlineAsm::get(

3084 FTy, AsmString, Constraints, HasSideEffect,

3085 false, AsmDialect, HasUnwindClobber);

3086 std::vectorllvm::Value\* RegResults;

3087 llvm::CallBrInst *CBR;

3088 llvm::DenseMap<llvm::BasicBlock *, SmallVector<llvm::Value *, 4>>

3089 CBRRegResults;

3090 if (IsGCCAsmGoto) {

3091 CBR = Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);

3093 UpdateAsmCallInst(*CBR, HasSideEffect, false, ReadOnly,

3096 ArgElemTypes, *this, RegResults);

3097

3098

3099

3100 if (!RegResults.empty()) {

3101 unsigned i = 0;

3102 for (llvm::BasicBlock *Dest : CBR->getIndirectDests()) {

3103 llvm::Twine SynthName = Dest->getName() + ".split";

3105 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);

3106 Builder.SetInsertPoint(SynthBB);

3107

3108 if (ResultRegTypes.size() == 1) {

3109 CBRRegResults[SynthBB].push_back(CBR);

3110 } else {

3111 for (unsigned j = 0, e = ResultRegTypes.size(); j != e; ++j) {

3112 llvm::Value *Tmp = Builder.CreateExtractValue(CBR, j, "asmresult");

3113 CBRRegResults[SynthBB].push_back(Tmp);

3114 }

3115 }

3116

3119 CBR->setIndirectDest(i++, SynthBB);

3120 }

3121 }

3122 } else if (HasUnwindClobber) {

3127 ArgElemTypes, *this, RegResults);

3128 } else {

3129 llvm::CallInst *Result =

3134 ArgElemTypes, *this, RegResults);

3135 }

3136

3137 EmitAsmStores(*this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,

3138 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,

3139 ResultRegIsFlagReg);

3140

3141

3142

3143

3144 if (IsGCCAsmGoto && !CBRRegResults.empty()) {

3145 for (llvm::BasicBlock *Succ : CBR->getIndirectDests()) {

3146 llvm::IRBuilderBase::InsertPointGuard IPG(Builder);

3147 Builder.SetInsertPoint(Succ, --(Succ->end()));

3148 EmitAsmStores(*this, S, CBRRegResults[Succ], ResultRegTypes,

3149 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,

3150 ResultTypeRequiresCast, ResultRegIsFlagReg);

3151 }

3152 }

3153}

3154

3156 const RecordDecl *RD = S.getCapturedRecordDecl();

3158

3159

3162

3165 E = S.capture_init_end();

3166 I != E; ++I, ++CurField) {

3168 if (CurField->hasCapturedVLAType()) {

3170 } else {

3172 }

3173 }

3174

3175 return SlotLV;

3176}

3177

3178

3179

3180llvm::Function *

3183

3184

3186 CGCapturedStmtRAII CapInfoRAII(CGF, new CGCapturedStmtInfo(S, K));

3187 llvm::Function *F = CGF.GenerateCapturedStmtFunction(S);

3188 delete CGF.CapturedStmtInfo;

3189

3190

3192

3193 return F;

3194}

3195

3199}

3200

3201

3202llvm::Function *

3205 "CapturedStmtInfo should be set when generating the captured function");

3206 const CapturedDecl *CD = S.getCapturedDecl();

3207 const RecordDecl *RD = S.getCapturedRecordDecl();

3209 assert(CD->hasBody() && "missing CapturedDecl body");

3210

3211

3215

3216

3220

3221 llvm::Function *F =

3222 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,

3226 F->addFnAttr(llvm::Attribute::NoUnwind);

3227

3228

3231

3234

3235

3238 for (auto *FD : RD->fields()) {

3239 if (FD->hasCapturedVLAType()) {

3240 auto *ExprArg =

3243 auto VAT = FD->getCapturedVLAType();

3244 VLASizeMap[VAT->getSizeExpr()] = ExprArg;

3245 }

3246 }

3247

3248

3253 }

3254

3258

3259 return F;

3260}

3261

3262

3263

3265 for (auto &I : *BB) {

3266 if (auto *CI = dyn_castllvm::ConvergenceControlInst(&I))

3267 return CI;

3268 }

3269 return nullptr;

3270}

3271

3272llvm::CallBase *

3273CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {

3275 assert(ParentToken);

3276

3277 llvm::Value *bundleArgs[] = {ParentToken};

3278 llvm::OperandBundleDef OB("convergencectrl", bundleArgs);

3279 auto *Output = llvm::CallBase::addOperandBundle(

3280 Input, llvm::LLVMContext::OB_convergencectrl, OB, Input->getIterator());

3281 Input->replaceAllUsesWith(Output);

3282 Input->eraseFromParent();

3283 return Output;

3284}

3285

3286llvm::ConvergenceControlInst *

3287CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {

3288 CGBuilderTy::InsertPoint IP = Builder.saveIP();

3289 if (BB->empty())

3290 Builder.SetInsertPoint(BB);

3291 else

3292 Builder.SetInsertPoint(BB->getFirstInsertionPt());

3293

3294 llvm::CallBase *CB = Builder.CreateIntrinsic(

3295 llvm::Intrinsic::experimental_convergence_loop, {}, {});

3297

3298 CB = addConvergenceControlToken(CB);

3299 return castllvm::ConvergenceControlInst(CB);

3300}

3301

3302llvm::ConvergenceControlInst *

3303CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {

3304 llvm::BasicBlock *BB = &F->getEntryBlock();

3308

3309

3310

3311 F->setConvergent();

3312

3313 CGBuilderTy::InsertPoint IP = Builder.saveIP();

3314 Builder.SetInsertPoint(&BB->front());

3315 llvm::CallBase *I = Builder.CreateIntrinsic(

3316 llvm::Intrinsic::experimental_convergence_entry, {}, {});

3317 assert(isallvm::IntrinsicInst(I));

3319

3320 return castllvm::ConvergenceControlInst(I);

3321}

Defines enum values for all the target-independent builtin functions.

static std::string AddVariableConstraints(const std::string &Constraint, const Expr &AsmExpr, const TargetInfo &Target, CodeGenModule &CGM, const AsmStmt &Stmt, const bool EarlyClobber, std::string *GCCReg=nullptr)

AddVariableConstraints - Look at AsmExpr and if it is a variable declared as using a particular regis...

static bool FindCaseStatementsForValue(const SwitchStmt &S, const llvm::APSInt &ConstantCondValue, SmallVectorImpl< const Stmt * > &ResultStmts, ASTContext &C, const SwitchCase *&ResultCase)

FindCaseStatementsForValue - Find the case statement being jumped to and then invoke CollectStatement...

static llvm::ConvergenceControlInst * getConvergenceToken(llvm::BasicBlock *BB)

static void EmitHipStdParUnsupportedAsm(CodeGenFunction *CGF, const AsmStmt &S)

static std::optional< SmallVector< uint64_t, 16 > > getLikelihoodWeights(ArrayRef< Stmt::Likelihood > Likelihoods)

static llvm::MDNode * getAsmSrcLocInfo(const StringLiteral *Str, CodeGenFunction &CGF)

getAsmSrcLocInfo - Return the !srcloc metadata node to attach to an inline asm call instruction.

static std::string SimplifyConstraint(const char *Constraint, const TargetInfo &Target, SmallVectorImpl< TargetInfo::ConstraintInfo > *OutCons=nullptr)

static bool isSwiftAsyncCallee(const CallExpr *CE)

Determine if the given call uses the swiftasync calling convention.

static CSFC_Result CollectStatementsForCase(const Stmt *S, const SwitchCase *Case, bool &FoundCase, SmallVectorImpl< const Stmt * > &ResultStmts)

static void EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S, const llvm::ArrayRef< llvm::Value * > RegResults, const llvm::ArrayRef< llvm::Type * > ResultRegTypes, const llvm::ArrayRef< llvm::Type * > ResultTruncRegTypes, const llvm::ArrayRef< LValue > ResultRegDests, const llvm::ArrayRef< QualType > ResultRegQualTys, const llvm::BitVector &ResultTypeRequiresCast, const llvm::BitVector &ResultRegIsFlagReg)

static bool hasEmptyLoopBody(const LoopStmt &S)

CSFC_Result

CollectStatementsForCase - Given the body of a 'switch' statement and a constant value that is being ...

static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, bool HasUnwindClobber, bool ReadOnly, bool ReadNone, bool NoMerge, bool NoConvergent, const AsmStmt &S, const std::vector< llvm::Type * > &ResultRegTypes, const std::vector< llvm::Type * > &ArgElemTypes, CodeGenFunction &CGF, std::vector< llvm::Value * > &RegResults)

llvm::MachO::Target Target

Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...

Defines the SourceManager interface.

APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...

bool toIntegralConstant(APSInt &Result, QualType SrcTy, const ASTContext &Ctx) const

Try to convert this value to an integral constant.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

SourceManager & getSourceManager()

QualType getTagDeclType(const TagDecl *Decl) const

Return the unique reference to the type for the specified TagDecl (struct/union/class/enum) decl.

QualType getRecordType(const RecordDecl *Decl) const

QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const

getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...

uint64_t getTypeSize(QualType T) const

Return the size of the specified (complete) type T, in bits.

AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.

Attr - This represents one attribute.

Represents an attribute applied to a statement.

BreakStmt - This represents a break.

CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

Represents the body of a CapturedStmt, and serves as its DeclContext.

ImplicitParamDecl * getContextParam() const

Retrieve the parameter containing captured variables.

param_iterator param_end() const

Retrieve an iterator one past the last parameter decl.

param_iterator param_begin() const

Retrieve an iterator pointing to the first parameter decl.

Stmt * getBody() const override

getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...

This captures a statement into a function.

Expr *const * const_capture_init_iterator

Const iterator that walks over the capture initialization arguments.

CapturedRegionKind getCapturedRegionKind() const

Retrieve the captured region kind.

CaseStmt - Represent a case statement.

bool hasProfileClangInstr() const

Check if Clang profile instrumenation is on.

bool hasReducedDebugInfo() const

Check if type and variable info should be emitted.

ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...

@ Indirect

Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...

Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...

llvm::Value * emitRawPointer(CodeGenFunction &CGF) const

Return the pointer contained in this class after authenticating it and adding offset to it if necessa...

llvm::Type * getElementType() const

Return the type of the values stored in this address.

Address withElementType(llvm::Type *ElemTy) const

Return address with different element type, but same pointer and alignment.

llvm::PointerType * getType() const

Return the type of the pointer value.

static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)

forAddr - Make a slot for an aggregate value.

A scoped helper to set the current debug location to the specified location or preferred location of ...

static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)

Set the IRBuilder to not attach debug locations.

llvm::StoreInst * CreateFlagStore(bool Value, llvm::Value *Addr)

Emit a store to an i1 flag variable.

llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)

llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")

This class gathers all debug information during compilation and is responsible for emitting to llvm g...

CGFunctionInfo - Class to encapsulate the information about a function definition.

ABIArgInfo & getReturnInfo()

CallingConv getASTCallingConvention() const

getASTCallingConvention() - Return the AST-specified calling convention.

virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)

Gets the OpenMP-specific address of the local variable.

virtual llvm::Value * getContextValue() const

virtual void setContextValue(llvm::Value *V)

bool isCXXThisExprCaptured() const

virtual FieldDecl * getThisFieldDecl() const

virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)

Emit the captured statement body.

virtual StringRef getHelperName() const

Get the name of the capture helper.

void rescopeLabels()

Change the cleanup scope of the labels in this lexical scope to match the scope of the enclosing cont...

void addLabel(const LabelDecl *label)

CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...

void EmitGotoStmt(const GotoStmt &S)

void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)

void FinishFunction(SourceLocation EndLoc=SourceLocation())

FinishFunction - Complete IR generation of the current function.

void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)

void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)

bool checkIfLoopMustProgress(const Expr *, bool HasEmptyBody)

Returns true if a loop must make progress, which means the mustprogress attribute can be added.

static TypeEvaluationKind getEvaluationKind(QualType T)

getEvaluationKind - Return the TypeEvaluationKind of QualType T.

static bool ContainsLabel(const Stmt *S, bool IgnoreCaseStmts=false)

ContainsLabel - Return true if the statement contains a label in it.

void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr)

EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.

JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)

The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...

void EmitSehCppScopeBegin()

void EmitIfStmt(const IfStmt &S)

void EmitWhileStmt(const WhileStmt &S, ArrayRef< const Attr * > Attrs={})

void EmitOMPOrderedDirective(const OMPOrderedDirective &S)

void EmitOMPTargetDirective(const OMPTargetDirective &S)

llvm::DenseMap< const VarDecl *, llvm::Value * > NRVOFlags

A mapping from NRVO variables to the flags used to indicate when the NRVO has been applied to this va...

bool IsOutlinedSEHHelper

True if the current function is an outlined SEH helper.

void EmitOMPAtomicDirective(const OMPAtomicDirective &S)

void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)

void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)

Address EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())

void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)

EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...

void EmitOMPReverseDirective(const OMPReverseDirective &S)

static bool hasScalarEvaluationKind(QualType T)

void EmitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &S)

CGCapturedStmtInfo * CapturedStmtInfo

void EmitIndirectGotoStmt(const IndirectGotoStmt &S)

void EmitDecl(const Decl &D)

EmitDecl - Emit a declaration.

void EmitCXXTryStmt(const CXXTryStmt &S)

bool EmitSimpleStmt(const Stmt *S, ArrayRef< const Attr * > Attrs)

EmitSimpleStmt - Try to emit a "simple" statement which does not necessarily require an insertion poi...

void EmitLabel(const LabelDecl *D)

EmitLabel - Emit the block for the given label.

void EmitOpenACCInitConstruct(const OpenACCInitConstruct &S)

void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)

void EmitOMPTaskDirective(const OMPTaskDirective &S)

void EmitOMPScanDirective(const OMPScanDirective &S)

void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)

void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)

SmallVector< llvm::ConvergenceControlInst *, 4 > ConvergenceTokenStack

Stack to track the controlled convergence tokens.

LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)

EmitLValue - Emit code to compute a designator that specifies the location of the expression.

void EmitCaseStmt(const CaseStmt &S, ArrayRef< const Attr * > Attrs)

llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)

createBasicBlock - Create an LLVM basic block.

void EmitDefaultStmt(const DefaultStmt &S, ArrayRef< const Attr * > Attrs)

const LangOptions & getLangOpts() const

void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)

void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)

LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)

EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...

void EmitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &S)

void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)

EmitBlock - Emit the given block.

bool InNoConvergentAttributedStmt

True if the current statement has noconvergent attribute.

void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)

void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S)

void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)

void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)

SmallVector< llvm::OperandBundleDef, 1 > getBundlesForFunclet(llvm::Value *Callee)

void EmitOpenACCWaitConstruct(const OpenACCWaitConstruct &S)

llvm::Value * EmitCheckedArgForAssume(const Expr *E)

Emits an argument for a call to a __builtin_assume.

void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)

void SimplifyForwardingBlocks(llvm::BasicBlock *BB)

SimplifyForwardingBlocks - If the given basic block is only a branch to another basic block,...

RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)

EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...

void EmitOMPParallelDirective(const OMPParallelDirective &S)

void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)

EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...

void EmitBlockAfterUses(llvm::BasicBlock *BB)

EmitBlockAfterUses - Emit the given block somewhere hopefully near its uses, and leave the insertion ...

void EmitContinueStmt(const ContinueStmt &S)

void EmitIgnoredExpr(const Expr *E)

EmitIgnoredExpr - Emit an expression in a context which ignores the result.

bool InNoMergeAttributedStmt

True if the current statement has nomerge attribute.

llvm::Type * ConvertTypeForMem(QualType T)

void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)

LValue MakeAddrLValueWithoutTBAA(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)

void EmitOMPForSimdDirective(const OMPForSimdDirective &S)

JumpDest ReturnBlock

ReturnBlock - Unified return block.

LValue EmitLValueForField(LValue Base, const FieldDecl *Field)

RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)

CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...

void EmitOMPFlushDirective(const OMPFlushDirective &S)

void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)

void EmitSEHLeaveStmt(const SEHLeaveStmt &S)

void EmitAttributedStmt(const AttributedStmt &S)

void EmitOMPCancelDirective(const OMPCancelDirective &S)

void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)

void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)

void EmitCaseStmtRange(const CaseStmt &S, ArrayRef< const Attr * > Attrs)

const TargetInfo & getTarget() const

void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)

llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)

Converts Location to a DebugLoc, if debug information is enabled.

void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef< const Attr * > Attrs={})

llvm::Value * getTypeSize(QualType Ty)

Returns calculated size of the specified type.

void EmitLabelStmt(const LabelStmt &S)

void EmitOMPDepobjDirective(const OMPDepobjDirective &S)

const Expr * RetExpr

If a return statement is being visited, this holds the return statment's result expression.

void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init)

void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit)

EmitComplexExprIntoLValue - Emit the given expression of complex type and place its result into the s...

void EmitOMPSingleDirective(const OMPSingleDirective &S)

void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)

void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S)

void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)

Emit simple code for OpenMP directives in Simd-only mode.

void EmitForStmt(const ForStmt &S, ArrayRef< const Attr * > Attrs={})

void EmitOMPDistributeDirective(const OMPDistributeDirective &S)

void EmitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &S)

RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)

EmitAnyExpr - Emit code to compute the specified expression which can have any type.

void EmitOMPParallelForDirective(const OMPParallelForDirective &S)

void EmitOMPTeamsDirective(const OMPTeamsDirective &S)

uint64_t getCurrentProfileCount()

Get the profiler's current count.

void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())

Emit code for the start of a function.

void EmitOMPUnrollDirective(const OMPUnrollDirective &S)

void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)

void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)

bool HaveInsertPoint() const

HaveInsertPoint - True if an insertion point is defined.

llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)

Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...

void EmitSwitchStmt(const SwitchStmt &S)

CGDebugInfo * getDebugInfo()

void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)

void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)

void EmitBranch(llvm::BasicBlock *Block)

EmitBranch - Emit a branch to the specified basic block from the current insert block,...

void EmitOpenACCDataConstruct(const OpenACCDataConstruct &S)

llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)

void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)

EmitAggregateCopy - Emit an aggregate copy.

void EmitSEHTryStmt(const SEHTryStmt &S)

void EmitOMPInteropDirective(const OMPInteropDirective &S)

const TargetCodeGenInfo & getTargetHooks() const

LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)

RValue EmitReferenceBindingToExpr(const Expr *E)

Emits a reference binding to the passed in expression.

void EmitAggExpr(const Expr *E, AggValueSlot AS)

EmitAggExpr - Emit the computation of the specified expression of aggregate type.

void EmitDeclStmt(const DeclStmt &S)

void EmitOMPScopeDirective(const OMPScopeDirective &S)

bool InNoInlineAttributedStmt

True if the current statement has noinline attribute.

void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)

void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)

void EmitCoroutineBody(const CoroutineBodyStmt &S)

Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())

void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)

ASTContext & getContext() const

void EmitOpenACCLoopConstruct(const OpenACCLoopConstruct &S)

void EmitBranchThroughCleanup(JumpDest Dest)

EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...

bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)

ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...

void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})

EmitStmt - Emit the code for the statement.

void EmitOMPTileDirective(const OMPTileDirective &S)

JumpDest getJumpDestForLabel(const LabelDecl *S)

getBasicBlockForLabel - Return the LLVM basicblock that the specified label maps to.

void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S)

llvm::Function * EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K)

void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)

llvm::Type * ConvertType(QualType T)

void EmitOMPSectionsDirective(const OMPSectionsDirective &S)

void EmitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &S)

llvm::CallBase * EmitCallOrInvoke(llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const Twine &Name="")

HLSLControlFlowHintAttr::Spelling HLSLControlFlowAttr

HLSL Branch attribute.

void EmitDoStmt(const DoStmt &S, ArrayRef< const Attr * > Attrs={})

bool InAlwaysInlineAttributedStmt

True if the current statement has always_inline attribute.

void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)

void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)

void EmitOpenACCComputeConstruct(const OpenACCComputeConstruct &S)

void EmitOMPSimdDirective(const OMPSimdDirective &S)

void EmitOMPCriticalDirective(const OMPCriticalDirective &S)

void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S)

void EmitOMPForDirective(const OMPForDirective &S)

void EmitOMPMetaDirective(const OMPMetaDirective &S)

llvm::Value * EvaluateExprAsBool(const Expr *E)

EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...

void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)

LValue InitCapturedStruct(const CapturedStmt &S)

void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)

void EmitReturnStmt(const ReturnStmt &S)

unsigned NextCleanupDestIndex

AggValueSlot::Overlap_t getOverlapForReturnValue()

Determine whether a return value slot may overlap some other object.

void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)

void EmitOMPMasterDirective(const OMPMasterDirective &S)

void EmitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &S)

void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)

void EmitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &S)

void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)

void EmitOMPAssumeDirective(const OMPAssumeDirective &S)

static bool mightAddDeclToScope(const Stmt *S)

Determine if the given statement might introduce a declaration into the current scope,...

void EmitOMPMaskedDirective(const OMPMaskedDirective &S)

uint64_t getProfileCount(const Stmt *S)

Get the profiler's count for the given statement.

static bool hasAggregateEvaluationKind(QualType T)

void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)

void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)

LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)

void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)

EmitStoreOfComplex - Store a complex number into the specified l-value.

void EmitBreakStmt(const BreakStmt &S)

Address GenerateCapturedStmtArgument(const CapturedStmt &S)

void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV)

const CallExpr * MustTailCall

const CGFunctionInfo * CurFnInfo

bool isObviouslyBranchWithoutCleanups(JumpDest Dest) const

isObviouslyBranchWithoutCleanups - Return true if a branch to the specified destination obviously has...

Address GetAddrOfLocalVar(const VarDecl *VD)

GetAddrOfLocalVar - Return the address of a local variable.

void EmitCoreturnStmt(const CoreturnStmt &S)

void EmitOpenACCSetConstruct(const OpenACCSetConstruct &S)

Address ReturnValue

ReturnValue - The temporary alloca to hold the return value.

void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)

void EmitOMPErrorDirective(const OMPErrorDirective &S)

void EmitOMPSectionDirective(const OMPSectionDirective &S)

void EmitOMPBarrierDirective(const OMPBarrierDirective &S)

void EmitStopPoint(const Stmt *S)

EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.

void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)

void EnsureInsertPoint()

EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.

void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)

llvm::LLVMContext & getLLVMContext()

void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)

bool SawAsmBlock

Whether we processed a Microsoft-style asm block during CodeGen.

llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)

EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...

void ResolveBranchFixups(llvm::BasicBlock *Target)

void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)

void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)

Increment the profiler's counter for the given statement by StepV.

void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)

void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)

Emit an OMPCanonicalLoop using the OpenMPIRBuilder.

void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)

llvm::BasicBlock * GetIndirectGotoBlock()

void EmitAsmStmt(const AsmStmt &S)

void EmitObjCAtTryStmt(const ObjCAtTryStmt &S)

void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)

EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...

void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)

static bool containsBreak(const Stmt *S)

containsBreak - Return true if the statement contains a break out of it.

This class organizes the cross-function state that is used while generating LLVM code.

void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)

Set the attributes on the LLVM function for the given decl and function info.

llvm::Module & getModule() const

DiagnosticsEngine & getDiags() const

void ErrorUnsupported(const Stmt *S, const char *Type)

Print out an error that codegen doesn't support the specified stmt yet.

const LangOptions & getLangOpts() const

CodeGenTypes & getTypes()

const llvm::DataLayout & getDataLayout() const

void Error(SourceLocation loc, StringRef error)

Emit a general error that something can't be done.

bool shouldEmitConvergenceTokens() const

CGOpenMPRuntime & getOpenMPRuntime()

Return a reference to the configured OpenMP runtime.

SanitizerMetadata * getSanitizerMetadata()

ASTContext & getContext() const

const TargetCodeGenInfo & getTargetCodeGenInfo()

const CodeGenOptions & getCodeGenOpts() const

llvm::LLVMContext & getLLVMContext()

llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})

void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn)

Assign counters to regions and configure them for PGO of a given function.

void markStmtMaybeUsed(const Stmt *S)

void setCurrentStmt(const Stmt *S)

If the execution count for the current statement is known, record that as the current count.

bool haveRegionCounts() const

Whether or not we have PGO region data for the current function.

llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)

GetFunctionType - Get the LLVM function type for.

const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)

A builtin function is a freestanding function using the default C conventions.

A saved depth on the scope stack.

bool encloses(stable_iterator I) const

Returns true if this scope encloses I.

static stable_iterator invalid()

stable_iterator getInnermostNormalCleanup() const

Returns the innermost normal cleanup on the stack, or stable_end() if there are no normal cleanups.

stable_iterator stable_begin() const

Create a stable reference to the top of the EH stack.

bool empty() const

Determines whether the exception-scopes stack is empty.

bool hasNormalCleanups() const

Determines whether there are any normal cleanups on the stack.

static stable_iterator stable_end()

Create a stable reference to the bottom of the EH stack.

FunctionArgList - Type for representing both the decl and type of parameters to a function.

LValue - This represents an lvalue references.

llvm::Value * getPointer(CodeGenFunction &CGF) const

Address getAddress() const

void pop()

End the current loop.

void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)

Begin a new structured loop.

RValue - This trivial value class is used to represent the result of an expression that is evaluated.

static RValue get(llvm::Value *V)

Address getAggregateAddress() const

getAggregateAddr() - Return the Value* of the address of the aggregate.

llvm::Value * getScalarVal() const

getScalarVal() - Return the Value* of this scalar value.

std::pair< llvm::Value *, llvm::Value * > getComplexVal() const

getComplexVal - Return the real/imag components of this complex value.

virtual void addReturnRegisterOutputs(CodeGen::CodeGenFunction &CGF, CodeGen::LValue ReturnValue, std::string &Constraints, std::vector< llvm::Type * > &ResultRegTypes, std::vector< llvm::Type * > &ResultTruncRegTypes, std::vector< CodeGen::LValue > &ResultRegDests, std::string &AsmString, unsigned NumOutputs) const

Adds constraints and types for result registers.

virtual bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, llvm::Type *Ty) const

Target hook to decide whether an inline asm operand can be passed by value.

CompoundStmt - This represents a group of statements like { stmt stmt }.

Stmt *const * const_body_iterator

ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...

ContinueStmt - This represents a continue.

specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...

A reference to a declared variable, function, enum, etc.

DeclStmt - Adaptor class for mixing declarations with statements and expressions.

SourceLocation getBodyRBrace() const

getBodyRBrace - Gets the right brace of the body, if a body exists.

virtual bool hasBody() const

Returns true if this Decl represents a declaration for a body of code, such as a function or method d...

SourceLocation getLocation() const

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

DoStmt - This represents a 'do/while' stmt.

This represents one expression.

bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const

EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...

Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY

Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...

llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const

EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.

Expr * IgnoreParens() LLVM_READONLY

Skip past any parentheses which might surround this expression until reaching a fixed point.

bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const

isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...

bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const

EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...

bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const

HasSideEffects - This routine returns true for all those expressions which have any effect other than...

SourceLocation getExprLoc() const LLVM_READONLY

getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...

Represents a member of a struct/union/class.

ForStmt - This represents a 'for (init;cond;inc)' stmt.

const Expr * getSubExpr() const

FunctionType - C99 6.7.5.3 - Function Declarators.

CallingConv getCallConv() const

This represents a GCC inline-assembly statement extension.

GlobalDecl - represents a global declaration.

GotoStmt - This represents a direct goto.

IfStmt - This represents an if/then/else.

IndirectGotoStmt - This represents an indirect goto.

Represents the declaration of a label.

LabelStmt - Represents a label, which has a substatement.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

bool assumeFunctionsAreConvergent() const

Represents a point when we exit a loop.

If a crash happens while one of these objects are live, the message is printed out along with the spe...

A (possibly-)qualified type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

QualType getCanonicalType() const

The collection of all-type qualifiers we support.

Represents a struct/union/class.

field_range fields() const

field_iterator field_begin() const

ReturnStmt - This represents a return, optionally of an expression: return; return 4;.

Scope - A scope is a transient data structure that is used while parsing the program.

Encodes a location in the source.

UIntTy getRawEncoding() const

When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.

This class handles loading and caching of source files into memory.

A trivial tuple used to represent a source range.

SourceLocation getEnd() const

SourceLocation getBegin() const

Stmt - This represents one statement.

StmtClass getStmtClass() const

Likelihood

The likelihood of a branch being taken.

@ LH_Unlikely

Branch has the [[unlikely]] attribute.

@ LH_None

No attribute set or branches of the IfStmt have the same attribute.

@ LH_Likely

Branch has the [[likely]] attribute.

static const Attr * getLikelihoodAttr(const Stmt *S)

SourceLocation getBeginLoc() const LLVM_READONLY

static Likelihood getLikelihood(ArrayRef< const Attr * > Attrs)

StringLiteral - This represents a string literal expression, e.g.

SourceLocation getBeginLoc() const LLVM_READONLY

SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target, unsigned *StartToken=nullptr, unsigned *StartTokenByteOffset=nullptr) const

getLocationOfByte - Return a source location that points to the specified byte of this string literal...

StringRef getString() const

const SwitchCase * getNextSwitchCase() const

SwitchStmt - This represents a 'switch' stmt.

Exposes information about the current target.

bool validateInputConstraint(MutableArrayRef< ConstraintInfo > OutputConstraints, ConstraintInfo &info) const

StringRef getNormalizedGCCRegisterName(StringRef Name, bool ReturnCanonical=false) const

Returns the "normalized" GCC register name.

bool validateOutputConstraint(ConstraintInfo &Info) const

virtual std::string_view getClobbers() const =0

Returns a string of target-specific clobbers, in LLVM format.

Token - This structure provides full information about a lexed token.

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

Represents a variable declaration or definition.

StorageClass getStorageClass() const

Returns the storage class as written in the source.

WhileStmt - This represents a 'while' stmt.

Defines the clang::TargetInfo interface.

bool Rem(InterpState &S, CodePtr OpPC)

  1. Pops the RHS from the stack.

bool Ret(InterpState &S, CodePtr &PC)

The JSON file list parser is used to communicate input to InstallAPI.

CapturedRegionKind

The different kinds of captured statement.

@ Asm

Assembly: we accept this only so that we can preprocess it.

@ Result

The result type of a method or function.

Diagnostic wrappers for TextAPI types for error reporting.

cl::opt< bool > EnableSingleByteCoverage

A jump destination is an abstract label, branching to which may require a jump out through normal cle...

void setScopeDepth(EHScopeStack::stable_iterator depth)

EHScopeStack::stable_iterator getScopeDepth() const

llvm::IntegerType * Int64Ty

llvm::IntegerType * IntPtrTy

llvm::PointerType * Int8PtrTy

EvalResult is a struct with detailed info about an evaluated expression.

APValue Val

Val - This is the value the expression can be folded to.

bool hasMatchingInput() const

Return true if this output operand has a matching (tied) input operand.

unsigned getTiedOperand() const

bool allowsMemory() const

bool requiresImmediateConstant() const

bool hasTiedOperand() const

Return true if this input operand is a matching constraint that ties it to an output operand.

bool allowsRegister() const