xref: /llvm-project/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp (revision 8e329593313bb792592529ee825a52683108df99)
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