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);
47 mlir::IntegerAttr &value);
51#define GET_ATTRDEF_CLASSES
52#include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc"
61Attribute CIRDialect::parseAttribute(DialectAsmParser &parser,
63 llvm::SMLoc typeLoc = parser.getCurrentLocation();
64 llvm::StringRef mnemonic;
66 OptionalParseResult parseResult =
67 generatedAttributeParser(parser, &mnemonic, type, genAttr);
68 if (parseResult.has_value())
70 parser.emitError(typeLoc,
"unknown attribute in CIR dialect");
74void CIRDialect::printAttribute(Attribute attr, DialectAsmPrinter &os)
const {
75 if (failed(generatedAttributePrinter(attr, os)))
76 llvm_unreachable(
"unexpected CIR type kind");
80 mlir::ArrayAttr members) {
82 llvm::interleaveComma(members, printer);
87 mlir::ArrayAttr &members) {
90 auto delimiter = AsmParser::Delimiter::Braces;
91 auto result = parser.parseCommaSeparatedList(delimiter, [&]() {
93 if (parser.parseAttribute(attr).failed())
94 return mlir::failure();
96 return mlir::success();
100 return mlir::failure();
102 members = mlir::ArrayAttr::get(parser.getContext(), elts);
103 return mlir::success();
111ConstRecordAttr::verify(function_ref<InFlightDiagnostic()> emitError,
112 mlir::Type type, ArrayAttr members) {
113 auto sTy = mlir::dyn_cast_if_present<cir::RecordType>(type);
115 return emitError() <<
"expected !cir.record type";
117 if (sTy.getMembers().size() != members.size())
118 return emitError() <<
"number of elements must match";
120 unsigned attrIdx = 0;
121 for (
auto &member : sTy.getMembers()) {
122 auto m = mlir::cast<mlir::TypedAttr>(members[attrIdx]);
123 if (member != m.getType())
124 return emitError() <<
"element at index " << attrIdx <<
" has type "
126 <<
" but the expected type for this element is "
138LogicalResult OptInfoAttr::verify(function_ref<InFlightDiagnostic()> emitError,
139 unsigned level,
unsigned size) {
142 <<
"optimization level must be between 0 and 3 inclusive";
145 <<
"size optimization level must be between 0 and 2 inclusive";
155static ParseResult
parseConstPtr(AsmParser &parser, mlir::IntegerAttr &value) {
157 if (parser.parseOptionalKeyword(
"null").succeeded()) {
158 value = parser.getBuilder().getI64IntegerAttr(0);
162 return parser.parseAttribute(value);
176template <
typename IntT>
178 if constexpr (std::is_signed_v<IntT>) {
179 return value.getSExtValue() != expectedValue;
181 return value.getZExtValue() != expectedValue;
185template <
typename IntT>
188 cir::IntTypeInterface ty) {
190 const bool isSigned = ty.isSigned();
191 if (p.parseInteger(ivalue))
192 return p.emitError(p.getCurrentLocation(),
"expected integer value");
194 value = mlir::APInt(ty.getWidth(), ivalue, isSigned,
true);
196 return p.emitError(p.getCurrentLocation(),
197 "integer value too large for the given type");
203 cir::IntTypeInterface ty) {
210 cir::IntTypeInterface ty) {
212 p << value.getSExtValue();
214 p << value.getZExtValue();
217LogicalResult IntAttr::verify(function_ref<InFlightDiagnostic()> emitError,
218 cir::IntTypeInterface type, llvm::APInt value) {
219 if (value.getBitWidth() != type.getWidth())
220 return emitError() <<
"type and value bitwidth mismatch: "
221 << type.getWidth() <<
" != " << value.getBitWidth();
234 FailureOr<APFloat> &value,
235 cir::FPTypeInterface fpType) {
237 APFloat parsedValue(0.0);
238 if (parser.parseFloat(fpType.getFloatSemantics(), parsedValue))
241 value.emplace(parsedValue);
245FPAttr FPAttr::getZero(Type type) {
248 mlir::cast<cir::FPTypeInterface>(type).getFloatSemantics()));
251LogicalResult FPAttr::verify(function_ref<InFlightDiagnostic()> emitError,
252 cir::FPTypeInterface fpType, APFloat value) {
253 if (APFloat::SemanticsToEnum(fpType.getFloatSemantics()) !=
254 APFloat::SemanticsToEnum(value.getSemantics()))
255 return emitError() <<
"floating-point semantics mismatch";
265ConstComplexAttr::verify(function_ref<InFlightDiagnostic()> emitError,
266 cir::ComplexType type, mlir::TypedAttr real,
267 mlir::TypedAttr imag) {
268 mlir::Type elemType = type.getElementType();
269 if (real.getType() != elemType)
271 <<
"type of the real part does not match the complex type";
273 if (imag.getType() != elemType)
275 <<
"type of the imaginary part does not match the complex type";
285ConstArrayAttr::verify(function_ref<InFlightDiagnostic()> emitError, Type type,
286 Attribute elts,
int trailingZerosNum) {
288 if (!(mlir::isa<ArrayAttr, StringAttr>(elts)))
289 return emitError() <<
"constant array expects ArrayAttr or StringAttr";
291 if (
auto strAttr = mlir::dyn_cast<StringAttr>(elts)) {
292 const auto arrayTy = mlir::cast<ArrayType>(type);
293 const auto intTy = mlir::dyn_cast<IntType>(arrayTy.getElementType());
296 if (!intTy || intTy.getWidth() != 8)
298 <<
"constant array element for string literals expects "
299 "!cir.int<u, 8> element type";
303 assert(mlir::isa<ArrayAttr>(elts));
304 const auto arrayAttr = mlir::cast<mlir::ArrayAttr>(elts);
305 const auto arrayTy = mlir::cast<ArrayType>(type);
308 if (arrayTy.getSize() != arrayAttr.size() + trailingZerosNum)
309 return emitError() <<
"constant array size should match type size";
313Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {
314 mlir::FailureOr<Type> resultTy;
315 mlir::FailureOr<Attribute> resultVal;
318 if (parser.parseLess())
322 resultVal = FieldParser<Attribute>::parse(parser);
323 if (failed(resultVal)) {
325 parser.getCurrentLocation(),
326 "failed to parse ConstArrayAttr parameter 'value' which is "
327 "to be a `Attribute`");
332 if (mlir::isa<ArrayAttr>(*resultVal)) {
334 if (parser.parseOptionalColon().failed()) {
337 resultTy = FieldParser<Type>::parse(parser);
338 if (failed(resultTy)) {
340 parser.getCurrentLocation(),
341 "failed to parse ConstArrayAttr parameter 'type' which is "
342 "to be a `::mlir::Type`");
347 auto ta = mlir::cast<TypedAttr>(*resultVal);
348 resultTy = ta.getType();
349 if (mlir::isa<mlir::NoneType>(*resultTy)) {
350 parser.emitError(parser.getCurrentLocation(),
351 "expected type declaration for string literal");
357 if (parser.parseOptionalComma().succeeded()) {
358 if (parser.parseOptionalKeyword(
"trailing_zeros").succeeded()) {
360 mlir::cast<cir::ArrayType>(resultTy.value()).getSize();
361 mlir::Attribute elts = resultVal.value();
362 if (
auto str = mlir::dyn_cast<mlir::StringAttr>(elts))
363 zeros = typeSize - str.size();
365 zeros = typeSize - mlir::cast<mlir::ArrayAttr>(elts).size();
372 if (parser.parseGreater())
375 return parser.getChecked<ConstArrayAttr>(
376 parser.getCurrentLocation(), parser.getContext(), resultTy.value(),
377 resultVal.value(), zeros);
380void ConstArrayAttr::print(AsmPrinter &printer)
const {
382 printer.printStrippedAttrOrType(getElts());
383 if (getTrailingZerosNum())
384 printer <<
", trailing_zeros";
393cir::ConstVectorAttr::verify(function_ref<InFlightDiagnostic()> emitError,
394 Type type, ArrayAttr elts) {
396 if (!mlir::isa<cir::VectorType>(type))
397 return emitError() <<
"type of cir::ConstVectorAttr is not a "
401 const auto vecType = mlir::cast<cir::VectorType>(type);
403 if (vecType.getSize() != elts.size())
405 <<
"number of constant elements should match vector size";
408 LogicalResult elementTypeCheck =
success();
409 elts.walkImmediateSubElements(
410 [&](Attribute element) {
411 if (elementTypeCheck.failed()) {
415 auto typedElement = mlir::dyn_cast<TypedAttr>(element);
417 typedElement.getType() != vecType.getElementType()) {
418 elementTypeCheck = failure();
419 emitError() <<
"constant type should match vector element type";
424 return elementTypeCheck;
431LogicalResult cir::VTableAttr::verify(
432 llvm::function_ref<mlir::InFlightDiagnostic()> emitError, mlir::Type type,
433 mlir::ArrayAttr data) {
434 auto sTy = mlir::dyn_cast_if_present<cir::RecordType>(type);
436 return emitError() <<
"expected !cir.record type result";
437 if (sTy.getMembers().empty() || data.empty())
438 return emitError() <<
"expected record type with one or more subtype";
440 if (cir::ConstRecordAttr::verify(emitError, type, data).failed())
443 for (
const auto &element : data.getAsRange<mlir::Attribute>()) {
444 const auto &constArrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(element);
446 return emitError() <<
"expected constant array subtype";
448 LogicalResult eltTypeCheck =
success();
449 auto arrayElts = mlir::cast<ArrayAttr>(constArrayAttr.getElts());
450 arrayElts.walkImmediateSubElements(
451 [&](mlir::Attribute attr) {
452 if (mlir::isa<ConstPtrAttr, GlobalViewAttr>(attr))
455 eltTypeCheck = emitError()
456 <<
"expected GlobalViewAttr or ConstPtrAttr";
458 [&](mlir::Type type) {});
459 if (eltTypeCheck.failed())
469void CIRDialect::registerAttributes() {
471#define GET_ATTRDEF_LIST
472#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)
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)