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 .Default([](
Type) -> StringRef {
49 llvm_unreachable(
"unexpected 'llvm' type kind");
56 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrint;
62 printer <<
'"' << type.
getName() <<
'"';
65 if (failed(cyclicPrint)) {
72 if (type.isIdentified() && type.isOpaque()) {
80 // Put the current type on stack to avoid infinite recursion.
82 llvm::interleaveComma(type.getBody(), printer.getStream(),
83 [&](Type subtype) { dispatchPrint(printer, subtype); });
97 void mlir::LLVM::detail::printType(Type type, AsmPrinter &printer) {
99 printer << "<<NULL-TYPE>>";
103 printer << getTypeKeyword(type);
105 llvm::TypeSwitch<Type>(type)
106 .Case<LLVMPointerType, LLVMArrayType, LLVMFixedVectorType,
107 LLVMScalableVectorType, LLVMFunctionType, LLVMTargetExtType>(
108 [&](auto type) { type.print(printer); })
109 .Case([&](LLVMStructType structType) {
110 printStructType(printer, structType);
114 //===----------------------------------------------------------------------===//
116 //===----------------------------------------------------------------------===//
118 static ParseResult dispatchParse(AsmParser &parser, Type &type);
123 static Type parseVectorType(AsmParser &parser) {
124 SmallVector<int64_t, 2> dims;
125 SMLoc dimPos, typePos;
127 SMLoc loc = parser.getCurrentLocation();
128 if (parser.parseLess() || parser.getCurrentLocation(&dimPos) ||
129 parser.parseDimensionList(dims, /*allowDynamic=*/true) ||
130 parser.getCurrentLocation(&typePos) ||
131 dispatchParse(parser, elementType) || parser.parseGreater())
134 // We parsed a generic dimension list, but vectors only support two forms:
135 // - single non-dynamic entry in the list (fixed vector);
136 // - two elements, the first dynamic (indicated by ShapedType::kDynamic)
138 // non-dynamic (scalable vector).
139 if (dims.empty() || dims.size() > 2 ||
140 ((dims.size() == 2) ^ (ShapedType::isDynamic(dims[0]))) ||
141 (dims.size() == 2 && ShapedType::isDynamic(dims[1]))) {
142 parser.emitError(dimPos)
143 << "expected '? x <integer> x <type>
' or '<integer> x <type>
'";
147 bool isScalable = dims.size() == 2;
149 return parser.getChecked<LLVMScalableVectorType>(loc, elementType, dims[1]);
150 if (elementType.isSignlessIntOrFloat()) {
151 parser.emitError(typePos)
152 << "cannot use !llvm.vec for built-in primitives, use 'vector
' instead";
155 return parser.getChecked<LLVMFixedVectorType>(loc, elementType, dims[0]);
160 static LLVMStructType trySetStructBody(LLVMStructType type,
161 ArrayRef<Type> subtypes, bool isPacked,
162 AsmParser &parser, SMLoc subtypesLoc) {
163 for (Type t : subtypes) {
164 if (!LLVMStructType::isValidElementType(t)) {
165 parser.emitError(subtypesLoc)
166 << "invalid LLVM structure element type: " << t;
167 return LLVMStructType();
171 if (succeeded(type.setBody(subtypes, isPacked)))
174 parser.emitError(subtypesLoc)
175 << "identified type already used with a different body";
176 return LLVMStructType();
184 static LLVMStructType parseStructType(AsmParser &parser) {
185 Location loc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
187 if (failed(parser.parseLess()))
188 return LLVMStructType();
190 // If we are parsing a self-reference to a recursive struct, i.e. the parsing
191 // stack already contains a struct with the same identifier, bail out after
194 bool isIdentified = succeeded(parser.parseOptionalString(&name));
196 SMLoc greaterLoc = parser.getCurrentLocation();
197 if (succeeded(parser.parseOptionalGreater())) {
198 auto type = LLVMStructType::getIdentifiedChecked(
199 [loc] { return emitError(loc); }, loc.getContext(), name);
200 if (succeeded(parser.tryStartCyclicParse(type))) {
203 "struct without a body only allowed in a recursive struct");
209 if (failed(parser.parseComma()))
210 return LLVMStructType();
213 // Handle intentionally opaque structs.
214 SMLoc kwLoc = parser.getCurrentLocation();
215 if (succeeded(parser.parseOptionalKeyword("opaque"))) {
217 return parser.emitError(kwLoc, "only identified structs can be opaque"),
219 if (failed(parser.parseGreater()))
220 return LLVMStructType();
221 auto type = LLVMStructType::getOpaqueChecked(
222 [loc] { return emitError(loc); }, loc.getContext(), name);
223 if (!type.isOpaque()) {
224 parser.emitError(kwLoc, "redeclaring defined struct as opaque");
225 return LLVMStructType();
230 FailureOr<AsmParser::CyclicParseReset> cyclicParse;
233 parser.tryStartCyclicParse(LLVMStructType::getIdentifiedChecked(
234 [loc] { return emitError(loc); }, loc.getContext(), name));
235 if (failed(cyclicParse)) {
236 parser.emitError(kwLoc,
237 "identifier already used for an enclosing struct");
242 // Check for packedness.
243 bool isPacked = succeeded(parser.parseOptionalKeyword("packed"));
244 if (failed(parser.parseLParen()))
245 return LLVMStructType();
247 // Fast pass for structs with zero subtypes.
248 if (succeeded(parser.parseOptionalRParen())) {
249 if (failed(parser.parseGreater()))
250 return LLVMStructType();
252 return LLVMStructType::getLiteralChecked([loc] { return emitError(loc); },
253 loc.getContext(), {}, isPacked);
254 auto type = LLVMStructType::getIdentifiedChecked(
255 [loc] { return emitError(loc); }, loc.getContext(), name);
256 return trySetStructBody(type, {}, isPacked, parser, kwLoc);
259 // Parse subtypes. For identified structs, put the identifier of the struct on
260 // the stack to support self-references in the recursive calls.
261 SmallVector<Type, 4> subtypes;
262 SMLoc subtypesLoc = parser.getCurrentLocation();
265 if (dispatchParse(parser, type))
266 return LLVMStructType();
267 subtypes.push_back(type);
268 } while (succeeded(parser.parseOptionalComma()));
270 if (parser.parseRParen() || parser.parseGreater())
271 return LLVMStructType();
273 // Construct the struct with body.
275 return LLVMStructType::getLiteralChecked(
276 [loc] { return emitError(loc); }, loc.getContext(), subtypes, isPacked);
277 auto type = LLVMStructType::getIdentifiedChecked(
278 [loc] { return emitError(loc); }, loc.getContext(), name);
279 return trySetStructBody(type, subtypes, isPacked, parser, subtypesLoc);
286 static Type dispatchParse(AsmParser &parser, bool allowAny = true) {
287 SMLoc keyLoc = parser.getCurrentLocation();
289 // Try parsing any MLIR type.
291 OptionalParseResult result = parser.parseOptionalType(type);
292 if (result.has_value()) {
293 if (failed(result.value()))
296 parser.emitError(keyLoc) << "unexpected type, expected keyword";
302 // If no type found, fallback to the shorthand form.
304 if (failed(parser.parseKeyword(&key)))
307 MLIRContext *ctx = parser.getContext();
308 return StringSwitch<function_ref<Type()>>(key)
309 .Case("void", [&] { return LLVMVoidType::get(ctx); })
310 .Case("ppc_fp128", [&] { return LLVMPPCFP128Type::get(ctx); })
311 .Case("token", [&] { return LLVMTokenType::get(ctx); })
312 .Case("label", [&] { return LLVMLabelType::get(ctx); })
313 .Case("metadata", [&] { return LLVMMetadataType::get(ctx); })
314 .Case("func", [&] { return LLVMFunctionType::parse(parser); })
315 .Case("ptr", [&] { return LLVMPointerType::parse(parser); })
316 .Case("vec", [&] { return parseVectorType(parser); })
317 .Case("array", [&] { return LLVMArrayType::parse(parser); })
318 .Case("struct", [&] { return parseStructType(parser); })
319 .Case("target", [&] { return LLVMTargetExtType::parse(parser); })
321 parser.emitError(keyLoc) << "unknown LLVM type: " << key;
327 static ParseResult dispatchParse(AsmParser &parser, Type &type) {
328 type = dispatchParse(parser);
329 return success(type != nullptr);
333 Type mlir::LLVM::detail::parseType(DialectAsmParser &parser) {
334 SMLoc loc = parser.getCurrentLocation();
335 Type type = dispatchParse(parser, /*allowAny=*/false);
338 if (!isCompatibleOuterType(type)) {
339 parser.emitError(loc) << "unexpected type, expected keyword";
345 ParseResult LLVM::parsePrettyLLVMType(AsmParser &p, Type &type) {
346 return dispatchParse(p, type);
349 void LLVM::printPrettyLLVMType(AsmPrinter &p, Type type) {
350 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.