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

1

2

3

4

5

6

7

8

9

10

11

12

14

18#include "mlir/IR/Location.h"

23

24#include

25

27

29 bool suppressNewContext)

32}

33

35

36

38 type = type.getCanonicalType();

39 while (true) {

40 switch (type->getTypeClass()) {

41#define TYPE(name, parent)

42#define ABSTRACT_TYPE(name, parent)

43#define NON_CANONICAL_TYPE(name, parent) case Type:📛

44#define DEPENDENT_TYPE(name, parent) case Type:📛

45#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(name, parent) case Type:📛

46#include "clang/AST/TypeNodes.inc"

47 llvm_unreachable("non-canonical or dependent type in IR-generation");

48

49 case Type::Auto:

50 case Type::DeducedTemplateSpecialization:

51 llvm_unreachable("undeduced type in IR-generation");

52

53

54 case Type::Builtin:

55 case Type::Pointer:

56 case Type::BlockPointer:

57 case Type::LValueReference:

58 case Type::RValueReference:

59 case Type::MemberPointer:

60 case Type::Vector:

61 case Type::ExtVector:

62 case Type::ConstantMatrix:

63 case Type::FunctionProto:

64 case Type::FunctionNoProto:

65 case Type::Enum:

66 case Type::ObjCObjectPointer:

67 case Type::Pipe:

68 case Type::BitInt:

69 case Type::HLSLAttributedResource:

70 case Type::HLSLInlineSpirv:

72

73

74 case Type::Complex:

76

77

78 case Type::ConstantArray:

79 case Type::IncompleteArray:

80 case Type::VariableArray:

81 case Type::Record:

82 case Type::ObjCObject:

83 case Type::ObjCInterface:

84 case Type::ArrayParameter:

86

87

88 case Type::Atomic:

90 continue;

91 }

92 llvm_unreachable("unknown type kind!");

93 }

94}

95

97 return cgm.getTypes().convertTypeForMem(t);

98}

99

101 return cgm.getTypes().convertType(t);

102}

103

105

106

111 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),

113 }

114

115 assert(currSrcLoc && "expected to inherit some source location");

117}

118

120

121

124 mlir::Location end = getLoc(srcLoc.getEnd());

126 mlir::Attribute metadata;

127 return mlir::FusedLoc::get(locs, metadata, &getMLIRContext());

128 }

131 }

132

133 return builder.getUnknownLoc();

134}

135

138 mlir::Attribute metadata;

139 return mlir::FusedLoc::get(locs, metadata, &getMLIRContext());

140}

141

143

144 if (s)

145 return false;

146

147

148

149

150

151

153 return true;

154

155

156

158 return true;

159

160

161

162

163

165 ignoreCaseStmts = true;

166

167

168 return std::any_of(s->child_begin(), s->child_end(),

169 [=](const Stmt *subStmt) {

170 return containsLabel(subStmt, ignoreCaseStmts);

171 });

172}

173

174

175

176

178 bool allowLabels) {

179 llvm::APSInt resultInt;

181 return false;

182

183 resultBool = resultInt.getBoolValue();

184 return true;

185}

186

187

188

189

191 llvm::APSInt &resultInt,

192 bool allowLabels) {

193

194

197 return false;

198

199 llvm::APSInt intValue = result.Val.getInt();

201 return false;

202

203 resultInt = intValue;

204 return true;

205}

206

207void CIRGenFunction::emitAndUpdateRetAlloca(QualType type, mlir::Location loc,

209 if (type->isVoidType()) {

211 false);

214 }

215}

216

217void CIRGenFunction::declare(mlir::Value addrVal, const Decl *var, QualType ty,

218 mlir::Location loc, CharUnits alignment,

219 bool isParam) {

221 assert(symbolTable.count(var) && "not supposed to be available just yet");

222

223 auto allocaOp = addrVal.getDefiningOpcir::AllocaOp();

224 assert(allocaOp && "expected cir::AllocaOp");

225

226 if (isParam)

227 allocaOp.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));

228 if (ty->isReferenceType() || ty.isConstQualified())

229 allocaOp.setConstantAttr(mlir::UnitAttr::get(&getMLIRContext()));

230

232}

233

237

238 auto applyCleanup = [&]() {

240

243 }

244 };

245

246

247

248

249

250

251

253 for (mlir::Block *retBlock : localScope->getRetBlocks()) {

254 mlir::OpBuilder::InsertionGuard guard(builder);

255 builder.setInsertionPointToEnd(retBlock);

256 retBlocks.push_back(retBlock);

257 mlir::Location retLoc = localScope->getRetLoc(retBlock);

258 emitReturn(retLoc);

259 }

260

261 auto insertCleanupAndLeave = [&](mlir::Block *insPt) {

262 mlir::OpBuilder::InsertionGuard guard(builder);

263 builder.setInsertionPointToEnd(insPt);

264

265

266

267 mlir::Block *cleanupBlock = localScope->getCleanupBlock(builder);

268

269

270 applyCleanup();

271

272

273 if (!cleanupBlock && localScope->getCleanupBlock(builder)) {

275 cir::BrOp::create(builder, insPt->back().getLoc(), cleanupBlock);

276 if (!cleanupBlock->mightHaveTerminator()) {

277 mlir::OpBuilder::InsertionGuard guard(builder);

278 builder.setInsertionPointToEnd(cleanupBlock);

279 cir::YieldOp::create(builder, localScope->endLoc);

280 }

281 }

282

283 if (localScope->depth == 0) {

284

285

286 if (localScope->getRetBlocks().size() == 1) {

287 mlir::Block *retBlock = localScope->getRetBlocks()[0];

288 mlir::Location retLoc = localScope->getRetLoc(retBlock);

289 if (retBlock->getUses().empty()) {

290 retBlock->erase();

291 } else {

292

293 if (cleanupBlock) {

294 for (mlir::BlockOperand &blockUse : retBlock->getUses()) {

295 cir::BrOp brOp = mlir::castcir::BrOp(blockUse.getOwner());

296 brOp.setSuccessor(cleanupBlock);

297 }

298 }

299

300 cir::BrOp::create(builder, retLoc, retBlock);

301 return;

302 }

303 }

304 emitImplicitReturn();

305 return;

306 }

307

308

309

310

311 if (!localScope->isTernary() && !insPt->mightHaveTerminator()) {

312 !retVal ? cir::YieldOp::create(builder, localScope->endLoc)

313 : cir::YieldOp::create(builder, localScope->endLoc, retVal);

314 }

315 };

316

317

318

319

320

321 mlir::Block *cleanupBlock = localScope->getCleanupBlock(builder);

322 if (cleanupBlock)

323 insertCleanupAndLeave(cleanupBlock);

324

325

326

327

328 mlir::Block *curBlock = builder.getBlock();

330 return;

331 if (curBlock->mightHaveTerminator() && curBlock->getTerminator())

332 return;

333

334

335 bool entryBlock = builder.getInsertionBlock()->isEntryBlock();

336 if (!entryBlock && curBlock->empty()) {

337 curBlock->erase();

338 for (mlir::Block *retBlock : retBlocks) {

339 if (retBlock->getUses().empty())

340 retBlock->erase();

341 }

342 return;

343 }

344

345

346 if (cleanupBlock) {

347 cir::BrOp::create(builder, curBlock->back().getLoc(), cleanupBlock);

348 return;

349 }

350

351

352 insertCleanupAndLeave(curBlock);

353}

354

355cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {

357

358

360

361 auto fn = dyn_castcir::FuncOp(cgf.curFn);

362 assert(fn && "emitReturn from non-function");

363 if (!fn.getFunctionType().hasVoidReturn()) {

364

365 auto value = cir::LoadOp::create(

366 builder, loc, fn.getFunctionType().getReturnType(), *cgf.fnRetAlloca);

367 return cir::ReturnOp::create(builder, loc,

369 }

370 return cir::ReturnOp::create(builder, loc);

371}

372

373

374

377

378

380 return classDecl->hasTrivialDestructor();

382}

383

384void CIRGenFunction::LexicalScope::emitImplicitReturn() {

385 CIRGenBuilderTy &builder = cgf.getBuilder();

386 LexicalScope *localScope = cgf.curLexScope;

387

389

390

391

392

393

394

395 if (cgf.getLangOpts().CPlusPlus && !fd->hasImplicitReturnZero() &&

396 !cgf.sawAsmBlock && !fd->getReturnType()->isVoidType() &&

397 builder.getInsertionBlock()) {

398 bool shouldEmitUnreachable =

399 cgf.cgm.getCodeGenOpts().StrictReturn ||

401

402 if (shouldEmitUnreachable) {

404 if (cgf.cgm.getCodeGenOpts().OptimizationLevel == 0)

405 cir::TrapOp::create(builder, localScope->endLoc);

406 else

407 cir::UnreachableOp::create(builder, localScope->endLoc);

408 builder.clearInsertionPoint();

409 return;

410 }

411 }

412

413 (void)emitReturn(localScope->endLoc);

414}

415

418 while (scope) {

419 if (scope->isTry())

420 return scope->getTry();

421 scope = scope->parentScope;

422 }

423 return nullptr;

424}

425

426

427

429 mlir::Value value) {

430 mlir::Type ty = cgf.convertType(var->getType());

431

432

433

434 if (value.getType() == ty)

435 return value;

436

437 assert((mlir::isacir::IntType(ty) || cir::isAnyFloatingPointType(ty)) &&

438 "unexpected promotion type");

439

440 if (mlir::isacir::IntType(ty))

441 return cgf.getBuilder().CIRBaseBuilderTy::createIntCast(value, ty);

442

444}

445

447 mlir::Block *entryBB,

450

451 if (fd && fd->hasAttr()) {

452 cgm.errorNYI(bodyBeginLoc, "naked function decl");

453 }

454

455

456 for (const auto nameValue : llvm::zip(args, entryBB->getArguments())) {

457 const VarDecl *paramVar = std::get<0>(nameValue);

458 mlir::Value paramVal = std::get<1>(nameValue);

461 paramVal.setLoc(paramLoc);

462

463 mlir::Value addrVal =

466 true);

467

468 declare(addrVal, paramVar, paramVar->getType(), paramLoc, alignment,

469 true);

470

472

476 if (isPromoted)

478

479

480

481 mlir::Location fnBodyBegin = getLoc(bodyBeginLoc);

482 builder.CIRBaseBuilderTy::createStore(fnBodyBegin, paramVal, addrVal);

483 }

484 assert(builder.getInsertionBlock() && "Should be valid");

485}

486

488 cir::FuncOp fn, cir::FuncType funcType,

492 "CIRGenFunction can only be used for one function at a time");

493

495

497

500 const auto *fd = dyn_cast_or_null(d);

502

504

505 mlir::Block *entryBB = &fn.getBlocks().front();

506 builder.setInsertionPointToStart(entryBB);

507

508

509

511 if (fd) {

512 if (Stmt *body = fd->getBody())

513 bodyBeginLoc = body->getBeginLoc();

514 else

515 bodyBeginLoc = fd->getLocation();

516 }

517

519

520

521

523

524

526 if (fd) {

527 if (Stmt *body = fd->getBody())

528 bodyEndLoc = body->getEndLoc();

529 else

530 bodyEndLoc = fd->getLocation();

531 }

532 emitAndUpdateRetAlloca(returnType, getLoc(bodyEndLoc),

533 getContext().getTypeAlignInChars(returnType));

534 }

535

536 if (isa_and_nonnull(d) &&

538 cgm.getCXXABI().emitInstanceFunctionProlog(loc, *this);

539

541 if (md->getParent()->isLambda() && md->getOverloadedOperator() == OO_Call) {

542

543 auto fn = dyn_castcir::FuncOp(curFn);

544 assert(fn && "lambda in non-function region");

545 fn.setLambda(true);

546

547

551

552

553

554

555

556

557 LValue thisFieldLValue =

560

561

563 } else {

564

565

568 }

569 }

570 for (auto *fd : md->getParent()->fields()) {

571 if (fd->hasCapturedVLAType())

572 cgm.errorNYI(loc, "lambda captured VLA type");

573 }

574 } else {

575

576

577

579 }

580

583 }

584}

585

587 for (cir::BlockAddressOp &blockAddress : cgm.unresolvedBlockAddressToLabel) {

588 cir::LabelOp labelOp =

589 cgm.lookupBlockAddressInfo(blockAddress.getBlockAddrInfo());

590 assert(labelOp && "expected cir.labelOp to already be emitted");

591 cgm.updateResolvedBlockAddress(blockAddress, labelOp);

592 }

593 cgm.unresolvedBlockAddressToLabel.clear();

594}

595

598 return;

601 mlir::OpBuilder::InsertionGuard guard(builder);

603 for (auto &[blockAdd, labelOp] : cgm.blockAddressToLabel) {

604 succesors.push_back(labelOp->getBlock());

605 rangeOperands.push_back(labelOp->getBlock()->getArguments());

606 }

607 cir::IndirectBrOp::create(builder, builder.getUnknownLoc(),

609 rangeOperands, succesors);

610 cgm.blockAddressToLabel.clear();

611}

612

614

615

618

619

620

621

622

625 indrBr.setPoison(true);

626 }

627

628

629

630

631

632

634 if (hasCleanups) {

636

638 }

639}

640

642

644

645 if (const CompoundStmt *block = dyn_cast(body))

647

648 return emitStmt(body, true);

649}

650

652

653

654

656 for (mlir::Block &block : func.getBlocks()) {

657 if (block.empty() && block.getUses().empty())

658 blocksToDelete.push_back(&block);

659 }

660 for (mlir::Block *block : blocksToDelete)

661 block->erase();

662}

663

665 cir::FuncType funcType) {

668

669 if (funcDecl->isInlineBuiltinDeclaration()) {

670

671

672

673 std::string fdInlineName = (cgm.getMangledName(funcDecl) + ".inline").str();

674 cir::FuncOp clone =

675 mlir::cast_or_nullcir::FuncOp(cgm.getGlobalValue(fdInlineName));

676 if (!clone) {

677 mlir::OpBuilder::InsertionGuard guard(builder);

678 builder.setInsertionPoint(fn);

679 clone = cir::FuncOp::create(builder, fn.getLoc(), fdInlineName,

680 fn.getFunctionType());

681 clone.setLinkage(cir::GlobalLinkageKind::InternalLinkage);

682 clone.setSymVisibility("private");

683 clone.setInlineKind(cir::InlineKind::AlwaysInline);

684 }

685 fn.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);

686 fn.setSymVisibility("private");

687 fn = clone;

688 } else {

689

690

691

694 if (LLVM_UNLIKELY(pd->isInlineBuiltinDeclaration())) {

695 std::string inlineName = funcDecl->getName().str() + ".inline";

696 if (auto inlineFn = mlir::cast_or_nullcir::FuncOp(

697 cgm.getGlobalValue(inlineName))) {

698

699

700

701 if (inlineFn

702 .replaceAllSymbolUses(fn.getSymNameAttr(), cgm.getModule())

703 .failed())

704 llvm_unreachable("Failed to replace inline builtin symbol uses");

705 inlineFn.erase();

706 }

707 break;

708 }

709 }

710 }

711

713 Stmt *body = funcDecl->getBody();

715 body ? body->getSourceRange() : funcDecl->getLocation();

716

718 : builder.getUnknownLoc()};

719

721 return clangLoc.isValid() ? getLoc(clangLoc) : builder.getUnknownLoc();

722 };

723 const mlir::Location fusedLoc = mlir::FusedLoc::get(

725 {validMLIRLoc(bodyRange.getBegin()), validMLIRLoc(bodyRange.getEnd())});

726 mlir::Block *entryBB = fn.addEntryBlock();

727

730

731

733 {

734 LexicalScope lexScope(*this, fusedLoc, entryBB);

735

736

738

739

740 if (body && isa_and_nonnull(body))

741 llvm::append_range(fnArgs, funcDecl->parameters());

742

748 funcDecl->hasAttr()) {

752

753

754

756 } else if (funcDecl->isDefaulted() && isa(funcDecl) &&

759

760

762 } else if (body) {

763

765 return nullptr;

766 }

767 } else {

768

769 llvm_unreachable("no definition for normal function");

770 }

771

772 if (mlir::failed(fn.verifyBody()))

773 return nullptr;

774

776 }

777

779 return fn;

780}

781

786

787 assert((cgm.getTarget().getCXXABI().hasConstructorVariants() ||

789 "can only generate complete ctor for this ABI");

790

792

794 cgm.getTarget().getCXXABI().hasConstructorVariants()) {

796 return;

797 }

798

800 Stmt *body = ctor->getBody(definition);

801 assert(definition == ctor && "emitting wrong constructor body");

802

803 if (isa_and_nonnull(body)) {

804 cgm.errorNYI(ctor->getSourceRange(), "emitConstructorBody: try body");

805 return;

806 }

807

810

811

812

813

814

816

817

818

819 if (mlir::failed(emitStmt(body, true))) {

820 cgm.errorNYI(ctor->getSourceRange(),

821 "emitConstructorBody: emit body statement failed.");

822 return;

823 }

824}

825

826

830

832

833

834

835

836

837

839 cgm.errorNYI(dtor->getSourceRange(), "abstract base class destructors");

840 return;

841 }

842

845

846

847

848

849

852 cgm.errorNYI(dtor->getSourceRange(), "emitConditionalArrayDtorCall");

859 }

860 return;

861 }

862

863

864

865 const bool isTryBody = isa_and_nonnull(body);

866 if (isTryBody)

867 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");

868

870

871

873

874

875

876

877

878

879 switch (dtorType) {

881 llvm_unreachable("not expecting a unified dtor");

883 llvm_unreachable("not expecting a COMDAT");

886 llvm_unreachable("already handled deleting case");

887

889 assert((body || getTarget().getCXXABI().isMicrosoft()) &&

890 "can't emit a dtor without a body for non-Microsoft ABIs");

891

892

894

895 if (!isTryBody) {

899 break;

900 }

901

902

903 [[fallthrough]];

904

906 assert(body);

907

908

910

912

913 if (isTryBody) {

914 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");

915 } else if (body) {

916 (void)emitStmt(body, true);

917 } else {

918 assert(dtor->isImplicit() && "bodyless dtor not implicit");

919

920 }

921

922

924

925 break;

926 }

927

928

930

931

932 if (isTryBody)

933 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");

934}

935

936

937

940

941

944 CharUnits align = cgm.getNaturalTypeAlignment(ty, &baseInfo);

946}

947

951 CharUnits alignment = cgm.getNaturalTypeAlignment(ty, &baseInfo);

955}

956

960 QualType retTy = fd->getReturnType();

961

962 const auto *md = dyn_cast(fd);

963 if (md && md->isInstance()) {

964 if (cgm.getCXXABI().hasThisReturn(gd))

965 cgm.errorNYI(fd->getSourceRange(), "this return");

966 else if (cgm.getCXXABI().hasMostDerivedReturn(gd))

967 cgm.errorNYI(fd->getSourceRange(), "most derived return");

968 cgm.getCXXABI().buildThisParam(*this, args);

969 }

970

971 if (const auto *cd = dyn_cast(fd))

972 if (cd->getInheritedConstructor())

973 cgm.errorNYI(fd->getSourceRange(),

974 "buildFunctionArgList: inherited constructor");

975

976 for (auto *param : fd->parameters())

977 args.push_back(param);

978

980 cgm.getCXXABI().addImplicitStructorParams(*this, retTy, args);

981

982 return retTy;

983}

984

985

986

987

989

991 default:

993 std::string("l-value not implemented for '") +

996 case Expr::ConditionalOperatorClass:

998 case Expr::BinaryConditionalOperatorClass:

1000 case Expr::ArraySubscriptExprClass:

1002 case Expr::ExtVectorElementExprClass:

1004 case Expr::UnaryOperatorClass:

1006 case Expr::StringLiteralClass:

1008 case Expr::MemberExprClass:

1010 case Expr::CompoundLiteralExprClass:

1012 case Expr::PredefinedExprClass:

1014 case Expr::BinaryOperatorClass:

1016 case Expr::CompoundAssignOperatorClass: {

1020 "CompoundAssignOperator with AtomicType");

1022 }

1025

1027 }

1028 case Expr::CallExprClass:

1029 case Expr::CXXMemberCallExprClass:

1030 case Expr::CXXOperatorCallExprClass:

1031 case Expr::UserDefinedLiteralClass:

1033 case Expr::ExprWithCleanupsClass: {

1038 return lv;

1039 }

1040 case Expr::CXXDefaultArgExprClass: {

1044 }

1045 case Expr::ParenExprClass:

1047 case Expr::GenericSelectionExprClass:

1049 case Expr::DeclRefExprClass:

1051 case Expr::CStyleCastExprClass:

1052 case Expr::CXXStaticCastExprClass:

1053 case Expr::CXXDynamicCastExprClass:

1054 case Expr::ImplicitCastExprClass:

1056 case Expr::MaterializeTemporaryExprClass:

1058 case Expr::OpaqueValueExprClass:

1060 case Expr::ChooseExprClass:

1062 }

1063}

1064

1067 llvm::raw_svector_ostream out(buffer);

1068 out << name << cnt;

1069 return std::string(out.str());

1070}

1071

1075

1079

1082

1085 return;

1086

1087

1089 cgm.errorNYI(loc, "Cast the dest ptr to the appropriate i8 pointer type");

1090 }

1091

1092

1094 if (size.isZero()) {

1095

1097 cgm.errorNYI(loc,

1098 "emitNullInitialization for zero size VariableArrayType");

1099 } else {

1100 return;

1101 }

1102 }

1103

1104

1105

1106

1107

1108 if (cgm.getTypes().isZeroInitializable(ty)) {

1109 cgm.errorNYI(loc, "type is not zero initializable");

1110 }

1111

1112

1113

1114

1115

1116 const mlir::Value zeroValue = builder.getNullValue(convertType(ty), loc);

1117 builder.createStore(loc, zeroValue, destPtr);

1118}

1119

1120

1123

1124 if (ce->getCastKind() == CK_UncheckedDerivedToBase)

1125 return false;

1126

1128

1129 return false;

1130 }

1131

1132 if (const ImplicitCastExpr *ice = dyn_cast(ce)) {

1133

1134 if (ice->isGLValue())

1135 return false;

1136 }

1137

1138 return true;

1139}

1140

1141

1142

1143mlir::Value

1147

1148

1149

1154 }

1155

1156 uint64_t countFromCLAs = 1;

1158

1159 auto cirArrayType = mlir::dyn_castcir::ArrayType(addr.getElementType());

1160

1161 while (cirArrayType) {

1163 countFromCLAs *= cirArrayType.getSize();

1164 eltType = arrayType->getElementType();

1165

1166 cirArrayType =

1167 mlir::dyn_castcir::ArrayType(cirArrayType.getElementType());

1168

1170 assert((!cirArrayType || arrayType) &&

1171 "CIR and Clang types are out-of-sync");

1172 }

1173

1175

1176

1177

1178 cgm.errorNYI(*currSrcLoc, "length for non-array underlying types");

1179 }

1180

1181 baseType = eltType;

1182 return builder.getConstInt(*currSrcLoc, sizeTy, countFromCLAs);

1183}

1184

1186

1188 return;

1189

1190 mlir::OpBuilder::InsertionGuard guard(builder);

1192 builder.createBlock(builder.getBlock()->getParent(), {}, {voidPtrTy},

1193 {builder.getUnknownLoc()});

1194}

1195

1198 SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue) {

1200 return cir::AssumeAlignedOp::create(builder, getLoc(assumptionLoc), ptrValue,

1201 alignment, offsetValue);

1202}

1203

1206 int64_t alignment, mlir::Value offsetValue) {

1210 offsetValue);

1211}

1212

1215 cgm.getASTContext().getAsVariableArrayType(type);

1216 assert(vla && "type was not a variable array type!");

1218}

1219

1222

1223 mlir::Value numElements;

1224

1226 do {

1227 elementType = type->getElementType();

1228 mlir::Value vlaSize = vlaSizeMap[type->getSizeExpr()];

1229 assert(vlaSize && "no size for VLA!");

1230 assert(vlaSize.getType() == sizeTy);

1231

1232 if (!numElements) {

1233 numElements = vlaSize;

1234 } else {

1235

1236

1237

1238 numElements =

1239 builder.createMul(numElements.getLoc(), numElements, vlaSize,

1241 }

1242 } while ((type = getContext().getAsVariableArrayType(elementType)));

1243

1244 assert(numElements && "Undefined elements number");

1245 return {numElements, elementType};

1246}

1247

1251 assert(vlaSize && "no size for VLA!");

1252 assert(vlaSize.getType() == sizeTy);

1254}

1255

1256

1257

1259 assert(type->isVariablyModifiedType() &&

1260 "Must pass variably modified type to EmitVLASizes!");

1261

1262

1263

1264 do {

1265 assert(type->isVariablyModifiedType());

1266

1267 const Type *ty = type.getTypePtr();

1269 case Type::CountAttributed:

1270 case Type::PackIndexing:

1271 case Type::ArrayParameter:

1272 case Type::HLSLAttributedResource:

1273 case Type::HLSLInlineSpirv:

1274 case Type::PredefinedSugar:

1275 cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType");

1276 break;

1277

1278#define TYPE(Class, Base)

1279#define ABSTRACT_TYPE(Class, Base)

1280#define NON_CANONICAL_TYPE(Class, Base)

1281#define DEPENDENT_TYPE(Class, Base) case Type::Class:

1282#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)

1283#include "clang/AST/TypeNodes.inc"

1284 llvm_unreachable(

1285 "dependent type must be resolved before the CIR codegen");

1286

1287

1288 case Type::Builtin:

1289 case Type::Complex:

1290 case Type::Vector:

1291 case Type::ExtVector:

1292 case Type::ConstantMatrix:

1293 case Type::Record:

1294 case Type::Enum:

1295 case Type::Using:

1296 case Type::TemplateSpecialization:

1297 case Type::ObjCTypeParam:

1298 case Type::ObjCObject:

1299 case Type::ObjCInterface:

1300 case Type::ObjCObjectPointer:

1301 case Type::BitInt:

1302 llvm_unreachable("type class is never variably-modified!");

1303

1304 case Type::Adjusted:

1306 break;

1307

1308 case Type::Decayed:

1310 break;

1311

1312 case Type::Pointer:

1314 break;

1315

1316 case Type::BlockPointer:

1318 break;

1319

1320 case Type::LValueReference:

1321 case Type::RValueReference:

1323 break;

1324

1325 case Type::MemberPointer:

1327 break;

1328

1329 case Type::ConstantArray:

1330 case Type::IncompleteArray:

1331

1333 break;

1334

1335 case Type::VariableArray: {

1336

1338

1339

1340

1342

1343

1344 mlir::Value &entry = vlaSizeMap[sizeExpr];

1345 if (!entry) {

1348

1349

1350

1351

1352 entry = builder.createIntCast(size, sizeTy);

1353 }

1354 }

1356 break;

1357 }

1358

1359 case Type::FunctionProto:

1360 case Type::FunctionNoProto:

1362 break;

1363

1364 case Type::Paren:

1365 case Type::TypeOf:

1366 case Type::UnaryTransform:

1367 case Type::Attributed:

1368 case Type::BTFTagAttributed:

1369 case Type::SubstTemplateTypeParm:

1370 case Type::MacroQualified:

1371

1373 break;

1374

1375 case Type::Typedef:

1376 case Type::Decltype:

1377 case Type::Auto:

1378 case Type::DeducedTemplateSpecialization:

1379

1380 return;

1381

1382 case Type::TypeOfExpr:

1383

1385 return;

1386

1387 case Type::Atomic:

1389 break;

1390

1391 case Type::Pipe:

1393 break;

1394 }

1395 } while (type->isVariablyModifiedType());

1396}

1397

1399 if (getContext().getBuiltinVaListType()->isArrayType())

1402}

1403

1404}

Defines the clang::Expr interface and subclasses for C++ expressions.

__device__ __2f16 float __ockl_bool s

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

SourceManager & getSourceManager()

CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const

Return a conservative estimate of the alignment of the specified decl D.

const ArrayType * getAsArrayType(QualType T) const

Type Query functions.

CharUnits getTypeSizeInChars(QualType T) const

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

Represents an array type, per C99 6.7.5.2 - Array Declarators.

QualType getElementType() const

mlir::Type getElementType() const

mlir::Value createFloatingCast(mlir::Value v, mlir::Type destType)

Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.

void forceCleanup()

Force the emission of cleanups now, instead of waiting until this object is destroyed.

static bool isConstructorDelegationValid(const clang::CXXConstructorDecl *ctor)

Checks whether the given constructor is a valid subject for the complete-to-base constructor delegati...

void emitFunctionProlog(const FunctionArgList &args, mlir::Block *entryBB, const FunctionDecl *fd, SourceLocation bodyBeginLoc)

Emit the function prologue: declare function arguments in the symbol table.

Definition CIRGenFunction.cpp:446

mlir::Type convertType(clang::QualType t)

Definition CIRGenFunction.cpp:100

LValue emitOpaqueValueLValue(const OpaqueValueExpr *e)

static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)

Return the cir::TypeEvaluationKind of QualType type.

Definition CIRGenFunction.cpp:37

clang::GlobalDecl curGD

The GlobalDecl for the current function being compiled or the global variable currently being initial...

EHScopeStack::stable_iterator prologueCleanupDepth

The cleanup depth enclosing all the cleanups associated with the parameters.

cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)

Definition CIRGenFunction.cpp:664

Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)

Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...

void emitVariablyModifiedType(QualType ty)

Definition CIRGenFunction.cpp:1258

RValue emitLoadOfLValue(LValue lv, SourceLocation loc)

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

const clang::LangOptions & getLangOpts() const

mlir::Value cxxStructorImplicitParamValue

~CIRGenFunction()

Definition CIRGenFunction.cpp:34

VlaSizePair getVLASize(const VariableArrayType *type)

Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...

Definition CIRGenFunction.cpp:1221

LValue makeNaturalAlignPointeeAddrLValue(mlir::Value v, clang::QualType t)

Given a value of type T* that may not be to a complete object, construct an l-vlaue withi the natural...

Definition CIRGenFunction.cpp:938

LValue emitMemberExpr(const MemberExpr *e)

const TargetInfo & getTarget() const

LValue emitConditionalOperatorLValue(const AbstractConditionalOperator *expr)

LValue emitLValue(const clang::Expr *e)

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

Definition CIRGenFunction.cpp:988

const clang::Decl * curFuncDecl

Address loadCXXThisAddress()

LValue emitLValueForLambdaField(const FieldDecl *field)

std::string getCounterRefTmpAsString()

Definition CIRGenFunction.cpp:1072

LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)

Definition CIRGenFunction.cpp:948

llvm::DenseMap< const Expr *, mlir::Value > vlaSizeMap

bool constantFoldsToSimpleInteger(const clang::Expr *cond, llvm::APSInt &resultInt, bool allowLabels=false)

If the specified expression does not fold to a constant, or if it does fold but contains a label,...

Definition CIRGenFunction.cpp:190

LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e)

mlir::Location getLoc(clang::SourceLocation srcLoc)

Helpers to convert Clang's SourceLocation to a MLIR Location.

Definition CIRGenFunction.cpp:104

bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)

If the specified expression does not fold to a constant, or if it does but contains a label,...

Definition CIRGenFunction.cpp:177

void emitDelegateCXXConstructorCall(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, const FunctionArgList &args, clang::SourceLocation loc)

VlaSizePair getVLAElements1D(const VariableArrayType *vla)

Return the number of elements for a single dimension for the given array type.

Definition CIRGenFunction.cpp:1249

mlir::Value emitArrayLength(const clang::ArrayType *arrayType, QualType &baseType, Address &addr)

Computes the length of an array in elements, as well as the base element type and a properly-typed fi...

Definition CIRGenFunction.cpp:1144

void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)

Definition CIRGenFunction.cpp:1080

LValue emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e)

llvm::ScopedHashTableScope< const clang::Decl *, mlir::Value > SymTableScopeTy

mlir::Block * indirectGotoBlock

IndirectBranch - The first time an indirect goto is seen we create a block reserved for the indirect ...

mlir::Operation * curFn

The current function or global initializer that is generated code for.

EHScopeStack ehStack

Tracks function scope overall cleanup handling.

void enterDtorCleanups(const CXXDestructorDecl *dtor, CXXDtorType type)

Enter the cleanups necessary to complete the given phase of destruction for a destructor.

llvm::SmallVector< const ParmVarDecl * > fnArgs

Save Parameter Decl for coroutine.

std::optional< mlir::Value > fnRetAlloca

The compiler-generated variable that holds the return value.

void emitImplicitAssignmentOperatorBody(FunctionArgList &args)

mlir::Type convertTypeForMem(QualType t)

Definition CIRGenFunction.cpp:96

clang::QualType buildFunctionArgList(clang::GlobalDecl gd, FunctionArgList &args)

Definition CIRGenFunction.cpp:957

void emitCtorPrologue(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, FunctionArgList &args)

This routine generates necessary code to initialize base classes and non-static data members belongin...

mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, mlir::Location loc, clang::CharUnits alignment, bool insertIntoFnEntryBlock, mlir::Value arraySize=nullptr)

LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)

Address returnValue

The temporary alloca to hold the return value.

void finishFunction(SourceLocation endLoc)

Definition CIRGenFunction.cpp:613

mlir::LogicalResult emitFunctionBody(const clang::Stmt *body)

Definition CIRGenFunction.cpp:641

std::string getCounterAggTmpAsString()

Definition CIRGenFunction.cpp:1076

LValue emitUnaryOpLValue(const clang::UnaryOperator *e)

clang::FieldDecl * lambdaThisCaptureField

const clang::Decl * curCodeDecl

This is the inner-most code context, which includes blocks.

void emitConstructorBody(FunctionArgList &args)

Definition CIRGenFunction.cpp:782

LValue emitCallExprLValue(const clang::CallExpr *e)

bool haveInsertPoint() const

True if an insertion point is defined.

void finishIndirectBranch()

Definition CIRGenFunction.cpp:596

LValue emitStringLiteralLValue(const StringLiteral *e, llvm::StringRef name=".str")

void resolveBlockAddresses()

Definition CIRGenFunction.cpp:586

mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)

Emit the computation of the specified expression of scalar type.

bool shouldNullCheckClassCastValue(const CastExpr *ce)

Definition CIRGenFunction.cpp:1121

CIRGenBuilderTy & getBuilder()

bool didCallStackSave

Whether a cir.stacksave operation has been added.

LValue emitBinaryOperatorLValue(const BinaryOperator *e)

void startFunction(clang::GlobalDecl gd, clang::QualType returnType, cir::FuncOp fn, cir::FuncType funcType, FunctionArgList args, clang::SourceLocation loc, clang::SourceLocation startLoc)

Emit code for the start of a function.

Definition CIRGenFunction.cpp:487

CIRGenModule & getCIRGenModule()

unsigned counterRefTmp

Hold counters for incrementally naming temporaries.

mlir::MLIRContext & getMLIRContext()

void emitDestructorBody(FunctionArgList &args)

Emits the body of the current destructor.

Definition CIRGenFunction.cpp:827

LValue emitCastLValue(const CastExpr *e)

Casts are never lvalues unless that cast is to a reference type.

bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)

Return true if the statement contains a label in it.

Definition CIRGenFunction.cpp:142

LValue emitDeclRefLValue(const clang::DeclRefExpr *e)

llvm::DenseMap< const clang::ValueDecl *, clang::FieldDecl * > lambdaCaptureFields

mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty, SourceLocation loc, SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue=nullptr)

Definition CIRGenFunction.cpp:1196

LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)

LValue emitPredefinedLValue(const PredefinedExpr *e)

void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)

void emitLambdaStaticInvokeBody(const CXXMethodDecl *md)

void instantiateIndirectGotoBlock()

Definition CIRGenFunction.cpp:1185

CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder, bool suppressNewContext=false)

Definition CIRGenFunction.cpp:28

std::optional< mlir::Location > currSrcLoc

Use to track source locations across nested visitor traversals.

LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e)

LValue emitExtVectorElementExpr(const ExtVectorElementExpr *e)

clang::ASTContext & getContext() const

void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr)

Set the address of a local variable.

mlir::Value cxxabiThisValue

mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})

void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth)

Takes the old cleanup stack size and emits the cleanup blocks that have been added.

Address emitVAListRef(const Expr *e)

Build a "reference" to a va_list; this is either the address or the value of the expression,...

Definition CIRGenFunction.cpp:1398

mlir::LogicalResult emitCompoundStmtWithoutScope(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())

void emitIgnoredExpr(const clang::Expr *e)

Emit code to compute the specified expression, ignoring the result.

LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e)

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

DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)

Helpers to emit "not yet implemented" error diagnostics.

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

Address getAddress() const

mlir::Value getPointer() const

mlir::Value getValue() const

Return the value of this scalar value.

Represents a C++ destructor within a class.

const CXXRecordDecl * getParent() const

Return the parent of this method declaration, which is the class in which this method is defined.

QualType getFunctionObjectParameterType() const

bool isAbstract() const

Determine whether this class has a pure virtual function.

bool isEmpty() const

Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).

CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...

CastKind getCastKind() const

CharUnits - This is an opaque type for sizes expressed in character units.

bool isZero() const

isZero - Test whether the quantity equals zero.

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

bool isImplicit() const

isImplicit - Indicates whether the declaration was implicitly generated by the implementation.

Decl * getNonClosureContext()

Find the innermost non-closure ancestor of this declaration, walking up through blocks,...

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 * IgnoreParens() LLVM_READONLY

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

Represents a function declaration or definition.

Stmt * getBody(const FunctionDecl *&Definition) const

Retrieve the body (definition) of the function.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

FunctionDecl * getPreviousDecl()

Return the previous declaration of this declaration or NULL if this is the first declaration.

GlobalDecl - represents a global declaration.

const Decl * getDecl() const

ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...

Represents an unpacked "presumed" location which can be presented to the user.

unsigned getColumn() const

Return the presumed column number of this location.

const char * getFilename() const

Return the presumed filename of this location.

unsigned getLine() const

Return the presumed line number of this location.

A (possibly-)qualified type.

bool isTriviallyCopyableType(const ASTContext &Context) const

Return true if this is a trivially copyable type (C++0x [basic.types]p9)

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

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

PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const

Returns the "presumed" location of a SourceLocation specifies.

A trivial tuple used to represent a source range.

SourceLocation getEnd() const

SourceLocation getBegin() const

Stmt - This represents one statement.

StmtClass getStmtClass() const

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

const char * getStmtClassName() const

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isAnyComplexType() const

TypeClass getTypeClass() const

const T * getAs() const

Member-template getAs'.

Represents a variable declaration or definition.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

Represents a C array with a specified size that is not an integer-constant-expression.

Expr * getSizeExpr() const

@ Type

The l-value was considered opaque, so the alignment was determined from a type.

@ Decl

The l-value was an access to a declared entity or something equivalently strong, like the address of ...

static std::string getVersionedTmpName(llvm::StringRef name, unsigned cnt)

Definition CIRGenFunction.cpp:1065

static bool mayDropFunctionReturn(const ASTContext &astContext, QualType returnType)

Definition CIRGenFunction.cpp:375

static mlir::Value emitArgumentDemotion(CIRGenFunction &cgf, const VarDecl *var, mlir::Value value)

An argument came in as a promoted argument; demote it back to its declared type.

Definition CIRGenFunction.cpp:428

static void eraseEmptyAndUnusedBlocks(cir::FuncOp func)

Definition CIRGenFunction.cpp:651

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

const AstTypeMatcher< ArrayType > arrayType

const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr

Matches expressions.

CXXCtorType

C++ constructor types.

@ Ctor_Base

Base object ctor.

@ Ctor_Complete

Complete object ctor.

bool isa(CodeGen::Address addr)

CXXDtorType

C++ destructor types.

@ Dtor_VectorDeleting

Vector deleting dtor.

@ Dtor_Comdat

The COMDAT used for dtors.

@ Dtor_Unified

GCC-style unified dtor.

@ Dtor_Base

Base object dtor.

@ Dtor_Complete

Complete object dtor.

@ Dtor_Deleting

Deleting dtor.

U cast(CodeGen::Address addr)

static bool vtableInitialization()

static bool constructABIArgDirectExtend()

static bool coroEndBuiltinCall()

static bool runCleanupsScope()

static bool emitTypeCheck()

static bool generateDebugInfo()

static bool cleanupWithPreservedValues()

static bool incrementProfileCounter()

Represents a scope, including function bodies, compound statements, and the substatements of if/while...

llvm::ArrayRef< mlir::Block * > getRetBlocks()

LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)

void cleanup()

Definition CIRGenFunction.cpp:234

mlir::Block * getCleanupBlock(mlir::OpBuilder &builder)

cir::TryOp getClosestTryParent()

Definition CIRGenFunction.cpp:416

mlir::Location getRetLoc(mlir::Block *b)

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

APValue Val

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