@@ -183,7 +183,7 @@ struct IntrinsicLibrary {
183
183
// / Generate FIR for call to Fortran intrinsic \p name with arguments \p arg
184
184
// / and expected result type \p resultType.
185
185
fir::ExtendedValue genIntrinsicCall (llvm::StringRef name,
186
- mlir::Type resultType,
186
+ llvm::Optional< mlir::Type> resultType,
187
187
llvm::ArrayRef<fir::ExtendedValue> arg);
188
188
189
189
// / Search a runtime function that is associated to the generic intrinsic name
@@ -209,6 +209,7 @@ struct IntrinsicLibrary {
209
209
mlir::Value genAnint (mlir::Type, llvm::ArrayRef<mlir::Value>);
210
210
mlir::Value genCeiling (mlir::Type, llvm::ArrayRef<mlir::Value>);
211
211
mlir::Value genConjg (mlir::Type, llvm::ArrayRef<mlir::Value>);
212
+ void genDateAndTime (llvm::ArrayRef<fir::ExtendedValue>);
212
213
mlir::Value genDim (mlir::Type, llvm::ArrayRef<mlir::Value>);
213
214
mlir::Value genDprod (mlir::Type, llvm::ArrayRef<mlir::Value>);
214
215
template <Extremum, ExtremumBehavior>
@@ -233,7 +234,9 @@ struct IntrinsicLibrary {
233
234
// / generate the related code.
234
235
using ElementalGenerator = decltype (&IntrinsicLibrary::genAbs);
235
236
using ExtendedGenerator = decltype (&IntrinsicLibrary::genLenTrim);
236
- using Generator = std::variant<ElementalGenerator, ExtendedGenerator>;
237
+ using SubroutineGenerator = decltype (&IntrinsicLibrary::genDateAndTime);
238
+ using Generator =
239
+ std::variant<ElementalGenerator, ExtendedGenerator, SubroutineGenerator>;
237
240
238
241
// / All generators can be outlined. This will build a function named
239
242
// / "fir."+ <generic name> + "." + <result type code> and generate the
@@ -269,6 +272,9 @@ struct IntrinsicLibrary {
269
272
mlir::Value invokeGenerator (ExtendedGenerator generator,
270
273
mlir::Type resultType,
271
274
llvm::ArrayRef<mlir::Value> args);
275
+ mlir::Value invokeGenerator (SubroutineGenerator generator,
276
+ mlir::Type resultType,
277
+ llvm::ArrayRef<mlir::Value> args);
272
278
273
279
// / Get pointer to unrestricted intrinsic. Generate the related unrestricted
274
280
// / intrinsic if it is not defined yet.
@@ -292,6 +298,7 @@ struct IntrinsicHandler {
292
298
// / more readable.
293
299
bool outline = false ;
294
300
};
301
+
295
302
using I = IntrinsicLibrary;
296
303
static constexpr IntrinsicHandler handlers[]{
297
304
{" abs" , &I::genAbs},
@@ -302,6 +309,7 @@ static constexpr IntrinsicHandler handlers[]{
302
309
{" ceiling" , &I::genCeiling},
303
310
{" char" , &I::genConversion},
304
311
{" conjg" , &I::genConjg},
312
+ {" date_and_time" , &I::genDateAndTime},
305
313
{" dim" , &I::genDim},
306
314
{" dble" , &I::genConversion},
307
315
{" dprod" , &I::genDprod},
@@ -761,24 +769,71 @@ IntrinsicLibrary::genElementalCall<IntrinsicLibrary::ExtendedGenerator>(
761
769
return std::invoke (generator, *this , resultType, args);
762
770
}
763
771
772
+ static fir::ExtendedValue
773
+ invokeHanlder (IntrinsicLibrary::ElementalGenerator generator,
774
+ const IntrinsicHandler &handler,
775
+ llvm::Optional<mlir::Type> resultType,
776
+ llvm::ArrayRef<fir::ExtendedValue> args, bool outline,
777
+ IntrinsicLibrary &lib) {
778
+ assert (resultType && " expect elemental intrinsic to be functions" );
779
+ return lib.genElementalCall (generator, handler.name , *resultType, args,
780
+ outline);
781
+ }
782
+
783
+ static fir::ExtendedValue
784
+ invokeHanlder (IntrinsicLibrary::ExtendedGenerator generator,
785
+ const IntrinsicHandler &handler,
786
+ llvm::Optional<mlir::Type> resultType,
787
+ llvm::ArrayRef<fir::ExtendedValue> args, bool outline,
788
+ IntrinsicLibrary &lib) {
789
+ assert (resultType && " expect intrinsic function" );
790
+ if (handler.isElemental )
791
+ return lib.genElementalCall (generator, handler.name , *resultType, args,
792
+ outline);
793
+ if (outline)
794
+ return lib.outlineInWrapper (generator, handler.name , *resultType, args);
795
+ return std::invoke (generator, lib, *resultType, args);
796
+ }
797
+ static fir::ExtendedValue
798
+ invokeHanlder (IntrinsicLibrary::SubroutineGenerator generator,
799
+ const IntrinsicHandler &handler,
800
+ llvm::Optional<mlir::Type> resultType,
801
+ llvm::ArrayRef<fir::ExtendedValue> args, bool outline,
802
+ IntrinsicLibrary &lib) {
803
+ // TODO
804
+ // if (outline)
805
+ // return outlineInWrapper(generator, handler.name, *resultType, args);
806
+ std::invoke (generator, lib, args);
807
+ return mlir::Value{};
808
+ }
809
+
810
+ // / Many intrinsics are not yet lowered, provide a clear error message to user
811
+ // / instead of hitting harder to understand asserts.
812
+ static void crashOnMissingIntrinsic (mlir::Location loc, llvm::StringRef name) {
813
+ mlir::emitError (loc,
814
+ " TODO: missing intrinsic lowering: " + llvm::Twine (name));
815
+ exit (1 );
816
+ }
817
+
764
818
fir::ExtendedValue
765
- IntrinsicLibrary::genIntrinsicCall (llvm::StringRef name, mlir::Type resultType,
819
+ IntrinsicLibrary::genIntrinsicCall (llvm::StringRef name,
820
+ llvm::Optional<mlir::Type> resultType,
766
821
llvm::ArrayRef<fir::ExtendedValue> args) {
767
822
for (auto &handler : handlers)
768
823
if (name == handler.name ) {
769
824
bool outline = handler.outline || outlineAllIntrinsics;
770
- if (const auto *elementalGenerator =
771
- std::get_if<ElementalGenerator>(&handler.generator ))
772
- return genElementalCall (*elementalGenerator, name, resultType, args,
773
- outline);
774
- const auto &generator = std::get<ExtendedGenerator>(handler.generator );
775
- if (handler.isElemental )
776
- return genElementalCall (generator, name, resultType, args, outline);
777
- if (outline)
778
- return outlineInWrapper (generator, name, resultType, args);
779
- return std::invoke (generator, *this , resultType, args);
825
+ return std::visit (
826
+ [&](auto &generator) -> fir::ExtendedValue {
827
+ return invokeHanlder (generator, handler, resultType, args, outline,
828
+ *this );
829
+ },
830
+ handler.generator );
780
831
}
781
832
833
+ if (!resultType)
834
+ // Subroutine should have a handler, they are likely missing for now.
835
+ crashOnMissingIntrinsic (loc, name);
836
+
782
837
// Try the runtime if no special handler was defined for the
783
838
// intrinsic being called. Maths runtime only has numerical elemental.
784
839
// No optional arguments are expected at this point, the code will
@@ -788,20 +843,17 @@ IntrinsicLibrary::genIntrinsicCall(llvm::StringRef name, mlir::Type resultType,
788
843
llvm::SmallVector<mlir::Value, 2 > mlirArgs;
789
844
for (const auto &extendedVal : args) {
790
845
auto val = toValue (extendedVal, builder, loc);
791
- if (!val) {
846
+ if (!val)
792
847
// If an absent optional gets there, most likely its handler has just
793
848
// not yet been defined.
794
- mlir::emitError (loc,
795
- " TODO: missing intrinsic lowering: " + llvm::Twine (name));
796
- exit (1 );
797
- }
849
+ crashOnMissingIntrinsic (loc, name);
798
850
mlirArgs.emplace_back (val);
799
851
}
800
852
mlir::FunctionType soughtFuncType =
801
- getFunctionType (resultType, mlirArgs, builder);
853
+ getFunctionType (* resultType, mlirArgs, builder);
802
854
803
855
auto runtimeCallGenerator = getRuntimeCallGenerator (name, soughtFuncType);
804
- return genElementalCall (runtimeCallGenerator, name, resultType, args,
856
+ return genElementalCall (runtimeCallGenerator, name, * resultType, args,
805
857
/* outline */ true );
806
858
}
807
859
@@ -830,14 +882,22 @@ IntrinsicLibrary::invokeGenerator(ExtendedGenerator generator,
830
882
return toValue (extendedResult, builder, loc);
831
883
}
832
884
885
+ mlir::Value
886
+ IntrinsicLibrary::invokeGenerator (SubroutineGenerator generator,
887
+ mlir::Type resultType,
888
+ llvm::ArrayRef<mlir::Value> args) {
889
+ llvm::SmallVector<fir::ExtendedValue, 2 > extendedArgs;
890
+ for (auto arg : args)
891
+ extendedArgs.emplace_back (toExtendedValue (arg, builder, loc));
892
+ std::invoke (generator, *this , extendedArgs);
893
+ return mlir::Value{};
894
+ }
895
+
833
896
template <typename GeneratorType>
834
897
mlir::FuncOp IntrinsicLibrary::getWrapper (GeneratorType generator,
835
898
llvm::StringRef name,
836
899
mlir::FunctionType funcType,
837
900
bool loadRefArguments) {
838
- assert (funcType.getNumResults () == 1 &&
839
- " expect one result for intrinsic functions" );
840
- auto resultType = funcType.getResult (0 );
841
901
std::string wrapperName = fir::mangleIntrinsicProcedure (name, funcType);
842
902
auto function = builder.getNamedFunction (wrapperName);
843
903
if (!function) {
@@ -868,6 +928,9 @@ mlir::FuncOp IntrinsicLibrary::getWrapper(GeneratorType generator,
868
928
}
869
929
870
930
IntrinsicLibrary localLib{*localBuilder, localLoc};
931
+ mlir::Type resultType;
932
+ if (funcType.getNumResults () == 1 )
933
+ resultType = funcType.getResult (0 );
871
934
auto result =
872
935
localLib.invokeGenerator (generator, resultType, localArguments);
873
936
localBuilder->create <mlir::ReturnOp>(localLoc, result);
@@ -1101,6 +1164,20 @@ mlir::Value IntrinsicLibrary::genConjg(mlir::Type resultType,
1101
1164
cplx, negImag, /* isImagPart=*/ true );
1102
1165
}
1103
1166
1167
+ // DATE_AND_TIME
1168
+ void IntrinsicLibrary::genDateAndTime (llvm::ArrayRef<fir::ExtendedValue> args) {
1169
+ assert (args.size () == 4 && " date_and_time has 4 args" );
1170
+ llvm::Optional<fir::CharBoxValue> date;
1171
+ if (auto *charBox = args[0 ].getCharBox ())
1172
+ date = *charBox;
1173
+ for (auto i = 1 ; i < 4 ; ++i)
1174
+ if (fir::getBase (args[i]))
1175
+ llvm::errs () << " TODO: lowering of DATE_AND_TIME arguments other than "
1176
+ " DATE not yet implemented\n " ;
1177
+
1178
+ Fortran::lower::genDateAndTime (builder, loc, date);
1179
+ }
1180
+
1104
1181
// DIM
1105
1182
mlir::Value IntrinsicLibrary::genDim (mlir::Type resultType,
1106
1183
llvm::ArrayRef<mlir::Value> args) {
@@ -1153,7 +1230,7 @@ mlir::Value IntrinsicLibrary::genIAnd(mlir::Type resultType,
1153
1230
mlir::Value IntrinsicLibrary::genIchar (mlir::Type resultType,
1154
1231
llvm::ArrayRef<mlir::Value> args) {
1155
1232
// There can be an optional kind in second argument.
1156
- assert (args.size () >= 1 && args. size () < = 2 );
1233
+ assert (args.size () = = 2 );
1157
1234
1158
1235
auto arg = args[0 ];
1159
1236
auto argTy = arg.getType ();
@@ -1360,7 +1437,7 @@ mlir::Value IntrinsicLibrary::genExtremum(mlir::Type,
1360
1437
fir::ExtendedValue
1361
1438
Fortran::lower::genIntrinsicCall (Fortran::lower::FirOpBuilder &builder,
1362
1439
mlir::Location loc, llvm::StringRef name,
1363
- mlir::Type resultType,
1440
+ llvm::Optional< mlir::Type> resultType,
1364
1441
llvm::ArrayRef<fir::ExtendedValue> args) {
1365
1442
return IntrinsicLibrary{builder, loc}.genIntrinsicCall (name, resultType,
1366
1443
args);
0 commit comments