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