12 #include "llvm/ADT/ScopeExit.h"
13 #include "llvm/ADT/SetVector.h"
14 #include "llvm/ADT/TypeSwitch.h"
28 !llvm::isa<IntegerType, FloatType, VectorType>(type))
36 .Case<LLVMVoidType>([&](
Type) {
return "void"; })
37 .Case<LLVMPPCFP128Type>([&](
Type) {
return "ppc_fp128"; })
38 .Case<LLVMTokenType>([&](
Type) {
return "token"; })
39 .Case<LLVMLabelType>([&](
Type) {
return "label"; })
40 .Case<LLVMMetadataType>([&](
Type) {
return "metadata"; })
41 .Case<LLVMFunctionType>([&](
Type) {
return "func"; })
42 .Case<LLVMPointerType>([&](
Type) {
return "ptr"; })
43 .Case<LLVMFixedVectorType, LLVMScalableVectorType>(
44 [&](
Type) {
return "vec"; })
45 .Case<LLVMArrayType>([&](
Type) {
return "array"; })
46 .Case<LLVMStructType>([&](
Type) {
return "struct"; })
47 .Case<LLVMTargetExtType>([&](
Type) {
return "target"; })
48 .Case<LLVMX86AMXType>([&](
Type) {
return "x86_amx"; })
49 .Default([](
Type) -> StringRef {
50 llvm_unreachable(
"unexpected 'llvm' type kind");
57 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrint;
63 printer <<
'"' << getName() <<
'"';
66 if (failed(cyclicPrint)) {
73 if (isIdentified() && isOpaque()) {
81 // Put the current type on stack to avoid infinite recursion.
83 llvm::interleaveComma(getBody(), printer.getStream(),
84 [&](Type subtype) { dispatchPrint(printer, subtype); });
98 void mlir::LLVM::detail::printType(Type type, AsmPrinter &printer) {
100 printer << "<<NULL-TYPE>>";
104 printer << getTypeKeyword(type);
106 llvm::TypeSwitch<Type>(type)
107 .Case<LLVMPointerType, LLVMArrayType, LLVMFixedVectorType,
108 LLVMScalableVectorType, LLVMFunctionType, LLVMTargetExtType,
109 LLVMStructType>([&](auto type) { type.print(printer); });
112 //===----------------------------------------------------------------------===//
114 //===----------------------------------------------------------------------===//
116 static ParseResult dispatchParse(AsmParser &parser, Type &type);
121 static Type parseVectorType(AsmParser &parser) {
122 SmallVector<int64_t, 2> dims;
123 SMLoc dimPos, typePos;
125 SMLoc loc = parser.getCurrentLocation();
126 if (parser.parseLess() || parser.getCurrentLocation(&dimPos) ||
127 parser.parseDimensionList(dims, /*allowDynamic=*/true) ||
128 parser.getCurrentLocation(&typePos) ||
129 dispatchParse(parser, elementType) || parser.parseGreater())
132 // We parsed a generic dimension list, but vectors only support two forms:
133 // - single non-dynamic entry in the list (fixed vector);
134 // - two elements, the first dynamic (indicated by ShapedType::kDynamic)
136 // non-dynamic (scalable vector).
137 if (dims.empty() || dims.size() > 2 ||
138 ((dims.size() == 2) ^ (ShapedType::isDynamic(dims[0]))) ||
139 (dims.size() == 2 && ShapedType::isDynamic(dims[1]))) {
140 parser.emitError(dimPos)
141 << "expected '? x <integer> x <type>
' or '<integer> x <type>
'";
145 bool isScalable = dims.size() == 2;
147 return parser.getChecked<LLVMScalableVectorType>(loc, elementType, dims[1]);
148 if (elementType.isSignlessIntOrFloat()) {
149 parser.emitError(typePos)
150 << "cannot use !llvm.vec for built-in primitives, use 'vector
' instead";
153 return parser.getChecked<LLVMFixedVectorType>(loc, elementType, dims[0]);
158 static LLVMStructType trySetStructBody(LLVMStructType type,
159 ArrayRef<Type> subtypes, bool isPacked,
160 AsmParser &parser, SMLoc subtypesLoc) {
161 for (Type t : subtypes) {
162 if (!LLVMStructType::isValidElementType(t)) {
163 parser.emitError(subtypesLoc)
164 << "invalid LLVM structure element type: " << t;
165 return LLVMStructType();
169 if (succeeded(type.setBody(subtypes, isPacked)))
172 parser.emitError(subtypesLoc)
173 << "identified type already used with a different body";
174 return LLVMStructType();
182 Type LLVMStructType::parse(AsmParser &parser) {
183 Location loc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
185 if (failed(parser.parseLess()))
186 return LLVMStructType();
188 // If we are parsing a self-reference to a recursive struct, i.e. the parsing
189 // stack already contains a struct with the same identifier, bail out after
192 bool isIdentified = succeeded(parser.parseOptionalString(&name));
194 SMLoc greaterLoc = parser.getCurrentLocation();
195 if (succeeded(parser.parseOptionalGreater())) {
196 auto type = LLVMStructType::getIdentifiedChecked(
197 [loc] { return emitError(loc); }, loc.getContext(), name);
198 if (succeeded(parser.tryStartCyclicParse(type))) {
201 "struct without a body only allowed in a recursive struct");
207 if (failed(parser.parseComma()))
208 return LLVMStructType();
211 // Handle intentionally opaque structs.
212 SMLoc kwLoc = parser.getCurrentLocation();
213 if (succeeded(parser.parseOptionalKeyword("opaque"))) {
215 return parser.emitError(kwLoc, "only identified structs can be opaque"),
217 if (failed(parser.parseGreater()))
218 return LLVMStructType();
219 auto type = LLVMStructType::getOpaqueChecked(
220 [loc] { return emitError(loc); }, loc.getContext(), name);
221 if (!type.isOpaque()) {
222 parser.emitError(kwLoc, "redeclaring defined struct as opaque");
223 return LLVMStructType();
228 FailureOr<AsmParser::CyclicParseReset> cyclicParse;
231 parser.tryStartCyclicParse(LLVMStructType::getIdentifiedChecked(
232 [loc] { return emitError(loc); }, loc.getContext(), name));
233 if (failed(cyclicParse)) {
234 parser.emitError(kwLoc,
235 "identifier already used for an enclosing struct");
240 // Check for packedness.
241 bool isPacked = succeeded(parser.parseOptionalKeyword("packed"));
242 if (failed(parser.parseLParen()))
243 return LLVMStructType();
245 // Fast pass for structs with zero subtypes.
246 if (succeeded(parser.parseOptionalRParen())) {
247 if (failed(parser.parseGreater()))
248 return LLVMStructType();
250 return LLVMStructType::getLiteralChecked([loc] { return emitError(loc); },
251 loc.getContext(), {}, isPacked);
252 auto type = LLVMStructType::getIdentifiedChecked(
253 [loc] { return emitError(loc); }, loc.getContext(), name);
254 return trySetStructBody(type, {}, isPacked, parser, kwLoc);
257 // Parse subtypes. For identified structs, put the identifier of the struct on
258 // the stack to support self-references in the recursive calls.
259 SmallVector<Type, 4> subtypes;
260 SMLoc subtypesLoc = parser.getCurrentLocation();
263 if (dispatchParse(parser, type))
264 return LLVMStructType();
265 subtypes.push_back(type);
266 } while (succeeded(parser.parseOptionalComma()));
268 if (parser.parseRParen() || parser.parseGreater())
269 return LLVMStructType();
271 // Construct the struct with body.
273 return LLVMStructType::getLiteralChecked(
274 [loc] { return emitError(loc); }, loc.getContext(), subtypes, isPacked);
275 auto type = LLVMStructType::getIdentifiedChecked(
276 [loc] { return emitError(loc); }, loc.getContext(), name);
277 return trySetStructBody(type, subtypes, isPacked, parser, subtypesLoc);
284 static Type dispatchParse(AsmParser &parser, bool allowAny = true) {
285 SMLoc keyLoc = parser.getCurrentLocation();
287 // Try parsing any MLIR type.
289 OptionalParseResult result = parser.parseOptionalType(type);
290 if (result.has_value()) {
291 if (failed(result.value()))
294 parser.emitError(keyLoc) << "unexpected type, expected keyword";
300 // If no type found, fallback to the shorthand form.
302 if (failed(parser.parseKeyword(&key)))
305 MLIRContext *ctx = parser.getContext();
306 return StringSwitch<function_ref<Type()>>(key)
307 .Case("void", [&] { return LLVMVoidType::get(ctx); })
308 .Case("ppc_fp128", [&] { return LLVMPPCFP128Type::get(ctx); })
309 .Case("token", [&] { return LLVMTokenType::get(ctx); })
310 .Case("label", [&] { return LLVMLabelType::get(ctx); })
311 .Case("metadata", [&] { return LLVMMetadataType::get(ctx); })
312 .Case("func", [&] { return LLVMFunctionType::parse(parser); })
313 .Case("ptr", [&] { return LLVMPointerType::parse(parser); })
314 .Case("vec", [&] { return parseVectorType(parser); })
315 .Case("array", [&] { return LLVMArrayType::parse(parser); })
316 .Case("struct", [&] { return LLVMStructType::parse(parser); })
317 .Case("target", [&] { return LLVMTargetExtType::parse(parser); })
318 .Case("x86_amx", [&] { return LLVMX86AMXType::get(ctx); })
320 parser.emitError(keyLoc) << "unknown LLVM type: " << key;
326 static ParseResult dispatchParse(AsmParser &parser, Type &type) {
327 type = dispatchParse(parser);
328 return success(type != nullptr);
332 Type mlir::LLVM::detail::parseType(DialectAsmParser &parser) {
333 SMLoc loc = parser.getCurrentLocation();
334 Type type = dispatchParse(parser, /*allowAny=*/false);
337 if (!isCompatibleOuterType(type)) {
338 parser.emitError(loc) << "unexpected type, expected keyword";
344 ParseResult LLVM::parsePrettyLLVMType(AsmParser &p, Type &type) {
345 return dispatchParse(p, type);
348 void LLVM::printPrettyLLVMType(AsmPrinter &p, Type type) {
349 return dispatchPrint(p, type);
static void dispatchPrint(AsmPrinter &printer, Type type)
If the given type is compatible with the LLVM dialect, prints it using internal functions to avoid ge...
static StringRef getTypeKeyword(Type type)
Returns the keyword to use for the given type.
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
This base class exposes generic asm printer hooks, usable across the various derived printers.
FailureOr< CyclicPrintReset > tryStartCyclicPrint(AttrOrTypeT attrOrType)
Attempts to start a cyclic printing region for attrOrType.
virtual void printType(Type type)
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
void printType(Type type, AsmPrinter &printer)
Prints an LLVM Dialect type.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
Include the generated interface declarations.