FLANG
RTBuilder.h
Go to the documentation of this file.
1//===-- RTBuilder.h ---------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
15//===----------------------------------------------------------------------===//
16
17#ifndef FORTRAN_OPTIMIZER_BUILDER_RUNTIME_RTBUILDER_H
18#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_RTBUILDER_H
19
20#include "flang/Common/uint128.h"
21#include "flang/Optimizer/Builder/FIRBuilder.h"
22#include "flang/Optimizer/Dialect/FIRType.h"
23#include "flang/Runtime/io-api.h"
24#include "flang/Runtime/reduce.h"
25#include "flang/Support/Fortran.h"
26#include "mlir/IR/BuiltinTypes.h"
27#include "mlir/IR/MLIRContext.h"
28#include "llvm/ADT/STLExtras.h"
29#include "llvm/ADT/SmallVector.h"
30#include <cstdint>
31
32#ifdef _MSC_VER
33// On Windows* OS GetCurrentProcessId returns DWORD aka uint32_t
34typedef std::uint32_t pid_t;
35#endif
36
37// Incomplete type indicating C99 complex ABI in interfaces. Beware, _Complex
38// and std::complex are layout compatible, but not compatible in all ABI call
39// interfaces (e.g. X86 32 bits). _Complex is not standard C++, so do not use
40// it here.
41struct c_float_complex_t;
42struct c_double_complex_t;
43
44namespace Fortran::runtime {
45class Descriptor;
46namespace typeInfo {
47class DerivedType;
48}
49} // namespace Fortran::runtime
50
51namespace fir::runtime {
52
53using TypeBuilderFunc = mlir::Type (*)(mlir::MLIRContext *);
54using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *);
55
56#define REDUCTION_REF_OPERATION_MODEL(T) \
57 template <> \
58 constexpr TypeBuilderFunc \
59 getModel<Fortran::runtime::ReferenceReductionOperation<T>>() { \
60 return [](mlir::MLIRContext *context) -> mlir::Type { \
61 TypeBuilderFunc f{getModel<T>()}; \
62 auto refTy = fir::ReferenceType::get(f(context)); \
63 return mlir::FunctionType::get(context, {refTy, refTy}, refTy); \
64 }; \
65 }
66
67#define REDUCTION_VALUE_OPERATION_MODEL(T) \
68 template <> \
69 constexpr TypeBuilderFunc \
70 getModel<Fortran::runtime::ValueReductionOperation<T>>() { \
71 return [](mlir::MLIRContext *context) -> mlir::Type { \
72 TypeBuilderFunc f{getModel<T>()}; \
73 auto refTy = fir::ReferenceType::get(f(context)); \
74 return mlir::FunctionType::get(context, {f(context), f(context)}, \
75 refTy); \
76 }; \
77 }
78
79#define REDUCTION_CHAR_OPERATION_MODEL(T) \
80 template <> \
81 constexpr TypeBuilderFunc \
82 getModel<Fortran::runtime::ReductionCharOperation<T>>() { \
83 return [](mlir::MLIRContext *context) -> mlir::Type { \
84 TypeBuilderFunc f{getModel<T>()}; \
85 auto voidTy = fir::LLVMPointerType::get( \
86 context, mlir::IntegerType::get(context, 8)); \
87 auto size_tTy = \
88 mlir::IntegerType::get(context, 8 * sizeof(std::size_t)); \
89 auto refTy = fir::ReferenceType::get(f(context)); \
90 return mlir::FunctionType::get( \
91 context, {refTy, size_tTy, refTy, refTy, size_tTy, size_tTy}, \
92 voidTy); \
93 }; \
94 }
95
96//===----------------------------------------------------------------------===//
97// Type builder models
98//===----------------------------------------------------------------------===//
99
100// TODO: all usages of sizeof in this file assume build == host == target.
101// This will need to be re-visited for cross compilation.
102
110template <typename T>
111static constexpr TypeBuilderFunc getModel();
112
113template <>
114constexpr TypeBuilderFunc getModel<unsigned int>() {
115 return [](mlir::MLIRContext *context) -> mlir::Type {
116 return mlir::IntegerType::get(context, 8 * sizeof(unsigned int));
117 };
118}
119template <>
120constexpr TypeBuilderFunc getModel<short int>() {
121 return [](mlir::MLIRContext *context) -> mlir::Type {
122 return mlir::IntegerType::get(context, 8 * sizeof(short int));
123 };
124}
125template <>
126constexpr TypeBuilderFunc getModel<short int *>() {
127 return [](mlir::MLIRContext *context) -> mlir::Type {
128 TypeBuilderFunc f{getModel<short int>()};
129 return fir::ReferenceType::get(f(context));
130 };
131}
132template <>
133constexpr TypeBuilderFunc getModel<const short int *>() {
134 return getModel<short int *>();
135}
136template <>
137constexpr TypeBuilderFunc getModel<int>() {
138 return [](mlir::MLIRContext *context) -> mlir::Type {
139 return mlir::IntegerType::get(context, 8 * sizeof(int));
140 };
141}
142template <>
143constexpr TypeBuilderFunc getModel<int &>() {
144 return [](mlir::MLIRContext *context) -> mlir::Type {
145 TypeBuilderFunc f{getModel<int>()};
146 return fir::ReferenceType::get(f(context));
147 };
148}
149template <>
150constexpr TypeBuilderFunc getModel<int *>() {
151 return getModel<int &>();
152}
153template <>
154constexpr TypeBuilderFunc getModel<const int *>() {
155 return [](mlir::MLIRContext *context) -> mlir::Type {
156 TypeBuilderFunc f{getModel<int>()};
157 return fir::ReferenceType::get(f(context));
158 };
159}
160template <>
161constexpr TypeBuilderFunc getModel<char *>() {
162 return [](mlir::MLIRContext *context) -> mlir::Type {
163 return fir::ReferenceType::get(mlir::IntegerType::get(context, 8));
164 };
165}
166template <>
167constexpr TypeBuilderFunc getModel<const char *>() {
168 return getModel<char *>();
169}
170template <>
171constexpr TypeBuilderFunc getModel<const char16_t *>() {
172 return [](mlir::MLIRContext *context) -> mlir::Type {
173 return fir::ReferenceType::get(mlir::IntegerType::get(context, 16));
174 };
175}
176template <>
177constexpr TypeBuilderFunc getModel<const char32_t *>() {
178 return [](mlir::MLIRContext *context) -> mlir::Type {
179 return fir::ReferenceType::get(mlir::IntegerType::get(context, 32));
180 };
181}
182template <>
183constexpr TypeBuilderFunc getModel<char>() {
184 return [](mlir::MLIRContext *context) -> mlir::Type {
185 return mlir::IntegerType::get(context, 8 * sizeof(char));
186 };
187}
188template <>
189constexpr TypeBuilderFunc getModel<signed char>() {
190 return [](mlir::MLIRContext *context) -> mlir::Type {
191 return mlir::IntegerType::get(context, 8 * sizeof(signed char));
192 };
193}
194template <>
195constexpr TypeBuilderFunc getModel<signed char *>() {
196 return [](mlir::MLIRContext *context) -> mlir::Type {
197 TypeBuilderFunc f{getModel<signed char>()};
198 return fir::ReferenceType::get(f(context));
199 };
200}
201template <>
202constexpr TypeBuilderFunc getModel<const signed char *>() {
203 return getModel<signed char *>();
204}
205template <>
206constexpr TypeBuilderFunc getModel<char16_t>() {
207 return [](mlir::MLIRContext *context) -> mlir::Type {
208 return mlir::IntegerType::get(context, 8 * sizeof(char16_t));
209 };
210}
211template <>
212constexpr TypeBuilderFunc getModel<char16_t *>() {
213 return [](mlir::MLIRContext *context) -> mlir::Type {
214 TypeBuilderFunc f{getModel<char16_t>()};
215 return fir::ReferenceType::get(f(context));
216 };
217}
218template <>
219constexpr TypeBuilderFunc getModel<char32_t>() {
220 return [](mlir::MLIRContext *context) -> mlir::Type {
221 return mlir::IntegerType::get(context, 8 * sizeof(char32_t));
222 };
223}
224template <>
225constexpr TypeBuilderFunc getModel<char32_t *>() {
226 return [](mlir::MLIRContext *context) -> mlir::Type {
227 TypeBuilderFunc f{getModel<char32_t>()};
228 return fir::ReferenceType::get(f(context));
229 };
230}
231template <>
232constexpr TypeBuilderFunc getModel<unsigned char>() {
233 return [](mlir::MLIRContext *context) -> mlir::Type {
234 return mlir::IntegerType::get(context, 8 * sizeof(unsigned char));
235 };
236}
237template <>
238constexpr TypeBuilderFunc getModel<void *>() {
239 return [](mlir::MLIRContext *context) -> mlir::Type {
240 return fir::LLVMPointerType::get(context,
241 mlir::IntegerType::get(context, 8));
242 };
243}
244template <>
245constexpr TypeBuilderFunc getModel<const void *>() {
246 return getModel<void *>();
247}
248template <>
249constexpr TypeBuilderFunc getModel<void (*)(int)>() {
250 return [](mlir::MLIRContext *context) -> mlir::Type {
251 return fir::LLVMPointerType::get(
252 context,
253 mlir::FunctionType::get(context, /*inputs=*/{}, /*results*/ {}));
254 };
255}
256template <>
257constexpr TypeBuilderFunc
258getModel<void *(*)(void *, const void *, unsigned long)>() {
259 return [](mlir::MLIRContext *context) -> mlir::Type {
260 auto voidPtrTy =
261 fir::LLVMPointerType::get(context, mlir::IntegerType::get(context, 8));
262 auto unsignedLongTy =
263 mlir::IntegerType::get(context, 8 * sizeof(unsigned long));
264 auto funcTy = mlir::FunctionType::get(
265 context, {voidPtrTy, voidPtrTy, unsignedLongTy}, {voidPtrTy});
266 return fir::LLVMPointerType::get(context, funcTy);
267 };
268}
269#ifdef _MSC_VER
270template <>
271constexpr TypeBuilderFunc
272getModel<void *(*)(void *, const void *, unsigned __int64)>() {
273 return [](mlir::MLIRContext *context) -> mlir::Type {
274 auto voidPtrTy =
275 fir::LLVMPointerType::get(context, mlir::IntegerType::get(context, 8));
276 auto uint64Ty = mlir::IntegerType::get(context, 64);
277 auto funcTy = mlir::FunctionType::get(
278 context, {voidPtrTy, voidPtrTy, uint64Ty}, {voidPtrTy});
279 return fir::LLVMPointerType::get(context, funcTy);
280 };
281}
282#endif
283template <>
284constexpr TypeBuilderFunc getModel<void (*)(void)>() {
285 return [](mlir::MLIRContext *context) -> mlir::Type {
286 return fir::LLVMPointerType::get(
287 context,
288 mlir::FunctionType::get(context, /*inputs=*/{}, /*results*/ {}));
289 };
290}
291template <>
292constexpr TypeBuilderFunc getModel<void **>() {
293 return [](mlir::MLIRContext *context) -> mlir::Type {
294 return fir::ReferenceType::get(
295 fir::LLVMPointerType::get(context, mlir::IntegerType::get(context, 8)));
296 };
297}
298template <>
299constexpr TypeBuilderFunc getModel<long>() {
300 return [](mlir::MLIRContext *context) -> mlir::Type {
301 return mlir::IntegerType::get(context, 8 * sizeof(long));
302 };
303}
304template <>
305constexpr TypeBuilderFunc getModel<long &>() {
306 return [](mlir::MLIRContext *context) -> mlir::Type {
307 TypeBuilderFunc f{getModel<long>()};
308 return fir::ReferenceType::get(f(context));
309 };
310}
311template <>
312constexpr TypeBuilderFunc getModel<long *>() {
313 return getModel<long &>();
314}
315template <>
316constexpr TypeBuilderFunc getModel<const long *>() {
317 return getModel<long *>();
318}
319template <>
320constexpr TypeBuilderFunc getModel<long long>() {
321 return [](mlir::MLIRContext *context) -> mlir::Type {
322 return mlir::IntegerType::get(context, 8 * sizeof(long long));
323 };
324}
325template <>
326constexpr TypeBuilderFunc getModel<Fortran::common::int128_t>() {
327 return [](mlir::MLIRContext *context) -> mlir::Type {
328 return mlir::IntegerType::get(context,
329 8 * sizeof(Fortran::common::int128_t));
330 };
331}
332template <>
333constexpr TypeBuilderFunc getModel<long long &>() {
334 return [](mlir::MLIRContext *context) -> mlir::Type {
335 TypeBuilderFunc f{getModel<long long>()};
336 return fir::ReferenceType::get(f(context));
337 };
338}
339template <>
340constexpr TypeBuilderFunc getModel<long long *>() {
341 return getModel<long long &>();
342}
343template <>
344constexpr TypeBuilderFunc getModel<const long long *>() {
345 return getModel<long long *>();
346}
347template <>
348constexpr TypeBuilderFunc getModel<unsigned long>() {
349 return [](mlir::MLIRContext *context) -> mlir::Type {
350 return mlir::IntegerType::get(context, 8 * sizeof(unsigned long));
351 };
352}
353template <>
354constexpr TypeBuilderFunc getModel<unsigned long long>() {
355 return [](mlir::MLIRContext *context) -> mlir::Type {
356 return mlir::IntegerType::get(context, 8 * sizeof(unsigned long long));
357 };
358}
359template <>
360constexpr TypeBuilderFunc getModel<double>() {
361 return [](mlir::MLIRContext *context) -> mlir::Type {
362 return mlir::Float64Type::get(context);
363 };
364}
365template <>
366constexpr TypeBuilderFunc getModel<double &>() {
367 return [](mlir::MLIRContext *context) -> mlir::Type {
368 TypeBuilderFunc f{getModel<double>()};
369 return fir::ReferenceType::get(f(context));
370 };
371}
372template <>
373constexpr TypeBuilderFunc getModel<double *>() {
374 return getModel<double &>();
375}
376template <>
377constexpr TypeBuilderFunc getModel<const double *>() {
378 return getModel<double *>();
379}
380template <>
381constexpr TypeBuilderFunc getModel<long double>() {
382 return [](mlir::MLIRContext *context) -> mlir::Type {
383 // See TODO at the top of the file. This is configuring for the host system
384 // - it might be incorrect when cross-compiling!
385 constexpr size_t size = sizeof(long double);
386 static_assert(size == 16 || size == 10 || size == 8,
387 "unsupported long double size");
388 if constexpr (size == 16)
389 return mlir::Float128Type::get(context);
390 if constexpr (size == 10)
391 return mlir::Float80Type::get(context);
392 if constexpr (size == 8)
393 return mlir::Float64Type::get(context);
394 llvm_unreachable("failed static assert");
395 };
396}
397template <>
398constexpr TypeBuilderFunc getModel<long double *>() {
399 return [](mlir::MLIRContext *context) -> mlir::Type {
400 TypeBuilderFunc f{getModel<long double>()};
401 return fir::ReferenceType::get(f(context));
402 };
403}
404template <>
405constexpr TypeBuilderFunc getModel<const long double *>() {
406 return getModel<long double *>();
407}
408template <>
409constexpr TypeBuilderFunc getModel<float>() {
410 return [](mlir::MLIRContext *context) -> mlir::Type {
411 return mlir::Float32Type::get(context);
412 };
413}
414template <>
415constexpr TypeBuilderFunc getModel<float &>() {
416 return [](mlir::MLIRContext *context) -> mlir::Type {
417 TypeBuilderFunc f{getModel<float>()};
418 return fir::ReferenceType::get(f(context));
419 };
420}
421template <>
422constexpr TypeBuilderFunc getModel<float *>() {
423 return getModel<float &>();
424}
425template <>
426constexpr TypeBuilderFunc getModel<const float *>() {
427 return getModel<float *>();
428}
429template <>
430constexpr TypeBuilderFunc getModel<bool>() {
431 return [](mlir::MLIRContext *context) -> mlir::Type {
432 return mlir::IntegerType::get(context, 1);
433 };
434}
435template <>
436constexpr TypeBuilderFunc getModel<bool &>() {
437 return [](mlir::MLIRContext *context) -> mlir::Type {
438 TypeBuilderFunc f{getModel<bool>()};
439 return fir::ReferenceType::get(f(context));
440 };
441}
442template <>
443constexpr TypeBuilderFunc getModel<bool *>() {
444 return [](mlir::MLIRContext *context) -> mlir::Type {
445 TypeBuilderFunc f{getModel<bool>()};
446 return fir::ReferenceType::get(f(context));
447 };
448}
449template <>
450constexpr TypeBuilderFunc getModel<unsigned short>() {
451 return [](mlir::MLIRContext *context) -> mlir::Type {
452 return mlir::IntegerType::get(
453 context, 8 * sizeof(unsigned short),
454 mlir::IntegerType::SignednessSemantics::Unsigned);
455 };
456}
457template <>
458constexpr TypeBuilderFunc getModel<unsigned char *>() {
459 return [](mlir::MLIRContext *context) -> mlir::Type {
460 return fir::ReferenceType::get(mlir::IntegerType::get(context, 8));
461 };
462}
463template <>
464constexpr TypeBuilderFunc getModel<const unsigned char *>() {
465 return getModel<unsigned char *>();
466}
467template <>
468constexpr TypeBuilderFunc getModel<unsigned short *>() {
469 return [](mlir::MLIRContext *context) -> mlir::Type {
470 return fir::ReferenceType::get(
471 mlir::IntegerType::get(context, 8 * sizeof(unsigned short)));
472 };
473}
474template <>
475constexpr TypeBuilderFunc getModel<const unsigned short *>() {
476 return getModel<unsigned short *>();
477}
478template <>
479constexpr TypeBuilderFunc getModel<unsigned *>() {
480 return getModel<int *>();
481}
482template <>
483constexpr TypeBuilderFunc getModel<const unsigned *>() {
484 return getModel<unsigned *>();
485}
486template <>
487constexpr TypeBuilderFunc getModel<unsigned long *>() {
488 return [](mlir::MLIRContext *context) -> mlir::Type {
489 return fir::ReferenceType::get(
490 mlir::IntegerType::get(context, 8 * sizeof(unsigned long)));
491 };
492}
493template <>
494constexpr TypeBuilderFunc getModel<const unsigned long *>() {
495 return getModel<unsigned long *>();
496}
497template <>
498constexpr TypeBuilderFunc getModel<unsigned long long *>() {
499 return [](mlir::MLIRContext *context) -> mlir::Type {
500 return fir::ReferenceType::get(
501 mlir::IntegerType::get(context, 8 * sizeof(unsigned long long)));
502 };
503}
504template <>
505constexpr TypeBuilderFunc getModel<const unsigned long long *>() {
506 return getModel<unsigned long long *>();
507}
508template <>
509constexpr TypeBuilderFunc getModel<Fortran::common::uint128_t>() {
510 return getModel<Fortran::common::int128_t>();
511}
512template <>
513constexpr TypeBuilderFunc getModel<Fortran::common::int128_t *>() {
514 return [](mlir::MLIRContext *context) -> mlir::Type {
515 TypeBuilderFunc f{getModel<Fortran::common::int128_t>()};
516 return fir::ReferenceType::get(f(context));
517 };
518}
519template <>
520constexpr TypeBuilderFunc getModel<Fortran::common::uint128_t *>() {
521 return getModel<Fortran::common::int128_t *>();
522}
523template <>
524constexpr TypeBuilderFunc getModel<const Fortran::common::uint128_t *>() {
525 return getModel<Fortran::common::uint128_t *>();
526}
527
528// getModel<std::complex<T>> are not implemented on purpose.
529// Prefer passing/returning the complex by reference in the runtime to
530// avoid ABI issues.
531// C++ std::complex is not an intrinsic type, and while it is storage
532// compatible with C/Fortran complex type, it follows the struct value passing
533// ABI rule, which may differ from how C complex are passed on some platforms.
534
535template <>
536constexpr TypeBuilderFunc getModel<std::complex<float> &>() {
537 return [](mlir::MLIRContext *context) -> mlir::Type {
538 mlir::Type floatTy = getModel<float>()(context);
539 return fir::ReferenceType::get(mlir::ComplexType::get(floatTy));
540 };
541}
542template <>
543constexpr TypeBuilderFunc getModel<std::complex<float> *>() {
544 return getModel<std::complex<float> &>();
545}
546template <>
547constexpr TypeBuilderFunc getModel<const std::complex<float> *>() {
548 return getModel<std::complex<float> *>();
549}
550template <>
551constexpr TypeBuilderFunc getModel<std::complex<double> &>() {
552 return [](mlir::MLIRContext *context) -> mlir::Type {
553 mlir::Type floatTy = getModel<double>()(context);
554 return fir::ReferenceType::get(mlir::ComplexType::get(floatTy));
555 };
556}
557template <>
558constexpr TypeBuilderFunc getModel<std::complex<double> *>() {
559 return getModel<std::complex<double> &>();
560}
561template <>
562constexpr TypeBuilderFunc getModel<const std::complex<double> *>() {
563 return getModel<std::complex<double> *>();
564}
565template <>
566constexpr TypeBuilderFunc getModel<c_float_complex_t>() {
567 return [](mlir::MLIRContext *context) -> mlir::Type {
568 mlir::Type floatTy = getModel<float>()(context);
569 return mlir::ComplexType::get(floatTy);
570 };
571}
572template <>
573constexpr TypeBuilderFunc getModel<c_double_complex_t>() {
574 return [](mlir::MLIRContext *context) -> mlir::Type {
575 mlir::Type floatTy = getModel<double>()(context);
576 return mlir::ComplexType::get(floatTy);
577 };
578}
579template <>
580constexpr TypeBuilderFunc getModel<const Fortran::runtime::Descriptor &>() {
581 return [](mlir::MLIRContext *context) -> mlir::Type {
582 return fir::BoxType::get(mlir::NoneType::get(context));
583 };
584}
585template <>
586constexpr TypeBuilderFunc getModel<Fortran::runtime::Descriptor &>() {
587 return [](mlir::MLIRContext *context) -> mlir::Type {
588 return fir::ReferenceType::get(
589 fir::BoxType::get(mlir::NoneType::get(context)));
590 };
591}
592template <>
593constexpr TypeBuilderFunc getModel<const Fortran::runtime::Descriptor *>() {
594 return getModel<const Fortran::runtime::Descriptor &>();
595}
596template <>
597constexpr TypeBuilderFunc getModel<Fortran::runtime::Descriptor *>() {
598 return getModel<Fortran::runtime::Descriptor &>();
599}
600template <>
601constexpr TypeBuilderFunc getModel<Fortran::common::TypeCategory>() {
602 return [](mlir::MLIRContext *context) -> mlir::Type {
603 return mlir::IntegerType::get(context,
604 sizeof(Fortran::common::TypeCategory) * 8);
605 };
606}
607template <>
608constexpr TypeBuilderFunc
609getModel<const Fortran::runtime::typeInfo::DerivedType &>() {
610 return [](mlir::MLIRContext *context) -> mlir::Type {
611 return fir::ReferenceType::get(mlir::NoneType::get(context));
612 };
613}
614template <>
615constexpr TypeBuilderFunc
616getModel<const Fortran::runtime::typeInfo::DerivedType *>() {
617 return [](mlir::MLIRContext *context) -> mlir::Type {
618 return fir::ReferenceType::get(mlir::NoneType::get(context));
619 };
620}
621template <>
622constexpr TypeBuilderFunc getModel<void>() {
623 return [](mlir::MLIRContext *context) -> mlir::Type {
624 return mlir::NoneType::get(context);
625 };
626}
627
628// Define additional runtime type models specific to IO.
629template <>
630constexpr TypeBuilderFunc getModel<Fortran::runtime::io::IoStatementState *>() {
631 return getModel<char *>();
632}
633template <>
634constexpr TypeBuilderFunc getModel<Fortran::runtime::io::Iostat>() {
635 return [](mlir::MLIRContext *context) -> mlir::Type {
636 return mlir::IntegerType::get(context,
637 8 * sizeof(Fortran::runtime::io::Iostat));
638 };
639}
640template <>
641constexpr TypeBuilderFunc
642getModel<const Fortran::runtime::io::NamelistGroup &>() {
643 return [](mlir::MLIRContext *context) -> mlir::Type {
644 return fir::ReferenceType::get(mlir::TupleType::get(context));
645 };
646}
647template <>
648constexpr TypeBuilderFunc
649getModel<const Fortran::runtime::io::NonTbpDefinedIoTable *>() {
650 return [](mlir::MLIRContext *context) -> mlir::Type {
651 return fir::ReferenceType::get(mlir::TupleType::get(context));
652 };
653}
654
655REDUCTION_REF_OPERATION_MODEL(std::int8_t)
656REDUCTION_VALUE_OPERATION_MODEL(std::int8_t)
657REDUCTION_REF_OPERATION_MODEL(std::int16_t)
658REDUCTION_VALUE_OPERATION_MODEL(std::int16_t)
659REDUCTION_REF_OPERATION_MODEL(std::int32_t)
660REDUCTION_VALUE_OPERATION_MODEL(std::int32_t)
661REDUCTION_REF_OPERATION_MODEL(std::int64_t)
662REDUCTION_VALUE_OPERATION_MODEL(std::int64_t)
663REDUCTION_REF_OPERATION_MODEL(Fortran::common::int128_t)
664REDUCTION_VALUE_OPERATION_MODEL(Fortran::common::int128_t)
665
666REDUCTION_REF_OPERATION_MODEL(std::uint8_t)
667REDUCTION_VALUE_OPERATION_MODEL(std::uint8_t)
668REDUCTION_REF_OPERATION_MODEL(std::uint16_t)
669REDUCTION_VALUE_OPERATION_MODEL(std::uint16_t)
670REDUCTION_REF_OPERATION_MODEL(std::uint32_t)
671REDUCTION_VALUE_OPERATION_MODEL(std::uint32_t)
672REDUCTION_REF_OPERATION_MODEL(std::uint64_t)
673REDUCTION_VALUE_OPERATION_MODEL(std::uint64_t)
674REDUCTION_REF_OPERATION_MODEL(Fortran::common::uint128_t)
675REDUCTION_VALUE_OPERATION_MODEL(Fortran::common::uint128_t)
676
677REDUCTION_REF_OPERATION_MODEL(float)
678REDUCTION_VALUE_OPERATION_MODEL(float)
679REDUCTION_REF_OPERATION_MODEL(double)
680REDUCTION_VALUE_OPERATION_MODEL(double)
681REDUCTION_REF_OPERATION_MODEL(long double)
682REDUCTION_VALUE_OPERATION_MODEL(long double)
683
684// FIXME: the runtime is not using the correct ABIs when calling complex
685// callbacks. lowering either need to create wrappers or just have an inline
686// implementation for it. https://github.com/llvm/llvm-project/issues/110674
687template <>
688constexpr TypeBuilderFunc
689getModel<Fortran::runtime::ValueReductionOperation<std::complex<float>>>() {
690 return [](mlir::MLIRContext *context) -> mlir::Type {
691 mlir::Type cplx = mlir::ComplexType::get(getModel<float>()(context));
692 auto refTy = fir::ReferenceType::get(cplx);
693 return mlir::FunctionType::get(context, {cplx, cplx}, refTy);
694 };
695}
696template <>
697constexpr TypeBuilderFunc
698getModel<Fortran::runtime::ValueReductionOperation<std::complex<double>>>() {
699 return [](mlir::MLIRContext *context) -> mlir::Type {
700 mlir::Type cplx = mlir::ComplexType::get(getModel<double>()(context));
701 auto refTy = fir::ReferenceType::get(cplx);
702 return mlir::FunctionType::get(context, {cplx, cplx}, refTy);
703 };
704}
705template <>
706constexpr TypeBuilderFunc
707getModel<Fortran::runtime::ReferenceReductionOperation<std::complex<float>>>() {
708 return [](mlir::MLIRContext *context) -> mlir::Type {
709 mlir::Type cplx = mlir::ComplexType::get(getModel<float>()(context));
710 auto refTy = fir::ReferenceType::get(cplx);
711 return mlir::FunctionType::get(context, {refTy, refTy}, refTy);
712 };
713}
714template <>
715constexpr TypeBuilderFunc getModel<
716 Fortran::runtime::ReferenceReductionOperation<std::complex<double>>>() {
717 return [](mlir::MLIRContext *context) -> mlir::Type {
718 mlir::Type cplx = mlir::ComplexType::get(getModel<double>()(context));
719 auto refTy = fir::ReferenceType::get(cplx);
720 return mlir::FunctionType::get(context, {refTy, refTy}, refTy);
721 };
722}
723
724REDUCTION_CHAR_OPERATION_MODEL(char)
725REDUCTION_CHAR_OPERATION_MODEL(char16_t)
726REDUCTION_CHAR_OPERATION_MODEL(char32_t)
727
728template <>
729constexpr TypeBuilderFunc
730getModel<Fortran::runtime::ReductionDerivedTypeOperation>() {
731 return [](mlir::MLIRContext *context) -> mlir::Type {
732 auto voidTy =
733 fir::LLVMPointerType::get(context, mlir::IntegerType::get(context, 8));
734 return mlir::FunctionType::get(context, {voidTy, voidTy, voidTy}, voidTy);
735 };
736}
737
738template <typename...>
740template <typename RT, typename... ATs>
741struct RuntimeTableKey<RT(ATs...)> {
742 static constexpr FuncTypeBuilderFunc getTypeModel() {
743 return [](mlir::MLIRContext *ctxt) {
744 TypeBuilderFunc ret = getModel<RT>();
745 std::array<TypeBuilderFunc, sizeof...(ATs)> args = {getModel<ATs>()...};
746 mlir::Type retTy = ret(ctxt);
747 llvm::SmallVector<mlir::Type, sizeof...(ATs)> argTys;
748 for (auto f : args)
749 argTys.push_back(f(ctxt));
750 if (mlir::isa<mlir::NoneType>(retTy))
751 return mlir::FunctionType::get(ctxt, argTys, {});
752 return mlir::FunctionType::get(ctxt, argTys, {retTy});
753 };
754 }
755};
756
757//===----------------------------------------------------------------------===//
758// Runtime table building (constexpr folded)
759//===----------------------------------------------------------------------===//
760
761template <char... Cs>
762using RuntimeIdentifier = std::integer_sequence<char, Cs...>;
763
764namespace details {
765template <typename T, T... As, T... Bs>
766static constexpr std::integer_sequence<T, As..., Bs...>
767concat(std::integer_sequence<T, As...>, std::integer_sequence<T, Bs...>) {
768 return {};
769}
770template <typename T, T... As, T... Bs, typename... Cs>
771static constexpr auto concat(std::integer_sequence<T, As...>,
772 std::integer_sequence<T, Bs...>, Cs...) {
773 return concat(std::integer_sequence<T, As..., Bs...>{}, Cs{}...);
774}
775template <typename T>
776static constexpr std::integer_sequence<T> concat(std::integer_sequence<T>) {
777 return {};
778}
779template <typename T, T a>
780static constexpr auto filterZero(std::integer_sequence<T, a>) {
781 if constexpr (a != 0) {
782 return std::integer_sequence<T, a>{};
783 } else {
784 return std::integer_sequence<T>{};
785 }
786}
787template <typename T, T... b>
788static constexpr auto filter(std::integer_sequence<T, b...>) {
789 if constexpr (sizeof...(b) > 0) {
790 return details::concat(filterZero(std::integer_sequence<T, b>{})...);
791 } else {
792 return std::integer_sequence<T>{};
793 }
794}
795} // namespace details
796
797template <typename...>
799template <typename KT, char... Cs>
800struct RuntimeTableEntry<RuntimeTableKey<KT>, RuntimeIdentifier<Cs...>> {
801 static constexpr FuncTypeBuilderFunc getTypeModel() {
803 }
804 static constexpr const char name[sizeof...(Cs) + 1] = {Cs..., '\0'};
805};
806
818#undef FirE
819#define FirE(L, I) (I < sizeof(L) / sizeof(*L) ? L[I] : 0)
820#define FirQuoteKey(X) #X
821#define ExpandAndQuoteKey(X) FirQuoteKey(X)
822#define FirMacroExpandKey(X) \
823 FirE(X, 0), FirE(X, 1), FirE(X, 2), FirE(X, 3), FirE(X, 4), FirE(X, 5), \
824 FirE(X, 6), FirE(X, 7), FirE(X, 8), FirE(X, 9), FirE(X, 10), \
825 FirE(X, 11), FirE(X, 12), FirE(X, 13), FirE(X, 14), FirE(X, 15), \
826 FirE(X, 16), FirE(X, 17), FirE(X, 18), FirE(X, 19), FirE(X, 20), \
827 FirE(X, 21), FirE(X, 22), FirE(X, 23), FirE(X, 24), FirE(X, 25), \
828 FirE(X, 26), FirE(X, 27), FirE(X, 28), FirE(X, 29), FirE(X, 30), \
829 FirE(X, 31), FirE(X, 32), FirE(X, 33), FirE(X, 34), FirE(X, 35), \
830 FirE(X, 36), FirE(X, 37), FirE(X, 38), FirE(X, 39), FirE(X, 40), \
831 FirE(X, 41), FirE(X, 42), FirE(X, 43), FirE(X, 44), FirE(X, 45), \
832 FirE(X, 46), FirE(X, 47), FirE(X, 48), FirE(X, 49)
833#define FirExpandKey(X) FirMacroExpandKey(FirQuoteKey(X))
834#define FirFullSeq(X) std::integer_sequence<char, FirExpandKey(X)>
835#define FirAsSequence(X) \
836 decltype(fir::runtime::details::filter(FirFullSeq(X){}))
837#define FirmkKey(X) \
838 fir::runtime::RuntimeTableEntry<fir::runtime::RuntimeTableKey<decltype(X)>, \
839 FirAsSequence(X)>
840#define mkRTKey(X) FirmkKey(RTNAME(X))
841#define EXPAND_AND_QUOTE_KEY(S) ExpandAndQuoteKey(RTNAME(S))
842
845template <typename RuntimeEntry>
846static mlir::func::FuncOp getRuntimeFunc(mlir::Location loc,
847 fir::FirOpBuilder &builder,
848 bool isIO = false) {
849 using namespace Fortran::runtime;
850 auto name = RuntimeEntry::name;
851 auto func = builder.getNamedFunction(name);
852 if (func)
853 return func;
854 auto funTy = RuntimeEntry::getTypeModel()(builder.getContext());
855 return builder.createRuntimeFunction(loc, name, funTy, isIO);
856}
857
859template <typename E>
860static mlir::func::FuncOp getIORuntimeFunc(mlir::Location loc,
861 fir::FirOpBuilder &builder) {
862 return getRuntimeFunc<E>(loc, builder, /*isIO=*/true);
863}
864
865inline llvm::SmallVector<mlir::Value>
866createArguments(fir::FirOpBuilder &builder, mlir::Location loc,
867 mlir::FunctionType fTy, llvm::ArrayRef<mlir::Value> args) {
868 return llvm::map_to_vector(llvm::zip_equal(fTy.getInputs(), args),
869 [&](const auto &pair) -> mlir::Value {
870 auto [type, argument] = pair;
871 return builder.createConvertWithVolatileCast(
872 loc, type, argument);
873 });
874}
875
877template <typename... As>
878llvm::SmallVector<mlir::Value>
879createArguments(fir::FirOpBuilder &builder, mlir::Location loc,
880 mlir::FunctionType fTy, As... args) {
881 return createArguments(builder, loc, fTy, {args...});
882}
883
884} // namespace fir::runtime
885
886#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_RTBUILDER_H
Definition FIRBuilder.h:59
mlir::func::FuncOp createRuntimeFunction(mlir::Location loc, llvm::StringRef name, mlir::FunctionType ty, bool isIO=false)
Definition FIRBuilder.cpp:56
mlir::func::FuncOp getNamedFunction(llvm::StringRef name)
Definition FIRBuilder.h:400
Definition OpenACC.h:20
Definition RTBuilder.h:798
Definition RTBuilder.h:739