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
@@ -913,9 +917,46 @@ FuncType FuncType::clone(TypeRange inputs, TypeRange results) const {
913917 return get (llvm::to_vector (inputs), results[0 ], isVarArg ());
914918}
915919
916- mlir::ParseResult parseFuncTypeArgs (mlir::AsmParser &p,
917- llvm::SmallVector<mlir::Type> ¶ms,
918- bool &isVarArg) {
920+ // A special parser is needed for function returning void to consume the "!void"
921+ // returned type in the case there is no alias defined.
922+ static mlir::ParseResult
923+ parseFuncTypeReturn (mlir::AsmParser &p,
924+ llvm::SmallVector<mlir::Type> &returnTypes) {
925+ if (p.parseOptionalExclamationKeyword (" !void" ).succeeded ())
926+ // !void means no return type.
927+ return p.parseLParen ();
928+ if (succeeded (p.parseOptionalLParen ()))
929+ // If we have already a '(', the function has no return type
930+ return mlir::success ();
931+
932+ mlir::Type type;
933+ auto result = p.parseOptionalType (type);
934+ if (!result.has_value ())
935+ return mlir::failure ();
936+ if (failed (*result) || isa<cir::VoidType>(type))
937+ // No return type specified.
938+ return p.parseLParen ();
939+ // Otherwise use the actual type.
940+ returnTypes.push_back (type);
941+ return p.parseLParen ();
942+ }
943+
944+ // A special pretty-printer for function returning void to emit a "!void"
945+ // returned type. Note that there is no real type used here since it does not
946+ // appear in the IR and thus the alias might not be defined and cannot be
947+ // referred to. This is why this is a pure syntactic-sugar string which is used.
948+ static void printFuncTypeReturn (mlir::AsmPrinter &p,
949+ mlir::ArrayRef<mlir::Type> returnTypes) {
950+ if (returnTypes.empty ())
951+ // Pretty-print no return type as "!void"
952+ p << " !void " ;
953+ else
954+ p << returnTypes << ' ' ;
955+ }
956+
957+ static mlir::ParseResult
958+ parseFuncTypeArgs (mlir::AsmParser &p, llvm::SmallVector<mlir::Type> ¶ms,
959+ bool &isVarArg) {
919960 isVarArg = false ;
920961 // `(` `)`
921962 if (succeeded (p.parseOptionalRParen ()))
@@ -945,8 +986,10 @@ mlir::ParseResult parseFuncTypeArgs(mlir::AsmParser &p,
945986 return p.parseRParen ();
946987}
947988
948- void printFuncTypeArgs (mlir::AsmPrinter &p, mlir::ArrayRef<mlir::Type> params,
949- bool isVarArg) {
989+ static void printFuncTypeArgs (mlir::AsmPrinter &p,
990+ mlir::ArrayRef<mlir::Type> params,
991+ bool isVarArg) {
992+ p << ' (' ;
950993 llvm::interleaveComma (params, p,
951994 [&p](mlir::Type type) { p.printType (type); });
952995 if (isVarArg) {
@@ -957,11 +1000,37 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef<mlir::Type> params,
9571000 p << ' )' ;
9581001}
9591002
960- llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes () const {
961- return static_cast <detail::FuncTypeStorage *>(getImpl ())->returnType ;
1003+ static mlir::ParseResult
1004+ parseFuncType (mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &returnTypes,
1005+ llvm::SmallVector<mlir::Type> ¶ms, bool &isVarArg) {
1006+ if (failed (parseFuncTypeReturn (p, returnTypes)))
1007+ return failure ();
1008+ return parseFuncTypeArgs (p, params, isVarArg);
1009+ }
1010+
1011+ static void printFuncType (mlir::AsmPrinter &p,
1012+ mlir::ArrayRef<mlir::Type> returnTypes,
1013+ mlir::ArrayRef<mlir::Type> params, bool isVarArg) {
1014+ printFuncTypeReturn (p, returnTypes);
1015+ printFuncTypeArgs (p, params, isVarArg);
9621016}
9631017
964- bool FuncType::isVoid () const { return mlir::isa<VoidType>(getReturnType ()); }
1018+ // Return the actual return type or an explicit !cir.void if the function does
1019+ // not return anything
1020+ mlir::Type FuncType::getReturnType () const {
1021+ if (isVoid ())
1022+ return cir::VoidType::get (getContext ());
1023+ return static_cast <detail::FuncTypeStorage *>(getImpl ())->returnTypes .front ();
1024+ }
1025+
1026+ bool FuncType::isVoid () const {
1027+ auto rt = static_cast <detail::FuncTypeStorage *>(getImpl ())->returnTypes ;
1028+ assert (rt.empty () ||
1029+ !mlir::isa<cir::VoidType>(rt.front ()) &&
1030+ " The return type for a function returning void should be empty "
1031+ " instead of a real !cir.void" );
1032+ return rt.empty ();
1033+ }
9651034
9661035// ===----------------------------------------------------------------------===//
9671036// MethodType Definitions
0 commit comments