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 case Stmt::SYCLKernelCallStmtClass:

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

119

120#define STMT(Type, Base)

121#define ABSTRACT_STMT(Op)

122#define EXPR(Type, Base) \

123 case Stmt::Type##Class:

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

125 {

126

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

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

129

131

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

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

134

135

136

137

138

139

140

141

142

143

144

145

146

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

148 outgoing->eraseFromParent();

149 Builder.ClearInsertionPoint();

150 }

151 break;

152 }

153

154 case Stmt::IndirectGotoStmtClass:

156

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

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

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

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

161

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

163

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

165 case Stmt::GCCAsmStmtClass:

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

167 case Stmt::CoroutineBodyStmtClass:

169 break;

170 case Stmt::CoreturnStmtClass:

172 break;

173 case Stmt::CapturedStmtClass: {

174 const CapturedStmt *CS = cast(S);

176 }

177 break;

178 case Stmt::ObjCAtTryStmtClass:

180 break;

181 case Stmt::ObjCAtCatchStmtClass:

182 llvm_unreachable(

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

184 case Stmt::ObjCAtFinallyStmtClass:

185 llvm_unreachable(

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

187 case Stmt::ObjCAtThrowStmtClass:

189 break;

190 case Stmt::ObjCAtSynchronizedStmtClass:

192 break;

193 case Stmt::ObjCForCollectionStmtClass:

195 break;

196 case Stmt::ObjCAutoreleasePoolStmtClass:

198 break;

199

200 case Stmt::CXXTryStmtClass:

202 break;

203 case Stmt::CXXForRangeStmtClass:

205 break;

206 case Stmt::SEHTryStmtClass:

208 break;

209 case Stmt::OMPMetaDirectiveClass:

211 break;

212 case Stmt::OMPCanonicalLoopClass:

214 break;

215 case Stmt::OMPParallelDirectiveClass:

217 break;

218 case Stmt::OMPSimdDirectiveClass:

220 break;

221 case Stmt::OMPTileDirectiveClass:

223 break;

224 case Stmt::OMPUnrollDirectiveClass:

226 break;

227 case Stmt::OMPReverseDirectiveClass:

229 break;

230 case Stmt::OMPInterchangeDirectiveClass:

232 break;

233 case Stmt::OMPForDirectiveClass:

235 break;

236 case Stmt::OMPForSimdDirectiveClass:

238 break;

239 case Stmt::OMPSectionsDirectiveClass:

241 break;

242 case Stmt::OMPSectionDirectiveClass:

244 break;

245 case Stmt::OMPSingleDirectiveClass:

247 break;

248 case Stmt::OMPMasterDirectiveClass:

250 break;

251 case Stmt::OMPCriticalDirectiveClass:

253 break;

254 case Stmt::OMPParallelForDirectiveClass:

256 break;

257 case Stmt::OMPParallelForSimdDirectiveClass:

259 break;

260 case Stmt::OMPParallelMasterDirectiveClass:

262 break;

263 case Stmt::OMPParallelSectionsDirectiveClass:

265 break;

266 case Stmt::OMPTaskDirectiveClass:

268 break;

269 case Stmt::OMPTaskyieldDirectiveClass:

271 break;

272 case Stmt::OMPErrorDirectiveClass:

274 break;

275 case Stmt::OMPBarrierDirectiveClass:

277 break;

278 case Stmt::OMPTaskwaitDirectiveClass:

280 break;

281 case Stmt::OMPTaskgroupDirectiveClass:

283 break;

284 case Stmt::OMPFlushDirectiveClass:

286 break;

287 case Stmt::OMPDepobjDirectiveClass:

289 break;

290 case Stmt::OMPScanDirectiveClass:

292 break;

293 case Stmt::OMPOrderedDirectiveClass:

295 break;

296 case Stmt::OMPAtomicDirectiveClass:

298 break;

299 case Stmt::OMPTargetDirectiveClass:

301 break;

302 case Stmt::OMPTeamsDirectiveClass:

304 break;

305 case Stmt::OMPCancellationPointDirectiveClass:

307 break;

308 case Stmt::OMPCancelDirectiveClass:

310 break;

311 case Stmt::OMPTargetDataDirectiveClass:

313 break;

314 case Stmt::OMPTargetEnterDataDirectiveClass:

316 break;

317 case Stmt::OMPTargetExitDataDirectiveClass:

319 break;

320 case Stmt::OMPTargetParallelDirectiveClass:

322 break;

323 case Stmt::OMPTargetParallelForDirectiveClass:

325 break;

326 case Stmt::OMPTaskLoopDirectiveClass:

328 break;

329 case Stmt::OMPTaskLoopSimdDirectiveClass:

331 break;

332 case Stmt::OMPMasterTaskLoopDirectiveClass:

334 break;

335 case Stmt::OMPMaskedTaskLoopDirectiveClass:

337 break;

338 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:

340 cast(*S));

341 break;

342 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:

344 cast(*S));

345 break;

346 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:

348 cast(*S));

349 break;

350 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:

352 cast(*S));

353 break;

354 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:

356 cast(*S));

357 break;

358 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:

360 cast(*S));

361 break;

362 case Stmt::OMPDistributeDirectiveClass:

364 break;

365 case Stmt::OMPTargetUpdateDirectiveClass:

367 break;

368 case Stmt::OMPDistributeParallelForDirectiveClass:

370 cast(*S));

371 break;

372 case Stmt::OMPDistributeParallelForSimdDirectiveClass:

374 cast(*S));

375 break;

376 case Stmt::OMPDistributeSimdDirectiveClass:

378 break;

379 case Stmt::OMPTargetParallelForSimdDirectiveClass:

381 cast(*S));

382 break;

383 case Stmt::OMPTargetSimdDirectiveClass:

385 break;

386 case Stmt::OMPTeamsDistributeDirectiveClass:

388 break;

389 case Stmt::OMPTeamsDistributeSimdDirectiveClass:

391 cast(*S));

392 break;

393 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:

395 cast(*S));

396 break;

397 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:

399 cast(*S));

400 break;

401 case Stmt::OMPTargetTeamsDirectiveClass:

403 break;

404 case Stmt::OMPTargetTeamsDistributeDirectiveClass:

406 cast(*S));

407 break;

408 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:

410 cast(*S));

411 break;

412 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:

414 cast(*S));

415 break;

416 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:

418 cast(*S));

419 break;

420 case Stmt::OMPInteropDirectiveClass:

422 break;

423 case Stmt::OMPDispatchDirectiveClass:

425 break;

426 case Stmt::OMPScopeDirectiveClass:

428 break;

429 case Stmt::OMPMaskedDirectiveClass:

431 break;

432 case Stmt::OMPGenericLoopDirectiveClass:

434 break;

435 case Stmt::OMPTeamsGenericLoopDirectiveClass:

437 break;

438 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:

440 cast(*S));

441 break;

442 case Stmt::OMPParallelGenericLoopDirectiveClass:

444 cast(*S));

445 break;

446 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:

448 cast(*S));

449 break;

450 case Stmt::OMPParallelMaskedDirectiveClass:

452 break;

453 case Stmt::OMPAssumeDirectiveClass:

455 break;

456 case Stmt::OpenACCComputeConstructClass:

458 break;

459 case Stmt::OpenACCLoopConstructClass:

461 break;

462 case Stmt::OpenACCCombinedConstructClass:

464 break;

465 case Stmt::OpenACCDataConstructClass:

467 break;

468 case Stmt::OpenACCEnterDataConstructClass:

470 break;

471 case Stmt::OpenACCExitDataConstructClass:

473 break;

474 case Stmt::OpenACCHostDataConstructClass:

476 break;

477 case Stmt::OpenACCWaitConstructClass:

479 break;

480 case Stmt::OpenACCInitConstructClass:

482 break;

483 case Stmt::OpenACCShutdownConstructClass:

485 break;

486 case Stmt::OpenACCSetConstructClass:

488 break;

489 case Stmt::OpenACCUpdateConstructClass:

491 break;

492 }

493}

494

497 switch (S->getStmtClass()) {

498 default:

499 return false;

500 case Stmt::NullStmtClass:

501 break;

502 case Stmt::CompoundStmtClass:

504 break;

505 case Stmt::DeclStmtClass:

507 break;

508 case Stmt::LabelStmtClass:

510 break;

511 case Stmt::AttributedStmtClass:

513 break;

514 case Stmt::GotoStmtClass:

516 break;

517 case Stmt::BreakStmtClass:

519 break;

520 case Stmt::ContinueStmtClass:

522 break;

523 case Stmt::DefaultStmtClass:

525 break;

526 case Stmt::CaseStmtClass:

528 break;

529 case Stmt::SEHLeaveStmtClass:

531 break;

532 case Stmt::SYCLKernelCallStmtClass:

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548 break;

549 }

550 return true;

551}

552

553

554

555

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

560

561

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

563

565}

566

569 bool GetLast,

571

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

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

575

577

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

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

580

581

582

583

584

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

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

590

591

593 } else {

594 llvm_unreachable("unknown value statement");

595 }

596 }

597

599

604 } else {

605

606

607

610 false);

611 }

612 } else {

614 }

615 }

616

617 return RetAlloca;

618}

619

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

622

623

624

625

627 return;

628

629

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

631 return;

632

633

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

635 return;

636

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

638 BI->eraseFromParent();

639 BB->eraseFromParent();

640}

641

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

644

645

647

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

649 delete BB;

650 return;

651 }

652

653

654

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

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

657 else

659 Builder.SetInsertPoint(BB);

660}

661

663

664

665

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

667

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

669

670

671 } else {

672

674 }

675

676 Builder.ClearInsertionPoint();

677}

678

680 bool inserted = false;

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

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

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

684 inserted = true;

685 break;

686 }

687 }

688

689 if (!inserted)

691

692 Builder.SetInsertPoint(block);

693}

694

695CodeGenFunction::JumpDest

697 JumpDest &Dest = LabelMap[D];

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

699

700

704 return Dest;

705}

706

708

709

710

713

714 JumpDest &Dest = LabelMap[D];

715

716

717

718 if (!Dest.isValid()) {

720

721

722

723 } else {

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

727 }

728

730

731

736 }

737 }

738

740}

741

742

743

745 assert(!Labels.empty());

748

749

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

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

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

757 }

758

759

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

762 }

763}

764

765

768

769

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

772

774}

775

777 bool nomerge = false;

778 bool noinline = false;

779 bool alwaysinline = false;

780 bool noconvergent = false;

781 HLSLControlFlowHintAttr::Spelling flattenOrBranch =

782 HLSLControlFlowHintAttr::SpellingNotCalculated;

783 const CallExpr *musttail = nullptr;

784

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

786 switch (A->getKind()) {

787 default:

788 break;

789 case attr::NoMerge:

790 nomerge = true;

791 break;

792 case attr::NoInline:

793 noinline = true;

794 break;

795 case attr::AlwaysInline:

796 alwaysinline = true;

797 break;

798 case attr::NoConvergent:

799 noconvergent = true;

800 break;

801 case attr::MustTail: {

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

803 const ReturnStmt *R = cast(Sub);

805 } break;

806 case attr::CXXAssume: {

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

811 Builder.CreateAssumption(AssumptionVal);

812 }

813 } break;

814 case attr::HLSLControlFlowHint: {

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

816 } break;

817 }

818 }

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

826}

827

829

830

831

834

836}

837

838

842 return;

843 }

844

845

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

849

850

852

853

854

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

856

858}

859

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

862

863

864

865 if (S.isConsteval()) {

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

867 if (Executed) {

868 RunCleanupsScope ExecutedScope(*this);

870 }

871 return;

872 }

873

874

875

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

878

879 if (S.getInit())

881

882 if (S.getConditionVariable())

883 EmitDecl(*S.getConditionVariable());

884

885

886

887 bool CondConstant;

889 S.isConstexpr())) {

890

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

892 const Stmt *Skipped = Else;

893 if (!CondConstant)

894 std::swap(Executed, Skipped);

895

896

897

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

899 if (CondConstant)

901 if (Executed) {

902 RunCleanupsScope ExecutedScope(*this);

904 }

906 return;

907 }

908 }

909

910

911

914 llvm::BasicBlock *ElseBlock = ContBlock;

915 if (Else)

917

918

919

920

921

922

923

924

925

926

927

928

934

935

936

937

938

939

940

943 else {

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

946 }

947

948

952 else

954 {

955 RunCleanupsScope ThenScope(*this);

957 }

959

960

961 if (Else) {

962 {

963

966 }

967

970 {

971 RunCleanupsScope ElseScope(*this);

973 }

974 {

975

978 }

979 }

980

981

983

984

985

988}

989

991 bool HasEmptyBody) {

994 return false;

995

996

997

998

999

1000

1002 bool CondIsConstInt =

1003 !ControllingExpression ||

1005 Result.Val.isInt());

1006

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

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

1009

1010

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

1012 return true;

1013

1014

1015

1016

1017

1018

1022 if (HasEmptyBody && CondIsTrue) {

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

1024 return false;

1025 }

1026 return true;

1027 }

1028 return false;

1029}

1030

1031

1032

1033

1034

1035

1036

1037

1038

1039

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

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

1042 if (S.getInc())

1043 return false;

1044 }

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

1046 if (!Body || isa(Body))

1047 return true;

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

1049 return Compound->body_empty();

1050 return false;

1051}

1052

1055

1056

1058 EmitBlock(LoopHeader.getBlock());

1059

1062 emitConvergenceLoopToken(LoopHeader.getBlock()));

1063

1064

1065

1067

1068

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

1070

1071

1072

1073

1074

1075

1076

1077

1078 RunCleanupsScope ConditionScope(*this);

1079

1080 if (S.getConditionVariable())

1081 EmitDecl(*S.getConditionVariable());

1082

1083

1084

1085

1087

1088

1089

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

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

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

1097

1098

1101

1102

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

1104 if (EmitBoolCondBranch) {

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

1106 if (ConditionScope.requiresCleanups())

1108 llvm::MDNode *Weights =

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

1111 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(

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

1114

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

1118 }

1121 diag::warn_attribute_has_no_effect_on_infinite_loop)

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

1124 S.getWhileLoc(),

1125 diag::note_attribute_has_no_effect_on_infinite_loop_here)

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

1127 }

1128

1129

1130

1131 {

1132 RunCleanupsScope BodyScope(*this);

1134

1137 else

1140 }

1141

1142 BreakContinueStack.pop_back();

1143

1144

1145 ConditionScope.ForceCleanup();

1146

1148

1150

1152

1153

1155

1156

1157

1158 if (!EmitBoolCondBranch)

1160

1161

1162

1165

1168}

1169

1174

1176

1177

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

1179

1180

1182

1185 else

1187

1190

1191 {

1192 RunCleanupsScope BodyScope(*this);

1194 }

1195

1197

1200

1201

1202

1203

1204

1205

1206

1208

1209 BreakContinueStack.pop_back();

1210

1211

1212

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

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

1215

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

1221

1222

1223 if (EmitBoolCondBranch) {

1226 BoolCondVal, LoopBody, LoopExit.getBlock(),

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

1228 }

1229

1231

1232

1234

1235

1236

1237 if (!EmitBoolCondBranch)

1239

1240

1241

1244

1247}

1248

1252

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

1254

1255

1256 if (S.getInit())

1258

1259

1260

1261

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

1265

1268

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

1274

1275

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

1277

1278

1279

1280

1281

1282

1283

1284

1285 JumpDest Continue;

1286 if (!S.getInc())

1287 Continue = CondDest;

1288 else if (!S.getConditionVariable())

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

1291

1292 if (S.getCond()) {

1293

1294

1295 if (S.getConditionVariable()) {

1296 EmitDecl(*S.getConditionVariable());

1297

1298

1299

1301 BreakContinueStack.back().ContinueBlock = Continue;

1302 }

1303

1304

1305

1308

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

1310

1311

1312 if (ForScope.requiresCleanups())

1314

1315

1317

1318

1319

1321 llvm::MDNode *Weights =

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

1324 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(

1326

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

1328

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

1332 }

1333

1335 } else {

1336

1337

1338 }

1339

1340

1343 else

1345 {

1346

1347

1348 RunCleanupsScope BodyScope(*this);

1350 }

1351

1352

1353 if (S.getInc()) {

1358 }

1359

1360 BreakContinueStack.pop_back();

1361

1362 ConditionScope.ForceCleanup();

1363

1366

1367 ForScope.ForceCleanup();

1368

1370

1371

1373

1374

1375

1378

1381}

1382

1383void

1387

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

1389

1390

1391 if (S.getInit())

1396

1397

1398

1399

1402

1405

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

1410

1411

1412

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

1414 if (ForScope.requiresCleanups())

1416

1417

1419

1420

1421

1423 llvm::MDNode *Weights =

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

1426 BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(

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

1429

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

1433 }

1434

1438 else

1440

1441

1443

1444

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

1446

1447 {

1448

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

1450 EmitStmt(S.getLoopVarStmt());

1452 }

1453

1455

1458

1459 BreakContinueStack.pop_back();

1460

1462

1463 ForScope.ForceCleanup();

1464

1466

1467

1469

1470

1471

1474

1477}

1478

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

1486 } else {

1488 true);

1489 }

1491}

1492

1493namespace {

1494

1495struct SaveRetExprRAII {

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

1499 }

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

1501 const Expr *OldRetExpr;

1503};

1504}

1505

1506

1510 if (calleeQualType->isFunctionPointerType() ||

1511 calleeQualType->isFunctionReferenceType() ||

1512 calleeQualType->isBlockPointerType() ||

1513 calleeQualType->isMemberFunctionPointerType()) {

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

1516 calleeType = ty;

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

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

1519

1521 } else {

1522 return false;

1523 }

1524 } else {

1525 return false;

1526 }

1528}

1529

1530

1531

1532

1534 if (requiresReturnValueCheck()) {

1536 auto *SLocPtr =

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

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

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

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

1543 }

1544

1545

1547 Builder.CreateUnreachable();

1548 Builder.ClearInsertionPoint();

1549 }

1550

1551

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

1553

1554

1555

1556

1557

1558

1559

1560

1561

1562 SaveRetExprRAII SaveRetExpr(RV, *this);

1563

1564 RunCleanupsScope cleanupScope(*this);

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

1566 RV = EWC->getSubExpr();

1567

1568

1569

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

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

1576 }

1577 }

1578 }

1579

1580

1581

1582

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

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

1589

1590

1591

1592

1593

1594

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

1598

1599

1600 if (RV) {

1602 }

1603 } else if (!RV) {

1604

1606

1607

1610 } else {

1616 true);

1617 else

1619 break;

1620 }

1623 true);

1624 break;

1632 break;

1633 }

1634 }

1635

1636 ++NumReturnExprs;

1638 ++NumSimpleReturnExprs;

1639

1640 cleanupScope.ForceCleanup();

1642}

1643

1645

1646

1649

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

1652}

1653

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

1656

1657

1658

1659

1662

1664}

1665

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

1668

1669

1670

1671

1674

1676}

1677

1678

1679

1680

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

1684

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

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

1687

1688

1689

1690

1694

1695

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

1697 return;

1698

1700 llvm::APInt Range = RHS - LHS;

1701

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

1703

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

1706

1707

1708

1709

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

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

1712 if (SwitchWeights)

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

1714 else if (SwitchLikelihood)

1715 SwitchLikelihood->push_back(LH);

1716

1717 if (Rem)

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

1720 ++LHS;

1721 }

1722 return;

1723 }

1724

1725

1726

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

1728

1729

1730

1731

1732 llvm::BasicBlock *FalseDest = CaseRangeBlock;

1734

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

1736 Builder.SetInsertPoint(CaseRangeBlock);

1737

1738

1739 llvm::Value *Diff =

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

1741 llvm::Value *Cond =

1743

1744 llvm::MDNode *Weights = nullptr;

1745 if (SwitchWeights) {

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

1748 Weights = createProfileWeights(ThisCount, DefaultCount);

1749

1750

1751

1752

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

1754 } else if (SwitchLikelihood)

1755 Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);

1756

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

1758

1759

1760 if (RestoreBB)

1761 Builder.SetInsertPoint(RestoreBB);

1762 else

1763 Builder.ClearInsertionPoint();

1764}

1765

1768

1769

1770

1771

1772

1773 if (!SwitchInsn) {

1775 return;

1776 }

1777

1778

1779 if (S.getRHS()) {

1781 return;

1782 }

1783

1784 llvm::ConstantInt *CaseVal =

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

1786

1787

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

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

1791 else

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

1793 if (CE) {

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

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

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

1799 }

1800

1801 if (SwitchLikelihood)

1803

1804

1805

1806

1809 isa(S.getSubStmt())) {

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

1811

1812

1814 if (SwitchWeights)

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

1817

1818

1819

1820 if (Builder.GetInsertBlock()) {

1822 Builder.ClearInsertionPoint();

1823 }

1824 return;

1825 }

1826 }

1827

1830 if (SwitchWeights)

1832 SwitchInsn->addCase(CaseVal, CaseDest);

1833

1834

1835

1836

1837

1838

1839

1840

1841

1842

1843

1844

1845

1846

1847 const CaseStmt *CurCase = &S;

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

1849

1850

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

1852 CurCase = NextCase;

1853 llvm::ConstantInt *CaseVal =

1855

1856 if (SwitchWeights)

1861 }

1862

1863

1864 if (SwitchLikelihood)

1866

1867 SwitchInsn->addCase(CaseVal, CaseDest);

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

1869 }

1870

1871

1872

1873

1876

1877

1879}

1880

1883

1884

1885

1886 if (!SwitchInsn) {

1888 return;

1889 }

1890

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

1892 assert(DefaultBlock->empty() &&

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

1894

1895 if (SwitchLikelihood)

1897

1899

1901}

1902

1903

1904

1905

1906

1907

1908

1909

1910

1911

1912

1913

1914

1915

1916

1917

1918

1919

1920

1921

1922

1923

1924

1925

1929 bool &FoundCase,

1931

1932 if (!S)

1934

1935

1936

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

1938 if (S == Case) {

1939 FoundCase = true;

1941 ResultStmts);

1942 }

1943

1944

1946 ResultStmts);

1947 }

1948

1949

1950

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

1953

1954

1955

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

1957

1958

1960 bool StartedInLiveCode = FoundCase;

1961 unsigned StartSize = ResultStmts.size();

1962

1963

1964 if (Case) {

1965

1966

1967

1968 bool HadSkippedDecl = false;

1969

1970

1971

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

1974

1978

1979

1980

1981

1982 if (FoundCase) {

1983

1984

1985 if (HadSkippedDecl)

1987

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

1992 }

1993 break;

1995

1996

1997

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

1999

2000 Case = nullptr;

2001

2002

2003

2004 if (HadSkippedDecl)

2006 break;

2007 }

2008 }

2009

2010 if (!FoundCase)

2012

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

2014 }

2015

2016

2017

2018 bool AnyDecls = false;

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

2021

2025

2026

2027 break;

2029

2030

2031

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

2036 }

2037 }

2038

2039

2040

2041

2042 if (AnyDecls) {

2043

2044

2045

2046

2047

2049 ResultStmts.resize(StartSize);

2050 ResultStmts.push_back(S);

2051 } else {

2053 }

2054 }

2055

2057 }

2058

2059

2060

2061

2062 if (Case) {

2066 }

2067

2068

2069

2071

2072

2073

2074 ResultStmts.push_back(S);

2076}

2077

2078

2079

2080

2081

2083 const llvm::APSInt &ConstantCondValue,

2087

2088

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

2090 const DefaultStmt *DefaultCase = nullptr;

2091

2093

2094

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

2096 DefaultCase = DS;

2097 continue;

2098 }

2099

2100

2101 const CaseStmt *CS = cast(Case);

2102

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

2104

2105

2107 break;

2108 }

2109

2110

2111

2112 if (!Case) {

2113

2114

2115 if (!DefaultCase)

2117 Case = DefaultCase;

2118 }

2119

2120

2121

2122

2123

2124

2125

2126

2127

2128 bool FoundCase = false;

2129 ResultCase = Case;

2132 FoundCase;

2133}

2134

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

2137

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

2139 return std::nullopt;

2140

2141 uint64_t NumUnlikely = 0;

2142 uint64_t NumNone = 0;

2143 uint64_t NumLikely = 0;

2144 for (const auto LH : Likelihoods) {

2145 switch (LH) {

2147 ++NumUnlikely;

2148 break;

2150 ++NumNone;

2151 break;

2153 ++NumLikely;

2154 break;

2155 }

2156 }

2157

2158

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

2160 return std::nullopt;

2161

2162

2163

2164

2165

2166

2167

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

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

2170 const uint64_t Unlikely = 0;

2171

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

2174 for (const auto LH : Likelihoods) {

2175 switch (LH) {

2177 Result.push_back(Unlikely);

2178 break;

2181 break;

2183 Result.push_back(Likely);

2184 break;

2185 }

2186 }

2187

2189}

2190

2192

2193 llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;

2196 llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;

2197

2198

2199

2200 llvm::APSInt ConstantCondValue;

2206 if (Case)

2208 RunCleanupsScope ExecutedScope(*this);

2209

2210 if (S.getInit())

2212

2213

2214

2215 if (S.getConditionVariable())

2216 EmitDecl(*S.getConditionVariable());

2217

2218

2219

2220

2221 SwitchInsn = nullptr;

2222

2223

2224

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

2229

2230

2231

2232 SwitchInsn = SavedSwitchInsn;

2233

2234 return;

2235 }

2236 }

2237

2239

2240 RunCleanupsScope ConditionScope(*this);

2241

2242 if (S.getInit())

2244

2245 if (S.getConditionVariable())

2246 EmitDecl(*S.getConditionVariable());

2248

2249

2250

2251

2252

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

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

2256

2258 unsigned NumCases = 0;

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

2260 Case;

2262 if (isa(Case))

2264 NumCases += 1;

2265 }

2267 SwitchWeights->reserve(NumCases);

2268

2269

2270 SwitchWeights->push_back(DefaultCount);

2273

2275 }

2276

2277 CaseRangeBlock = DefaultBlock;

2278

2279

2280 Builder.ClearInsertionPoint();

2281

2282

2283

2284 JumpDest OuterContinue;

2285 if (!BreakContinueStack.empty())

2286 OuterContinue = BreakContinueStack.back().ContinueBlock;

2287

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

2289

2290

2292

2293 BreakContinueStack.pop_back();

2294

2295

2296

2297 SwitchInsn->setDefaultDest(CaseRangeBlock);

2298

2299

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

2301

2302

2303 if (ConditionScope.requiresCleanups()) {

2305

2306

2307 } else {

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

2309 delete DefaultBlock;

2310 }

2311 }

2312

2313 ConditionScope.ForceCleanup();

2314

2315

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

2318

2319

2320

2321

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

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

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

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

2328 MDHelper.createUnpredictable());

2329 }

2330 }

2331

2332 if (SwitchWeights) {

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

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

2335

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

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

2338 createProfileWeights(*SwitchWeights));

2339 delete SwitchWeights;

2340 } else if (SwitchLikelihood) {

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

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

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

2345 if (LHW) {

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

2348 createProfileWeights(*LHW));

2349 }

2350 delete SwitchLikelihood;

2351 }

2352 SwitchInsn = SavedSwitchInsn;

2353 SwitchWeights = SavedSwitchWeights;

2354 SwitchLikelihood = SavedSwitchLikelihood;

2355 CaseRangeBlock = SavedCRBlock;

2356}

2357

2358static std::string

2362

2363 while (*Constraint) {

2364 switch (*Constraint) {

2365 default:

2366 Result += Target.convertConstraint(Constraint);

2367 break;

2368

2369 case '*':

2370 case '?':

2371 case '!':

2372 case '=':

2373 case '+':

2374 break;

2375 case '#':

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

2377 Constraint++;

2378 break;

2379 case '&':

2380 case '%':

2381 Result += *Constraint;

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

2383 Constraint++;

2384 break;

2385 case ',':

2387 break;

2388 case 'g':

2390 break;

2391 case '[': {

2392 assert(OutCons &&

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

2394 unsigned Index;

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

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

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

2398 break;

2399 }

2400 }

2401

2402 Constraint++;

2403 }

2404

2406}

2407

2408

2409

2410

2411static std::string

2414 const AsmStmt &Stmt, const bool EarlyClobber,

2415 std::string *GCCReg = nullptr) {

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

2417 if (!AsmDeclRef)

2418 return Constraint;

2422 return Constraint;

2424 return Constraint;

2427 return Constraint;

2428 StringRef Register = Attr->getLabel();

2429 assert(Target.isValidGCCRegisterName(Register));

2430

2431

2433 if (Target.validateOutputConstraint(Info) &&

2436 return Constraint;

2437 }

2438

2439 Register = Target.getNormalizedGCCRegisterName(Register);

2440 if (GCCReg != nullptr)

2441 *GCCReg = Register.str();

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

2443}

2444

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

2451

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

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

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

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

2457

2459 nullptr};

2460 }

2461 }

2462

2464 ConstraintStr += '*';

2466}

2467

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

2470 const Expr *InputExpr,

2471 std::string &ConstraintStr) {

2472

2473

2478

2479 llvm::APSInt IntResult;

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

2483 }

2484

2488 nullptr};

2489 }

2490

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

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

2500}

2501

2502

2503

2504

2505

2509

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

2512 StringRef StrVal = Str->getString();

2513 if (!StrVal.empty()) {

2516 unsigned StartToken = 0;

2517 unsigned ByteOffset = 0;

2518

2519

2520

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

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

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

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

2527 }

2528 }

2529

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

2531}

2532

2534 bool HasUnwindClobber, bool ReadOnly,

2535 bool ReadNone, bool NoMerge, bool NoConvergent,

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

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

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

2541 if (!HasUnwindClobber)

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

2543

2544 if (NoMerge)

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

2546

2547 if (!HasSideEffect) {

2548 if (ReadNone)

2549 Result.setDoesNotAccessMemory();

2550 else if (ReadOnly)

2551 Result.setOnlyReadsMemory();

2552 }

2553

2554

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

2556 if (Pair.value()) {

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

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

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

2560 }

2561 }

2562

2563

2564

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

2566 Result.setMetadata("srcloc",

2568 else {

2569

2570 llvm::Constant *Loc =

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

2572 Result.setMetadata("srcloc",

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

2575 }

2576

2578

2579

2580

2581

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

2583

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

2585 RegResults.push_back(&Result);

2586 } else {

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

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

2589 RegResults.push_back(Tmp);

2590 }

2591 }

2592}

2593

2594static void

2601 const llvm::BitVector &ResultTypeRequiresCast,

2602 const llvm::BitVector &ResultRegIsFlagReg) {

2606

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

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

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

2610

2611

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

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

2614

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

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

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

2618

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

2620

2621

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

2623 llvm::Value *IsBooleanValue =

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

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

2626 Builder.CreateCall(FnAssume, IsBooleanValue);

2627 }

2628

2629

2630

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

2632

2633

2634

2635 if (TruncTy->isFloatingPointTy())

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

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

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

2639 Tmp = Builder.CreateTrunc(

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

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

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

2643 uint64_t TmpSize =

2645 Tmp = Builder.CreatePtrToInt(

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

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

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

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

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

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

2652 }

2653 }

2654

2655 LValue Dest = ResultRegDests[i];

2656

2657

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

2663 continue;

2664 }

2665

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

2671 diag::err_store_value_to_reg);

2672 return;

2673 }

2675 }

2677 }

2678}

2679

2682 constexpr auto Name = "__ASM__hipstdpar_unsupported";

2683

2684 StringRef Asm;

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

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

2687

2689

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

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

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

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

2694

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

2696}

2697

2699

2700 CodeGenFunction::RunCleanupsScope Cleanups(*this);

2701

2702

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

2704

2705

2708

2710 bool IsValidTargetAsm = true;

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

2712 StringRef Name;

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

2714 Name = GAS->getOutputName(i);

2717 if (IsHipStdPar && !IsValid)

2718 IsValidTargetAsm = false;

2719 else

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

2721 OutputConstraintInfos.push_back(Info);

2722 }

2723

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

2725 StringRef Name;

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

2727 Name = GAS->getInputName(i);

2729 bool IsValid =

2731 if (IsHipStdPar && !IsValid)

2732 IsValidTargetAsm = false;

2733 else

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

2735 InputConstraintInfos.push_back(Info);

2736 }

2737

2738 if (!IsValidTargetAsm)

2740

2741 std::string Constraints;

2742

2743 std::vector ResultRegDests;

2744 std::vector ResultRegQualTys;

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

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

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

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

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

2750 llvm::BitVector ResultTypeRequiresCast;

2751 llvm::BitVector ResultRegIsFlagReg;

2752

2753

2754 std::string InOutConstraints;

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

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

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

2758

2759

2760 std::vectorstd::string OutputConstraints;

2761

2762

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

2764

2765

2766

2767

2768

2769

2770

2771 bool ReadOnly = true, ReadNone = true;

2772

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

2775

2776

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

2779 getTarget(), &OutputConstraintInfos);

2780

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

2783

2784 std::string GCCReg;

2788 &GCCReg);

2789

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

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

2792

2793 OutputConstraints.push_back(OutputConstraint);

2795 if (!Constraints.empty())

2796 Constraints += ',';

2797

2798

2799

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

2804

2805 Constraints += "=" + OutputConstraint;

2806 ResultRegQualTys.push_back(QTy);

2807 ResultRegDests.push_back(Dest);

2808

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

2810 ResultRegIsFlagReg.push_back(IsFlagReg);

2811

2815 Ty->isAggregateType());

2816

2817 ResultTruncRegTypes.push_back(Ty);

2818 ResultTypeRequiresCast.push_back(RequiresCast);

2819

2820 if (RequiresCast) {

2822 if (Size)

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

2824 else

2826 }

2827 ResultRegTypes.push_back(Ty);

2828

2829

2830

2832 unsigned InputNo;

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

2836 break;

2837 }

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

2839

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

2842

2845

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

2847 }

2848 }

2849 if (llvm::Type* AdjTy =

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

2851 ResultRegTypes.back()))

2852 ResultRegTypes.back() = AdjTy;

2853 else {

2855 diag::err_asm_invalid_type_in_input)

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

2857 }

2858

2859

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

2861 LargestVectorWidth =

2862 std::max((uint64_t)LargestVectorWidth,

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

2864 } else {

2866

2867

2868

2869

2870

2873

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

2877 Constraints += "=*";

2878 Constraints += OutputConstraint;

2879 ReadOnly = ReadNone = false;

2880 }

2881

2883 InOutConstraints += ',';

2884

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

2886 llvm::Value *Arg;

2887 llvm::Type *ArgElemType;

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

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

2891

2892 if (llvm::Type* AdjTy =

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

2894 Arg->getType()))

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

2896

2897

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

2899 LargestVectorWidth =

2900 std::max((uint64_t)LargestVectorWidth,

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

2902

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

2905 else

2906 InOutConstraints += OutputConstraint;

2907

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

2909 InOutArgElemTypes.push_back(ArgElemType);

2910 InOutArgs.push_back(Arg);

2911 }

2912 }

2913

2914

2915

2916 if (isa(&S)) {

2919

2922 *this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,

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

2925 }

2926 }

2927

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

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

2930

2932

2934 ReadNone = false;

2935

2936 if (!Constraints.empty())

2937 Constraints += ',';

2938

2939

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

2942 &OutputConstraintInfos);

2943

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

2947

2948 std::string ReplaceConstraint (InputConstraint);

2949 llvm::Value *Arg;

2950 llvm::Type *ArgElemType;

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

2952

2953

2954

2955

2956

2957

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

2962

2965

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

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

2969 if (isallvm::IntegerType(OutputTy))

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

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

2973 else if (OutputTy->isFloatingPointTy())

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

2975 }

2976

2977 ReplaceConstraint = OutputConstraints[Output];

2978 }

2979 if (llvm::Type* AdjTy =

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

2981 Arg->getType()))

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

2983 else

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

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

2986

2987

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

2989 LargestVectorWidth =

2990 std::max((uint64_t)LargestVectorWidth,

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

2992

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

2994 ArgElemTypes.push_back(ArgElemType);

2995 Args.push_back(Arg);

2996 Constraints += InputConstraint;

2997 }

2998

2999

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

3001 ArgTypes.push_back(InOutArgTypes[i]);

3002 ArgElemTypes.push_back(InOutArgElemTypes[i]);

3003 Args.push_back(InOutArgs[i]);

3004 }

3005 Constraints += InOutConstraints;

3006

3007

3009 llvm::BasicBlock *Fallthrough = nullptr;

3010 bool IsGCCAsmGoto = false;

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

3012 IsGCCAsmGoto = GS->isAsmGoto();

3013 if (IsGCCAsmGoto) {

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

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

3017 if (!Constraints.empty())

3018 Constraints += ',';

3019 Constraints += "!i";

3020 }

3022 }

3023 }

3024

3025 bool HasUnwindClobber = false;

3026

3027

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

3029 StringRef Clobber = S.getClobber(i);

3030

3031 if (Clobber == "memory")

3032 ReadOnly = ReadNone = false;

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

3034 HasUnwindClobber = true;

3035 continue;

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

3039 getTarget().isSPRegName(Clobber)) {

3041 diag::warn_stack_clash_protection_inline_asm);

3042 }

3043 }

3044

3045 if (isa(&S)) {

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

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

3048 continue;

3049 std:🧵:size_type position1 =

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

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

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

3053 continue;

3054 }

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

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

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

3058 continue;

3059 }

3060 }

3061 }

3062 if (!Constraints.empty())

3063 Constraints += ',';

3064

3065 Constraints += "~{";

3066 Constraints += Clobber;

3067 Constraints += '}';

3068 }

3069

3070 assert(!(HasUnwindClobber && IsGCCAsmGoto) &&

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

3072

3073

3075 if (!MachineClobbers.empty()) {

3076 if (!Constraints.empty())

3077 Constraints += ',';

3078 Constraints += MachineClobbers;

3079 }

3080

3081 llvm::Type *ResultType;

3082 if (ResultRegTypes.empty())

3083 ResultType = VoidTy;

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

3085 ResultType = ResultRegTypes[0];

3086 else

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

3088

3089 llvm::FunctionType *FTy =

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

3091

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

3093

3094 llvm::InlineAsm::AsmDialect GnuAsmDialect =

3096 ? llvm::InlineAsm::AD_ATT

3097 : llvm::InlineAsm::AD_Intel;

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

3099 llvm::InlineAsm::AD_Intel : GnuAsmDialect;

3100

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

3102 FTy, AsmString, Constraints, HasSideEffect,

3103 false, AsmDialect, HasUnwindClobber);

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

3105 llvm::CallBrInst *CBR;

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

3107 CBRRegResults;

3108 if (IsGCCAsmGoto) {

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

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

3114 ArgElemTypes, *this, RegResults);

3115

3116

3117

3118 if (!RegResults.empty()) {

3119 unsigned i = 0;

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

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

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

3124 Builder.SetInsertPoint(SynthBB);

3125

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

3127 CBRRegResults[SynthBB].push_back(CBR);

3128 } else {

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

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

3131 CBRRegResults[SynthBB].push_back(Tmp);

3132 }

3133 }

3134

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

3138 }

3139 }

3140 } else if (HasUnwindClobber) {

3145 ArgElemTypes, *this, RegResults);

3146 } else {

3147 llvm::CallInst *Result =

3152 ArgElemTypes, *this, RegResults);

3153 }

3154

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

3156 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,

3157 ResultRegIsFlagReg);

3158

3159

3160

3161

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

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

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

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

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

3167 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,

3168 ResultTypeRequiresCast, ResultRegIsFlagReg);

3169 }

3170 }

3171}

3172

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

3176

3177

3180

3183 E = S.capture_init_end();

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

3186 if (CurField->hasCapturedVLAType()) {

3188 } else {

3190 }

3191 }

3192

3193 return SlotLV;

3194}

3195

3196

3197

3198llvm::Function *

3201

3202

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

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

3206 delete CGF.CapturedStmtInfo;

3207

3208

3210

3211 return F;

3212}

3213

3217}

3218

3219

3220llvm::Function *

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

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

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

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

3228

3229

3233

3234

3238

3239 llvm::Function *F =

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

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

3245

3246

3249

3252

3253

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

3257 if (FD->hasCapturedVLAType()) {

3258 auto *ExprArg =

3261 auto VAT = FD->getCapturedVLAType();

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

3263 }

3264 }

3265

3266

3271 }

3272

3276

3277 return F;

3278}

3279

3280

3281

3283 for (auto &I : *BB) {

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

3285 return CI;

3286 }

3287 return nullptr;

3288}

3289

3290llvm::CallBase *

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

3293 assert(ParentToken);

3294

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

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

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

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

3299 Input->replaceAllUsesWith(Output);

3300 Input->eraseFromParent();

3301 return Output;

3302}

3303

3304llvm::ConvergenceControlInst *

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

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

3307 if (BB->empty())

3308 Builder.SetInsertPoint(BB);

3309 else

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

3311

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

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

3315

3316 CB = addConvergenceControlToken(CB);

3317 return castllvm::ConvergenceControlInst(CB);

3318}

3319

3320llvm::ConvergenceControlInst *

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

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

3326

3327

3328

3329 F->setConvergent();

3330

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

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

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

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

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

3337

3338 return castllvm::ConvergenceControlInst(I);

3339}

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