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 <<
'"' << type.
getName() <<
'"';
66 if (failed(cyclicPrint)) {
73 if (type.isIdentified() && type.isOpaque()) {
81 // Put the current type on stack to avoid infinite recursion.
83 llvm::interleaveComma(type.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 [&](auto type) { type.print(printer); })
110 .Case([&](LLVMStructType structType) {
111 printStructType(printer, structType);
115 //===----------------------------------------------------------------------===//
117 //===----------------------------------------------------------------------===//
119 static ParseResult dispatchParse(AsmParser &parser, Type &type);
124 static Type parseVectorType(AsmParser &parser) {
125 SmallVector<int64_t, 2> dims;
126 SMLoc dimPos, typePos;
128 SMLoc loc = parser.getCurrentLocation();
129 if (parser.parseLess() || parser.getCurrentLocation(&dimPos) ||
130 parser.parseDimensionList(dims, /*allowDynamic=*/true) ||
131 parser.getCurrentLocation(&typePos) ||
132 dispatchParse(parser, elementType) || parser.parseGreater())
135 // We parsed a generic dimension list, but vectors only support two forms:
136 // - single non-dynamic entry in the list (fixed vector);
137 // - two elements, the first dynamic (indicated by ShapedType::kDynamic)
139 // non-dynamic (scalable vector).
140 if (dims.empty() || dims.size() > 2 ||
141 ((dims.size() == 2) ^ (ShapedType::isDynamic(dims[0]))) ||
142 (dims.size() == 2 && ShapedType::isDynamic(dims[1]))) {
143 parser.emitError(dimPos)
144 << "expected '? x <integer> x <type>
' or '<integer> x <type>
'";
148 bool isScalable = dims.size() == 2;
150 return parser.getChecked<LLVMScalableVectorType>(loc, elementType, dims[1]);
151 if (elementType.isSignlessIntOrFloat()) {
152 parser.emitError(typePos)
153 << "cannot use !llvm.vec for built-in primitives, use 'vector
' instead";
156 return parser.getChecked<LLVMFixedVectorType>(loc, elementType, dims[0]);
161 static LLVMStructType trySetStructBody(LLVMStructType type,
162 ArrayRef<Type> subtypes, bool isPacked,
163 AsmParser &parser, SMLoc subtypesLoc) {
164 for (Type t : subtypes) {
165 if (!LLVMStructType::isValidElementType(t)) {
166 parser.emitError(subtypesLoc)
167 << "invalid LLVM structure element type: " << t;
168 return LLVMStructType();
172 if (succeeded(type.setBody(subtypes, isPacked)))
175 parser.emitError(subtypesLoc)
176 << "identified type already used with a different body";
177 return LLVMStructType();
185 static LLVMStructType parseStructType(AsmParser &parser) {
186 Location loc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
188 if (failed(parser.parseLess()))
189 return LLVMStructType();
191 // If we are parsing a self-reference to a recursive struct, i.e. the parsing
192 // stack already contains a struct with the same identifier, bail out after
195 bool isIdentified = succeeded(parser.parseOptionalString(&name));
197 SMLoc greaterLoc = parser.getCurrentLocation();
198 if (succeeded(parser.parseOptionalGreater())) {
199 auto type = LLVMStructType::getIdentifiedChecked(
200 [loc] { return emitError(loc); }, loc.getContext(), name);
201 if (succeeded(parser.tryStartCyclicParse(type))) {
204 "struct without a body only allowed in a recursive struct");
210 if (failed(parser.parseComma()))
211 return LLVMStructType();
214 // Handle intentionally opaque structs.
215 SMLoc kwLoc = parser.getCurrentLocation();
216 if (succeeded(parser.parseOptionalKeyword("opaque"))) {
218 return parser.emitError(kwLoc, "only identified structs can be opaque"),
220 if (failed(parser.parseGreater()))
221 return LLVMStructType();
222 auto type = LLVMStructType::getOpaqueChecked(
223 [loc] { return emitError(loc); }, loc.getContext(), name);
224 if (!type.isOpaque()) {
225 parser.emitError(kwLoc, "redeclaring defined struct as opaque");
226 return LLVMStructType();
231 FailureOr<AsmParser::CyclicParseReset> cyclicParse;
234 parser.tryStartCyclicParse(LLVMStructType::getIdentifiedChecked(
235 [loc] { return emitError(loc); }, loc.getContext(), name));
236 if (failed(cyclicParse)) {
237 parser.emitError(kwLoc,
238 "identifier already used for an enclosing struct");
243 // Check for packedness.
244 bool isPacked = succeeded(parser.parseOptionalKeyword("packed"));
245 if (failed(parser.parseLParen()))
246 return LLVMStructType();
248 // Fast pass for structs with zero subtypes.
249 if (succeeded(parser.parseOptionalRParen())) {
250 if (failed(parser.parseGreater()))
251 return LLVMStructType();
253 return LLVMStructType::getLiteralChecked([loc] { return emitError(loc); },
254 loc.getContext(), {}, isPacked);
255 auto type = LLVMStructType::getIdentifiedChecked(
256 [loc] { return emitError(loc); }, loc.getContext(), name);
257 return trySetStructBody(type, {}, isPacked, parser, kwLoc);
260 // Parse subtypes. For identified structs, put the identifier of the struct on
261 // the stack to support self-references in the recursive calls.
262 SmallVector<Type, 4> subtypes;
263 SMLoc subtypesLoc = parser.getCurrentLocation();
266 if (dispatchParse(parser, type))
267 return LLVMStructType();
268 subtypes.push_back(type);
269 } while (succeeded(parser.parseOptionalComma()));
271 if (parser.parseRParen() || parser.parseGreater())
272 return LLVMStructType();
274 // Construct the struct with body.
276 return LLVMStructType::getLiteralChecked(
277 [loc] { return emitError(loc); }, loc.getContext(), subtypes, isPacked);
278 auto type = LLVMStructType::getIdentifiedChecked(
279 [loc] { return emitError(loc); }, loc.getContext(), name);
280 return trySetStructBody(type, subtypes, isPacked, parser, subtypesLoc);
287 static Type dispatchParse(AsmParser &parser, bool allowAny = true) {
288 SMLoc keyLoc = parser.getCurrentLocation();
290 // Try parsing any MLIR type.
292 OptionalParseResult result = parser.parseOptionalType(type);
293 if (result.has_value()) {
294 if (failed(result.value()))
297 parser.emitError(keyLoc) << "unexpected type, expected keyword";
303 // If no type found, fallback to the shorthand form.
305 if (failed(parser.parseKeyword(&key)))
308 MLIRContext *ctx = parser.getContext();
309 return StringSwitch<function_ref<Type()>>(key)
310 .Case("void", [&] { return LLVMVoidType::get(ctx); })
311 .Case("ppc_fp128", [&] { return LLVMPPCFP128Type::get(ctx); })
312 .Case("token", [&] { return LLVMTokenType::get(ctx); })
313 .Case("label", [&] { return LLVMLabelType::get(ctx); })
314 .Case("metadata", [&] { return LLVMMetadataType::get(ctx); })
315 .Case("func", [&] { return LLVMFunctionType::parse(parser); })
316 .Case("ptr", [&] { return LLVMPointerType::parse(parser); })
317 .Case("vec", [&] { return parseVectorType(parser); })
318 .Case("array", [&] { return LLVMArrayType::parse(parser); })
319 .Case("struct", [&] { return parseStructType(parser); })
320 .Case("target", [&] { return LLVMTargetExtType::parse(parser); })
321 .Case("x86_amx", [&] { return LLVMX86AMXType::get(ctx); })
323 parser.emitError(keyLoc) << "unknown LLVM type: " << key;
329 static ParseResult dispatchParse(AsmParser &parser, Type &type) {
330 type = dispatchParse(parser);
331 return success(type != nullptr);
335 Type mlir::LLVM::detail::parseType(DialectAsmParser &parser) {
336 SMLoc loc = parser.getCurrentLocation();
337 Type type = dispatchParse(parser, /*allowAny=*/false);
340 if (!isCompatibleOuterType(type)) {
341 parser.emitError(loc) << "unexpected type, expected keyword";
347 ParseResult LLVM::parsePrettyLLVMType(AsmParser &p, Type &type) {
348 return dispatchParse(p, type);
351 void LLVM::printPrettyLLVMType(AsmPrinter &p, Type type) {
352 return dispatchPrint(p, type);
static void printStructType(AsmPrinter &printer, LLVMStructType type)
Prints a structure 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.
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)
LLVM dialect structure type representing a collection of different-typed elements manipulated togethe...
StringRef getName()
Returns the name of an identified struct.
bool isIdentified() const
Checks if a struct is identified.
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.