3333#include " llvm/ADT/TypeSwitch.h"
3434#include " llvm/Support/ErrorHandling.h"
3535#include " llvm/Support/MathExtras.h"
36+ #include < cassert>
3637#include < optional>
3738
3839using cir::MissingFeatures;
@@ -42,13 +43,16 @@ using cir::MissingFeatures;
4243// ===----------------------------------------------------------------------===//
4344
4445static mlir::ParseResult
45- parseFuncTypeArgs (mlir::AsmParser &p, llvm::SmallVector<mlir::Type> ¶ms,
46- bool &isVarArg);
47- static void printFuncTypeArgs (mlir::AsmPrinter &p,
48- mlir::ArrayRef<mlir::Type> params, bool isVarArg);
46+ parseFuncType (mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &returnTypes,
47+ llvm::SmallVector<mlir::Type> ¶ms, bool &isVarArg);
48+
49+ static void printFuncType (mlir::AsmPrinter &p,
50+ mlir::ArrayRef<mlir::Type> returnTypes,
51+ mlir::ArrayRef<mlir::Type> params, bool isVarArg);
4952
5053static mlir::ParseResult parsePointerAddrSpace (mlir::AsmParser &p,
5154 mlir::Attribute &addrSpaceAttr);
55+
5256static void printPointerAddrSpace (mlir::AsmPrinter &p,
5357 mlir::Attribute addrSpaceAttr);
5458
@@ -813,9 +817,46 @@ FuncType FuncType::clone(TypeRange inputs, TypeRange results) const {
813817 return get (llvm::to_vector (inputs), results[0 ], isVarArg ());
814818}
815819
816- mlir::ParseResult parseFuncTypeArgs (mlir::AsmParser &p,
817- llvm::SmallVector<mlir::Type> ¶ms,
818- bool &isVarArg) {
820+ // A special parser is needed for function returning void to consume the "!void"
821+ // returned type in the case there is no alias defined.
822+ static mlir::ParseResult
823+ parseFuncTypeReturn (mlir::AsmParser &p,
824+ llvm::SmallVector<mlir::Type> &returnTypes) {
825+ if (p.parseOptionalExclamationKeyword (" !void" ).succeeded ())
826+ // !void means no return type.
827+ return p.parseLParen ();
828+ if (succeeded (p.parseOptionalLParen ()))
829+ // If we have already a '(', the function has no return type
830+ return mlir::success ();
831+
832+ mlir::Type type;
833+ auto result = p.parseOptionalType (type);
834+ if (!result.has_value ())
835+ return mlir::failure ();
836+ if (failed (*result) || isa<cir::VoidType>(type))
837+ // No return type specified.
838+ return p.parseLParen ();
839+ // Otherwise use the actual type.
840+ returnTypes.push_back (type);
841+ return p.parseLParen ();
842+ }
843+
844+ // A special pretty-printer for function returning void to emit a "!void"
845+ // returned type. Note that there is no real type used here since it does not
846+ // appear in the IR and thus the alias might not be defined and cannot be
847+ // referred to. This is why this is a pure syntactic-sugar string which is used.
848+ static void printFuncTypeReturn (mlir::AsmPrinter &p,
849+ mlir::ArrayRef<mlir::Type> returnTypes) {
850+ if (returnTypes.empty ())
851+ // Pretty-print no return type as "!void"
852+ p << " !void " ;
853+ else
854+ p << returnTypes << ' ' ;
855+ }
856+
857+ static mlir::ParseResult
858+ parseFuncTypeArgs (mlir::AsmParser &p, llvm::SmallVector<mlir::Type> ¶ms,
859+ bool &isVarArg) {
819860 isVarArg = false ;
820861 // `(` `)`
821862 if (succeeded (p.parseOptionalRParen ()))
@@ -845,8 +886,10 @@ mlir::ParseResult parseFuncTypeArgs(mlir::AsmParser &p,
845886 return p.parseRParen ();
846887}
847888
848- void printFuncTypeArgs (mlir::AsmPrinter &p, mlir::ArrayRef<mlir::Type> params,
849- bool isVarArg) {
889+ static void printFuncTypeArgs (mlir::AsmPrinter &p,
890+ mlir::ArrayRef<mlir::Type> params,
891+ bool isVarArg) {
892+ p << ' (' ;
850893 llvm::interleaveComma (params, p,
851894 [&p](mlir::Type type) { p.printType (type); });
852895 if (isVarArg) {
@@ -857,11 +900,37 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef<mlir::Type> params,
857900 p << ' )' ;
858901}
859902
860- llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes () const {
861- return static_cast <detail::FuncTypeStorage *>(getImpl ())->returnType ;
903+ static mlir::ParseResult
904+ parseFuncType (mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &returnTypes,
905+ llvm::SmallVector<mlir::Type> ¶ms, bool &isVarArg) {
906+ if (failed (parseFuncTypeReturn (p, returnTypes)))
907+ return failure ();
908+ return parseFuncTypeArgs (p, params, isVarArg);
909+ }
910+
911+ static void printFuncType (mlir::AsmPrinter &p,
912+ mlir::ArrayRef<mlir::Type> returnTypes,
913+ mlir::ArrayRef<mlir::Type> params, bool isVarArg) {
914+ printFuncTypeReturn (p, returnTypes);
915+ printFuncTypeArgs (p, params, isVarArg);
862916}
863917
864- bool FuncType::isVoid () const { return mlir::isa<VoidType>(getReturnType ()); }
918+ // Return the actual return type or an explicit !cir.void if the function does
919+ // not return anything
920+ mlir::Type FuncType::getReturnType () const {
921+ if (isVoid ())
922+ return cir::VoidType::get (getContext ());
923+ return static_cast <detail::FuncTypeStorage *>(getImpl ())->returnTypes .front ();
924+ }
925+
926+ bool FuncType::isVoid () const {
927+ auto rt = static_cast <detail::FuncTypeStorage *>(getImpl ())->returnTypes ;
928+ assert (rt.empty () ||
929+ !mlir::isa<cir::VoidType>(rt.front ()) &&
930+ " The return type for a function returning void should be empty "
931+ " instead of a real !cir.void" );
932+ return rt.empty ();
933+ }
865934
866935// ===----------------------------------------------------------------------===//
867936// MethodType Definitions
0 commit comments