15#include "mlir/IR/DialectImplementation.h"
16#include "llvm/ADT/TypeSwitch.h"
24 mlir::ArrayAttr &members);
31 cir::IntTypeInterface ty);
34 cir::IntTypeInterface ty);
41static mlir::ParseResult
43 mlir::FailureOr<llvm::APFloat> &value,
44 cir::FPTypeInterface fpType);
51 cir::TargetAddressSpaceAttr &attr);
54 cir::TargetAddressSpaceAttr attr);
57 mlir::IntegerAttr &value);
61#define GET_ATTRDEF_CLASSES
62#include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc"
71Attribute CIRDialect::parseAttribute(DialectAsmParser &parser,
73 llvm::SMLoc typeLoc = parser.getCurrentLocation();
74 llvm::StringRef mnemonic;
76 OptionalParseResult parseResult =
77 generatedAttributeParser(parser, &mnemonic, type, genAttr);
78 if (parseResult.has_value())
80 parser.emitError(typeLoc,
"unknown attribute in CIR dialect");
84void CIRDialect::printAttribute(Attribute attr, DialectAsmPrinter &os)
const {
85 if (failed(generatedAttributePrinter(attr, os)))
86 llvm_unreachable(
"unexpected CIR type kind");
90 mlir::ArrayAttr members) {
92 llvm::interleaveComma(members, printer);
97 mlir::ArrayAttr &members) {
100 auto delimiter = AsmParser::Delimiter::Braces;
101 auto result = parser.parseCommaSeparatedList(delimiter, [&]() {
102 mlir::TypedAttr attr;
103 if (parser.parseAttribute(attr).failed())
104 return mlir::failure();
105 elts.push_back(attr);
106 return mlir::success();
110 return mlir::failure();
112 members = mlir::ArrayAttr::get(parser.getContext(), elts);
113 return mlir::success();
121ConstRecordAttr::verify(function_ref<InFlightDiagnostic()> emitError,
122 mlir::Type type, ArrayAttr members) {
123 auto sTy = mlir::dyn_cast_if_present<cir::RecordType>(type);
125 return emitError() <<
"expected !cir.record type";
127 if (sTy.getMembers().size() != members.size())
128 return emitError() <<
"number of elements must match";
130 unsigned attrIdx = 0;
131 for (
auto &member : sTy.getMembers()) {
132 auto m = mlir::cast<mlir::TypedAttr>(members[attrIdx]);
133 if (member != m.getType())
134 return emitError() <<
"element at index " << attrIdx <<
" has type "
136 <<
" but the expected type for this element is "
148LogicalResult OptInfoAttr::verify(function_ref<InFlightDiagnostic()> emitError,
149 unsigned level,
unsigned size) {
152 <<
"optimization level must be between 0 and 3 inclusive";
155 <<
"size optimization level must be between 0 and 2 inclusive";
165static ParseResult
parseConstPtr(AsmParser &parser, mlir::IntegerAttr &value) {
167 if (parser.parseOptionalKeyword(
"null").succeeded()) {
168 value = parser.getBuilder().getI64IntegerAttr(0);
172 return parser.parseAttribute(value);
186template <
typename IntT>
188 if constexpr (std::is_signed_v<IntT>) {
189 return value.getSExtValue() != expectedValue;
191 return value.getZExtValue() != expectedValue;
195template <
typename IntT>
198 cir::IntTypeInterface ty) {
200 const bool isSigned = ty.isSigned();
201 if (p.parseInteger(ivalue))
202 return p.emitError(p.getCurrentLocation(),
"expected integer value");
204 value = mlir::APInt(ty.getWidth(), ivalue, isSigned,
true);
206 return p.emitError(p.getCurrentLocation(),
207 "integer value too large for the given type");
213 cir::IntTypeInterface ty) {
220 cir::IntTypeInterface ty) {
222 p << value.getSExtValue();
224 p << value.getZExtValue();
227LogicalResult IntAttr::verify(function_ref<InFlightDiagnostic()> emitError,
228 cir::IntTypeInterface type, llvm::APInt value) {
229 if (value.getBitWidth() != type.getWidth())
230 return emitError() <<
"type and value bitwidth mismatch: "
231 << type.getWidth() <<
" != " << value.getBitWidth();
244 FailureOr<APFloat> &value,
245 cir::FPTypeInterface fpType) {
247 APFloat parsedValue(0.0);
248 if (parser.parseFloat(fpType.getFloatSemantics(), parsedValue))
251 value.emplace(parsedValue);
255FPAttr FPAttr::getZero(Type type) {
258 mlir::cast<cir::FPTypeInterface>(type).getFloatSemantics()));
261LogicalResult FPAttr::verify(function_ref<InFlightDiagnostic()> emitError,
262 cir::FPTypeInterface fpType, APFloat value) {
263 if (APFloat::SemanticsToEnum(fpType.getFloatSemantics()) !=
264 APFloat::SemanticsToEnum(value.getSemantics()))
265 return emitError() <<
"floating-point semantics mismatch";
275ConstComplexAttr::verify(function_ref<InFlightDiagnostic()> emitError,
276 cir::ComplexType type, mlir::TypedAttr real,
277 mlir::TypedAttr imag) {
278 mlir::Type elemType = type.getElementType();
279 if (real.getType() != elemType)
281 <<
"type of the real part does not match the complex type";
283 if (imag.getType() != elemType)
285 <<
"type of the imaginary part does not match the complex type";
295ConstArrayAttr::verify(function_ref<InFlightDiagnostic()> emitError, Type type,
296 Attribute elts,
int trailingZerosNum) {
298 if (!(mlir::isa<ArrayAttr, StringAttr>(elts)))
299 return emitError() <<
"constant array expects ArrayAttr or StringAttr";
301 if (
auto strAttr = mlir::dyn_cast<StringAttr>(elts)) {
302 const auto arrayTy = mlir::cast<ArrayType>(type);
303 const auto intTy = mlir::dyn_cast<IntType>(arrayTy.getElementType());
306 if (!intTy || intTy.getWidth() != 8)
308 <<
"constant array element for string literals expects "
309 "!cir.int<u, 8> element type";
313 assert(mlir::isa<ArrayAttr>(elts));
314 const auto arrayAttr = mlir::cast<mlir::ArrayAttr>(elts);
315 const auto arrayTy = mlir::cast<ArrayType>(type);
318 if (arrayTy.getSize() != arrayAttr.size() + trailingZerosNum)
319 return emitError() <<
"constant array size should match type size";
323Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {
324 mlir::FailureOr<Type> resultTy;
325 mlir::FailureOr<Attribute> resultVal;
328 if (parser.parseLess())
332 resultVal = FieldParser<Attribute>::parse(parser);
333 if (failed(resultVal)) {
335 parser.getCurrentLocation(),
336 "failed to parse ConstArrayAttr parameter 'value' which is "
337 "to be a `Attribute`");
342 if (mlir::isa<ArrayAttr>(*resultVal)) {
344 if (parser.parseOptionalColon().failed()) {
347 resultTy = FieldParser<Type>::parse(parser);
348 if (failed(resultTy)) {
350 parser.getCurrentLocation(),
351 "failed to parse ConstArrayAttr parameter 'type' which is "
352 "to be a `::mlir::Type`");
357 auto ta = mlir::cast<TypedAttr>(*resultVal);
358 resultTy = ta.getType();
359 if (mlir::isa<mlir::NoneType>(*resultTy)) {
360 parser.emitError(parser.getCurrentLocation(),
361 "expected type declaration for string literal");
367 if (parser.parseOptionalComma().succeeded()) {
368 if (parser.parseOptionalKeyword(
"trailing_zeros").succeeded()) {
370 mlir::cast<cir::ArrayType>(resultTy.value()).getSize();
371 mlir::Attribute elts = resultVal.value();
372 if (
auto str = mlir::dyn_cast<mlir::StringAttr>(elts))
373 zeros = typeSize - str.size();
375 zeros = typeSize - mlir::cast<mlir::ArrayAttr>(elts).size();
382 if (parser.parseGreater())
385 return parser.getChecked<ConstArrayAttr>(
386 parser.getCurrentLocation(), parser.getContext(), resultTy.value(),
387 resultVal.value(), zeros);
390void ConstArrayAttr::print(AsmPrinter &printer)
const {
392 printer.printStrippedAttrOrType(getElts());
393 if (getTrailingZerosNum())
394 printer <<
", trailing_zeros";
403cir::ConstVectorAttr::verify(function_ref<InFlightDiagnostic()> emitError,
404 Type type, ArrayAttr elts) {
406 if (!mlir::isa<cir::VectorType>(type))
407 return emitError() <<
"type of cir::ConstVectorAttr is not a "
411 const auto vecType = mlir::cast<cir::VectorType>(type);
413 if (vecType.getSize() != elts.size())
415 <<
"number of constant elements should match vector size";
418 LogicalResult elementTypeCheck =
success();
419 elts.walkImmediateSubElements(
420 [&](Attribute element) {
421 if (elementTypeCheck.failed()) {
425 auto typedElement = mlir::dyn_cast<TypedAttr>(element);
427 typedElement.getType() != vecType.getElementType()) {
428 elementTypeCheck = failure();
429 emitError() <<
"constant type should match vector element type";
434 return elementTypeCheck;
441LogicalResult cir::VTableAttr::verify(
442 llvm::function_ref<mlir::InFlightDiagnostic()> emitError, mlir::Type type,
443 mlir::ArrayAttr data) {
444 auto sTy = mlir::dyn_cast_if_present<cir::RecordType>(type);
446 return emitError() <<
"expected !cir.record type result";
447 if (sTy.getMembers().empty() || data.empty())
448 return emitError() <<
"expected record type with one or more subtype";
450 if (cir::ConstRecordAttr::verify(emitError, type, data).failed())
453 for (
const auto &element : data.getAsRange<mlir::Attribute>()) {
454 const auto &constArrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(element);
456 return emitError() <<
"expected constant array subtype";
458 LogicalResult eltTypeCheck =
success();
459 auto arrayElts = mlir::cast<ArrayAttr>(constArrayAttr.getElts());
460 arrayElts.walkImmediateSubElements(
461 [&](mlir::Attribute attr) {
462 if (mlir::isa<ConstPtrAttr, GlobalViewAttr>(attr))
465 eltTypeCheck = emitError()
466 <<
"expected GlobalViewAttr or ConstPtrAttr";
468 [&](mlir::Type type) {});
469 if (eltTypeCheck.failed())
479std::string DynamicCastInfoAttr::getAlias()
const {
482 std::string alias =
"dyn_cast_info_";
484 alias.append(getSrcRtti().getSymbol().getValue());
485 alias.push_back(
'_');
486 alias.append(getDestRtti().getSymbol().getValue());
491LogicalResult DynamicCastInfoAttr::verify(
492 function_ref<InFlightDiagnostic()> emitError, cir::GlobalViewAttr srcRtti,
493 cir::GlobalViewAttr destRtti, mlir::FlatSymbolRefAttr runtimeFunc,
494 mlir::FlatSymbolRefAttr badCastFunc, cir::IntAttr offsetHint) {
495 auto isRttiPtr = [](mlir::Type ty) {
498 auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty);
502 auto pointeeIntTy = mlir::dyn_cast<cir::IntType>(ptrTy.getPointee());
506 return pointeeIntTy.isUnsigned() && pointeeIntTy.getWidth() == 8;
509 if (!isRttiPtr(srcRtti.getType()))
510 return emitError() <<
"srcRtti must be an RTTI pointer";
512 if (!isRttiPtr(destRtti.getType()))
513 return emitError() <<
"destRtti must be an RTTI pointer";
522void CIRDialect::registerAttributes() {
524#define GET_ATTRDEF_LIST
525#include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc"
static mlir::ParseResult parseFloatLiteral(mlir::AsmParser &parser, mlir::FailureOr< llvm::APFloat > &value, cir::FPTypeInterface fpType)
static mlir::ParseResult parseIntLiteralImpl(mlir::AsmParser &p, llvm::APInt &value, cir::IntTypeInterface ty)
static void printConstPtr(mlir::AsmPrinter &p, mlir::IntegerAttr value)
static void printRecordMembers(mlir::AsmPrinter &p, mlir::ArrayAttr members)
static mlir::ParseResult parseIntLiteral(mlir::AsmParser &parser, llvm::APInt &value, cir::IntTypeInterface ty)
mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p, cir::TargetAddressSpaceAttr &attr)
static void printIntLiteral(mlir::AsmPrinter &p, llvm::APInt value, cir::IntTypeInterface ty)
static mlir::ParseResult parseConstPtr(mlir::AsmParser &parser, mlir::IntegerAttr &value)
static bool isTooLargeForType(const mlir::APInt &value, IntT expectedValue)
static void printFloatLiteral(mlir::AsmPrinter &p, llvm::APFloat value, mlir::Type ty)
static mlir::ParseResult parseRecordMembers(mlir::AsmParser &parser, mlir::ArrayAttr &members)
void printTargetAddressSpace(mlir::AsmPrinter &p, cir::TargetAddressSpaceAttr attr)