33
33
#include " llvm/ADT/TypeSwitch.h"
34
34
#include " llvm/Support/ErrorHandling.h"
35
35
#include " llvm/Support/MathExtras.h"
36
+ #include < cassert>
36
37
#include < optional>
37
38
38
39
using cir::MissingFeatures;
@@ -41,12 +42,13 @@ using cir::MissingFeatures;
41
42
// CIR Custom Parser/Printer Signatures
42
43
// ===----------------------------------------------------------------------===//
43
44
44
- static 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);
45
+ static mlir::ParseResult parseFuncType (mlir::AsmParser &p,
46
+ mlir::Type &optionalReturnTypes,
47
+ llvm::SmallVector<mlir::Type> ¶ms,
48
+ bool &isVarArg);
49
49
50
+ static void printFuncType (mlir::AsmPrinter &p, mlir::Type optionalReturnTypes,
51
+ mlir::ArrayRef<mlir::Type> params, bool isVarArg);
50
52
static mlir::ParseResult parsePointerAddrSpace (mlir::AsmParser &p,
51
53
mlir::Attribute &addrSpaceAttr);
52
54
static void printPointerAddrSpace (mlir::AsmPrinter &p,
@@ -813,9 +815,38 @@ FuncType FuncType::clone(TypeRange inputs, TypeRange results) const {
813
815
return get (llvm::to_vector (inputs), results[0 ], isVarArg ());
814
816
}
815
817
816
- mlir::ParseResult parseFuncTypeArgs (mlir::AsmParser &p,
817
- llvm::SmallVector<mlir::Type> ¶ms,
818
- bool &isVarArg) {
818
+ // A special parser is needed for function returning void to handle the missing
819
+ // type.
820
+ static mlir::ParseResult parseFuncTypeReturn (mlir::AsmParser &p,
821
+ mlir::Type &optionalReturnType) {
822
+ if (succeeded (p.parseOptionalLParen ())) {
823
+ // If we have already a '(', the function has no return type
824
+ optionalReturnType = {};
825
+ return mlir::success ();
826
+ }
827
+ mlir::Type type;
828
+ if (p.parseType (type))
829
+ return mlir::failure ();
830
+ if (isa<cir::VoidType>(type))
831
+ // An explicit !cir.void means also no return type.
832
+ optionalReturnType = {};
833
+ else
834
+ // Otherwise use the actual type.
835
+ optionalReturnType = type;
836
+ return p.parseLParen ();
837
+ }
838
+
839
+ // A special pretty-printer for function returning or not a result.
840
+ static void printFuncTypeReturn (mlir::AsmPrinter &p,
841
+ mlir::Type optionalReturnType) {
842
+ if (optionalReturnType)
843
+ p << optionalReturnType << ' ' ;
844
+ p << ' (' ;
845
+ }
846
+
847
+ static mlir::ParseResult
848
+ parseFuncTypeArgs (mlir::AsmParser &p, llvm::SmallVector<mlir::Type> ¶ms,
849
+ bool &isVarArg) {
819
850
isVarArg = false ;
820
851
// `(` `)`
821
852
if (succeeded (p.parseOptionalRParen ()))
@@ -845,8 +876,9 @@ mlir::ParseResult parseFuncTypeArgs(mlir::AsmParser &p,
845
876
return p.parseRParen ();
846
877
}
847
878
848
- void printFuncTypeArgs (mlir::AsmPrinter &p, mlir::ArrayRef<mlir::Type> params,
849
- bool isVarArg) {
879
+ static void printFuncTypeArgs (mlir::AsmPrinter &p,
880
+ mlir::ArrayRef<mlir::Type> params,
881
+ bool isVarArg) {
850
882
llvm::interleaveComma (params, p,
851
883
[&p](mlir::Type type) { p.printType (type); });
852
884
if (isVarArg) {
@@ -857,11 +889,49 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef<mlir::Type> params,
857
889
p << ' )' ;
858
890
}
859
891
892
+ // Use a custom parser to handle the optional return and argument types without
893
+ // an optional anchor.
894
+ static mlir::ParseResult parseFuncType (mlir::AsmParser &p,
895
+ mlir::Type &optionalReturnTypes,
896
+ llvm::SmallVector<mlir::Type> ¶ms,
897
+ bool &isVarArg) {
898
+ if (failed (parseFuncTypeReturn (p, optionalReturnTypes)))
899
+ return failure ();
900
+ return parseFuncTypeArgs (p, params, isVarArg);
901
+ }
902
+
903
+ static void printFuncType (mlir::AsmPrinter &p, mlir::Type optionalReturnTypes,
904
+ mlir::ArrayRef<mlir::Type> params, bool isVarArg) {
905
+ printFuncTypeReturn (p, optionalReturnTypes);
906
+ printFuncTypeArgs (p, params, isVarArg);
907
+ }
908
+
909
+ // Return the actual return type or an explicit !cir.void if the function does
910
+ // not return anything
911
+ mlir::Type FuncType::getReturnType () const {
912
+ if (isVoid ())
913
+ return cir::VoidType::get (getContext ());
914
+ return static_cast <detail::FuncTypeStorage *>(getImpl ())->optionalReturnType ;
915
+ }
916
+
917
+ // / Returns the result type of the function as an ArrayRef, enabling better
918
+ // / integration with generic MLIR utilities.
860
919
llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes () const {
861
- return static_cast <detail::FuncTypeStorage *>(getImpl ())->returnType ;
920
+ if (isVoid ())
921
+ return {};
922
+ return static_cast <detail::FuncTypeStorage *>(getImpl ())->optionalReturnType ;
862
923
}
863
924
864
- bool FuncType::isVoid () const { return mlir::isa<VoidType>(getReturnType ()); }
925
+ // Whether the function returns void
926
+ bool FuncType::isVoid () const {
927
+ auto rt =
928
+ static_cast <detail::FuncTypeStorage *>(getImpl ())->optionalReturnType ;
929
+ assert (!rt ||
930
+ !mlir::isa<cir::VoidType>(rt) &&
931
+ " The return type for a function returning void should be empty "
932
+ " instead of a real !cir.void" );
933
+ return !rt;
934
+ }
865
935
866
936
// ===----------------------------------------------------------------------===//
867
937
// MethodType Definitions
0 commit comments