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<LLVMArrayType>([&](
Type) {
return "array"; })
44 .Case<LLVMStructType>([&](
Type) {
return "struct"; })
45 .Case<LLVMTargetExtType>([&](
Type) {
return "target"; })
46 .Case<LLVMX86AMXType>([&](
Type) {
return "x86_amx"; })
47 .Default([](
Type) -> StringRef {
48 llvm_unreachable(
"unexpected 'llvm' type kind");
55 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrint;
61 printer <<
'"' << getName() <<
'"';
64 if (failed(cyclicPrint)) {
71 if (isIdentified() && isOpaque()) {
79 // Put the current type on stack to avoid infinite recursion.
81 llvm::interleaveComma(getBody(), printer.getStream(),
82 [&](Type subtype) { dispatchPrint(printer, subtype); });
96 void mlir::LLVM::detail::printType(Type type, AsmPrinter &printer) {
98 printer << "<<NULL-TYPE>>";
102 printer << getTypeKeyword(type);
104 llvm::TypeSwitch<Type>(type)
105 .Case<LLVMPointerType, LLVMArrayType, LLVMFunctionType, LLVMTargetExtType,
106 LLVMStructType>([&](auto type) { type.print(printer); });
109 //===----------------------------------------------------------------------===//
111 //===----------------------------------------------------------------------===//
113 static ParseResult dispatchParse(AsmParser &parser, Type &type);
117 static LLVMStructType trySetStructBody(LLVMStructType type,
118 ArrayRef<Type> subtypes, bool isPacked,
119 AsmParser &parser, SMLoc subtypesLoc) {
120 for (Type t : subtypes) {
121 if (!LLVMStructType::isValidElementType(t)) {
122 parser.emitError(subtypesLoc)
123 << "invalid LLVM structure element type: " << t;
124 return LLVMStructType();
128 if (succeeded(type.setBody(subtypes, isPacked)))
131 parser.emitError(subtypesLoc)
132 << "identified type already used with a different body";
133 return LLVMStructType();
141 Type LLVMStructType::parse(AsmParser &parser) {
142 Location loc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
144 if (failed(parser.parseLess()))
145 return LLVMStructType();
147 // If we are parsing a self-reference to a recursive struct, i.e. the parsing
148 // stack already contains a struct with the same identifier, bail out after
151 bool isIdentified = succeeded(parser.parseOptionalString(&name));
153 SMLoc greaterLoc = parser.getCurrentLocation();
154 if (succeeded(parser.parseOptionalGreater())) {
155 auto type = LLVMStructType::getIdentifiedChecked(
156 [loc] { return emitError(loc); }, loc.getContext(), name);
157 if (succeeded(parser.tryStartCyclicParse(type))) {
160 "struct without a body only allowed in a recursive struct");
166 if (failed(parser.parseComma()))
167 return LLVMStructType();
170 // Handle intentionally opaque structs.
171 SMLoc kwLoc = parser.getCurrentLocation();
172 if (succeeded(parser.parseOptionalKeyword("opaque"))) {
174 return parser.emitError(kwLoc, "only identified structs can be opaque"),
176 if (failed(parser.parseGreater()))
177 return LLVMStructType();
178 auto type = LLVMStructType::getOpaqueChecked(
179 [loc] { return emitError(loc); }, loc.getContext(), name);
180 if (!type.isOpaque()) {
181 parser.emitError(kwLoc, "redeclaring defined struct as opaque");
182 return LLVMStructType();
187 FailureOr<AsmParser::CyclicParseReset> cyclicParse;
190 parser.tryStartCyclicParse(LLVMStructType::getIdentifiedChecked(
191 [loc] { return emitError(loc); }, loc.getContext(), name));
192 if (failed(cyclicParse)) {
193 parser.emitError(kwLoc,
194 "identifier already used for an enclosing struct");
199 // Check for packedness.
200 bool isPacked = succeeded(parser.parseOptionalKeyword("packed"));
201 if (failed(parser.parseLParen()))
202 return LLVMStructType();
204 // Fast pass for structs with zero subtypes.
205 if (succeeded(parser.parseOptionalRParen())) {
206 if (failed(parser.parseGreater()))
207 return LLVMStructType();
209 return LLVMStructType::getLiteralChecked([loc] { return emitError(loc); },
210 loc.getContext(), {}, isPacked);
211 auto type = LLVMStructType::getIdentifiedChecked(
212 [loc] { return emitError(loc); }, loc.getContext(), name);
213 return trySetStructBody(type, {}, isPacked, parser, kwLoc);
216 // Parse subtypes. For identified structs, put the identifier of the struct on
217 // the stack to support self-references in the recursive calls.
218 SmallVector<Type, 4> subtypes;
219 SMLoc subtypesLoc = parser.getCurrentLocation();
222 if (dispatchParse(parser, type))
223 return LLVMStructType();
224 subtypes.push_back(type);
225 } while (succeeded(parser.parseOptionalComma()));
227 if (parser.parseRParen() || parser.parseGreater())
228 return LLVMStructType();
230 // Construct the struct with body.
232 return LLVMStructType::getLiteralChecked(
233 [loc] { return emitError(loc); }, loc.getContext(), subtypes, isPacked);
234 auto type = LLVMStructType::getIdentifiedChecked(
235 [loc] { return emitError(loc); }, loc.getContext(), name);
236 return trySetStructBody(type, subtypes, isPacked, parser, subtypesLoc);
243 static Type dispatchParse(AsmParser &parser, bool allowAny = true) {
244 SMLoc keyLoc = parser.getCurrentLocation();
246 // Try parsing any MLIR type.
248 OptionalParseResult result = parser.parseOptionalType(type);
249 if (result.has_value()) {
250 if (failed(result.value()))
253 parser.emitError(keyLoc) << "unexpected type, expected keyword";
259 // If no type found, fallback to the shorthand form.
261 if (failed(parser.parseKeyword(&key)))
264 MLIRContext *ctx = parser.getContext();
265 return StringSwitch<function_ref<Type()>>(key)
266 .Case("void", [&] { return LLVMVoidType::get(ctx); })
267 .Case("ppc_fp128", [&] { return LLVMPPCFP128Type::get(ctx); })
268 .Case("token", [&] { return LLVMTokenType::get(ctx); })
269 .Case("label", [&] { return LLVMLabelType::get(ctx); })
270 .Case("metadata", [&] { return LLVMMetadataType::get(ctx); })
271 .Case("func", [&] { return LLVMFunctionType::parse(parser); })
272 .Case("ptr", [&] { return LLVMPointerType::parse(parser); })
273 .Case("array", [&] { return LLVMArrayType::parse(parser); })
274 .Case("struct", [&] { return LLVMStructType::parse(parser); })
275 .Case("target", [&] { return LLVMTargetExtType::parse(parser); })
276 .Case("x86_amx", [&] { return LLVMX86AMXType::get(ctx); })
278 parser.emitError(keyLoc) << "unknown LLVM type: " << key;
284 static ParseResult dispatchParse(AsmParser &parser, Type &type) {
285 type = dispatchParse(parser);
286 return success(type != nullptr);
290 Type mlir::LLVM::detail::parseType(DialectAsmParser &parser) {
291 SMLoc loc = parser.getCurrentLocation();
292 Type type = dispatchParse(parser, /*allowAny=*/false);
295 if (!isCompatibleOuterType(type)) {
296 parser.emitError(loc) << "unexpected type, expected keyword";
302 ParseResult LLVM::parsePrettyLLVMType(AsmParser &p, Type &type) {
303 return dispatchParse(p, type);
306 void LLVM::printPrettyLLVMType(AsmPrinter &p, Type type) {
307 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.