12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/TypeSwitch.h"
27 !(llvm::isa<IntegerType, FloatType, VectorType>(type) ||
28 (llvm::isa<PtrLikeTypeInterface>(type) &&
29 !llvm::isa<LLVMPointerType>(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 .DefaultUnreachable(
"unexpected 'llvm' type kind");
54 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrint;
61 llvm::printEscapedString(getName(), printer.
getStream());
72 if (isIdentified() && isOpaque()) {
80 // Put the current type on stack to avoid infinite recursion.
82 llvm::interleaveComma(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, LLVMFunctionType, LLVMTargetExtType,
107 LLVMStructType>([&](auto type) { type.print(printer); });
110 //===----------------------------------------------------------------------===//
112 //===----------------------------------------------------------------------===//
114 static ParseResult dispatchParse(AsmParser &parser, Type &type);
118 static LLVMStructType trySetStructBody(LLVMStructType type,
119 ArrayRef<Type> subtypes, bool isPacked,
120 AsmParser &parser, SMLoc subtypesLoc) {
121 for (Type t : subtypes) {
122 if (!LLVMStructType::isValidElementType(t)) {
123 parser.emitError(subtypesLoc)
124 << "invalid LLVM structure element type: " << t;
125 return LLVMStructType();
129 if (succeeded(type.setBody(subtypes, isPacked)))
132 parser.emitError(subtypesLoc)
133 << "identified type already used with a different body";
134 return LLVMStructType();
142 Type LLVMStructType::parse(AsmParser &parser) {
143 Location loc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
145 if (failed(parser.parseLess()))
146 return LLVMStructType();
148 // If we are parsing a self-reference to a recursive struct, i.e. the parsing
149 // stack already contains a struct with the same identifier, bail out after
152 bool isIdentified = succeeded(parser.parseOptionalString(&name));
154 SMLoc greaterLoc = parser.getCurrentLocation();
155 if (succeeded(parser.parseOptionalGreater())) {
156 auto type = LLVMStructType::getIdentifiedChecked(
157 [loc] { return emitError(loc); }, loc.getContext(), name);
158 if (succeeded(parser.tryStartCyclicParse(type))) {
161 "struct without a body only allowed in a recursive struct");
167 if (failed(parser.parseComma()))
168 return LLVMStructType();
171 // Handle intentionally opaque structs.
172 SMLoc kwLoc = parser.getCurrentLocation();
173 if (succeeded(parser.parseOptionalKeyword("opaque"))) {
175 return parser.emitError(kwLoc, "only identified structs can be opaque"),
177 if (failed(parser.parseGreater()))
178 return LLVMStructType();
179 auto type = LLVMStructType::getOpaqueChecked(
180 [loc] { return emitError(loc); }, loc.getContext(), name);
181 if (!type.isOpaque()) {
182 parser.emitError(kwLoc, "redeclaring defined struct as opaque");
183 return LLVMStructType();
188 FailureOr<AsmParser::CyclicParseReset> cyclicParse;
191 parser.tryStartCyclicParse(LLVMStructType::getIdentifiedChecked(
192 [loc] { return emitError(loc); }, loc.getContext(), name));
193 if (failed(cyclicParse)) {
194 parser.emitError(kwLoc,
195 "identifier already used for an enclosing struct");
200 // Check for packedness.
201 bool isPacked = succeeded(parser.parseOptionalKeyword("packed"));
202 if (failed(parser.parseLParen()))
203 return LLVMStructType();
205 // Fast pass for structs with zero subtypes.
206 if (succeeded(parser.parseOptionalRParen())) {
207 if (failed(parser.parseGreater()))
208 return LLVMStructType();
210 return LLVMStructType::getLiteralChecked([loc] { return emitError(loc); },
211 loc.getContext(), {}, isPacked);
212 auto type = LLVMStructType::getIdentifiedChecked(
213 [loc] { return emitError(loc); }, loc.getContext(), name);
214 return trySetStructBody(type, {}, isPacked, parser, kwLoc);
217 // Parse subtypes. For identified structs, put the identifier of the struct on
218 // the stack to support self-references in the recursive calls.
219 SmallVector<Type, 4> subtypes;
220 SMLoc subtypesLoc = parser.getCurrentLocation();
223 if (dispatchParse(parser, type))
224 return LLVMStructType();
225 subtypes.push_back(type);
226 } while (succeeded(parser.parseOptionalComma()));
228 if (parser.parseRParen() || parser.parseGreater())
229 return LLVMStructType();
231 // Construct the struct with body.
233 return LLVMStructType::getLiteralChecked(
234 [loc] { return emitError(loc); }, loc.getContext(), subtypes, isPacked);
235 auto type = LLVMStructType::getIdentifiedChecked(
236 [loc] { return emitError(loc); }, loc.getContext(), name);
237 return trySetStructBody(type, subtypes, isPacked, parser, subtypesLoc);
244 static Type dispatchParse(AsmParser &parser, bool allowAny = true) {
245 SMLoc keyLoc = parser.getCurrentLocation();
247 // Try parsing any MLIR type.
249 OptionalParseResult result = parser.parseOptionalType(type);
250 if (result.has_value()) {
251 if (failed(result.value()))
254 parser.emitError(keyLoc) << "unexpected type, expected keyword";
260 // If no type found, fallback to the shorthand form.
262 if (failed(parser.parseKeyword(&key)))
265 MLIRContext *ctx = parser.getContext();
266 return StringSwitch<function_ref<Type()>>(key)
267 .Case("void", [&] { return LLVMVoidType::get(ctx); })
268 .Case("ppc_fp128", [&] { return LLVMPPCFP128Type::get(ctx); })
269 .Case("token", [&] { return LLVMTokenType::get(ctx); })
270 .Case("label", [&] { return LLVMLabelType::get(ctx); })
271 .Case("metadata", [&] { return LLVMMetadataType::get(ctx); })
272 .Case("func", [&] { return LLVMFunctionType::parse(parser); })
273 .Case("ptr", [&] { return LLVMPointerType::parse(parser); })
274 .Case("array", [&] { return LLVMArrayType::parse(parser); })
275 .Case("struct", [&] { return LLVMStructType::parse(parser); })
276 .Case("target", [&] { return LLVMTargetExtType::parse(parser); })
277 .Case("x86_amx", [&] { return LLVMX86AMXType::get(ctx); })
279 parser.emitError(keyLoc) << "unknown LLVM type: " << key;
285 static ParseResult dispatchParse(AsmParser &parser, Type &type) {
286 type = dispatchParse(parser);
287 return success(type != nullptr);
291 Type mlir::LLVM::detail::parseType(DialectAsmParser &parser) {
292 SMLoc loc = parser.getCurrentLocation();
293 Type type = dispatchParse(parser, /*allowAny=*/false);
296 if (!isCompatibleOuterType(type)) {
297 parser.emitError(loc) << "unexpected type, expected keyword";
303 ParseResult LLVM::parsePrettyLLVMType(AsmParser &p, Type &type) {
304 return dispatchParse(p, type);
307 void LLVM::printPrettyLLVMType(AsmPrinter &p, Type type) {
308 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.