12 #include "llvm/ADT/ScopeExit.h"
13 #include "llvm/ADT/SetVector.h"
14 #include "llvm/ADT/StringExtras.h"
15 #include "llvm/ADT/TypeSwitch.h"
29 !llvm::isa<IntegerType, FloatType, VectorType>(type))
37 .Case<LLVMVoidType>([&](
Type) {
return "void"; })
38 .Case<LLVMPPCFP128Type>([&](
Type) {
return "ppc_fp128"; })
39 .Case<LLVMTokenType>([&](
Type) {
return "token"; })
40 .Case<LLVMLabelType>([&](
Type) {
return "label"; })
41 .Case<LLVMMetadataType>([&](
Type) {
return "metadata"; })
42 .Case<LLVMFunctionType>([&](
Type) {
return "func"; })
43 .Case<LLVMPointerType>([&](
Type) {
return "ptr"; })
44 .Case<LLVMArrayType>([&](
Type) {
return "array"; })
45 .Case<LLVMStructType>([&](
Type) {
return "struct"; })
46 .Case<LLVMTargetExtType>([&](
Type) {
return "target"; })
47 .Case<LLVMX86AMXType>([&](
Type) {
return "x86_amx"; })
48 .Default([](
Type) -> StringRef {
49 llvm_unreachable(
"unexpected 'llvm' type kind");
56 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrint;
63 llvm::printEscapedString(getName(), printer.
getStream());
67 if (failed(cyclicPrint)) {
74 if (isIdentified() && isOpaque()) {
82 // Put the current type on stack to avoid infinite recursion.
84 llvm::interleaveComma(getBody(), printer.getStream(),
85 [&](Type subtype) { dispatchPrint(printer, subtype); });
99 void mlir::LLVM::detail::printType(Type type, AsmPrinter &printer) {
101 printer << "<<NULL-TYPE>>";
105 printer << getTypeKeyword(type);
107 llvm::TypeSwitch<Type>(type)
108 .Case<LLVMPointerType, LLVMArrayType, LLVMFunctionType, LLVMTargetExtType,
109 LLVMStructType>([&](auto type) { type.print(printer); });
112 //===----------------------------------------------------------------------===//
114 //===----------------------------------------------------------------------===//
116 static ParseResult dispatchParse(AsmParser &parser, Type &type);
120 static LLVMStructType trySetStructBody(LLVMStructType type,
121 ArrayRef<Type> subtypes, bool isPacked,
122 AsmParser &parser, SMLoc subtypesLoc) {
123 for (Type t : subtypes) {
124 if (!LLVMStructType::isValidElementType(t)) {
125 parser.emitError(subtypesLoc)
126 << "invalid LLVM structure element type: " << t;
127 return LLVMStructType();
131 if (succeeded(type.setBody(subtypes, isPacked)))
134 parser.emitError(subtypesLoc)
135 << "identified type already used with a different body";
136 return LLVMStructType();
144 Type LLVMStructType::parse(AsmParser &parser) {
145 Location loc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
147 if (failed(parser.parseLess()))
148 return LLVMStructType();
150 // If we are parsing a self-reference to a recursive struct, i.e. the parsing
151 // stack already contains a struct with the same identifier, bail out after
154 bool isIdentified = succeeded(parser.parseOptionalString(&name));
156 SMLoc greaterLoc = parser.getCurrentLocation();
157 if (succeeded(parser.parseOptionalGreater())) {
158 auto type = LLVMStructType::getIdentifiedChecked(
159 [loc] { return emitError(loc); }, loc.getContext(), name);
160 if (succeeded(parser.tryStartCyclicParse(type))) {
163 "struct without a body only allowed in a recursive struct");
169 if (failed(parser.parseComma()))
170 return LLVMStructType();
173 // Handle intentionally opaque structs.
174 SMLoc kwLoc = parser.getCurrentLocation();
175 if (succeeded(parser.parseOptionalKeyword("opaque"))) {
177 return parser.emitError(kwLoc, "only identified structs can be opaque"),
179 if (failed(parser.parseGreater()))
180 return LLVMStructType();
181 auto type = LLVMStructType::getOpaqueChecked(
182 [loc] { return emitError(loc); }, loc.getContext(), name);
183 if (!type.isOpaque()) {
184 parser.emitError(kwLoc, "redeclaring defined struct as opaque");
185 return LLVMStructType();
190 FailureOr<AsmParser::CyclicParseReset> cyclicParse;
193 parser.tryStartCyclicParse(LLVMStructType::getIdentifiedChecked(
194 [loc] { return emitError(loc); }, loc.getContext(), name));
195 if (failed(cyclicParse)) {
196 parser.emitError(kwLoc,
197 "identifier already used for an enclosing struct");
202 // Check for packedness.
203 bool isPacked = succeeded(parser.parseOptionalKeyword("packed"));
204 if (failed(parser.parseLParen()))
205 return LLVMStructType();
207 // Fast pass for structs with zero subtypes.
208 if (succeeded(parser.parseOptionalRParen())) {
209 if (failed(parser.parseGreater()))
210 return LLVMStructType();
212 return LLVMStructType::getLiteralChecked([loc] { return emitError(loc); },
213 loc.getContext(), {}, isPacked);
214 auto type = LLVMStructType::getIdentifiedChecked(
215 [loc] { return emitError(loc); }, loc.getContext(), name);
216 return trySetStructBody(type, {}, isPacked, parser, kwLoc);
219 // Parse subtypes. For identified structs, put the identifier of the struct on
220 // the stack to support self-references in the recursive calls.
221 SmallVector<Type, 4> subtypes;
222 SMLoc subtypesLoc = parser.getCurrentLocation();
225 if (dispatchParse(parser, type))
226 return LLVMStructType();
227 subtypes.push_back(type);
228 } while (succeeded(parser.parseOptionalComma()));
230 if (parser.parseRParen() || parser.parseGreater())
231 return LLVMStructType();
233 // Construct the struct with body.
235 return LLVMStructType::getLiteralChecked(
236 [loc] { return emitError(loc); }, loc.getContext(), subtypes, isPacked);
237 auto type = LLVMStructType::getIdentifiedChecked(
238 [loc] { return emitError(loc); }, loc.getContext(), name);
239 return trySetStructBody(type, subtypes, isPacked, parser, subtypesLoc);
246 static Type dispatchParse(AsmParser &parser, bool allowAny = true) {
247 SMLoc keyLoc = parser.getCurrentLocation();
249 // Try parsing any MLIR type.
251 OptionalParseResult result = parser.parseOptionalType(type);
252 if (result.has_value()) {
253 if (failed(result.value()))
256 parser.emitError(keyLoc) << "unexpected type, expected keyword";
262 // If no type found, fallback to the shorthand form.
264 if (failed(parser.parseKeyword(&key)))
267 MLIRContext *ctx = parser.getContext();
268 return StringSwitch<function_ref<Type()>>(key)
269 .Case("void", [&] { return LLVMVoidType::get(ctx); })
270 .Case("ppc_fp128", [&] { return LLVMPPCFP128Type::get(ctx); })
271 .Case("token", [&] { return LLVMTokenType::get(ctx); })
272 .Case("label", [&] { return LLVMLabelType::get(ctx); })
273 .Case("metadata", [&] { return LLVMMetadataType::get(ctx); })
274 .Case("func", [&] { return LLVMFunctionType::parse(parser); })
275 .Case("ptr", [&] { return LLVMPointerType::parse(parser); })
276 .Case("array", [&] { return LLVMArrayType::parse(parser); })
277 .Case("struct", [&] { return LLVMStructType::parse(parser); })
278 .Case("target", [&] { return LLVMTargetExtType::parse(parser); })
279 .Case("x86_amx", [&] { return LLVMX86AMXType::get(ctx); })
281 parser.emitError(keyLoc) << "unknown LLVM type: " << key;
287 static ParseResult dispatchParse(AsmParser &parser, Type &type) {
288 type = dispatchParse(parser);
289 return success(type != nullptr);
293 Type mlir::LLVM::detail::parseType(DialectAsmParser &parser) {
294 SMLoc loc = parser.getCurrentLocation();
295 Type type = dispatchParse(parser, /*allowAny=*/false);
298 if (!isCompatibleOuterType(type)) {
299 parser.emitError(loc) << "unexpected type, expected keyword";
305 ParseResult LLVM::parsePrettyLLVMType(AsmParser &p, Type &type) {
306 return dispatchParse(p, type);
309 void LLVM::printPrettyLLVMType(AsmPrinter &p, Type type) {
310 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)
virtual raw_ostream & getStream() const
Return the raw output stream used by this printer.
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.