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

1

2

3

4

5

6

7

8

9

10

11

12

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

19#include "mlir/IR/BuiltinAttributeInterfaces.h"

20#include "mlir/IR/BuiltinAttributes.h"

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

33#include "llvm/ADT/STLExtras.h"

34#include "llvm/Support/ErrorHandling.h"

35#include

36#include

37

38using namespace clang;

40

41

42

43

44

45namespace {

46class ConstExprEmitter;

47

49 mlir::Type eltTy = cgm.uCharTy;

54 return bld.getConstArray(mlir::ArrayAttr::get(bld.getContext(), elts),

55 cir::ArrayType::get(eltTy, arSize));

56 }

57

58 return cir::ZeroAttr::get(eltTy);

59}

60

61static mlir::Attribute

62emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,

63 mlir::Type commonElementType, unsigned arrayBound,

65 mlir::TypedAttr filler);

66

67struct ConstantAggregateBuilderUtils {

68 CIRGenModule &cgm;

69 cir::CIRDataLayout dataLayout;

70

71 ConstantAggregateBuilderUtils(CIRGenModule &cgm)

72 : cgm(cgm), dataLayout{cgm.getModule()} {}

73

74 CharUnits getAlignment(const mlir::TypedAttr c) const {

76 dataLayout.getAlignment(c.getType(), true));

77 }

78

79 CharUnits getSize(mlir::Type ty) const {

81 }

82

83 CharUnits getSize(const mlir::TypedAttr c) const {

84 return getSize(c.getType());

85 }

86

87 mlir::TypedAttr getPadding(CharUnits size) const {

88 return computePadding(cgm, size);

89 }

90};

91

92

93

94class ConstantAggregateBuilder : private ConstantAggregateBuilderUtils {

95 struct Element {

96 Element(mlir::TypedAttr element, CharUnits offset)

97 : element(element), offset(offset) {}

98

99 mlir::TypedAttr element;

100

101 CharUnits offset;

102 };

103

104

105

106

107

108

109

110 llvm::SmallVector<Element, 32> elements;

111

112

113

114

116

117

118

119 bool naturalLayout = true;

120

121 bool split(size_t index, CharUnits hint);

122 std::optional<size_t> splitAt(CharUnits pos);

123

124 static mlir::Attribute buildFrom(CIRGenModule &cgm, ArrayRef elems,

125 CharUnits startOffset, CharUnits size,

126 bool naturalLayout, mlir::Type desiredTy,

127 bool allowOversized);

128

129public:

130 ConstantAggregateBuilder(CIRGenModule &cgm)

131 : ConstantAggregateBuilderUtils(cgm) {}

132

133

134

135

136

137

138 bool add(mlir::TypedAttr typedAttr, CharUnits offset, bool allowOverwrite);

139

140

141 bool addBits(llvm::APInt bits, uint64_t offsetInBits, bool allowOverwrite);

142

143

144

145 void condense(CharUnits offset, mlir::Type desiredTy);

146

147

148

149

150

151

152 mlir::Attribute build(mlir::Type desiredTy, bool allowOversized) const {

153 return buildFrom(cgm, elements, CharUnits::Zero(), size, naturalLayout,

154 desiredTy, allowOversized);

155 }

156};

157

158template <typename Container, typename Range = std::initializer_list<

159 typename Container::value_type>>

160static void replace(Container &c, size_t beginOff, size_t endOff, Range vals) {

161 assert(beginOff <= endOff && "invalid replacement range");

162 llvm::replace(c, c.begin() + beginOff, c.begin() + endOff, vals);

163}

164

165bool ConstantAggregateBuilder::add(mlir::TypedAttr typedAttr, CharUnits offset,

166 bool allowOverwrite) {

167

168 if (offset >= size) {

169 CharUnits align = getAlignment(typedAttr);

170 CharUnits alignedSize = size.alignTo(align);

171 if (alignedSize > offset || offset.alignTo(align) != offset) {

172 naturalLayout = false;

173 } else if (alignedSize < offset) {

174 elements.emplace_back(getPadding(offset - size), size);

175 }

176 elements.emplace_back(typedAttr, offset);

177 size = offset + getSize(typedAttr);

178 return true;

179 }

180

181

182 std::optional<size_t> firstElemToReplace = splitAt(offset);

183 if (!firstElemToReplace)

184 return false;

185

186 CharUnits cSize = getSize(typedAttr);

187 std::optional<size_t> lastElemToReplace = splitAt(offset + cSize);

188 if (!lastElemToReplace)

189 return false;

190

191 assert((firstElemToReplace == lastElemToReplace || allowOverwrite) &&

192 "unexpectedly overwriting field");

193

194 Element newElt(typedAttr, offset);

195 replace(elements, *firstElemToReplace, *lastElemToReplace, {newElt});

196 size = std::max(size, offset + cSize);

197 naturalLayout = false;

198 return true;

199}

200

201bool ConstantAggregateBuilder::addBits(llvm::APInt bits, uint64_t offsetInBits,

202 bool allowOverwrite) {

203 const ASTContext &astContext = cgm.getASTContext();

206

207

208

209 unsigned offsetWithinChar = offsetInBits % charWidth;

210

211

212

213 for (CharUnits offsetInChars =

215 ; ++offsetInChars) {

216

217 unsigned wantedBits =

218 std::min((uint64_t)bits.getBitWidth(), charWidth - offsetWithinChar);

219

220

221

222 llvm::APInt bitsThisChar = bits;

223 if (bitsThisChar.getBitWidth() < charWidth)

224 bitsThisChar = bitsThisChar.zext(charWidth);

226

227

228 int shift = bits.getBitWidth() - charWidth + offsetWithinChar;

229 if (shift > 0)

230 bitsThisChar.lshrInPlace(shift);

231 else if (shift < 0)

232 bitsThisChar = bitsThisChar.shl(-shift);

233 } else {

234 bitsThisChar = bitsThisChar.shl(offsetWithinChar);

235 }

236 if (bitsThisChar.getBitWidth() > charWidth)

237 bitsThisChar = bitsThisChar.trunc(charWidth);

238

239 if (wantedBits == charWidth) {

240

241 add(cir::IntAttr::get(charTy, bitsThisChar), offsetInChars,

242 allowOverwrite);

243 } else {

244

245

246

247 std::optional<size_t> firstElemToUpdate = splitAt(offsetInChars);

248 if (!firstElemToUpdate)

249 return false;

250 std::optional<size_t> lastElemToUpdate =

252 if (!lastElemToUpdate)

253 return false;

254 assert(*lastElemToUpdate - *firstElemToUpdate < 2 &&

255 "should have at most one element covering one byte");

256

257

258 llvm::APInt updateMask(charWidth, 0);

260 updateMask.setBits(charWidth - offsetWithinChar - wantedBits,

261 charWidth - offsetWithinChar);

262 else

263 updateMask.setBits(offsetWithinChar, offsetWithinChar + wantedBits);

264 bitsThisChar &= updateMask;

265 bool isNull = false;

266 if (*firstElemToUpdate < elements.size()) {

267 auto firstEltToUpdate =

268 mlir::dyn_castcir::IntAttr(elements[*firstElemToUpdate].element);

269 isNull = firstEltToUpdate && firstEltToUpdate.isNullValue();

270 }

271

272 if (*firstElemToUpdate == *lastElemToUpdate || isNull) {

273

274 add(cir::IntAttr::get(charTy, bitsThisChar), offsetInChars,

275 true);

276 } else {

277 cir::IntAttr ci =

278 mlir::dyn_castcir::IntAttr(elements[*firstElemToUpdate].element);

279

280

281 if (!ci)

282 return false;

283

284

285 assert(ci.getBitWidth() == charWidth && "splitAt failed");

286 assert((!(ci.getValue() & updateMask) || allowOverwrite) &&

287 "unexpectedly overwriting bitfield");

288 bitsThisChar |= (ci.getValue() & ~updateMask);

289 elements[*firstElemToUpdate].element =

290 cir::IntAttr::get(charTy, bitsThisChar);

291 }

292 }

293

294

295 if (wantedBits == bits.getBitWidth())

296 break;

297

298

300 bits.lshrInPlace(wantedBits);

301 bits = bits.trunc(bits.getBitWidth() - wantedBits);

302

303

304 offsetWithinChar = 0;

305 }

306

307 return true;

308}

309

310

311

312

313

314std::optional<size_t> ConstantAggregateBuilder::splitAt(CharUnits pos) {

315 if (pos >= size)

316 return elements.size();

317

318 while (true) {

319

320 Element *iter =

321 llvm::upper_bound(elements, pos, [](CharUnits pos, const Element &elt) {

322 return pos < elt.offset;

323 });

324

325 if (iter == elements.begin())

326 return 0;

327

328 size_t index = iter - elements.begin() - 1;

329 const Element &elt = elements[index];

330

331

332 if (elt.offset == pos)

333 return index;

334

335

336 CharUnits eltEnd = elt.offset + getSize(elt.element);

337 if (eltEnd <= pos)

338 return index + 1;

339

340

341 if (!split(index, pos))

342 return std::nullopt;

343 }

344}

345

346

347

348

349bool ConstantAggregateBuilder::split(size_t index, CharUnits hint) {

350 cgm.errorNYI("split constant at index");

351 return false;

352}

353

354void ConstantAggregateBuilder::condense(CharUnits offset,

355 mlir::Type desiredTy) {

356 CharUnits desiredSize = getSize(desiredTy);

357

358 std::optional<size_t> firstElemToReplace = splitAt(offset);

359 if (!firstElemToReplace)

360 return;

361 size_t first = *firstElemToReplace;

362

363 std::optional<size_t> lastElemToReplace = splitAt(offset + desiredSize);

364 if (!lastElemToReplace)

365 return;

366 size_t last = *lastElemToReplace;

367

368 size_t length = last - first;

370 return;

371

372 if (length == 1 && elements[first].offset == offset &&

373 getSize(elements[first].element) == desiredSize) {

374 cgm.errorNYI("re-wrapping single element records");

375 return;

376 }

377

378

379 SmallVector subElems(elements.begin() + first,

380 elements.begin() + last);

381 mlir::Attribute replacement =

382 buildFrom(cgm, subElems, offset, desiredSize,

383 false, desiredTy, false);

384

385

386 Element newElt(mlir::castmlir::TypedAttr(replacement), offset);

387 replace(elements, first, last, {newElt});

388}

389

390mlir::Attribute

391ConstantAggregateBuilder::buildFrom(CIRGenModule &cgm, ArrayRef elems,

392 CharUnits startOffset, CharUnits size,

393 bool naturalLayout, mlir::Type desiredTy,

394 bool allowOversized) {

395 ConstantAggregateBuilderUtils utils(cgm);

396

397 if (elems.empty())

398 return cir::UndefAttr::get(desiredTy);

399

400

401

402 if (mlir::isacir::ArrayType(desiredTy)) {

403 cgm.errorNYI("array aggregate constants");

404 return {};

405 }

406

407

408

409

410 CharUnits desiredSize = utils.getSize(desiredTy);

411 if (size > desiredSize) {

412 assert(allowOversized && "elems are oversized");

413 desiredSize = size;

414 }

415

416

418 for (auto [e, offset] : elems)

419 align = std::max(align, utils.getAlignment(e));

420

421

422 CharUnits alignedSize = size.alignTo(align);

423

424 bool packed = false;

425 bool padded = false;

426

427 llvm::SmallVector<mlir::Attribute, 32> unpackedElems;

428 if (desiredSize < alignedSize || desiredSize.alignTo(align) != desiredSize) {

429 naturalLayout = false;

430 packed = true;

431 } else {

432

433

434 unpackedElems.reserve(elems.size() + 1);

435 llvm::transform(elems, std::back_inserter(unpackedElems),

436 std::mem_fn(&Element::element));

437 if (desiredSize > alignedSize)

438 unpackedElems.push_back(utils.getPadding(desiredSize - size));

439 }

440

441

442

443

444 llvm::SmallVector<mlir::Attribute, 32> packedElems;

445 packedElems.reserve(elems.size());

446 if (!naturalLayout) {

448 for (auto [element, offset] : elems) {

449 CharUnits align = utils.getAlignment(element);

450 CharUnits naturalOffset = sizeSoFar.alignTo(align);

451 CharUnits desiredOffset = offset - startOffset;

452 assert(desiredOffset >= sizeSoFar && "elements out of order");

453

454 if (desiredOffset != naturalOffset)

455 packed = true;

456 if (desiredOffset != sizeSoFar)

457 packedElems.push_back(utils.getPadding(desiredOffset - sizeSoFar));

458 packedElems.push_back(element);

459 sizeSoFar = desiredOffset + utils.getSize(element);

460 }

461

462

463 if (packed) {

464 assert(sizeSoFar <= desiredSize &&

465 "requested size is too small for contents");

466

467 if (sizeSoFar < desiredSize)

468 packedElems.push_back(utils.getPadding(desiredSize - sizeSoFar));

469 }

470 }

471

472 CIRGenBuilderTy &builder = cgm.getBuilder();

473 auto arrAttr = mlir::ArrayAttr::get(builder.getContext(),

474 packed ? packedElems : unpackedElems);

475

477 if (auto desired = mlir::dyn_castcir::RecordType(desiredTy))

478 if (desired.isLayoutIdentical(recordType))

480

482}

483

484

485

486

487

488class ConstRecordBuilder {

489 CIRGenModule &cgm;

490 ConstantEmitter &emitter;

491 ConstantAggregateBuilder &builder;

492 CharUnits startOffset;

493

494public:

495 static mlir::Attribute buildRecord(ConstantEmitter &emitter,

496 InitListExpr *ile, QualType valTy);

497 static mlir::Attribute buildRecord(ConstantEmitter &emitter,

498 const APValue &value, QualType valTy);

499 static bool updateRecord(ConstantEmitter &emitter,

500 ConstantAggregateBuilder &constant, CharUnits offset,

501 InitListExpr *updater);

502

503private:

504 ConstRecordBuilder(ConstantEmitter &emitter,

505 ConstantAggregateBuilder &builder, CharUnits startOffset)

506 : cgm(emitter.cgm), emitter(emitter), builder(builder),

507 startOffset(startOffset) {}

508

509 bool appendField(const FieldDecl *field, uint64_t fieldOffset,

510 mlir::TypedAttr initCst, bool allowOverwrite = false);

511

512 bool appendBytes(CharUnits fieldOffsetInChars, mlir::TypedAttr initCst,

513 bool allowOverwrite = false);

514

515 bool appendBitField(const FieldDecl *field, uint64_t fieldOffset,

516 cir::IntAttr ci, bool allowOverwrite = false);

517

518

519

520

521

522

523

524

525

526 bool applyZeroInitPadding(const ASTRecordLayout &layout, unsigned fieldNo,

527 const FieldDecl &field, bool allowOverwrite,

528 CharUnits &sizeSoFar, bool &zeroFieldSize);

529

530

531

532

533

534

535 bool applyZeroInitPadding(const ASTRecordLayout &layout, bool allowOverwrite,

536 CharUnits &sizeSoFar);

537

538 bool build(InitListExpr *ile, bool allowOverwrite);

539 bool build(const APValue &val, const RecordDecl *rd, bool isPrimaryBase,

540 const CXXRecordDecl *vTableClass, CharUnits baseOffset);

541

542 mlir::Attribute finalize(QualType ty);

543};

544

545bool ConstRecordBuilder::appendField(const FieldDecl *field,

546 uint64_t fieldOffset,

547 mlir::TypedAttr initCst,

548 bool allowOverwrite) {

549 const ASTContext &astContext = cgm.getASTContext();

550

551 CharUnits fieldOffsetInChars = astContext.toCharUnitsFromBits(fieldOffset);

552

553 return appendBytes(fieldOffsetInChars, initCst, allowOverwrite);

554}

555

556bool ConstRecordBuilder::appendBytes(CharUnits fieldOffsetInChars,

557 mlir::TypedAttr initCst,

558 bool allowOverwrite) {

559 return builder.add(initCst, startOffset + fieldOffsetInChars, allowOverwrite);

560}

561

562bool ConstRecordBuilder::appendBitField(const FieldDecl *field,

563 uint64_t fieldOffset, cir::IntAttr ci,

564 bool allowOverwrite) {

565 const CIRGenRecordLayout &rl =

567 const CIRGenBitFieldInfo &info = rl.getBitFieldInfo(field);

568 llvm::APInt fieldValue = ci.getValue();

569

570

571

572

573

574 if (info.size > fieldValue.getBitWidth())

575 fieldValue = fieldValue.zext(info.size);

576

577

578 if (info.size < fieldValue.getBitWidth())

579 fieldValue = fieldValue.trunc(info.size);

580

581 return builder.addBits(fieldValue,

583 allowOverwrite);

584}

585

586bool ConstRecordBuilder::applyZeroInitPadding(

587 const ASTRecordLayout &layout, unsigned fieldNo, const FieldDecl &field,

588 bool allowOverwrite, CharUnits &sizeSoFar, bool &zeroFieldSize) {

590 CharUnits startOffset =

592 if (sizeSoFar < startOffset) {

593 if (!appendBytes(sizeSoFar, computePadding(cgm, startOffset - sizeSoFar),

594 allowOverwrite))

595 return false;

596 }

597

599 CharUnits fieldSize =

601 sizeSoFar = startOffset + fieldSize;

602 zeroFieldSize = fieldSize.isZero();

603 } else {

604 const CIRGenRecordLayout &rl =

606 const CIRGenBitFieldInfo &info = rl.getBitFieldInfo(&field);

607 uint64_t endBitOffset = startBitOffset + info.size;

610 sizeSoFar++;

611 zeroFieldSize = info.size == 0;

612 }

613 return true;

614}

615

616bool ConstRecordBuilder::applyZeroInitPadding(const ASTRecordLayout &layout,

617 bool allowOverwrite,

618 CharUnits &sizeSoFar) {

619 CharUnits totalSize = layout.getSize();

620 if (sizeSoFar < totalSize) {

621 if (!appendBytes(sizeSoFar, computePadding(cgm, totalSize - sizeSoFar),

622 allowOverwrite))

623 return false;

624 }

625 sizeSoFar = totalSize;

626 return true;

627}

628

629bool ConstRecordBuilder::build(InitListExpr *ile, bool allowOverwrite) {

632

633

634

635

636 if (auto *cxxrd = dyn_cast(rd))

637 if (cxxrd->getNumBases())

638 return false;

639

641 bool zeroFieldSize = false;

643

644 unsigned elementNo = 0;

645 for (auto [index, field] : llvm::enumerate(rd->fields())) {

646

647

650 continue;

651

652

654 continue;

655

656

657

658 Expr *init = nullptr;

659 if (elementNo < ile->getNumInits())

660 init = ile->getInit(elementNo++);

661 if (isa_and_nonnull(init))

662 continue;

663

664

665

668 return false;

669 continue;

670 }

671

672 if (zeroInitPadding &&

673 !applyZeroInitPadding(layout, index, *field, allowOverwrite, sizeSoFar,

674 zeroFieldSize))

675 return false;

676

677

678

679

680 if (allowOverwrite &&

683 return false;

684 }

685

686 mlir::Attribute eltInitAttr =

690 if (!eltInitAttr)

691 return false;

692

693 mlir::TypedAttr eltInit = mlir::castmlir::TypedAttr(eltInitAttr);

695

696 if (!appendField(field, layout.getFieldOffset(index), eltInit,

697 allowOverwrite))

698 return false;

699

700

701 if (field->hasAttr())

702 allowOverwrite = true;

703 } else {

704

705 if (auto constInt = dyn_castcir::IntAttr(eltInit)) {

706 if (!appendBitField(field, layout.getFieldOffset(index), constInt,

707 allowOverwrite))

708 return false;

709 } else {

710

711

712 return false;

713 }

714 }

715 }

716

717 return !zeroInitPadding ||

718 applyZeroInitPadding(layout, allowOverwrite, sizeSoFar);

719}

720

721namespace {

722struct BaseInfo {

723 BaseInfo(const CXXRecordDecl *decl, CharUnits offset, unsigned index)

724 : decl(decl), offset(offset), index(index) {}

725

726 const CXXRecordDecl *decl;

727 CharUnits offset;

728 unsigned index;

729

730 bool operator<(const BaseInfo &o) const { return offset < o.offset; }

731};

732}

733

734bool ConstRecordBuilder::build(const APValue &val, const RecordDecl *rd,

735 bool isPrimaryBase,

736 const CXXRecordDecl *vTableClass,

737 CharUnits offset) {

739 if (const CXXRecordDecl *cd = dyn_cast(rd)) {

740

742 CIRGenBuilderTy &builder = cgm.getBuilder();

743 cir::GlobalOp vtable =

745 clang::VTableLayout::AddressPointLocation addressPoint =

750 mlir::ArrayAttr indices = builder.getArrayAttr({

751 builder.getI32IntegerAttr(addressPoint.VTableIndex),

753 });

754 cir::GlobalViewAttr vtableInit =

756 if (!appendBytes(offset, vtableInit))

757 return false;

758 }

759

760

761

762 SmallVector bases;

763 bases.reserve(cd->getNumBases());

764 for (auto [index, base] : llvm::enumerate(cd->bases())) {

765 assert(!base.isVirtual() && "should not have virtual bases here");

766 const CXXRecordDecl *bd = base.getType()->getAsCXXRecordDecl();

768 bases.push_back(BaseInfo(bd, baseOffset, index));

769 }

770#ifdef EXPENSIVE_CHECKS

771 assert(llvm::is_sorted(bases) && "bases not sorted by offset");

772#endif

773

774 for (BaseInfo &base : bases) {

775 bool isPrimaryBase = layout.getPrimaryBase() == base.decl;

776 build(val.getStructBase(base.index), base.decl, isPrimaryBase,

777 vTableClass, offset + base.offset);

778 }

779 }

780

782

783 bool allowOverwrite = false;

784 for (auto [index, field] : llvm::enumerate(rd->fields())) {

785

787 continue;

788

789

791 continue;

792

793

794 const APValue &fieldValue =

796 mlir::TypedAttr eltInit = mlir::castmlir::TypedAttr(

798 if (!eltInit)

799 return false;

800

802

803 if (!appendField(field, layout.getFieldOffset(index) + offsetBits,

804 eltInit, allowOverwrite))

805 return false;

806

807

808 if (field->hasAttr())

809 allowOverwrite = true;

810 } else {

811

812 if (auto constInt = dyn_castcir::IntAttr(eltInit)) {

813 if (!appendBitField(field, layout.getFieldOffset(index) + offsetBits,

814 constInt, allowOverwrite))

815 return false;

816 } else {

817

818

819 return false;

820 }

821 }

822 }

823

824 return true;

825}

826

827mlir::Attribute ConstRecordBuilder::finalize(QualType type) {

828 type = type.getNonReferenceType();

829 RecordDecl *rd =

833}

834

835mlir::Attribute ConstRecordBuilder::buildRecord(ConstantEmitter &emitter,

836 InitListExpr *ile,

837 QualType valTy) {

838 ConstantAggregateBuilder constant(emitter.cgm);

839 ConstRecordBuilder builder(emitter, constant, CharUnits::Zero());

840

841 if (!builder.build(ile, false))

842 return nullptr;

843

844 return builder.finalize(valTy);

845}

846

847mlir::Attribute ConstRecordBuilder::buildRecord(ConstantEmitter &emitter,

849 QualType valTy) {

850 ConstantAggregateBuilder constant(emitter.cgm);

851 ConstRecordBuilder builder(emitter, constant, CharUnits::Zero());

852

853 const RecordDecl *rd =

854 valTy->castAsclang::RecordType()->getDecl()->getDefinitionOrSelf();

855 const CXXRecordDecl *cd = dyn_cast(rd);

856 if (!builder.build(val, rd, false, cd, CharUnits::Zero()))

857 return nullptr;

858

859 return builder.finalize(valTy);

860}

861

862bool ConstRecordBuilder::updateRecord(ConstantEmitter &emitter,

863 ConstantAggregateBuilder &constant,

864 CharUnits offset, InitListExpr *updater) {

865 return ConstRecordBuilder(emitter, constant, offset)

866 .build(updater, true);

867}

868

869

870

871

872

873

874

875

876

877

878

879

880class ConstExprEmitter

881 : public StmtVisitor<ConstExprEmitter, mlir::Attribute, QualType> {

882 CIRGenModule &cgm;

883 [[maybe_unused]] ConstantEmitter &emitter;

884

885public:

886 ConstExprEmitter(ConstantEmitter &emitter)

887 : cgm(emitter.cgm), emitter(emitter) {}

888

889

890

891

892

893 mlir::Attribute VisitStmt(Stmt *s, QualType t) { return {}; }

894

895 mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {

897 return result;

899 }

900

901 mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {

903 }

904

905 mlir::Attribute

906 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,

907 QualType t) {

909 }

910

911 mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,

912 QualType t) {

914 }

915

916 mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {

918 }

919

920 mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {

922 }

923

924 mlir::Attribute VisitCastExpr(CastExpr *e, QualType destType) {

925 if (const auto *ece = dyn_cast(e))

927 const_cast<CIRGenFunction *>(emitter.cgf));

928

930

932 case CK_ToUnion:

933 case CK_AddressSpaceConversion:

934 case CK_ReinterpretMemberPointer:

935 case CK_DerivedToBaseMemberPointer:

936 case CK_BaseToDerivedMemberPointer:

938 return {};

939

940 case CK_LValueToRValue:

941 case CK_AtomicToNonAtomic:

942 case CK_NonAtomicToAtomic:

943 case CK_NoOp:

944 case CK_ConstructorConversion:

945 return Visit(subExpr, destType);

946

947 case CK_IntToOCLSampler:

948 llvm_unreachable("global sampler variables are not generated");

949

950 case CK_Dependent:

951 llvm_unreachable("saw dependent cast!");

952

953 case CK_BuiltinFnToFnPtr:

954 llvm_unreachable("builtin functions are handled elsewhere");

955

956

957 case CK_ObjCObjectLValueCast:

958 case CK_ARCProduceObject:

959 case CK_ARCConsumeObject:

960 case CK_ARCReclaimReturnedObject:

961 case CK_ARCExtendBlockObject:

962 case CK_CopyAndAutoreleaseBlockObject:

963 return {};

964

965

966

967 case CK_BitCast:

968 case CK_ToVoid:

969 case CK_Dynamic:

970 case CK_LValueBitCast:

971 case CK_LValueToRValueBitCast:

972 case CK_NullToMemberPointer:

973 case CK_UserDefinedConversion:

974 case CK_CPointerToObjCPointerCast:

975 case CK_BlockPointerToObjCPointerCast:

976 case CK_AnyPointerToBlockPointerCast:

977 case CK_ArrayToPointerDecay:

978 case CK_FunctionToPointerDecay:

979 case CK_BaseToDerived:

980 case CK_DerivedToBase:

981 case CK_UncheckedDerivedToBase:

982 case CK_MemberPointerToBoolean:

983 case CK_VectorSplat:

984 case CK_FloatingRealToComplex:

985 case CK_FloatingComplexToReal:

986 case CK_FloatingComplexToBoolean:

987 case CK_FloatingComplexCast:

988 case CK_FloatingComplexToIntegralComplex:

989 case CK_IntegralRealToComplex:

990 case CK_IntegralComplexToReal:

991 case CK_IntegralComplexToBoolean:

992 case CK_IntegralComplexCast:

993 case CK_IntegralComplexToFloatingComplex:

994 case CK_PointerToIntegral:

995 case CK_PointerToBoolean:

996 case CK_NullToPointer:

997 case CK_IntegralCast:

998 case CK_BooleanToSignedIntegral:

999 case CK_IntegralToPointer:

1000 case CK_IntegralToBoolean:

1001 case CK_IntegralToFloating:

1002 case CK_FloatingToIntegral:

1003 case CK_FloatingToBoolean:

1004 case CK_FloatingCast:

1005 case CK_FloatingToFixedPoint:

1006 case CK_FixedPointToFloating:

1007 case CK_FixedPointCast:

1008 case CK_FixedPointToBoolean:

1009 case CK_FixedPointToIntegral:

1010 case CK_IntegralToFixedPoint:

1011 case CK_ZeroToOCLOpaqueType:

1012 case CK_MatrixCast:

1013 case CK_HLSLArrayRValue:

1014 case CK_HLSLVectorTruncation:

1015 case CK_HLSLMatrixTruncation:

1016 case CK_HLSLElementwiseCast:

1017 case CK_HLSLAggregateSplatCast:

1018 return {};

1019 }

1020 llvm_unreachable("Invalid CastKind");

1021 }

1022

1023 mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {

1024

1025

1026 return Visit(die->getExpr(), t);

1027 }

1028

1029 mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {

1030

1032 }

1033

1034 mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,

1035 QualType t) {

1037 }

1038

1039 mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *e,

1040 QualType t) {

1042 }

1043

1044 mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {

1046 return Visit(ile->getInit(0), t);

1047

1049

1050

1052 return {};

1053 }

1054

1056 return ConstRecordBuilder::buildRecord(emitter, ile, t);

1057 }

1058

1060

1061

1063 return {};

1064 }

1065

1066 return {};

1067 }

1068

1069 mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,

1070 QualType destType) {

1071 mlir::Attribute c = Visit(e->getBase(), destType);

1072 if (c)

1073 return {};

1074

1076 "ConstExprEmitter::VisitDesignatedInitUpdateExpr");

1077 return {};

1078 }

1079

1080 mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {

1082 return {};

1083

1084

1086 assert(e->getNumArgs() == 1 && "trivial ctor with > 1 argument");

1088 "trivial ctor has argument but isn't a copy/move ctor");

1089

1092 "argument to copy ctor is of wrong type");

1093

1094

1095

1096 if (auto const *mte = dyn_cast(arg))

1097 return Visit(mte->getSubExpr(), ty);

1098

1099

1100

1102

1103

1104 return {};

1105 }

1106

1108 }

1109

1110 mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {

1111

1113 }

1114

1115 mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {

1116 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitObjCEncodeExpr");

1117 return {};

1118 }

1119

1120 mlir::Attribute VisitUnaryExtension(const UnaryOperator *e, QualType t) {

1122 }

1123

1124

1125 mlir::Type convertType(QualType t) { return cgm.convertType(t); }

1126};

1127

1128

1130 if (const auto *at = type->getAs()) {

1132 type.getQualifiers());

1133 }

1134 return type;

1135}

1136

1137static mlir::Attribute

1138emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,

1139 mlir::Type commonElementType, unsigned arrayBound,

1140 SmallVectorImplmlir::TypedAttr &elements,

1141 mlir::TypedAttr filler) {

1142 CIRGenBuilderTy &builder = cgm.getBuilder();

1143

1144 unsigned nonzeroLength = arrayBound;

1145 if (elements.size() < nonzeroLength && builder.isNullValue(filler))

1146 nonzeroLength = elements.size();

1147

1148 if (nonzeroLength == elements.size()) {

1149 while (nonzeroLength > 0 &&

1150 builder.isNullValue(elements[nonzeroLength - 1]))

1151 --nonzeroLength;

1152 }

1153

1154 if (nonzeroLength == 0)

1155 return cir::ZeroAttr::get(desiredType);

1156

1157 const unsigned trailingZeroes = arrayBound - nonzeroLength;

1158

1159

1160 if (trailingZeroes >= 8) {

1161 assert(elements.size() >= nonzeroLength &&

1162 "missing initializer for non-zero element");

1163

1164 if (commonElementType && nonzeroLength >= 8) {

1165

1166

1167

1168 SmallVectormlir::Attribute eles;

1169 eles.reserve(nonzeroLength);

1170 for (const auto &element : elements)

1171 eles.push_back(element);

1172 auto initial = cir::ConstArrayAttr::get(

1173 cir::ArrayType::get(commonElementType, nonzeroLength),

1174 mlir::ArrayAttr::get(builder.getContext(), eles));

1175 elements.resize(2);

1176 elements[0] = initial;

1177 } else {

1178

1179

1180 elements.resize(nonzeroLength + 1);

1181 }

1182

1183 mlir::Type fillerType =

1184 commonElementType

1185 ? commonElementType

1186 : mlir::castcir::ArrayType(desiredType).getElementType();

1187 fillerType = cir::ArrayType::get(fillerType, trailingZeroes);

1188 elements.back() = cir::ZeroAttr::get(fillerType);

1189 commonElementType = nullptr;

1190 } else if (elements.size() != arrayBound) {

1191 elements.resize(arrayBound, filler);

1192

1193 if (filler.getType() != commonElementType)

1194 commonElementType = {};

1195 }

1196

1197 if (commonElementType) {

1198 SmallVectormlir::Attribute eles;

1199 eles.reserve(elements.size());

1200

1201 for (const auto &element : elements)

1202 eles.push_back(element);

1203

1204 return cir::ConstArrayAttr::get(

1205 cir::ArrayType::get(commonElementType, arrayBound),

1206 mlir::ArrayAttr::get(builder.getContext(), eles));

1207 }

1208

1209 SmallVectormlir::Attribute eles;

1210 eles.reserve(elements.size());

1211 for (auto const &element : elements)

1212 eles.push_back(element);

1213

1214 auto arrAttr = mlir::ArrayAttr::get(builder.getContext(), eles);

1216}

1217

1218}

1219

1220

1221

1222

1223

1224namespace {

1225

1226

1227struct ConstantLValue {

1228 llvm::PointerUnion<mlir::Value, mlir::Attribute> value;

1229 bool hasOffsetApplied;

1230

1231 ConstantLValue(std::nullptr_t)

1232 : value(nullptr), hasOffsetApplied(false) {}

1233 ConstantLValue(cir::GlobalViewAttr address)

1234 : value(address), hasOffsetApplied(false) {}

1235

1236 ConstantLValue() : value(nullptr), hasOffsetApplied(false) {}

1237};

1238

1239

1240class ConstantLValueEmitter

1241 : public ConstStmtVisitor<ConstantLValueEmitter, ConstantLValue> {

1242 CIRGenModule &cgm;

1243 ConstantEmitter &emitter;

1245 QualType destType;

1246

1247

1248 friend StmtVisitorBase;

1249

1250public:

1251 ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,

1252 QualType destType)

1253 : cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}

1254

1255 mlir::Attribute tryEmit();

1256

1257private:

1258 mlir::Attribute tryEmitAbsolute(mlir::Type destTy);

1259 ConstantLValue tryEmitBase(const APValue::LValueBase &base);

1260

1261 ConstantLValue VisitStmt(const Stmt *s) { return nullptr; }

1262 ConstantLValue VisitConstantExpr(const ConstantExpr *e);

1263 ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *e);

1264 ConstantLValue VisitStringLiteral(const StringLiteral *e);

1265 ConstantLValue VisitObjCBoxedExpr(const ObjCBoxedExpr *e);

1266 ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *e);

1267 ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *e);

1268 ConstantLValue VisitPredefinedExpr(const PredefinedExpr *e);

1269 ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *e);

1270 ConstantLValue VisitCallExpr(const CallExpr *e);

1271 ConstantLValue VisitBlockExpr(const BlockExpr *e);

1272 ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *e);

1273 ConstantLValue

1274 VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);

1275

1276

1277 mlir::ArrayAttr getOffset(mlir::Type ty) {

1279 cir::CIRDataLayout layout(cgm.getModule());

1280 SmallVector<int64_t, 3> idxVec;

1282 idxVec);

1283

1284 llvm::SmallVector<mlir::Attribute, 3> indices;

1285 for (int64_t i : idxVec) {

1286 mlir::IntegerAttr intAttr = cgm.getBuilder().getI32IntegerAttr(i);

1287 indices.push_back(intAttr);

1288 }

1289

1290 if (indices.empty())

1291 return {};

1292 return cgm.getBuilder().getArrayAttr(indices);

1293 }

1294

1295

1296 ConstantLValue applyOffset(ConstantLValue &c) {

1297

1298 if (auto attr = mlir::dyn_castmlir::Attribute(c.value)) {

1299 if (auto gv = mlir::dyn_castcir::GlobalViewAttr(attr)) {

1300 auto baseTy = mlir::castcir::PointerType(gv.getType()).getPointee();

1302 assert(!gv.getIndices() && "Global view is already indexed");

1303 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(),

1304 getOffset(baseTy));

1305 }

1306 llvm_unreachable("Unsupported attribute type to offset");

1307 }

1308

1309 cgm.errorNYI("ConstantLValue: non-attribute offset");

1310 return {};

1311 }

1312};

1313

1314}

1315

1316mlir::Attribute ConstantLValueEmitter::tryEmit() {

1317 const APValue::LValueBase &base = value.getLValueBase();

1318

1319

1320

1321

1322

1323

1324

1325

1327 assert(mlir::isacir::PointerType(destTy));

1328

1329

1330

1331 if (!base)

1332 return tryEmitAbsolute(destTy);

1333

1334

1335 ConstantLValue result = tryEmitBase(base);

1336

1337

1338 llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;

1339 if (!value)

1340 return {};

1341

1342

1343 if (!result.hasOffsetApplied)

1344 value = applyOffset(result).value;

1345

1346

1347

1348 if (mlir::isacir::PointerType(destTy)) {

1349 if (auto attr = mlir::dyn_castmlir::Attribute(value))

1350 return attr;

1351 cgm.errorNYI("ConstantLValueEmitter: non-attribute pointer");

1352 return {};

1353 }

1354

1355 cgm.errorNYI("ConstantLValueEmitter: other?");

1356 return {};

1357}

1358

1359

1360

1361mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {

1362

1363 auto destPtrTy = mlir::castcir::PointerType(destTy);

1365 destPtrTy, value.getLValueOffset().getQuantity());

1366}

1367

1368ConstantLValue

1369ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {

1370

1371 if (const ValueDecl *d = base.dyn_cast<const ValueDecl *>()) {

1372

1373

1375

1376 if (d->hasAttr()) {

1377 cgm.errorNYI(d->getSourceRange(),

1378 "ConstantLValueEmitter: emit pointer base for weakref");

1379 return {};

1380 }

1381

1382 if (auto *fd = dyn_cast(d)) {

1384 CIRGenBuilderTy &builder = cgm.getBuilder();

1385 mlir::MLIRContext *mlirContext = builder.getContext();

1386 return cir::GlobalViewAttr::get(

1387 builder.getPointerTo(fop.getFunctionType()),

1388 mlir::FlatSymbolRefAttr::get(mlirContext, fop.getSymNameAttr()));

1389 }

1390

1391 if (auto *vd = dyn_cast(d)) {

1392

1393 if (!vd->hasLocalStorage()) {

1394 if (vd->isFileVarDecl() || vd->hasExternalStorage())

1396

1397 if (vd->isLocalVarDecl()) {

1398 cgm.errorNYI(vd->getSourceRange(),

1399 "ConstantLValueEmitter: local var decl");

1400 return {};

1401 }

1402 }

1403 }

1404

1405

1406

1407

1408

1409 cgm.errorNYI(d->getSourceRange(),

1410 "ConstantLValueEmitter: unhandled value decl");

1411 return {};

1412 }

1413

1414

1415 if (base.dyn_cast()) {

1416 cgm.errorNYI("ConstantLValueEmitter: typeid");

1417 return {};

1418 }

1419

1420

1421 return Visit(base.get<const Expr *>());

1422}

1423

1424ConstantLValue ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *e) {

1426 return {};

1427}

1428

1429ConstantLValue

1430ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *e) {

1432 return {};

1433}

1434

1435ConstantLValue

1436ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *e) {

1438}

1439

1440ConstantLValue

1441ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *e) {

1443 return {};

1444}

1445

1446ConstantLValue

1447ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *e) {

1449 "ConstantLValueEmitter: objc string literal");

1450 return {};

1451}

1452

1453ConstantLValue

1454ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *e) {

1456 return {};

1457}

1458

1459ConstantLValue

1460ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *e) {

1462 return {};

1463}

1464

1465ConstantLValue

1466ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *e) {

1468 return {};

1469}

1470

1471ConstantLValue ConstantLValueEmitter::VisitCallExpr(const CallExpr *e) {

1473 return {};

1474}

1475

1476ConstantLValue ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *e) {

1478 return {};

1479}

1480

1481ConstantLValue

1482ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *e) {

1484 return {};

1485}

1486

1487ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(

1488 const MaterializeTemporaryExpr *e) {

1490 "ConstantLValueEmitter: materialize temporary expr");

1491 return {};

1492}

1493

1494

1495

1496

1497

1499 initializeNonAbstract();

1501}

1502

1504 assert(initializedNonAbstract &&

1505 "finalizing emitter that was used for abstract emission?");

1506 assert(!finalized && "finalizing emitter multiple times");

1507 assert(!gv.isDeclaration());

1508#ifndef NDEBUG

1509

1510 finalized = true;

1511#endif

1512}

1513

1514mlir::Attribute

1516 AbstractStateRAII state(*this, true);

1518}

1519

1521 assert((!initializedNonAbstract || finalized || failed) &&

1522 "not finalized after being initialized for non-abstract emission");

1523}

1524

1526 mlir::Type baseType,

1528

1530 bool asCompleteObject) {

1532 mlir::Type ty = (asCompleteObject ? layout.getCIRType()

1534 auto recordTy = mlir::castcir::RecordType(ty);

1535

1536 unsigned numElements = recordTy.getNumElements();

1538

1539 auto *cxxrd = dyn_cast(rd);

1540

1541 if (cxxrd) {

1543 if (base.isVirtual()) {

1544

1545

1546 continue;

1547 }

1548

1550

1556 continue;

1557

1559 mlir::Type baseType = recordTy.getElementType(fieldIndex);

1561 }

1562 }

1563

1564

1566

1567

1570 unsigned fieldIndex = layout.getCIRFieldNo(field);

1572 }

1573

1574

1577 break;

1579 if (fieldRD->findFirstNamedDataMember())

1580 break;

1581 }

1582 }

1583

1584

1585 if (cxxrd && asCompleteObject) {

1586 for ([[maybe_unused]] const CXXBaseSpecifier &vbase : cxxrd->vbases()) {

1587 cgm.errorNYI(vbase.getSourceRange(), "emitNullConstant: virtual base");

1588 return {};

1589 }

1590 }

1591

1592

1593 for (unsigned i = 0; i != numElements; ++i) {

1594 if (!elements[i]) {

1596 return {};

1597 }

1598 }

1599

1600 mlir::MLIRContext *mlirContext = recordTy.getContext();

1601 return cir::ConstRecordAttr::get(recordTy,

1602 mlir::ArrayAttr::get(mlirContext, elements));

1603}

1604

1605

1607 mlir::Type baseType,

1611

1612

1615

1616

1617 return emitNullConstant(cgm, baseDecl, false);

1618}

1619

1621

1622

1623

1627 if (const auto *e = dyn_cast_or_null(d.getInit())) {

1629

1630

1631

1632

1635 if (cxxrd->getNumBases() != 0) {

1636

1637

1638 cgm.errorNYI("tryEmitPrivateForVarInit: cxx record with bases");

1639 return {};

1640 }

1641 if (cgm.getTypes().isZeroInitializable(cxxrd)) {

1642

1643

1644 cgm.errorNYI(

1645 "tryEmitPrivateForVarInit: non-zero-initializable cxx record");

1646 return {};

1647 }

1648 return cir::ZeroAttr::get(cgm.convertType(d.getType()));

1649 }

1650 }

1651 }

1652 }

1654

1656 assert(e && "No initializer to emit");

1657

1659

1662 if (mlir::Attribute c = ConstExprEmitter(*this).Visit(const_cast<Expr *>(e),

1663 nonMemoryDestType))

1665 }

1666

1667

1668

1671

1672 return {};

1673}

1674

1677 return {};

1678

1681 retType = cgm.getASTContext().getLValueReferenceType(retType);

1682

1684}

1685

1689 mlir::TypedAttr c = tryEmitPrivate(e, nonMemoryDestType);

1690 if (c) {

1692 return mlir::castmlir::TypedAttr(attr);

1693 }

1694 return nullptr;

1695}

1696

1703

1706 AbstractStateRAII state{*this, true};

1707 mlir::Attribute c = mlir::castmlir::Attribute(tryEmitPrivate(e, destType));

1708 if (c)

1710 "emitAbstract failed, emit null constaant");

1711 return c;

1712}

1713

1717 AbstractStateRAII state(*this, true);

1719 if (c)

1720 cgm.errorNYI(loc, "emitAbstract failed, emit null constaant");

1721 return c;

1722}

1723

1727 cir::ConstantOp cstOp =

1728 cgm.emitNullConstant(t, loc).getDefiningOpcir::ConstantOp();

1729 assert(cstOp && "expected cir.const op");

1731}

1732

1735

1737 cgm.errorNYI("emitForMemory: atomic type");

1738 return {};

1739 }

1740

1741 return c;

1742}

1743

1745 mlir::Attribute c,

1747

1749 cgm.errorNYI("atomic constants");

1750 }

1751

1752 return c;

1753}

1754

1757 assert(!destType->isVoidType() && "can't emit a void constant");

1758

1759 if (mlir::Attribute c =

1760 ConstExprEmitter(*this).Visit(const_cast<Expr *>(e), destType))

1761 return llvm::dyn_castmlir::TypedAttr(c);

1762

1764

1765 bool success = false;

1766

1769 else

1770 success =

1772

1775 return llvm::dyn_castmlir::TypedAttr(c);

1776 }

1777

1778 return nullptr;

1779}

1780

1783 auto &builder = cgm.getBuilder();

1784 switch (value.getKind()) {

1787 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate none or indeterminate");

1788 return {};

1790 mlir::Type ty = cgm.convertType(destType);

1791 if (mlir::isacir::BoolType(ty))

1793 assert(mlir::isacir::IntType(ty) && "expected integral type");

1794 return cir::IntAttr::get(ty, value.getInt());

1795 }

1797 const llvm::APFloat &init = value.getFloat();

1798 if (&init.getSemantics() == &llvm::APFloat::IEEEhalf() &&

1799 cgm.getASTContext().getLangOpts().NativeHalfType &&

1800 cgm.getASTContext().getTargetInfo().useFP16ConversionIntrinsics()) {

1801 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate half");

1802 return {};

1803 }

1804

1805 mlir::Type ty = cgm.convertType(destType);

1806 assert(mlir::isacir::FPTypeInterface(ty) &&

1807 "expected floating-point type");

1808 return cir::FPAttr::get(ty, init);

1809 }

1811 const ArrayType *arrayTy = cgm.getASTContext().getAsArrayType(destType);

1813 const unsigned numElements = value.getArraySize();

1815

1816 mlir::Attribute filler;

1819 if (!filler)

1820 return {};

1821 }

1822

1824 if (filler && builder.isNullValue(filler))

1825 elements.reserve(numInitElts + 1);

1826 else

1827 elements.reserve(numInitElts);

1828

1829 mlir::Type commonElementType;

1830 for (unsigned i = 0; i < numInitElts; ++i) {

1832 const mlir::Attribute element =

1834 if (!element)

1835 return {};

1836

1837 const mlir::TypedAttr elementTyped = mlir::castmlir::TypedAttr(element);

1838 if (i == 0)

1839 commonElementType = elementTyped.getType();

1840 else if (elementTyped.getType() != commonElementType) {

1841 commonElementType = {};

1842 }

1843

1844 elements.push_back(elementTyped);

1845 }

1846

1847 mlir::TypedAttr typedFiller = llvm::cast_or_nullmlir::TypedAttr(filler);

1848 if (filler && !typedFiller)

1849 cgm.errorNYI("array filler should always be typed");

1850

1851 mlir::Type desiredType = cgm.convertType(destType);

1852 return emitArrayConstant(cgm, desiredType, commonElementType, numElements,

1853 elements, typedFiller);

1854 }

1856 const QualType elementType =

1859

1861 elements.reserve(numElements);

1862

1863 for (unsigned i = 0; i < numElements; ++i) {

1864 const mlir::Attribute element =

1866 if (!element)

1867 return {};

1868 elements.push_back(element);

1869 }

1870

1871 const auto desiredVecTy =

1872 mlir::castcir::VectorType(cgm.convertType(destType));

1873

1874 return cir::ConstVectorAttr::get(

1875 desiredVecTy,

1876 mlir::ArrayAttr::get(cgm.getBuilder().getContext(), elements));

1877 }

1880

1883 cgm.errorNYI(

1884 "ConstExprEmitter::tryEmitPrivate member pointer to derived member");

1885 return {};

1886 }

1887

1889 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer to method");

1890 return {};

1891 }

1892

1893 auto cirTy = mlir::castcir::DataMemberType(cgm.convertType(destType));

1894

1897 }

1899 return ConstantLValueEmitter(*this, value, destType).tryEmit();

1902 return ConstRecordBuilder::buildRecord(*this, value, destType);

1905 mlir::Type desiredType = cgm.convertType(destType);

1906 auto complexType = mlir::dyn_castcir::ComplexType(desiredType);

1907

1908 mlir::Type complexElemTy = complexType.getElementType();

1912 return cir::ConstComplexAttr::get(builder.getContext(), complexType,

1913 cir::IntAttr::get(complexElemTy, real),

1914 cir::IntAttr::get(complexElemTy, imag));

1915 }

1916

1918 "expected floating-point type");

1921 return cir::ConstComplexAttr::get(builder.getContext(), complexType,

1922 cir::FPAttr::get(complexElemTy, real),

1923 cir::FPAttr::get(complexElemTy, imag));

1924 }

1927 cgm.errorNYI(

1928 "ConstExprEmitter::tryEmitPrivate fixed point, addr label diff");

1929 return {};

1930 }

1931 llvm_unreachable("Unknown APValue kind");

1932}

1933

1937

1940 return builder.getConstNullPtrAttr(getTypes().convertTypeForMem(t));

1941

1942 if (getTypes().isZeroInitializable(t))

1943 return builder.getZeroInitAttr(getTypes().convertTypeForMem(t));

1944

1945 if (getASTContext().getAsConstantArrayType(t)) {

1946 errorNYI("CIRGenModule::emitNullConstantAttr ConstantArrayType");

1947 return {};

1948 }

1949

1950 if (const RecordType *rt = t->getAs())

1951 return ::emitNullConstant(*this, rt->getDecl(), true);

1952

1954 "Should only see pointers to data members here!");

1955

1956 errorNYI("CIRGenModule::emitNullConstantAttr unsupported type");

1957 return {};

1958}

1959

1960mlir::TypedAttr

1962 return ::emitNullConstant(*this, record, false);

1963}

Defines the clang::ASTContext interface.

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

static QualType getNonMemoryType(CodeGenModule &CGM, QualType type)

static mlir::TypedAttr emitNullConstant(CIRGenModule &cgm, const RecordDecl *rd, bool asCompleteObject)

Definition CIRGenExprConstant.cpp:1529

static mlir::TypedAttr emitNullConstantForBase(CIRGenModule &cgm, mlir::Type baseType, const CXXRecordDecl *baseDecl)

Emit the null constant for a base subobject.

Definition CIRGenExprConstant.cpp:1606

__device__ __2f16 float __ockl_bool s

__device__ __2f16 float c

cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})

Get constant address of a global variable as an MLIR attribute.

cir::BoolAttr getCIRBoolAttr(bool state)

cir::PointerType getPointerTo(mlir::Type ty)

mlir::TypedAttr getZeroInitAttr(mlir::Type ty)

mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)

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

bool hasArrayFiller() const

const LValueBase getLValueBase() const

APValue & getArrayInitializedElt(unsigned I)

APValue & getStructField(unsigned i)

const FieldDecl * getUnionField() const

APSInt & getComplexIntImag()

ValueKind getKind() const

bool isMemberPointerToDerivedMember() const

unsigned getArrayInitializedElts() const

const ValueDecl * getMemberPointerDecl() const

APValue & getUnionValue()

CharUnits & getLValueOffset()

APValue & getVectorElt(unsigned I)

APValue & getArrayFiller()

unsigned getVectorLength() const

unsigned getArraySize() const

@ Indeterminate

This object has an indeterminate value (C++ [basic.indet]).

@ None

There is no such object (it's outside its lifetime).

APSInt & getComplexIntReal()

APFloat & getComplexFloatImag()

APFloat & getComplexFloatReal()

APValue & getStructBase(unsigned i)

const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const

Get or compute information about the layout of the specified record (struct/union/class) D,...

QualType getQualifiedType(SplitQualType split) const

Un-split a SplitQualType.

int64_t toBits(CharUnits CharSize) const

Convert a size in characters to a size in bits.

CharUnits getTypeSizeInChars(QualType T) const

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

CharUnits toCharUnitsFromBits(int64_t BitSize) const

Convert a size in bits to a size in characters.

static bool hasSameUnqualifiedType(QualType T1, QualType T2)

Determine whether the given types are equivalent after cvr-qualifiers have been removed.

uint64_t getCharWidth() const

Return the size of the character type, in bits.

bool hasOwnVFPtr() const

hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...

CharUnits getSize() const

getSize - Get the record size in characters.

uint64_t getFieldOffset(unsigned FieldNo) const

getFieldOffset - Get the offset of the given field index, in bits.

CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const

getBaseClassOffset - Get the offset, in chars, for the given base class.

const CXXRecordDecl * getPrimaryBase() const

getPrimaryBase - Get the primary base for this record.

CharUnits getNonVirtualSize() const

getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...

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

QualType getElementType() const

cir::ConstRecordAttr getAnonConstRecord(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type ty={})

mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type type={})

bool isNullValue(mlir::Attribute attr) const

cir::RecordType getCompleteRecordType(mlir::ArrayAttr fields, bool packed=false, bool padded=false, llvm::StringRef name="")

void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)

cir::ConstArrayAttr getConstArray(mlir::Attribute attrs, cir::ArrayType arrayTy) const

cir::IntType getUIntNTy(int n)

cir::DataMemberAttr getDataMemberAttr(cir::DataMemberType ty, unsigned memberIndex)

virtual cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd, CharUnits vptrOffset)=0

Get the address of the vtable for the given record decl which should be used for the vptr at the give...

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.

clang::ASTContext & getASTContext() const

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

CIRGenBuilderTy & getBuilder()

ItaniumVTableContext & getItaniumVTableContext()

mlir::TypedAttr emitNullConstantForBase(const CXXRecordDecl *record)

Return a null constant appropriate for zero-initializing a base class with the given type.

Definition CIRGenExprConstant.cpp:1961

cir::FuncOp getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType=nullptr, bool forVTable=false, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)

Return the address of the given function.

mlir::TypedAttr emitNullConstantAttr(QualType t)

Definition CIRGenExprConstant.cpp:1938

void emitExplicitCastExprType(const ExplicitCastExpr *e, CIRGenFunction *cgf=nullptr)

Emit type info if type of an expression is a variably modified type.

const cir::CIRDataLayout getDataLayout() const

cir::GlobalViewAttr getAddrOfGlobalVarAttr(const VarDecl *d)

Return the mlir::GlobalViewAttr for the address of the given global.

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

Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.

mlir::Value emitNullConstant(QualType t, mlir::Location loc)

Return the result of value-initializing the given type, i.e.

Definition CIRGenExprConstant.cpp:1934

mlir::ModuleOp getModule() const

CIRGenCXXABI & getCXXABI() const

cir::GlobalViewAttr getAddrOfConstantStringFromLiteral(const StringLiteral *s, llvm::StringRef name=".str")

Return a global symbol reference to a constant array for the given string literal.

bool shouldZeroInitPadding() const

mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e)

Return a constant array for the given string.

This class handles record and union layout info while lowering AST types to CIR types.

cir::RecordType getCIRType() const

Return the "complete object" LLVM type associated with this record.

cir::RecordType getBaseSubobjectCIRType() const

Return the "base subobject" LLVM type associated with this record.

const CIRGenBitFieldInfo & getBitFieldInfo(const clang::FieldDecl *fd) const

Return the BitFieldInfo that corresponds to the field FD.

unsigned getCIRFieldNo(const clang::FieldDecl *fd) const

Return cir::RecordType element number that corresponds to the field FD.

bool isZeroInitializableAsBase() const

Check whether this struct can be C++ zero-initialized with a zeroinitializer when considered as a bas...

unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const

const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)

Return record layout info for the given record decl.

mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)

Convert type T into an mlir::Type.

void finalize(cir::GlobalOp gv)

Definition CIRGenExprConstant.cpp:1503

mlir::Attribute emitForMemory(mlir::Attribute c, QualType destType)

Definition CIRGenExprConstant.cpp:1733

mlir::Attribute emitNullForMemory(mlir::Location loc, QualType t)

mlir::TypedAttr tryEmitPrivate(const Expr *e, QualType destType)

Definition CIRGenExprConstant.cpp:1755

mlir::Attribute tryEmitPrivateForVarInit(const VarDecl &d)

Definition CIRGenExprConstant.cpp:1620

mlir::Attribute tryEmitPrivateForMemory(const Expr *e, QualType destTy)

Definition CIRGenExprConstant.cpp:1686

mlir::Attribute emitAbstract(const Expr *e, QualType destType)

Emit the result of the given expression as an abstract constant, asserting that it succeeded.

Definition CIRGenExprConstant.cpp:1704

~ConstantEmitter()

Definition CIRGenExprConstant.cpp:1520

const CIRGenFunction * cgf

mlir::Attribute tryEmitForInitializer(const VarDecl &d)

Try to emit the initializer of the given declaration as an abstract constant.

Definition CIRGenExprConstant.cpp:1498

mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d)

Try to emit the initializer of the given declaration as an abstract constant.

Definition CIRGenExprConstant.cpp:1515

mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce)

Definition CIRGenExprConstant.cpp:1675

Represents a base class of a C++ class.

Expr * getArg(unsigned Arg)

Return the specified argument.

CXXConstructorDecl * getConstructor() const

Get the constructor that this expression will (ultimately) call.

unsigned getNumArgs() const

Return the number of arguments to the constructor call.

Represents a C++ constructor within a class.

bool isDefaultConstructor() const

Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...

bool isCopyOrMoveConstructor(unsigned &TypeQuals) const

Determine whether this is a copy or move constructor.

Expr * getExpr()

Get the initialization expression that will be used.

Represents a C++ struct/union/class.

SourceRange getSourceRange() const LLVM_READONLY

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.

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

static CharUnits One()

One - Construct a CharUnits quantity of one.

static CharUnits fromQuantity(QuantityType Quantity)

fromQuantity - Construct a CharUnits quantity from a raw integer type.

CharUnits alignTo(const CharUnits &Align) const

alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...

static CharUnits Zero()

Zero - Construct a CharUnits quantity of zero.

Expr * getChosenSubExpr() const

getChosenSubExpr - Return the subexpression chosen according to the condition.

const Expr * getInitializer() const

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

APValue getAPValueResult() const

SourceLocation getBeginLoc() const LLVM_READONLY

bool hasAPValueResult() const

SourceLocation getBeginLoc() const LLVM_READONLY

This represents one expression.

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

EvaluateAsLValue - Evaluate an expression to see if we can fold it to an lvalue with link time known ...

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...

Represents a member of a struct/union/class.

bool isBitField() const

Determines whether this field is a bitfield.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

const RecordDecl * getParent() const

Returns the parent of this field declaration, which is the struct in which this field is defined.

bool isZeroSize(const ASTContext &Ctx) const

Determine if this field is a subobject of zero size, that is, either a zero-length bit-field or a fie...

bool isUnnamedBitField() const

Determines whether this is an unnamed bitfield.

const Expr * getSubExpr() const

bool isTrivial() const

Whether this function is "trivial" in some specialized C++ senses.

Expr * getResultExpr()

Return the result expression of this controlling expression.

bool isTransparent() const

Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...

FieldDecl * getInitializedFieldInUnion()

If this initializes a union, specifies which field in the union to initialize.

const Expr * getInit(unsigned Init) const

const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)

Expr * getSubExpr() const

Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation getBeginLoc() const LLVM_READONLY

const Expr * getSubExpr() const

PointerType - C99 6.7.5.1 - Pointer Declarators.

A (possibly-)qualified type.

Represents a struct/union/class.

bool hasFlexibleArrayMember() const

field_range fields() const

RecordDecl * getDefinitionOrSelf() const

Encodes a location in the source.

SourceRange getSourceRange() const LLVM_READONLY

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

SourceLocation getBeginLoc() const LLVM_READONLY

Expr * getReplacement() const

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

RecordDecl * getAsRecordDecl() const

Retrieves the RecordDecl this type refers to.

CXXRecordDecl * castAsCXXRecordDecl() const

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

bool isMemberDataPointerType() const

RecordDecl * castAsRecordDecl() const

bool isVectorType() const

const T * getAs() const

Member-template getAs'.

bool isRecordType() const

Expr * getSubExpr() const

AddressPointLocation getAddressPoint(BaseSubobject Base) const

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.

APValue * evaluateValue() const

Attempt to evaluate the value of the initializer attached to this declaration, and produce notes expl...

bool hasConstantInitialization() const

Determine whether this variable has constant initialization.

const Expr * getInit() const

bool hasLocalStorage() const

Returns true if a variable with function scope is a non-static local variable.

Represents a GCC generic vector type.

bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd)

isEmptyFieldForLayout - Return true if the field is "empty", that is, either a zero-width bit-field o...

bool isEmptyRecordForLayout(const ASTContext &context, QualType t)

isEmptyRecordForLayout - Return true if a structure contains only empty base classes (per isEmptyReco...

const internal::VariadicAllOfMatcher< Attr > attr

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

const AstTypeMatcher< ComplexType > complexType

const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl

Matches field declarations.

const AstTypeMatcher< RecordType > recordType

constexpr size_t align(size_t Size)

Aligns a size to the pointer alignment.

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

bool isa(CodeGen::Address addr)

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

bool operator<(DeclarationName LHS, DeclarationName RHS)

Ordering on two declaration names.

bool declaresSameEntity(const Decl *D1, const Decl *D2)

Determine whether two declarations declare the same entity.

void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)

U cast(CodeGen::Address addr)

__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)

float __ovld __cnfn length(float)

Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)

static bool ctorConstLvalueToRvalueConversion()

static bool addressPointerAuthInfo()

static bool constEmitterArrayILE()

static bool constEmitterVectorILE()

unsigned size

The total size of the bit-field, in bits.

mlir::Type uCharTy

ClangIR char.

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 hasSideEffects() const

Return true if the evaluated expression has side effects.

unsigned AddressPointIndex