@@ -937,66 +937,51 @@ FuncType FuncType::clone(TypeRange inputs, TypeRange results) const {
937937// type.
938938static mlir::ParseResult parseFuncTypeReturn (mlir::AsmParser &p,
939939 mlir::Type &optionalReturnType) {
940- if (succeeded (p.parseOptionalLParen ())) {
941- // If we have already a '(', the function has no return type
942- optionalReturnType = {};
943- return mlir::success ();
940+ if (succeeded (p.parseOptionalArrow ())) {
941+ // `->` found. It must be followed by the return type.
942+ return p.parseType (optionalReturnType);
944943 }
945- mlir::Type type;
946- if (p.parseType (type))
947- return mlir::failure ();
948- if (isa<cir::VoidType>(type))
949- // An explicit !cir.void means also no return type.
950- optionalReturnType = {};
951- else
952- // Otherwise use the actual type.
953- optionalReturnType = type;
954- return p.parseLParen ();
944+ // Function has `void` return in C++, no return in MLIR.
945+ optionalReturnType = {};
946+ return success ();
955947}
956948
957949// A special pretty-printer for function returning or not a result.
958950static void printFuncTypeReturn (mlir::AsmPrinter &p,
959951 mlir::Type optionalReturnType) {
960952 if (optionalReturnType)
961- p << optionalReturnType << ' ' ;
962- p << ' (' ;
953+ p << " -> " << optionalReturnType;
963954}
964955
965956static mlir::ParseResult
966957parseFuncTypeArgs (mlir::AsmParser &p, llvm::SmallVector<mlir::Type> ¶ms,
967958 bool &isVarArg) {
968959 isVarArg = false ;
969- // `(` `)`
970- if (succeeded (p.parseOptionalRParen ()))
960+ if (failed (p.parseLParen ()))
961+ return failure ();
962+ if (succeeded (p.parseOptionalRParen ())) {
963+ // `()` empty argument list
971964 return mlir::success ();
972-
973- // `(` `...` `)`
974- if (succeeded (p.parseOptionalEllipsis ())) {
975- isVarArg = true ;
976- return p.parseRParen ();
977965 }
978-
979- // type (`,` type)* (`,` `...`)?
980- mlir::Type type;
981- if (p.parseType (type))
982- return mlir::failure ();
983- params.push_back (type);
984- while (succeeded (p.parseOptionalComma ())) {
966+ do {
985967 if (succeeded (p.parseOptionalEllipsis ())) {
968+ // `...`, which must be the last thing in the list.
986969 isVarArg = true ;
987- return p.parseRParen ();
970+ break ;
971+ } else {
972+ mlir::Type argType;
973+ if (failed (p.parseType (argType)))
974+ return failure ();
975+ params.push_back (argType);
988976 }
989- if (p.parseType (type))
990- return mlir::failure ();
991- params.push_back (type);
992- }
993-
977+ } while (succeeded (p.parseOptionalComma ()));
994978 return p.parseRParen ();
995979}
996980
997981static void printFuncTypeArgs (mlir::AsmPrinter &p,
998982 mlir::ArrayRef<mlir::Type> params,
999983 bool isVarArg) {
984+ p << ' (' ;
1000985 llvm::interleaveComma (params, p,
1001986 [&p](mlir::Type type) { p.printType (type); });
1002987 if (isVarArg) {
@@ -1010,45 +995,52 @@ static void printFuncTypeArgs(mlir::AsmPrinter &p,
1010995// Use a custom parser to handle the optional return and argument types without
1011996// an optional anchor.
1012997static mlir::ParseResult parseFuncType (mlir::AsmParser &p,
1013- mlir::Type &optionalReturnTypes ,
998+ mlir::Type &optionalReturnType ,
1014999 llvm::SmallVector<mlir::Type> ¶ms,
10151000 bool &isVarArg) {
1016- if (failed (parseFuncTypeReturn (p, optionalReturnTypes )))
1001+ if (failed (parseFuncTypeArgs (p, params, isVarArg )))
10171002 return failure ();
1018- return parseFuncTypeArgs (p, params, isVarArg );
1003+ return parseFuncTypeReturn (p, optionalReturnType );
10191004}
10201005
1021- static void printFuncType (mlir::AsmPrinter &p, mlir::Type optionalReturnTypes ,
1006+ static void printFuncType (mlir::AsmPrinter &p, mlir::Type optionalReturnType ,
10221007 mlir::ArrayRef<mlir::Type> params, bool isVarArg) {
1023- printFuncTypeReturn (p, optionalReturnTypes);
10241008 printFuncTypeArgs (p, params, isVarArg);
1009+ printFuncTypeReturn (p, optionalReturnType);
10251010}
10261011
1027- // Return the actual return type or an explicit !cir.void if the function does
1028- // not return anything
1012+ // / Get the C-style return type of the function, which is !cir.void if the
1013+ // / function returns nothing and the actual return type otherwise.
10291014mlir::Type FuncType::getReturnType () const {
1030- if (isVoid ())
1015+ if (hasVoidReturn ())
10311016 return cir::VoidType::get (getContext ());
1032- return static_cast <detail::FuncTypeStorage *>( getImpl ())-> optionalReturnType ;
1017+ return getOptionalReturnType () ;
10331018}
10341019
1035- // / Returns the result type of the function as an ArrayRef, enabling better
1036- // / integration with generic MLIR utilities.
1020+ // / Get the MLIR-style return type of the function, which is an empty
1021+ // / ArrayRef if the function returns nothing and a single-element ArrayRef
1022+ // / with the actual return type otherwise.
10371023llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes () const {
1038- if (isVoid ())
1024+ if (hasVoidReturn ())
10391025 return {};
1040- return static_cast <detail::FuncTypeStorage *>(getImpl ())->optionalReturnType ;
1041- }
1042-
1043- // Whether the function returns void
1044- bool FuncType::isVoid () const {
1045- auto rt =
1046- static_cast <detail::FuncTypeStorage *>(getImpl ())->optionalReturnType ;
1047- assert (!rt ||
1048- !mlir::isa<cir::VoidType>(rt) &&
1049- " The return type for a function returning void should be empty "
1050- " instead of a real !cir.void" );
1051- return !rt;
1026+ // Can't use getOptionalReturnType() here because llvm::ArrayRef hold a
1027+ // pointer to its elements and doesn't do lifetime extension. That would
1028+ // result in returning a pointer to a temporary that has gone out of scope.
1029+ return getImpl ()->optionalReturnType ;
1030+ }
1031+
1032+ // Does the fuction type return nothing?
1033+ bool FuncType::hasVoidReturn () const { return !getOptionalReturnType (); }
1034+
1035+ mlir::LogicalResult
1036+ FuncType::verify (llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1037+ llvm::ArrayRef<mlir::Type> argTypes, mlir::Type returnType,
1038+ bool isVarArg) {
1039+ if (returnType && mlir::isa<cir::VoidType>(returnType)) {
1040+ emitError () << " !cir.func cannot have an explicit 'void' return type" ;
1041+ return mlir::failure ();
1042+ }
1043+ return mlir::success ();
10521044}
10531045
10541046// ===----------------------------------------------------------------------===//
0 commit comments