1 //===- CIRAttrs.cpp - MLIR CIR Attributes ---------------------------------===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the attributes in the CIR dialect. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/CIR/Dialect/IR/CIRDialect.h" 14 15 #include "mlir/IR/DialectImplementation.h" 16 #include "llvm/ADT/TypeSwitch.h" 17 18 static void printFloatLiteral(mlir::AsmPrinter &p, llvm::APFloat value, 19 mlir::Type ty); 20 static mlir::ParseResult 21 parseFloatLiteral(mlir::AsmParser &parser, 22 mlir::FailureOr<llvm::APFloat> &value, 23 cir::CIRFPTypeInterface fpType); 24 25 static mlir::ParseResult parseConstPtr(mlir::AsmParser &parser, 26 mlir::IntegerAttr &value); 27 28 static void printConstPtr(mlir::AsmPrinter &p, mlir::IntegerAttr value); 29 30 #define GET_ATTRDEF_CLASSES 31 #include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc" 32 33 using namespace mlir; 34 using namespace cir; 35 36 //===----------------------------------------------------------------------===// 37 // General CIR parsing / printing 38 //===----------------------------------------------------------------------===// 39 40 Attribute CIRDialect::parseAttribute(DialectAsmParser &parser, 41 Type type) const { 42 llvm::SMLoc typeLoc = parser.getCurrentLocation(); 43 llvm::StringRef mnemonic; 44 Attribute genAttr; 45 OptionalParseResult parseResult = 46 generatedAttributeParser(parser, &mnemonic, type, genAttr); 47 if (parseResult.has_value()) 48 return genAttr; 49 parser.emitError(typeLoc, "unknown attribute in CIR dialect"); 50 return Attribute(); 51 } 52 53 void CIRDialect::printAttribute(Attribute attr, DialectAsmPrinter &os) const { 54 if (failed(generatedAttributePrinter(attr, os))) 55 llvm_unreachable("unexpected CIR type kind"); 56 } 57 58 //===----------------------------------------------------------------------===// 59 // ConstPtrAttr definitions 60 //===----------------------------------------------------------------------===// 61 62 // TODO(CIR): Consider encoding the null value differently and use conditional 63 // assembly format instead of custom parsing/printing. 64 static ParseResult parseConstPtr(AsmParser &parser, mlir::IntegerAttr &value) { 65 66 if (parser.parseOptionalKeyword("null").succeeded()) { 67 value = mlir::IntegerAttr::get( 68 mlir::IntegerType::get(parser.getContext(), 64), 0); 69 return success(); 70 } 71 72 return parser.parseAttribute(value); 73 } 74 75 static void printConstPtr(AsmPrinter &p, mlir::IntegerAttr value) { 76 if (!value.getInt()) 77 p << "null"; 78 else 79 p << value; 80 } 81 82 //===----------------------------------------------------------------------===// 83 // IntAttr definitions 84 //===----------------------------------------------------------------------===// 85 86 Attribute IntAttr::parse(AsmParser &parser, Type odsType) { 87 mlir::APInt apValue; 88 89 if (!mlir::isa<IntType>(odsType)) 90 return {}; 91 auto type = mlir::cast<IntType>(odsType); 92 93 // Consume the '<' symbol. 94 if (parser.parseLess()) 95 return {}; 96 97 // Fetch arbitrary precision integer value. 98 if (type.isSigned()) { 99 int64_t value = 0; 100 if (parser.parseInteger(value)) { 101 parser.emitError(parser.getCurrentLocation(), "expected integer value"); 102 } else { 103 apValue = mlir::APInt(type.getWidth(), value, type.isSigned(), 104 /*implicitTrunc=*/true); 105 if (apValue.getSExtValue() != value) 106 parser.emitError(parser.getCurrentLocation(), 107 "integer value too large for the given type"); 108 } 109 } else { 110 uint64_t value = 0; 111 if (parser.parseInteger(value)) { 112 parser.emitError(parser.getCurrentLocation(), "expected integer value"); 113 } else { 114 apValue = mlir::APInt(type.getWidth(), value, type.isSigned(), 115 /*implicitTrunc=*/true); 116 if (apValue.getZExtValue() != value) 117 parser.emitError(parser.getCurrentLocation(), 118 "integer value too large for the given type"); 119 } 120 } 121 122 // Consume the '>' symbol. 123 if (parser.parseGreater()) 124 return {}; 125 126 return IntAttr::get(type, apValue); 127 } 128 129 void IntAttr::print(AsmPrinter &printer) const { 130 auto type = mlir::cast<IntType>(getType()); 131 printer << '<'; 132 if (type.isSigned()) 133 printer << getSInt(); 134 else 135 printer << getUInt(); 136 printer << '>'; 137 } 138 139 LogicalResult IntAttr::verify(function_ref<InFlightDiagnostic()> emitError, 140 Type type, APInt value) { 141 if (!mlir::isa<IntType>(type)) { 142 emitError() << "expected 'simple.int' type"; 143 return failure(); 144 } 145 146 auto intType = mlir::cast<IntType>(type); 147 if (value.getBitWidth() != intType.getWidth()) { 148 emitError() << "type and value bitwidth mismatch: " << intType.getWidth() 149 << " != " << value.getBitWidth(); 150 return failure(); 151 } 152 153 return success(); 154 } 155 156 //===----------------------------------------------------------------------===// 157 // FPAttr definitions 158 //===----------------------------------------------------------------------===// 159 160 static void printFloatLiteral(AsmPrinter &p, APFloat value, Type ty) { 161 p << value; 162 } 163 164 static ParseResult parseFloatLiteral(AsmParser &parser, 165 FailureOr<APFloat> &value, 166 CIRFPTypeInterface fpType) { 167 168 APFloat parsedValue(0.0); 169 if (parser.parseFloat(fpType.getFloatSemantics(), parsedValue)) 170 return failure(); 171 172 value.emplace(parsedValue); 173 return success(); 174 } 175 176 FPAttr FPAttr::getZero(Type type) { 177 return get(type, 178 APFloat::getZero( 179 mlir::cast<CIRFPTypeInterface>(type).getFloatSemantics())); 180 } 181 182 LogicalResult FPAttr::verify(function_ref<InFlightDiagnostic()> emitError, 183 CIRFPTypeInterface fpType, APFloat value) { 184 if (APFloat::SemanticsToEnum(fpType.getFloatSemantics()) != 185 APFloat::SemanticsToEnum(value.getSemantics())) { 186 emitError() << "floating-point semantics mismatch"; 187 return failure(); 188 } 189 190 return success(); 191 } 192 193 //===----------------------------------------------------------------------===// 194 // CIR Dialect 195 //===----------------------------------------------------------------------===// 196 197 void CIRDialect::registerAttributes() { 198 addAttributes< 199 #define GET_ATTRDEF_LIST 200 #include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc" 201 >(); 202 } 203