2020// CIR Custom Parser/Printer Signatures
2121// ===----------------------------------------------------------------------===//
2222
23- static mlir::ParseResult
24- parseFuncTypeArgs (mlir::AsmParser &p, llvm::SmallVector<mlir::Type> ¶ms,
25- bool &isVarArg);
26- static void printFuncTypeArgs (mlir::AsmPrinter &p,
27- mlir::ArrayRef<mlir::Type> params, bool isVarArg);
23+ static mlir::ParseResult parseFuncType (mlir::AsmParser &p,
24+ mlir::Type &optionalReturnTypes,
25+ llvm::SmallVector<mlir::Type> ¶ms,
26+ bool &isVarArg);
27+ static void printFuncType (mlir::AsmPrinter &p, mlir::Type optionalReturnTypes,
28+ mlir::ArrayRef<mlir::Type> params, bool isVarArg);
2829
2930// ===----------------------------------------------------------------------===//
3031// Get autogenerated stuff
@@ -282,40 +283,55 @@ FuncType FuncType::clone(TypeRange inputs, TypeRange results) const {
282283 return get (llvm::to_vector (inputs), results[0 ], isVarArg ());
283284}
284285
285- mlir::ParseResult parseFuncTypeArgs (mlir::AsmParser &p,
286- llvm::SmallVector<mlir::Type> ¶ms,
287- bool &isVarArg) {
286+ // A special parser is needed for function returning void to handle the missing
287+ // type.
288+ static mlir::ParseResult parseFuncTypeReturn (mlir::AsmParser &p,
289+ mlir::Type &optionalReturnType) {
290+ if (succeeded (p.parseOptionalArrow ())) {
291+ // `->` found. It must be followed by the return type.
292+ return p.parseType (optionalReturnType);
293+ }
294+ // Function has `void` return in C++, no return in MLIR.
295+ optionalReturnType = {};
296+ return success ();
297+ }
298+
299+ // A special pretty-printer for function returning or not a result.
300+ static void printFuncTypeReturn (mlir::AsmPrinter &p,
301+ mlir::Type optionalReturnType) {
302+ if (optionalReturnType)
303+ p << " -> " << optionalReturnType;
304+ }
305+
306+ static mlir::ParseResult
307+ parseFuncTypeArgs (mlir::AsmParser &p, llvm::SmallVector<mlir::Type> ¶ms,
308+ bool &isVarArg) {
288309 isVarArg = false ;
289- // `(` `)`
290- if (succeeded (p.parseOptionalRParen ()))
310+ if (failed (p.parseLParen ()))
311+ return failure ();
312+ if (succeeded (p.parseOptionalRParen ())) {
313+ // `()` empty argument list
291314 return mlir::success ();
292-
293- // `(` `...` `)`
294- if (succeeded (p.parseOptionalEllipsis ())) {
295- isVarArg = true ;
296- return p.parseRParen ();
297315 }
298-
299- // type (`,` type)* (`,` `...`)?
300- mlir::Type type;
301- if (p.parseType (type))
302- return mlir::failure ();
303- params.push_back (type);
304- while (succeeded (p.parseOptionalComma ())) {
316+ do {
305317 if (succeeded (p.parseOptionalEllipsis ())) {
318+ // `...`, which must be the last thing in the list.
306319 isVarArg = true ;
307- return p.parseRParen ();
320+ break ;
321+ } else {
322+ mlir::Type argType;
323+ if (failed (p.parseType (argType)))
324+ return failure ();
325+ params.push_back (argType);
308326 }
309- if (p.parseType (type))
310- return mlir::failure ();
311- params.push_back (type);
312- }
313-
327+ } while (succeeded (p.parseOptionalComma ()));
314328 return p.parseRParen ();
315329}
316330
317- void printFuncTypeArgs (mlir::AsmPrinter &p, mlir::ArrayRef<mlir::Type> params,
318- bool isVarArg) {
331+ static void printFuncTypeArgs (mlir::AsmPrinter &p,
332+ mlir::ArrayRef<mlir::Type> params,
333+ bool isVarArg) {
334+ p << ' (' ;
319335 llvm::interleaveComma (params, p,
320336 [&p](mlir::Type type) { p.printType (type); });
321337 if (isVarArg) {
@@ -326,11 +342,56 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef<mlir::Type> params,
326342 p << ' )' ;
327343}
328344
345+ // Use a custom parser to handle the optional return and argument types without
346+ // an optional anchor.
347+ static mlir::ParseResult parseFuncType (mlir::AsmParser &p,
348+ mlir::Type &optionalReturnType,
349+ llvm::SmallVector<mlir::Type> ¶ms,
350+ bool &isVarArg) {
351+ if (failed (parseFuncTypeArgs (p, params, isVarArg)))
352+ return failure ();
353+ return parseFuncTypeReturn (p, optionalReturnType);
354+ }
355+
356+ static void printFuncType (mlir::AsmPrinter &p, mlir::Type optionalReturnType,
357+ mlir::ArrayRef<mlir::Type> params, bool isVarArg) {
358+ printFuncTypeArgs (p, params, isVarArg);
359+ printFuncTypeReturn (p, optionalReturnType);
360+ }
361+
362+ // / Get the C-style return type of the function, which is !cir.void if the
363+ // / function returns nothing and the actual return type otherwise.
364+ mlir::Type FuncType::getReturnType () const {
365+ if (hasVoidReturn ())
366+ return cir::VoidType::get (getContext ());
367+ return getOptionalReturnType ();
368+ }
369+
370+ // / Get the MLIR-style return type of the function, which is an empty
371+ // / ArrayRef if the function returns nothing and a single-element ArrayRef
372+ // / with the actual return type otherwise.
329373llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes () const {
330- return static_cast <detail::FuncTypeStorage *>(getImpl ())->returnType ;
374+ if (hasVoidReturn ())
375+ return {};
376+ // Can't use getOptionalReturnType() here because llvm::ArrayRef hold a
377+ // pointer to its elements and doesn't do lifetime extension. That would
378+ // result in returning a pointer to a temporary that has gone out of scope.
379+ return getImpl ()->optionalReturnType ;
331380}
332381
333- bool FuncType::isVoid () const { return mlir::isa<VoidType>(getReturnType ()); }
382+ // Does the fuction type return nothing?
383+ bool FuncType::hasVoidReturn () const { return !getOptionalReturnType (); }
384+
385+ mlir::LogicalResult
386+ FuncType::verify (llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
387+ llvm::ArrayRef<mlir::Type> argTypes, mlir::Type returnType,
388+ bool isVarArg) {
389+ if (returnType && mlir::isa<cir::VoidType>(returnType)) {
390+ emitError () << " !cir.func cannot have an explicit 'void' return type" ;
391+ return mlir::failure ();
392+ }
393+ return mlir::success ();
394+ }
334395
335396// ===----------------------------------------------------------------------===//
336397// BoolType
0 commit comments