1947 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This contains code to emit Constant Expr nodes as LLVM code.10//11//===----------------------------------------------------------------------===//12 13#include "Address.h"14#include "CIRGenCXXABI.h"15#include "CIRGenConstantEmitter.h"16#include "CIRGenModule.h"17#include "CIRGenRecordLayout.h"18#include "mlir/IR/Attributes.h"19#include "mlir/IR/BuiltinAttributeInterfaces.h"20#include "mlir/IR/BuiltinAttributes.h"21#include "clang/AST/APValue.h"22#include "clang/AST/ASTContext.h"23#include "clang/AST/Attr.h"24#include "clang/AST/CharUnits.h"25#include "clang/AST/OperationKinds.h"26#include "clang/AST/RecordLayout.h"27#include "clang/AST/StmtVisitor.h"28#include "clang/Basic/Builtins.h"29#include "clang/CIR/Dialect/IR/CIRAttrs.h"30#include "clang/CIR/Dialect/IR/CIRTypes.h"31#include "clang/CIR/MissingFeatures.h"32#include "llvm/ADT/ArrayRef.h"33#include "llvm/ADT/STLExtras.h"34#include "llvm/Support/ErrorHandling.h"35#include <functional>36#include <iterator>37 38using namespace clang;39using namespace clang::CIRGen;40 41//===----------------------------------------------------------------------===//42// ConstantAggregateBuilder43//===----------------------------------------------------------------------===//44 45namespace {46class ConstExprEmitter;47 48static mlir::TypedAttr computePadding(CIRGenModule &cgm, CharUnits size) {49 mlir::Type eltTy = cgm.uCharTy;50 clang::CharUnits::QuantityType arSize = size.getQuantity();51 CIRGenBuilderTy &bld = cgm.getBuilder();52 if (size > CharUnits::One()) {53 SmallVector<mlir::Attribute> elts(arSize, cir::ZeroAttr::get(eltTy));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::Attribute62emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,63 mlir::Type commonElementType, unsigned arrayBound,64 SmallVectorImpl<mlir::TypedAttr> &elements,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 {75 return CharUnits::fromQuantity(76 dataLayout.getAlignment(c.getType(), /*useABIAlign=*/true));77 }78 79 CharUnits getSize(mlir::Type ty) const {80 return CharUnits::fromQuantity(dataLayout.getTypeAllocSize(ty));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/// Incremental builder for an mlir::TypedAttr holding a record or array93/// constant.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 /// Describes the offset of `element` within the constant.101 CharUnits offset;102 };103 /// The elements of the constant. The elements are kept in increasing offset104 /// order, and we ensure that there is no overlap:105 /// elements.offset[i+1] >= elements.offset[i] + getSize(elements.element[i])106 ///107 /// This may contain explicit padding elements (in order to create a108 /// natural layout), but need not. Gaps between elements are implicitly109 /// considered to be filled with undef.110 llvm::SmallVector<Element, 32> elements;111 112 /// The size of the constant (the maximum end offset of any added element).113 /// May be larger than the end of elems.back() if we split the last element114 /// and removed some trailing undefs.115 CharUnits size = CharUnits::Zero();116 117 /// This is true only if laying out elems in order as the elements of a118 /// non-packed LLVM struct will give the correct layout.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<Element> 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 /// Update or overwrite the value starting at \p offset with \c c.134 ///135 /// \param allowOverwrite If \c true, this constant might overwrite (part of)136 /// a constant that has already been added. This flag is only used to137 /// detect bugs.138 bool add(mlir::TypedAttr typedAttr, CharUnits offset, bool allowOverwrite);139 140 /// Update or overwrite the bits starting at \p offsetInBits with \p bits.141 bool addBits(llvm::APInt bits, uint64_t offsetInBits, bool allowOverwrite);142 143 /// Attempt to condense the value starting at \p offset to a constant of type144 /// \p desiredTy.145 void condense(CharUnits offset, mlir::Type desiredTy);146 147 /// Produce a constant representing the entire accumulated value, ideally of148 /// the specified type. If \p allowOversized, the constant might be larger149 /// than implied by \p desiredTy (eg, if there is a flexible array member).150 /// Otherwise, the constant will be of exactly the same size as \p desiredTy151 /// even if we can't represent it as that type.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 // Common case: appending to a layout.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 // Uncommon case: constant overlaps what we've already created.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();204 const uint64_t charWidth = astContext.getCharWidth();205 mlir::Type charTy = cgm.getBuilder().getUIntNTy(charWidth);206 207 // Offset of where we want the first bit to go within the bits of the208 // current char.209 unsigned offsetWithinChar = offsetInBits % charWidth;210 211 // We split bit-fields up into individual bytes. Walk over the bytes and212 // update them.213 for (CharUnits offsetInChars =214 astContext.toCharUnitsFromBits(offsetInBits - offsetWithinChar);215 /**/; ++offsetInChars) {216 // Number of bits we want to fill in this char.217 unsigned wantedBits =218 std::min((uint64_t)bits.getBitWidth(), charWidth - offsetWithinChar);219 220 // Get a char containing the bits we want in the right places. The other221 // bits have unspecified values.222 llvm::APInt bitsThisChar = bits;223 if (bitsThisChar.getBitWidth() < charWidth)224 bitsThisChar = bitsThisChar.zext(charWidth);225 if (cgm.getDataLayout().isBigEndian()) {226 // Figure out how much to shift by. We may need to left-shift if we have227 // less than one byte of Bits left.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 // Got a full byte: just add it directly.241 add(cir::IntAttr::get(charTy, bitsThisChar), offsetInChars,242 allowOverwrite);243 } else {244 // Partial byte: update the existing integer if there is one. If we245 // can't split out a 1-CharUnit range to update, then we can't add246 // these bits and fail the entire constant emission.247 std::optional<size_t> firstElemToUpdate = splitAt(offsetInChars);248 if (!firstElemToUpdate)249 return false;250 std::optional<size_t> lastElemToUpdate =251 splitAt(offsetInChars + CharUnits::One());252 if (!lastElemToUpdate)253 return false;254 assert(*lastElemToUpdate - *firstElemToUpdate < 2 &&255 "should have at most one element covering one byte");256 257 // Figure out which bits we want and discard the rest.258 llvm::APInt updateMask(charWidth, 0);259 if (cgm.getDataLayout().isBigEndian())260 updateMask.setBits(charWidth - offsetWithinChar - wantedBits,261 charWidth - offsetWithinChar);262 else263 updateMask.setBits(offsetWithinChar, offsetWithinChar + wantedBits);264 bitsThisChar &= updateMask;265 bool isNull = false;266 if (*firstElemToUpdate < elements.size()) {267 auto firstEltToUpdate =268 mlir::dyn_cast<cir::IntAttr>(elements[*firstElemToUpdate].element);269 isNull = firstEltToUpdate && firstEltToUpdate.isNullValue();270 }271 272 if (*firstElemToUpdate == *lastElemToUpdate || isNull) {273 // All existing bits are either zero or undef.274 add(cir::IntAttr::get(charTy, bitsThisChar), offsetInChars,275 /*allowOverwrite*/ true);276 } else {277 cir::IntAttr ci =278 mlir::dyn_cast<cir::IntAttr>(elements[*firstElemToUpdate].element);279 // In order to perform a partial update, we need the existing bitwise280 // value, which we can only extract for a constant int.281 if (!ci)282 return false;283 // Because this is a 1-CharUnit range, the constant occupying it must284 // be exactly one CharUnit wide.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 // Stop if we've added all the bits.295 if (wantedBits == bits.getBitWidth())296 break;297 298 // Remove the consumed bits from Bits.299 if (!cgm.getDataLayout().isBigEndian())300 bits.lshrInPlace(wantedBits);301 bits = bits.trunc(bits.getBitWidth() - wantedBits);302 303 // The remaining bits go at the start of the following bytes.304 offsetWithinChar = 0;305 }306 307 return true;308}309 310/// Returns a position within elements such that all elements311/// before the returned index end before pos and all elements at or after312/// the returned index begin at or after pos. Splits elements as necessary313/// to ensure this. Returns std::nullopt if we find something we can't split.314std::optional<size_t> ConstantAggregateBuilder::splitAt(CharUnits pos) {315 if (pos >= size)316 return elements.size();317 318 while (true) {319 // Find the first element that starts after pos.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 // If we already have an element starting at pos, we're done.332 if (elt.offset == pos)333 return index;334 335 // Check for overlap with the element that starts before pos.336 CharUnits eltEnd = elt.offset + getSize(elt.element);337 if (eltEnd <= pos)338 return index + 1;339 340 // Try to decompose it into smaller constants.341 if (!split(index, pos))342 return std::nullopt;343 }344}345 346/// Split the constant at index, if possible. Return true if we did.347/// Hint indicates the location at which we'd like to split, but may be348/// ignored.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;369 if (length == 0)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 // Build a new constant from the elements in the range.379 SmallVector<Element> subElems(elements.begin() + first,380 elements.begin() + last);381 mlir::Attribute replacement =382 buildFrom(cgm, subElems, offset, desiredSize,383 /*naturalLayout=*/false, desiredTy, false);384 385 // Replace the range with the condensed constant.386 Element newElt(mlir::cast<mlir::TypedAttr>(replacement), offset);387 replace(elements, first, last, {newElt});388}389 390mlir::Attribute391ConstantAggregateBuilder::buildFrom(CIRGenModule &cgm, ArrayRef<Element> 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 // If we want an array type, see if all the elements are the same type and401 // appropriately spaced.402 if (mlir::isa<cir::ArrayType>(desiredTy)) {403 cgm.errorNYI("array aggregate constants");404 return {};405 }406 407 // The size of the constant we plan to generate. This is usually just the size408 // of the initialized type, but in AllowOversized mode (i.e. flexible array409 // init), it can be larger.410 CharUnits desiredSize = utils.getSize(desiredTy);411 if (size > desiredSize) {412 assert(allowOversized && "elems are oversized");413 desiredSize = size;414 }415 416 // The natural alignment of an unpacked CIR record with the given elements.417 CharUnits align = CharUnits::One();418 for (auto [e, offset] : elems)419 align = std::max(align, utils.getAlignment(e));420 421 // The natural size of an unpacked LLVM struct with the given elements.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 // The natural layout would be too small. Add padding to fix it. (This433 // is ignored if we choose a packed layout.)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 // If we don't have a natural layout, insert padding as necessary.442 // As we go, double-check to see if we can actually just emit Elems443 // as a non-packed record and do so opportunistically if possible.444 llvm::SmallVector<mlir::Attribute, 32> packedElems;445 packedElems.reserve(elems.size());446 if (!naturalLayout) {447 CharUnits sizeSoFar = CharUnits::Zero();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 // If we're using the packed layout, pad it out to the desired size if462 // necessary.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 476 cir::RecordType recordType = builder.getCompleteRecordType(arrAttr, packed);477 if (auto desired = mlir::dyn_cast<cir::RecordType>(desiredTy))478 if (desired.isLayoutIdentical(recordType))479 recordType = desired;480 481 return builder.getConstRecordOrZeroAttr(arrAttr, packed, padded, recordType);482}483 484//===----------------------------------------------------------------------===//485// ConstRecordBuilder486//===----------------------------------------------------------------------===//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 /// Applies zero-initialization to padding bytes before and within a field.519 /// \param layout The record layout containing field offset information.520 /// \param fieldNo The field index in the record.521 /// \param field The field declaration.522 /// \param allowOverwrite Whether to allow overwriting existing values.523 /// \param sizeSoFar The current size processed, updated by this function.524 /// \param zeroFieldSize Set to true if the field has zero size.525 /// \returns true on success, false if padding could not be applied.526 bool applyZeroInitPadding(const ASTRecordLayout &layout, unsigned fieldNo,527 const FieldDecl &field, bool allowOverwrite,528 CharUnits &sizeSoFar, bool &zeroFieldSize);529 530 /// Applies zero-initialization to trailing padding bytes in a record.531 /// \param layout The record layout containing size information.532 /// \param allowOverwrite Whether to allow overwriting existing values.533 /// \param sizeSoFar The current size processed.534 /// \returns true on success, false if padding could not be applied.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 =566 cgm.getTypes().getCIRGenRecordLayout(field->getParent());567 const CIRGenBitFieldInfo &info = rl.getBitFieldInfo(field);568 llvm::APInt fieldValue = ci.getValue();569 570 // Promote the size of FieldValue if necessary571 // FIXME: This should never occur, but currently it can because initializer572 // constants are cast to bool, and because clang is not enforcing bitfield573 // width limits.574 if (info.size > fieldValue.getBitWidth())575 fieldValue = fieldValue.zext(info.size);576 577 // Truncate the size of FieldValue to the bit field size.578 if (info.size < fieldValue.getBitWidth())579 fieldValue = fieldValue.trunc(info.size);580 581 return builder.addBits(fieldValue,582 cgm.getASTContext().toBits(startOffset) + fieldOffset,583 allowOverwrite);584}585 586bool ConstRecordBuilder::applyZeroInitPadding(587 const ASTRecordLayout &layout, unsigned fieldNo, const FieldDecl &field,588 bool allowOverwrite, CharUnits &sizeSoFar, bool &zeroFieldSize) {589 uint64_t startBitOffset = layout.getFieldOffset(fieldNo);590 CharUnits startOffset =591 cgm.getASTContext().toCharUnitsFromBits(startBitOffset);592 if (sizeSoFar < startOffset) {593 if (!appendBytes(sizeSoFar, computePadding(cgm, startOffset - sizeSoFar),594 allowOverwrite))595 return false;596 }597 598 if (!field.isBitField()) {599 CharUnits fieldSize =600 cgm.getASTContext().getTypeSizeInChars(field.getType());601 sizeSoFar = startOffset + fieldSize;602 zeroFieldSize = fieldSize.isZero();603 } else {604 const CIRGenRecordLayout &rl =605 cgm.getTypes().getCIRGenRecordLayout(field.getParent());606 const CIRGenBitFieldInfo &info = rl.getBitFieldInfo(&field);607 uint64_t endBitOffset = startBitOffset + info.size;608 sizeSoFar = cgm.getASTContext().toCharUnitsFromBits(endBitOffset);609 if (endBitOffset % cgm.getASTContext().getCharWidth() != 0)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) {630 RecordDecl *rd = ile->getType()->castAsRecordDecl();631 const ASTRecordLayout &layout = cgm.getASTContext().getASTRecordLayout(rd);632 633 // Bail out if we have base classes. We could support these, but they only634 // arise in C++1z where we will have already constant folded most interesting635 // cases. FIXME: There are still a few more cases we can handle this way.636 if (auto *cxxrd = dyn_cast<CXXRecordDecl>(rd))637 if (cxxrd->getNumBases())638 return false;639 640 const bool zeroInitPadding = cgm.shouldZeroInitPadding();641 bool zeroFieldSize = false;642 CharUnits sizeSoFar = CharUnits::Zero();643 644 unsigned elementNo = 0;645 for (auto [index, field] : llvm::enumerate(rd->fields())) {646 647 // If this is a union, skip all the fields that aren't being initialized.648 if (rd->isUnion() &&649 !declaresSameEntity(ile->getInitializedFieldInUnion(), field))650 continue;651 652 // Don't emit anonymous bitfields.653 if (field->isUnnamedBitField())654 continue;655 656 // Get the initializer. A record can include fields without initializers,657 // we just use explicit null values for them.658 Expr *init = nullptr;659 if (elementNo < ile->getNumInits())660 init = ile->getInit(elementNo++);661 if (isa_and_nonnull<NoInitExpr>(init))662 continue;663 664 // Zero-sized fields are not emitted, but their initializers may still665 // prevent emission of this record as a constant.666 if (field->isZeroSize(cgm.getASTContext())) {667 if (init->HasSideEffects(cgm.getASTContext()))668 return false;669 continue;670 }671 672 if (zeroInitPadding &&673 !applyZeroInitPadding(layout, index, *field, allowOverwrite, sizeSoFar,674 zeroFieldSize))675 return false;676 677 // When emitting a DesignatedInitUpdateExpr, a nested InitListExpr678 // represents additional overwriting of our current constant value, and not679 // a new constant to emit independently.680 if (allowOverwrite &&681 (field->getType()->isArrayType() || field->getType()->isRecordType())) {682 cgm.errorNYI(field->getSourceRange(), "designated init lists");683 return false;684 }685 686 mlir::Attribute eltInitAttr =687 init ? emitter.tryEmitPrivateForMemory(init, field->getType())688 : emitter.emitNullForMemory(cgm.getLoc(ile->getSourceRange()),689 field->getType());690 if (!eltInitAttr)691 return false;692 693 mlir::TypedAttr eltInit = mlir::cast<mlir::TypedAttr>(eltInitAttr);694 if (!field->isBitField()) {695 // Handle non-bitfield members.696 if (!appendField(field, layout.getFieldOffset(index), eltInit,697 allowOverwrite))698 return false;699 // After emitting a non-empty field with [[no_unique_address]], we may700 // need to overwrite its tail padding.701 if (field->hasAttr<NoUniqueAddressAttr>())702 allowOverwrite = true;703 } else {704 // Otherwise we have a bitfield.705 if (auto constInt = dyn_cast<cir::IntAttr>(eltInit)) {706 if (!appendBitField(field, layout.getFieldOffset(index), constInt,707 allowOverwrite))708 return false;709 } else {710 // We are trying to initialize a bitfield with a non-trivial constant,711 // this must require run-time code.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} // namespace733 734bool ConstRecordBuilder::build(const APValue &val, const RecordDecl *rd,735 bool isPrimaryBase,736 const CXXRecordDecl *vTableClass,737 CharUnits offset) {738 const ASTRecordLayout &layout = cgm.getASTContext().getASTRecordLayout(rd);739 if (const CXXRecordDecl *cd = dyn_cast<CXXRecordDecl>(rd)) {740 // Add a vtable pointer, if we need one and it hasn't already been added.741 if (layout.hasOwnVFPtr()) {742 CIRGenBuilderTy &builder = cgm.getBuilder();743 cir::GlobalOp vtable =744 cgm.getCXXABI().getAddrOfVTable(vTableClass, CharUnits());745 clang::VTableLayout::AddressPointLocation addressPoint =746 cgm.getItaniumVTableContext()747 .getVTableLayout(vTableClass)748 .getAddressPoint(BaseSubobject(cd, offset));749 assert(!cir::MissingFeatures::addressPointerAuthInfo());750 mlir::ArrayAttr indices = builder.getArrayAttr({751 builder.getI32IntegerAttr(addressPoint.VTableIndex),752 builder.getI32IntegerAttr(addressPoint.AddressPointIndex),753 });754 cir::GlobalViewAttr vtableInit =755 cgm.getBuilder().getGlobalViewAttr(vtable, indices);756 if (!appendBytes(offset, vtableInit))757 return false;758 }759 760 // Accumulate and sort bases, in order to visit them in address order, which761 // may not be the same as declaration order.762 SmallVector<BaseInfo> 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();767 CharUnits baseOffset = layout.getBaseClassOffset(bd);768 bases.push_back(BaseInfo(bd, baseOffset, index));769 }770#ifdef EXPENSIVE_CHECKS771 assert(llvm::is_sorted(bases) && "bases not sorted by offset");772#endif773 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 781 uint64_t offsetBits = cgm.getASTContext().toBits(offset);782 783 bool allowOverwrite = false;784 for (auto [index, field] : llvm::enumerate(rd->fields())) {785 // If this is a union, skip all the fields that aren't being initialized.786 if (rd->isUnion() && !declaresSameEntity(val.getUnionField(), field))787 continue;788 789 // Don't emit anonymous bitfields or zero-sized fields.790 if (field->isUnnamedBitField() || field->isZeroSize(cgm.getASTContext()))791 continue;792 793 // Emit the value of the initializer.794 const APValue &fieldValue =795 rd->isUnion() ? val.getUnionValue() : val.getStructField(index);796 mlir::TypedAttr eltInit = mlir::cast<mlir::TypedAttr>(797 emitter.tryEmitPrivateForMemory(fieldValue, field->getType()));798 if (!eltInit)799 return false;800 801 if (!field->isBitField()) {802 // Handle non-bitfield members.803 if (!appendField(field, layout.getFieldOffset(index) + offsetBits,804 eltInit, allowOverwrite))805 return false;806 // After emitting a non-empty field with [[no_unique_address]], we may807 // need to overwrite its tail padding.808 if (field->hasAttr<NoUniqueAddressAttr>())809 allowOverwrite = true;810 } else {811 // Otherwise we have a bitfield.812 if (auto constInt = dyn_cast<cir::IntAttr>(eltInit)) {813 if (!appendBitField(field, layout.getFieldOffset(index) + offsetBits,814 constInt, allowOverwrite))815 return false;816 } else {817 // We are trying to initialize a bitfield with a non-trivial constant,818 // this must require run-time code.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 =830 type->castAs<clang::RecordType>()->getDecl()->getDefinitionOrSelf();831 mlir::Type valTy = cgm.convertType(type);832 return builder.build(valTy, rd->hasFlexibleArrayMember());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, /*allowOverwrite*/ false))842 return nullptr;843 844 return builder.finalize(valTy);845}846 847mlir::Attribute ConstRecordBuilder::buildRecord(ConstantEmitter &emitter,848 const APValue &val,849 QualType valTy) {850 ConstantAggregateBuilder constant(emitter.cgm);851 ConstRecordBuilder builder(emitter, constant, CharUnits::Zero());852 853 const RecordDecl *rd =854 valTy->castAs<clang::RecordType>()->getDecl()->getDefinitionOrSelf();855 const CXXRecordDecl *cd = dyn_cast<CXXRecordDecl>(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, /*allowOverwrite*/ true);867}868 869//===----------------------------------------------------------------------===//870// ConstExprEmitter871//===----------------------------------------------------------------------===//872 873// This class only needs to handle arrays, structs and unions.874//875// In LLVM codegen, when outside C++11 mode, those types are not constant876// folded, while all other types are handled by constant folding.877//878// In CIR codegen, instead of folding things here, we should defer that work879// to MLIR: do not attempt to do much here.880class ConstExprEmitter881 : 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 // Visitor Methods891 //===--------------------------------------------------------------------===//892 893 mlir::Attribute VisitStmt(Stmt *s, QualType t) { return {}; }894 895 mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {896 if (mlir::Attribute result = emitter.tryEmitConstantExpr(ce))897 return result;898 return Visit(ce->getSubExpr(), t);899 }900 901 mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {902 return Visit(pe->getSubExpr(), t);903 }904 905 mlir::Attribute906 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,907 QualType t) {908 return Visit(pe->getReplacement(), t);909 }910 911 mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,912 QualType t) {913 return Visit(ge->getResultExpr(), t);914 }915 916 mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {917 return Visit(ce->getChosenSubExpr(), t);918 }919 920 mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {921 return Visit(e->getInitializer(), t);922 }923 924 mlir::Attribute VisitCastExpr(CastExpr *e, QualType destType) {925 if (const auto *ece = dyn_cast<ExplicitCastExpr>(e))926 cgm.emitExplicitCastExprType(ece,927 const_cast<CIRGenFunction *>(emitter.cgf));928 929 Expr *subExpr = e->getSubExpr();930 931 switch (e->getCastKind()) {932 case CK_ToUnion:933 case CK_AddressSpaceConversion:934 case CK_ReinterpretMemberPointer:935 case CK_DerivedToBaseMemberPointer:936 case CK_BaseToDerivedMemberPointer:937 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCastExpr");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 // These will never be supported.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 // These don't need to be handled here because Evaluate knows how to966 // evaluate them in the cases where they can be folded.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_HLSLElementwiseCast:1016 case CK_HLSLAggregateSplatCast:1017 return {};1018 }1019 llvm_unreachable("Invalid CastKind");1020 }1021 1022 mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {1023 // No need for a DefaultInitExprScope: we don't handle 'this' in a1024 // constant expression.1025 return Visit(die->getExpr(), t);1026 }1027 1028 mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {1029 // Since this about constant emission no need to wrap this under a scope.1030 return Visit(e->getSubExpr(), t);1031 }1032 1033 mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,1034 QualType t) {1035 return Visit(e->getSubExpr(), t);1036 }1037 1038 mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *e,1039 QualType t) {1040 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(t));1041 }1042 1043 mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {1044 if (ile->isTransparent())1045 return Visit(ile->getInit(0), t);1046 1047 if (ile->getType()->isArrayType()) {1048 // If we return null here, the non-constant initializer will take care of1049 // it, but we would prefer to handle it here.1050 assert(!cir::MissingFeatures::constEmitterArrayILE());1051 return {};1052 }1053 1054 if (ile->getType()->isRecordType()) {1055 return ConstRecordBuilder::buildRecord(emitter, ile, t);1056 }1057 1058 if (ile->getType()->isVectorType()) {1059 // If we return null here, the non-constant initializer will take care of1060 // it, but we would prefer to handle it here.1061 assert(!cir::MissingFeatures::constEmitterVectorILE());1062 return {};1063 }1064 1065 return {};1066 }1067 1068 mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,1069 QualType destType) {1070 mlir::Attribute c = Visit(e->getBase(), destType);1071 if (!c)1072 return {};1073 1074 cgm.errorNYI(e->getBeginLoc(),1075 "ConstExprEmitter::VisitDesignatedInitUpdateExpr");1076 return {};1077 }1078 1079 mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {1080 if (!e->getConstructor()->isTrivial())1081 return {};1082 1083 // Only default and copy/move constructors can be trivial.1084 if (e->getNumArgs()) {1085 assert(e->getNumArgs() == 1 && "trivial ctor with > 1 argument");1086 assert(e->getConstructor()->isCopyOrMoveConstructor() &&1087 "trivial ctor has argument but isn't a copy/move ctor");1088 1089 Expr *arg = e->getArg(0);1090 assert(cgm.getASTContext().hasSameUnqualifiedType(ty, arg->getType()) &&1091 "argument to copy ctor is of wrong type");1092 1093 // Look through the temporary; it's just converting the value to an lvalue1094 // to pass it to the constructor.1095 if (auto const *mte = dyn_cast<MaterializeTemporaryExpr>(arg))1096 return Visit(mte->getSubExpr(), ty);1097 1098 // TODO: Investigate whether there are cases that can fall through to here1099 // that need to be handled. This is missing in classic codegen also.1100 assert(!cir::MissingFeatures::ctorConstLvalueToRvalueConversion());1101 1102 // Don't try to support arbitrary lvalue-to-rvalue conversions for now.1103 return {};1104 }1105 1106 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(ty));1107 }1108 1109 mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {1110 // This is a string literal initializing an array in an initializer.1111 return cgm.getConstantArrayFromStringLiteral(e);1112 }1113 1114 mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {1115 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitObjCEncodeExpr");1116 return {};1117 }1118 1119 mlir::Attribute VisitUnaryExtension(const UnaryOperator *e, QualType t) {1120 return Visit(e->getSubExpr(), t);1121 }1122 1123 // Utility methods1124 mlir::Type convertType(QualType t) { return cgm.convertType(t); }1125};1126 1127// TODO(cir): this can be shared with LLVM's codegen1128static QualType getNonMemoryType(CIRGenModule &cgm, QualType type) {1129 if (const auto *at = type->getAs<AtomicType>()) {1130 return cgm.getASTContext().getQualifiedType(at->getValueType(),1131 type.getQualifiers());1132 }1133 return type;1134}1135 1136static mlir::Attribute1137emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,1138 mlir::Type commonElementType, unsigned arrayBound,1139 SmallVectorImpl<mlir::TypedAttr> &elements,1140 mlir::TypedAttr filler) {1141 CIRGenBuilderTy &builder = cgm.getBuilder();1142 1143 unsigned nonzeroLength = arrayBound;1144 if (elements.size() < nonzeroLength && builder.isNullValue(filler))1145 nonzeroLength = elements.size();1146 1147 if (nonzeroLength == elements.size()) {1148 while (nonzeroLength > 0 &&1149 builder.isNullValue(elements[nonzeroLength - 1]))1150 --nonzeroLength;1151 }1152 1153 if (nonzeroLength == 0)1154 return cir::ZeroAttr::get(desiredType);1155 1156 const unsigned trailingZeroes = arrayBound - nonzeroLength;1157 1158 // Add a zeroinitializer array filler if we have lots of trailing zeroes.1159 if (trailingZeroes >= 8) {1160 assert(elements.size() >= nonzeroLength &&1161 "missing initializer for non-zero element");1162 1163 if (commonElementType && nonzeroLength >= 8) {1164 // If all the elements had the same type up to the trailing zeroes and1165 // there are eight or more nonzero elements, emit a struct of two arrays1166 // (the nonzero data and the zeroinitializer).1167 SmallVector<mlir::Attribute> eles;1168 eles.reserve(nonzeroLength);1169 for (const auto &element : elements)1170 eles.push_back(element);1171 auto initial = cir::ConstArrayAttr::get(1172 cir::ArrayType::get(commonElementType, nonzeroLength),1173 mlir::ArrayAttr::get(builder.getContext(), eles));1174 elements.resize(2);1175 elements[0] = initial;1176 } else {1177 // Otherwise, emit a struct with individual elements for each nonzero1178 // initializer, followed by a zeroinitializer array filler.1179 elements.resize(nonzeroLength + 1);1180 }1181 1182 mlir::Type fillerType =1183 commonElementType1184 ? commonElementType1185 : mlir::cast<cir::ArrayType>(desiredType).getElementType();1186 fillerType = cir::ArrayType::get(fillerType, trailingZeroes);1187 elements.back() = cir::ZeroAttr::get(fillerType);1188 commonElementType = nullptr;1189 } else if (elements.size() != arrayBound) {1190 elements.resize(arrayBound, filler);1191 1192 if (filler.getType() != commonElementType)1193 commonElementType = {};1194 }1195 1196 if (commonElementType) {1197 SmallVector<mlir::Attribute> eles;1198 eles.reserve(elements.size());1199 1200 for (const auto &element : elements)1201 eles.push_back(element);1202 1203 return cir::ConstArrayAttr::get(1204 cir::ArrayType::get(commonElementType, arrayBound),1205 mlir::ArrayAttr::get(builder.getContext(), eles));1206 }1207 1208 SmallVector<mlir::Attribute> eles;1209 eles.reserve(elements.size());1210 for (auto const &element : elements)1211 eles.push_back(element);1212 1213 auto arrAttr = mlir::ArrayAttr::get(builder.getContext(), eles);1214 return builder.getAnonConstRecord(arrAttr, /*packed=*/true);1215}1216 1217} // namespace1218 1219//===----------------------------------------------------------------------===//1220// ConstantLValueEmitter1221//===----------------------------------------------------------------------===//1222 1223namespace {1224/// A struct which can be used to peephole certain kinds of finalization1225/// that normally happen during l-value emission.1226struct ConstantLValue {1227 llvm::PointerUnion<mlir::Value, mlir::Attribute> value;1228 bool hasOffsetApplied;1229 1230 /*implicit*/ ConstantLValue(std::nullptr_t)1231 : value(nullptr), hasOffsetApplied(false) {}1232 /*implicit*/ ConstantLValue(cir::GlobalViewAttr address)1233 : value(address), hasOffsetApplied(false) {}1234 1235 ConstantLValue() : value(nullptr), hasOffsetApplied(false) {}1236};1237 1238/// A helper class for emitting constant l-values.1239class ConstantLValueEmitter1240 : public ConstStmtVisitor<ConstantLValueEmitter, ConstantLValue> {1241 CIRGenModule &cgm;1242 ConstantEmitter &emitter;1243 const APValue &value;1244 QualType destType;1245 1246 // Befriend StmtVisitorBase so that we don't have to expose Visit*.1247 friend StmtVisitorBase;1248 1249public:1250 ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,1251 QualType destType)1252 : cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}1253 1254 mlir::Attribute tryEmit();1255 1256private:1257 mlir::Attribute tryEmitAbsolute(mlir::Type destTy);1258 ConstantLValue tryEmitBase(const APValue::LValueBase &base);1259 1260 ConstantLValue VisitStmt(const Stmt *s) { return nullptr; }1261 ConstantLValue VisitConstantExpr(const ConstantExpr *e);1262 ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *e);1263 ConstantLValue VisitStringLiteral(const StringLiteral *e);1264 ConstantLValue VisitObjCBoxedExpr(const ObjCBoxedExpr *e);1265 ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *e);1266 ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *e);1267 ConstantLValue VisitPredefinedExpr(const PredefinedExpr *e);1268 ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *e);1269 ConstantLValue VisitCallExpr(const CallExpr *e);1270 ConstantLValue VisitBlockExpr(const BlockExpr *e);1271 ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *e);1272 ConstantLValue1273 VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);1274 1275 /// Return GEP-like value offset1276 mlir::ArrayAttr getOffset(mlir::Type ty) {1277 int64_t offset = value.getLValueOffset().getQuantity();1278 cir::CIRDataLayout layout(cgm.getModule());1279 SmallVector<int64_t, 3> idxVec;1280 cgm.getBuilder().computeGlobalViewIndicesFromFlatOffset(offset, ty, layout,1281 idxVec);1282 1283 llvm::SmallVector<mlir::Attribute, 3> indices;1284 for (int64_t i : idxVec) {1285 mlir::IntegerAttr intAttr = cgm.getBuilder().getI32IntegerAttr(i);1286 indices.push_back(intAttr);1287 }1288 1289 if (indices.empty())1290 return {};1291 return cgm.getBuilder().getArrayAttr(indices);1292 }1293 1294 /// Apply the value offset to the given constant.1295 ConstantLValue applyOffset(ConstantLValue &c) {1296 // Handle attribute constant LValues.1297 if (auto attr = mlir::dyn_cast<mlir::Attribute>(c.value)) {1298 if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(attr)) {1299 auto baseTy = mlir::cast<cir::PointerType>(gv.getType()).getPointee();1300 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);1301 assert(!gv.getIndices() && "Global view is already indexed");1302 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(),1303 getOffset(baseTy));1304 }1305 llvm_unreachable("Unsupported attribute type to offset");1306 }1307 1308 cgm.errorNYI("ConstantLValue: non-attribute offset");1309 return {};1310 }1311};1312 1313} // namespace1314 1315mlir::Attribute ConstantLValueEmitter::tryEmit() {1316 const APValue::LValueBase &base = value.getLValueBase();1317 1318 // The destination type should be a pointer or reference1319 // type, but it might also be a cast thereof.1320 //1321 // FIXME: the chain of casts required should be reflected in the APValue.1322 // We need this in order to correctly handle things like a ptrtoint of a1323 // non-zero null pointer and addrspace casts that aren't trivially1324 // represented in LLVM IR.1325 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);1326 assert(mlir::isa<cir::PointerType>(destTy));1327 1328 // If there's no base at all, this is a null or absolute pointer,1329 // possibly cast back to an integer type.1330 if (!base)1331 return tryEmitAbsolute(destTy);1332 1333 // Otherwise, try to emit the base.1334 ConstantLValue result = tryEmitBase(base);1335 1336 // If that failed, we're done.1337 llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;1338 if (!value)1339 return {};1340 1341 // Apply the offset if necessary and not already done.1342 if (!result.hasOffsetApplied)1343 value = applyOffset(result).value;1344 1345 // Convert to the appropriate type; this could be an lvalue for1346 // an integer. FIXME: performAddrSpaceCast1347 if (mlir::isa<cir::PointerType>(destTy)) {1348 if (auto attr = mlir::dyn_cast<mlir::Attribute>(value))1349 return attr;1350 cgm.errorNYI("ConstantLValueEmitter: non-attribute pointer");1351 return {};1352 }1353 1354 cgm.errorNYI("ConstantLValueEmitter: other?");1355 return {};1356}1357 1358/// Try to emit an absolute l-value, such as a null pointer or an integer1359/// bitcast to pointer type.1360mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {1361 // If we're producing a pointer, this is easy.1362 auto destPtrTy = mlir::cast<cir::PointerType>(destTy);1363 return cgm.getBuilder().getConstPtrAttr(1364 destPtrTy, value.getLValueOffset().getQuantity());1365}1366 1367ConstantLValue1368ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {1369 // Handle values.1370 if (const ValueDecl *d = base.dyn_cast<const ValueDecl *>()) {1371 // The constant always points to the canonical declaration. We want to look1372 // at properties of the most recent declaration at the point of emission.1373 d = cast<ValueDecl>(d->getMostRecentDecl());1374 1375 if (d->hasAttr<WeakRefAttr>()) {1376 cgm.errorNYI(d->getSourceRange(),1377 "ConstantLValueEmitter: emit pointer base for weakref");1378 return {};1379 }1380 1381 if (auto *fd = dyn_cast<FunctionDecl>(d)) {1382 cir::FuncOp fop = cgm.getAddrOfFunction(fd);1383 CIRGenBuilderTy &builder = cgm.getBuilder();1384 mlir::MLIRContext *mlirContext = builder.getContext();1385 return cir::GlobalViewAttr::get(1386 builder.getPointerTo(fop.getFunctionType()),1387 mlir::FlatSymbolRefAttr::get(mlirContext, fop.getSymNameAttr()));1388 }1389 1390 if (auto *vd = dyn_cast<VarDecl>(d)) {1391 // We can never refer to a variable with local storage.1392 if (!vd->hasLocalStorage()) {1393 if (vd->isFileVarDecl() || vd->hasExternalStorage())1394 return cgm.getAddrOfGlobalVarAttr(vd);1395 1396 if (vd->isLocalVarDecl()) {1397 cgm.errorNYI(vd->getSourceRange(),1398 "ConstantLValueEmitter: local var decl");1399 return {};1400 }1401 }1402 }1403 1404 // Classic codegen handles MSGuidDecl,UnnamedGlobalConstantDecl, and1405 // TemplateParamObjectDecl, but it can also fall through from VarDecl,1406 // in which case it silently returns nullptr. For now, let's emit an1407 // error to see what cases we need to handle.1408 cgm.errorNYI(d->getSourceRange(),1409 "ConstantLValueEmitter: unhandled value decl");1410 return {};1411 }1412 1413 // Handle typeid(T).1414 if (base.dyn_cast<TypeInfoLValue>()) {1415 cgm.errorNYI("ConstantLValueEmitter: typeid");1416 return {};1417 }1418 1419 // Otherwise, it must be an expression.1420 return Visit(base.get<const Expr *>());1421}1422 1423ConstantLValue ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *e) {1424 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: constant expr");1425 return {};1426}1427 1428ConstantLValue1429ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *e) {1430 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: compound literal");1431 return {};1432}1433 1434ConstantLValue1435ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *e) {1436 return cgm.getAddrOfConstantStringFromLiteral(e);1437}1438 1439ConstantLValue1440ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *e) {1441 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc encode expr");1442 return {};1443}1444 1445ConstantLValue1446ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *e) {1447 cgm.errorNYI(e->getSourceRange(),1448 "ConstantLValueEmitter: objc string literal");1449 return {};1450}1451 1452ConstantLValue1453ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *e) {1454 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc boxed expr");1455 return {};1456}1457 1458ConstantLValue1459ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *e) {1460 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: predefined expr");1461 return {};1462}1463 1464ConstantLValue1465ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *e) {1466 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: addr label expr");1467 return {};1468}1469 1470ConstantLValue ConstantLValueEmitter::VisitCallExpr(const CallExpr *e) {1471 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: call expr");1472 return {};1473}1474 1475ConstantLValue ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *e) {1476 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: block expr");1477 return {};1478}1479 1480ConstantLValue1481ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *e) {1482 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: cxx typeid expr");1483 return {};1484}1485 1486ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(1487 const MaterializeTemporaryExpr *e) {1488 cgm.errorNYI(e->getSourceRange(),1489 "ConstantLValueEmitter: materialize temporary expr");1490 return {};1491}1492 1493//===----------------------------------------------------------------------===//1494// ConstantEmitter1495//===----------------------------------------------------------------------===//1496 1497mlir::Attribute ConstantEmitter::tryEmitForInitializer(const VarDecl &d) {1498 initializeNonAbstract();1499 return markIfFailed(tryEmitPrivateForVarInit(d));1500}1501 1502void ConstantEmitter::finalize(cir::GlobalOp gv) {1503 assert(initializedNonAbstract &&1504 "finalizing emitter that was used for abstract emission?");1505 assert(!finalized && "finalizing emitter multiple times");1506 assert(!gv.isDeclaration());1507#ifndef NDEBUG1508 // Note that we might also be Failed.1509 finalized = true;1510#endif // NDEBUG1511}1512 1513mlir::Attribute1514ConstantEmitter::tryEmitAbstractForInitializer(const VarDecl &d) {1515 AbstractStateRAII state(*this, true);1516 return tryEmitPrivateForVarInit(d);1517}1518 1519ConstantEmitter::~ConstantEmitter() {1520 assert((!initializedNonAbstract || finalized || failed) &&1521 "not finalized after being initialized for non-abstract emission");1522}1523 1524static mlir::TypedAttr emitNullConstantForBase(CIRGenModule &cgm,1525 mlir::Type baseType,1526 const CXXRecordDecl *baseDecl);1527 1528static mlir::TypedAttr emitNullConstant(CIRGenModule &cgm, const RecordDecl *rd,1529 bool asCompleteObject) {1530 const CIRGenRecordLayout &layout = cgm.getTypes().getCIRGenRecordLayout(rd);1531 mlir::Type ty = (asCompleteObject ? layout.getCIRType()1532 : layout.getBaseSubobjectCIRType());1533 auto recordTy = mlir::cast<cir::RecordType>(ty);1534 1535 unsigned numElements = recordTy.getNumElements();1536 SmallVector<mlir::Attribute> elements(numElements);1537 1538 auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);1539 // Fill in all the bases.1540 if (cxxrd) {1541 for (const CXXBaseSpecifier &base : cxxrd->bases()) {1542 if (base.isVirtual()) {1543 // Ignore virtual bases; if we're laying out for a complete1544 // object, we'll lay these out later.1545 continue;1546 }1547 1548 const auto *baseDecl = base.getType()->castAsCXXRecordDecl();1549 // Ignore empty bases.1550 if (isEmptyRecordForLayout(cgm.getASTContext(), base.getType()) ||1551 cgm.getASTContext()1552 .getASTRecordLayout(baseDecl)1553 .getNonVirtualSize()1554 .isZero())1555 continue;1556 1557 unsigned fieldIndex = layout.getNonVirtualBaseCIRFieldNo(baseDecl);1558 mlir::Type baseType = recordTy.getElementType(fieldIndex);1559 elements[fieldIndex] = emitNullConstantForBase(cgm, baseType, baseDecl);1560 }1561 }1562 1563 // Fill in all the fields.1564 for (const FieldDecl *field : rd->fields()) {1565 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we1566 // will fill in later.)1567 if (!field->isBitField() &&1568 !isEmptyFieldForLayout(cgm.getASTContext(), field)) {1569 unsigned fieldIndex = layout.getCIRFieldNo(field);1570 elements[fieldIndex] = cgm.emitNullConstantAttr(field->getType());1571 }1572 1573 // For unions, stop after the first named field.1574 if (rd->isUnion()) {1575 if (field->getIdentifier())1576 break;1577 if (const auto *fieldRD = field->getType()->getAsRecordDecl())1578 if (fieldRD->findFirstNamedDataMember())1579 break;1580 }1581 }1582 1583 // Fill in the virtual bases, if we're working with the complete object.1584 if (cxxrd && asCompleteObject) {1585 for ([[maybe_unused]] const CXXBaseSpecifier &vbase : cxxrd->vbases()) {1586 cgm.errorNYI(vbase.getSourceRange(), "emitNullConstant: virtual base");1587 return {};1588 }1589 }1590 1591 // Now go through all other fields and zero them out.1592 for (unsigned i = 0; i != numElements; ++i) {1593 if (!elements[i]) {1594 cgm.errorNYI(rd->getSourceRange(), "emitNullConstant: field not zeroed");1595 return {};1596 }1597 }1598 1599 mlir::MLIRContext *mlirContext = recordTy.getContext();1600 return cir::ConstRecordAttr::get(recordTy,1601 mlir::ArrayAttr::get(mlirContext, elements));1602}1603 1604/// Emit the null constant for a base subobject.1605static mlir::TypedAttr emitNullConstantForBase(CIRGenModule &cgm,1606 mlir::Type baseType,1607 const CXXRecordDecl *baseDecl) {1608 const CIRGenRecordLayout &baseLayout =1609 cgm.getTypes().getCIRGenRecordLayout(baseDecl);1610 1611 // Just zero out bases that don't have any pointer to data members.1612 if (baseLayout.isZeroInitializableAsBase())1613 return cgm.getBuilder().getZeroInitAttr(baseType);1614 1615 // Otherwise, we can just use its null constant.1616 return emitNullConstant(cgm, baseDecl, /*asCompleteObject=*/false);1617}1618 1619mlir::Attribute ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &d) {1620 // Make a quick check if variable can be default NULL initialized1621 // and avoid going through rest of code which may do, for c++11,1622 // initialization of memory to all NULLs.1623 if (!d.hasLocalStorage()) {1624 QualType ty = cgm.getASTContext().getBaseElementType(d.getType());1625 if (ty->isRecordType()) {1626 if (const auto *e = dyn_cast_or_null<CXXConstructExpr>(d.getInit())) {1627 const CXXConstructorDecl *cd = e->getConstructor();1628 // FIXME: we should probably model this more closely to C++ than1629 // just emitting a global with zero init (mimic what we do for trivial1630 // assignments and whatnots). Since this is for globals shouldn't1631 // be a problem for the near future.1632 if (cd->isTrivial() && cd->isDefaultConstructor()) {1633 const auto *cxxrd = ty->castAsCXXRecordDecl();1634 if (cxxrd->getNumBases() != 0) {1635 // There may not be anything additional to do here, but this will1636 // force us to pause and test this path when it is supported.1637 cgm.errorNYI("tryEmitPrivateForVarInit: cxx record with bases");1638 return {};1639 }1640 if (!cgm.getTypes().isZeroInitializable(cxxrd)) {1641 // To handle this case, we really need to go through1642 // emitNullConstant, but we need an attribute, not a value1643 cgm.errorNYI(1644 "tryEmitPrivateForVarInit: non-zero-initializable cxx record");1645 return {};1646 }1647 return cir::ZeroAttr::get(cgm.convertType(d.getType()));1648 }1649 }1650 }1651 }1652 inConstantContext = d.hasConstantInitialization();1653 1654 const Expr *e = d.getInit();1655 assert(e && "No initializer to emit");1656 1657 QualType destType = d.getType();1658 1659 if (!destType->isReferenceType()) {1660 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);1661 if (mlir::Attribute c = ConstExprEmitter(*this).Visit(const_cast<Expr *>(e),1662 nonMemoryDestType))1663 return emitForMemory(c, destType);1664 }1665 1666 // Try to emit the initializer. Note that this can allow some things that1667 // are not allowed by tryEmitPrivateForMemory alone.1668 if (APValue *value = d.evaluateValue())1669 return tryEmitPrivateForMemory(*value, destType);1670 1671 return {};1672}1673 1674mlir::Attribute ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *ce) {1675 if (!ce->hasAPValueResult())1676 return {};1677 1678 QualType retType = ce->getType();1679 if (ce->isGLValue())1680 retType = cgm.getASTContext().getLValueReferenceType(retType);1681 1682 return emitAbstract(ce->getBeginLoc(), ce->getAPValueResult(), retType);1683}1684 1685mlir::Attribute ConstantEmitter::tryEmitPrivateForMemory(const Expr *e,1686 QualType destType) {1687 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);1688 mlir::TypedAttr c = tryEmitPrivate(e, nonMemoryDestType);1689 if (c) {1690 mlir::Attribute attr = emitForMemory(c, destType);1691 return mlir::cast<mlir::TypedAttr>(attr);1692 }1693 return nullptr;1694}1695 1696mlir::Attribute ConstantEmitter::tryEmitPrivateForMemory(const APValue &value,1697 QualType destType) {1698 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);1699 mlir::Attribute c = tryEmitPrivate(value, nonMemoryDestType);1700 return (c ? emitForMemory(c, destType) : nullptr);1701}1702 1703mlir::Attribute ConstantEmitter::emitAbstract(const Expr *e,1704 QualType destType) {1705 AbstractStateRAII state{*this, true};1706 mlir::Attribute c = mlir::cast<mlir::Attribute>(tryEmitPrivate(e, destType));1707 if (!c)1708 cgm.errorNYI(e->getSourceRange(),1709 "emitAbstract failed, emit null constaant");1710 return c;1711}1712 1713mlir::Attribute ConstantEmitter::emitAbstract(SourceLocation loc,1714 const APValue &value,1715 QualType destType) {1716 AbstractStateRAII state(*this, true);1717 mlir::Attribute c = tryEmitPrivate(value, destType);1718 if (!c)1719 cgm.errorNYI(loc, "emitAbstract failed, emit null constaant");1720 return c;1721}1722 1723mlir::Attribute ConstantEmitter::emitNullForMemory(mlir::Location loc,1724 CIRGenModule &cgm,1725 QualType t) {1726 cir::ConstantOp cstOp =1727 cgm.emitNullConstant(t, loc).getDefiningOp<cir::ConstantOp>();1728 assert(cstOp && "expected cir.const op");1729 return emitForMemory(cgm, cstOp.getValue(), t);1730}1731 1732mlir::Attribute ConstantEmitter::emitForMemory(mlir::Attribute c,1733 QualType destType) {1734 // For an _Atomic-qualified constant, we may need to add tail padding.1735 if (destType->getAs<AtomicType>()) {1736 cgm.errorNYI("emitForMemory: atomic type");1737 return {};1738 }1739 1740 return c;1741}1742 1743mlir::Attribute ConstantEmitter::emitForMemory(CIRGenModule &cgm,1744 mlir::Attribute c,1745 QualType destType) {1746 // For an _Atomic-qualified constant, we may need to add tail padding.1747 if (destType->getAs<AtomicType>()) {1748 cgm.errorNYI("atomic constants");1749 }1750 1751 return c;1752}1753 1754mlir::TypedAttr ConstantEmitter::tryEmitPrivate(const Expr *e,1755 QualType destType) {1756 assert(!destType->isVoidType() && "can't emit a void constant");1757 1758 if (mlir::Attribute c =1759 ConstExprEmitter(*this).Visit(const_cast<Expr *>(e), destType))1760 return llvm::dyn_cast<mlir::TypedAttr>(c);1761 1762 Expr::EvalResult result;1763 1764 bool success = false;1765 1766 if (destType->isReferenceType())1767 success = e->EvaluateAsLValue(result, cgm.getASTContext());1768 else1769 success =1770 e->EvaluateAsRValue(result, cgm.getASTContext(), inConstantContext);1771 1772 if (success && !result.hasSideEffects()) {1773 mlir::Attribute c = tryEmitPrivate(result.Val, destType);1774 return llvm::dyn_cast<mlir::TypedAttr>(c);1775 }1776 1777 return nullptr;1778}1779 1780mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,1781 QualType destType) {1782 auto &builder = cgm.getBuilder();1783 switch (value.getKind()) {1784 case APValue::None:1785 case APValue::Indeterminate:1786 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate none or indeterminate");1787 return {};1788 case APValue::Int: {1789 mlir::Type ty = cgm.convertType(destType);1790 if (mlir::isa<cir::BoolType>(ty))1791 return builder.getCIRBoolAttr(value.getInt().getZExtValue());1792 assert(mlir::isa<cir::IntType>(ty) && "expected integral type");1793 return cir::IntAttr::get(ty, value.getInt());1794 }1795 case APValue::Float: {1796 const llvm::APFloat &init = value.getFloat();1797 if (&init.getSemantics() == &llvm::APFloat::IEEEhalf() &&1798 !cgm.getASTContext().getLangOpts().NativeHalfType &&1799 cgm.getASTContext().getTargetInfo().useFP16ConversionIntrinsics()) {1800 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate half");1801 return {};1802 }1803 1804 mlir::Type ty = cgm.convertType(destType);1805 assert(mlir::isa<cir::FPTypeInterface>(ty) &&1806 "expected floating-point type");1807 return cir::FPAttr::get(ty, init);1808 }1809 case APValue::Array: {1810 const ArrayType *arrayTy = cgm.getASTContext().getAsArrayType(destType);1811 const QualType arrayElementTy = arrayTy->getElementType();1812 const unsigned numElements = value.getArraySize();1813 const unsigned numInitElts = value.getArrayInitializedElts();1814 1815 mlir::Attribute filler;1816 if (value.hasArrayFiller()) {1817 filler = tryEmitPrivate(value.getArrayFiller(), arrayElementTy);1818 if (!filler)1819 return {};1820 }1821 1822 SmallVector<mlir::TypedAttr, 16> elements;1823 if (filler && builder.isNullValue(filler))1824 elements.reserve(numInitElts + 1);1825 else1826 elements.reserve(numInitElts);1827 1828 mlir::Type commonElementType;1829 for (unsigned i = 0; i < numInitElts; ++i) {1830 const APValue &arrayElement = value.getArrayInitializedElt(i);1831 const mlir::Attribute element =1832 tryEmitPrivateForMemory(arrayElement, arrayElementTy);1833 if (!element)1834 return {};1835 1836 const mlir::TypedAttr elementTyped = mlir::cast<mlir::TypedAttr>(element);1837 if (i == 0)1838 commonElementType = elementTyped.getType();1839 else if (elementTyped.getType() != commonElementType) {1840 commonElementType = {};1841 }1842 1843 elements.push_back(elementTyped);1844 }1845 1846 mlir::TypedAttr typedFiller = llvm::cast_or_null<mlir::TypedAttr>(filler);1847 if (filler && !typedFiller)1848 cgm.errorNYI("array filler should always be typed");1849 1850 mlir::Type desiredType = cgm.convertType(destType);1851 return emitArrayConstant(cgm, desiredType, commonElementType, numElements,1852 elements, typedFiller);1853 }1854 case APValue::Vector: {1855 const QualType elementType =1856 destType->castAs<VectorType>()->getElementType();1857 const unsigned numElements = value.getVectorLength();1858 1859 SmallVector<mlir::Attribute, 16> elements;1860 elements.reserve(numElements);1861 1862 for (unsigned i = 0; i < numElements; ++i) {1863 const mlir::Attribute element =1864 tryEmitPrivateForMemory(value.getVectorElt(i), elementType);1865 if (!element)1866 return {};1867 elements.push_back(element);1868 }1869 1870 const auto desiredVecTy =1871 mlir::cast<cir::VectorType>(cgm.convertType(destType));1872 1873 return cir::ConstVectorAttr::get(1874 desiredVecTy,1875 mlir::ArrayAttr::get(cgm.getBuilder().getContext(), elements));1876 }1877 case APValue::MemberPointer: {1878 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer");1879 return {};1880 }1881 case APValue::LValue:1882 return ConstantLValueEmitter(*this, value, destType).tryEmit();1883 case APValue::Struct:1884 case APValue::Union:1885 return ConstRecordBuilder::buildRecord(*this, value, destType);1886 case APValue::ComplexInt:1887 case APValue::ComplexFloat: {1888 mlir::Type desiredType = cgm.convertType(destType);1889 auto complexType = mlir::dyn_cast<cir::ComplexType>(desiredType);1890 1891 mlir::Type complexElemTy = complexType.getElementType();1892 if (isa<cir::IntType>(complexElemTy)) {1893 const llvm::APSInt &real = value.getComplexIntReal();1894 const llvm::APSInt &imag = value.getComplexIntImag();1895 return cir::ConstComplexAttr::get(builder.getContext(), complexType,1896 cir::IntAttr::get(complexElemTy, real),1897 cir::IntAttr::get(complexElemTy, imag));1898 }1899 1900 assert(isa<cir::FPTypeInterface>(complexElemTy) &&1901 "expected floating-point type");1902 const llvm::APFloat &real = value.getComplexFloatReal();1903 const llvm::APFloat &imag = value.getComplexFloatImag();1904 return cir::ConstComplexAttr::get(builder.getContext(), complexType,1905 cir::FPAttr::get(complexElemTy, real),1906 cir::FPAttr::get(complexElemTy, imag));1907 }1908 case APValue::FixedPoint:1909 case APValue::AddrLabelDiff:1910 cgm.errorNYI(1911 "ConstExprEmitter::tryEmitPrivate fixed point, addr label diff");1912 return {};1913 }1914 llvm_unreachable("Unknown APValue kind");1915}1916 1917mlir::Value CIRGenModule::emitNullConstant(QualType t, mlir::Location loc) {1918 return builder.getConstant(loc, emitNullConstantAttr(t));1919}1920 1921mlir::TypedAttr CIRGenModule::emitNullConstantAttr(QualType t) {1922 if (t->getAs<PointerType>())1923 return builder.getConstNullPtrAttr(getTypes().convertTypeForMem(t));1924 1925 if (getTypes().isZeroInitializable(t))1926 return builder.getZeroInitAttr(getTypes().convertTypeForMem(t));1927 1928 if (getASTContext().getAsConstantArrayType(t)) {1929 errorNYI("CIRGenModule::emitNullConstantAttr ConstantArrayType");1930 return {};1931 }1932 1933 if (const RecordType *rt = t->getAs<RecordType>())1934 return ::emitNullConstant(*this, rt->getDecl(), /*asCompleteObject=*/true);1935 1936 assert(t->isMemberDataPointerType() &&1937 "Should only see pointers to data members here!");1938 1939 errorNYI("CIRGenModule::emitNullConstantAttr unsupported type");1940 return {};1941}1942 1943mlir::TypedAttr1944CIRGenModule::emitNullConstantForBase(const CXXRecordDecl *record) {1945 return ::emitNullConstant(*this, record, false);1946}1947