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/Fortran.h"
21#include "flang/Common/uint128.h"
22#include "flang/Optimizer/Builder/FIRBuilder.h"
23#include "flang/Optimizer/Dialect/FIRDialect.h"
24#include "flang/Optimizer/Dialect/FIRType.h"
25#include "flang/Runtime/reduce.h"
26#include "mlir/IR/BuiltinTypes.h"
27#include "mlir/IR/MLIRContext.h"
28#include "llvm/ADT/SmallVector.h"
29#include <cstdint>
30#include <functional>
31
32#ifdef _WIN32
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<void (*)(int)>() {
246 return [](mlir::MLIRContext *context) -> mlir::Type {
247 return fir::LLVMPointerType::get(
248 context,
249 mlir::FunctionType::get(context, /*inputs=*/{}, /*results*/ {}));
250 };
251}
252template <>
253constexpr TypeBuilderFunc getModel<void **>() {
254 return [](mlir::MLIRContext *context) -> mlir::Type {
255 return fir::ReferenceType::get(
256 fir::LLVMPointerType::get(context, mlir::IntegerType::get(context, 8)));
257 };
258}
259template <>
260constexpr TypeBuilderFunc getModel<long>() {
261 return [](mlir::MLIRContext *context) -> mlir::Type {
262 return mlir::IntegerType::get(context, 8 * sizeof(long));
263 };
264}
265template <>
266constexpr TypeBuilderFunc getModel<long &>() {
267 return [](mlir::MLIRContext *context) -> mlir::Type {
268 TypeBuilderFunc f{getModel<long>()};
269 return fir::ReferenceType::get(f(context));
270 };
271}
272template <>
273constexpr TypeBuilderFunc getModel<long *>() {
274 return getModel<long &>();
275}
276template <>
277constexpr TypeBuilderFunc getModel<const long *>() {
278 return getModel<long *>();
279}
280template <>
281constexpr TypeBuilderFunc getModel<long long>() {
282 return [](mlir::MLIRContext *context) -> mlir::Type {
283 return mlir::IntegerType::get(context, 8 * sizeof(long long));
284 };
285}
286template <>
287constexpr TypeBuilderFunc getModel<Fortran::common::int128_t>() {
288 return [](mlir::MLIRContext *context) -> mlir::Type {
289 return mlir::IntegerType::get(context,
290 8 * sizeof(Fortran::common::int128_t));
291 };
292}
293template <>
294constexpr TypeBuilderFunc getModel<long long &>() {
295 return [](mlir::MLIRContext *context) -> mlir::Type {
296 TypeBuilderFunc f{getModel<long long>()};
297 return fir::ReferenceType::get(f(context));
298 };
299}
300template <>
301constexpr TypeBuilderFunc getModel<long long *>() {
302 return getModel<long long &>();
303}
304template <>
305constexpr TypeBuilderFunc getModel<const long long *>() {
306 return getModel<long long *>();
307}
308template <>
309constexpr TypeBuilderFunc getModel<unsigned long>() {
310 return [](mlir::MLIRContext *context) -> mlir::Type {
311 return mlir::IntegerType::get(context, 8 * sizeof(unsigned long));
312 };
313}
314template <>
315constexpr TypeBuilderFunc getModel<unsigned long long>() {
316 return [](mlir::MLIRContext *context) -> mlir::Type {
317 return mlir::IntegerType::get(context, 8 * sizeof(unsigned long long));
318 };
319}
320template <>
321constexpr TypeBuilderFunc getModel<double>() {
322 return [](mlir::MLIRContext *context) -> mlir::Type {
323 return mlir::Float64Type::get(context);
324 };
325}
326template <>
327constexpr TypeBuilderFunc getModel<double &>() {
328 return [](mlir::MLIRContext *context) -> mlir::Type {
329 TypeBuilderFunc f{getModel<double>()};
330 return fir::ReferenceType::get(f(context));
331 };
332}
333template <>
334constexpr TypeBuilderFunc getModel<double *>() {
335 return getModel<double &>();
336}
337template <>
338constexpr TypeBuilderFunc getModel<const double *>() {
339 return getModel<double *>();
340}
341template <>
342constexpr TypeBuilderFunc getModel<long double>() {
343 return [](mlir::MLIRContext *context) -> mlir::Type {
344 // See TODO at the top of the file. This is configuring for the host system
345 // - it might be incorrect when cross-compiling!
346 constexpr size_t size = sizeof(long double);
347 static_assert(size == 16 || size == 10 || size == 8,
348 "unsupported long double size");
349 if constexpr (size == 16)
350 return mlir::Float128Type::get(context);
351 if constexpr (size == 10)
352 return mlir::Float80Type::get(context);
353 if constexpr (size == 8)
354 return mlir::Float64Type::get(context);
355 llvm_unreachable("failed static assert");
356 };
357}
358template <>
359constexpr TypeBuilderFunc getModel<long double *>() {
360 return [](mlir::MLIRContext *context) -> mlir::Type {
361 TypeBuilderFunc f{getModel<long double>()};
362 return fir::ReferenceType::get(f(context));
363 };
364}
365template <>
366constexpr TypeBuilderFunc getModel<const long double *>() {
367 return getModel<long double *>();
368}
369template <>
370constexpr TypeBuilderFunc getModel<float>() {
371 return [](mlir::MLIRContext *context) -> mlir::Type {
372 return mlir::Float32Type::get(context);
373 };
374}
375template <>
376constexpr TypeBuilderFunc getModel<float &>() {
377 return [](mlir::MLIRContext *context) -> mlir::Type {
378 TypeBuilderFunc f{getModel<float>()};
379 return fir::ReferenceType::get(f(context));
380 };
381}
382template <>
383constexpr TypeBuilderFunc getModel<float *>() {
384 return getModel<float &>();
385}
386template <>
387constexpr TypeBuilderFunc getModel<const float *>() {
388 return getModel<float *>();
389}
390template <>
391constexpr TypeBuilderFunc getModel<bool>() {
392 return [](mlir::MLIRContext *context) -> mlir::Type {
393 return mlir::IntegerType::get(context, 1);
394 };
395}
396template <>
397constexpr TypeBuilderFunc getModel<bool &>() {
398 return [](mlir::MLIRContext *context) -> mlir::Type {
399 TypeBuilderFunc f{getModel<bool>()};
400 return fir::ReferenceType::get(f(context));
401 };
402}
403template <>
404constexpr TypeBuilderFunc getModel<unsigned short>() {
405 return [](mlir::MLIRContext *context) -> mlir::Type {
406 return mlir::IntegerType::get(
407 context, 8 * sizeof(unsigned short),
408 mlir::IntegerType::SignednessSemantics::Unsigned);
409 };
410}
411template <>
412constexpr TypeBuilderFunc getModel<unsigned char *>() {
413 return [](mlir::MLIRContext *context) -> mlir::Type {
414 return fir::ReferenceType::get(mlir::IntegerType::get(context, 8));
415 };
416}
417template <>
418constexpr TypeBuilderFunc getModel<const unsigned char *>() {
419 return getModel<unsigned char *>();
420}
421template <>
422constexpr TypeBuilderFunc getModel<unsigned short *>() {
423 return [](mlir::MLIRContext *context) -> mlir::Type {
424 return fir::ReferenceType::get(
425 mlir::IntegerType::get(context, 8 * sizeof(unsigned short)));
426 };
427}
428template <>
429constexpr TypeBuilderFunc getModel<const unsigned short *>() {
430 return getModel<unsigned short *>();
431}
432template <>
433constexpr TypeBuilderFunc getModel<unsigned *>() {
434 return getModel<int *>();
435}
436template <>
437constexpr TypeBuilderFunc getModel<const unsigned *>() {
438 return getModel<unsigned *>();
439}
440template <>
441constexpr TypeBuilderFunc getModel<unsigned long *>() {
442 return [](mlir::MLIRContext *context) -> mlir::Type {
443 return fir::ReferenceType::get(
444 mlir::IntegerType::get(context, 8 * sizeof(unsigned long)));
445 };
446}
447template <>
448constexpr TypeBuilderFunc getModel<const unsigned long *>() {
449 return getModel<unsigned long *>();
450}
451template <>
452constexpr TypeBuilderFunc getModel<unsigned long long *>() {
453 return [](mlir::MLIRContext *context) -> mlir::Type {
454 return fir::ReferenceType::get(
455 mlir::IntegerType::get(context, 8 * sizeof(unsigned long long)));
456 };
457}
458template <>
459constexpr TypeBuilderFunc getModel<const unsigned long long *>() {
460 return getModel<unsigned long long *>();
461}
462template <>
463constexpr TypeBuilderFunc getModel<Fortran::common::uint128_t>() {
464 return getModel<Fortran::common::int128_t>();
465}
466template <>
467constexpr TypeBuilderFunc getModel<Fortran::common::int128_t *>() {
468 return [](mlir::MLIRContext *context) -> mlir::Type {
469 TypeBuilderFunc f{getModel<Fortran::common::int128_t>()};
470 return fir::ReferenceType::get(f(context));
471 };
472}
473template <>
474constexpr TypeBuilderFunc getModel<Fortran::common::uint128_t *>() {
475 return getModel<Fortran::common::int128_t *>();
476}
477template <>
478constexpr TypeBuilderFunc getModel<const Fortran::common::uint128_t *>() {
479 return getModel<Fortran::common::uint128_t *>();
480}
481
482// getModel<std::complex<T>> are not implemented on purpose.
483// Prefer passing/returning the complex by reference in the runtime to
484// avoid ABI issues.
485// C++ std::complex is not an intrinsic type, and while it is storage
486// compatible with C/Fortran complex type, it follows the struct value passing
487// ABI rule, which may differ from how C complex are passed on some platforms.
488
489template <>
490constexpr TypeBuilderFunc getModel<std::complex<float> &>() {
491 return [](mlir::MLIRContext *context) -> mlir::Type {
492 mlir::Type floatTy = getModel<float>()(context);
493 return fir::ReferenceType::get(mlir::ComplexType::get(floatTy));
494 };
495}
496template <>
497constexpr TypeBuilderFunc getModel<std::complex<float> *>() {
498 return getModel<std::complex<float> &>();
499}
500template <>
501constexpr TypeBuilderFunc getModel<const std::complex<float> *>() {
502 return getModel<std::complex<float> *>();
503}
504template <>
505constexpr TypeBuilderFunc getModel<std::complex<double> &>() {
506 return [](mlir::MLIRContext *context) -> mlir::Type {
507 mlir::Type floatTy = getModel<double>()(context);
508 return fir::ReferenceType::get(mlir::ComplexType::get(floatTy));
509 };
510}
511template <>
512constexpr TypeBuilderFunc getModel<std::complex<double> *>() {
513 return getModel<std::complex<double> &>();
514}
515template <>
516constexpr TypeBuilderFunc getModel<const std::complex<double> *>() {
517 return getModel<std::complex<double> *>();
518}
519template <>
520constexpr TypeBuilderFunc getModel<c_float_complex_t>() {
521 return [](mlir::MLIRContext *context) -> mlir::Type {
522 mlir::Type floatTy = getModel<float>()(context);
523 return mlir::ComplexType::get(floatTy);
524 };
525}
526template <>
527constexpr TypeBuilderFunc getModel<c_double_complex_t>() {
528 return [](mlir::MLIRContext *context) -> mlir::Type {
529 mlir::Type floatTy = getModel<double>()(context);
530 return mlir::ComplexType::get(floatTy);
531 };
532}
533template <>
534constexpr TypeBuilderFunc getModel<const Fortran::runtime::Descriptor &>() {
535 return [](mlir::MLIRContext *context) -> mlir::Type {
536 return fir::BoxType::get(mlir::NoneType::get(context));
537 };
538}
539template <>
540constexpr TypeBuilderFunc getModel<Fortran::runtime::Descriptor &>() {
541 return [](mlir::MLIRContext *context) -> mlir::Type {
542 return fir::ReferenceType::get(
543 fir::BoxType::get(mlir::NoneType::get(context)));
544 };
545}
546template <>
547constexpr TypeBuilderFunc getModel<const Fortran::runtime::Descriptor *>() {
548 return getModel<const Fortran::runtime::Descriptor &>();
549}
550template <>
551constexpr TypeBuilderFunc getModel<Fortran::runtime::Descriptor *>() {
552 return getModel<Fortran::runtime::Descriptor &>();
553}
554template <>
555constexpr TypeBuilderFunc getModel<Fortran::common::TypeCategory>() {
556 return [](mlir::MLIRContext *context) -> mlir::Type {
557 return mlir::IntegerType::get(context,
558 sizeof(Fortran::common::TypeCategory) * 8);
559 };
560}
561template <>
562constexpr TypeBuilderFunc
563getModel<const Fortran::runtime::typeInfo::DerivedType &>() {
564 return [](mlir::MLIRContext *context) -> mlir::Type {
565 return fir::ReferenceType::get(mlir::NoneType::get(context));
566 };
567}
568template <>
569constexpr TypeBuilderFunc
570getModel<const Fortran::runtime::typeInfo::DerivedType *>() {
571 return [](mlir::MLIRContext *context) -> mlir::Type {
572 return fir::ReferenceType::get(mlir::NoneType::get(context));
573 };
574}
575template <>
576constexpr TypeBuilderFunc getModel<void>() {
577 return [](mlir::MLIRContext *context) -> mlir::Type {
578 return mlir::NoneType::get(context);
579 };
580}
581
582REDUCTION_REF_OPERATION_MODEL(std::int8_t)
583REDUCTION_VALUE_OPERATION_MODEL(std::int8_t)
584REDUCTION_REF_OPERATION_MODEL(std::int16_t)
585REDUCTION_VALUE_OPERATION_MODEL(std::int16_t)
586REDUCTION_REF_OPERATION_MODEL(std::int32_t)
587REDUCTION_VALUE_OPERATION_MODEL(std::int32_t)
588REDUCTION_REF_OPERATION_MODEL(std::int64_t)
589REDUCTION_VALUE_OPERATION_MODEL(std::int64_t)
590REDUCTION_REF_OPERATION_MODEL(Fortran::common::int128_t)
591REDUCTION_VALUE_OPERATION_MODEL(Fortran::common::int128_t)
592
593REDUCTION_REF_OPERATION_MODEL(std::uint8_t)
594REDUCTION_VALUE_OPERATION_MODEL(std::uint8_t)
595REDUCTION_REF_OPERATION_MODEL(std::uint16_t)
596REDUCTION_VALUE_OPERATION_MODEL(std::uint16_t)
597REDUCTION_REF_OPERATION_MODEL(std::uint32_t)
598REDUCTION_VALUE_OPERATION_MODEL(std::uint32_t)
599REDUCTION_REF_OPERATION_MODEL(std::uint64_t)
600REDUCTION_VALUE_OPERATION_MODEL(std::uint64_t)
601REDUCTION_REF_OPERATION_MODEL(Fortran::common::uint128_t)
602REDUCTION_VALUE_OPERATION_MODEL(Fortran::common::uint128_t)
603
604REDUCTION_REF_OPERATION_MODEL(float)
605REDUCTION_VALUE_OPERATION_MODEL(float)
606REDUCTION_REF_OPERATION_MODEL(double)
607REDUCTION_VALUE_OPERATION_MODEL(double)
608REDUCTION_REF_OPERATION_MODEL(long double)
609REDUCTION_VALUE_OPERATION_MODEL(long double)
610
611// FIXME: the runtime is not using the correct ABIs when calling complex
612// callbacks. lowering either need to create wrappers or just have an inline
613// implementation for it. https://github.com/llvm/llvm-project/issues/110674
614template <>
615constexpr TypeBuilderFunc
616getModel<Fortran::runtime::ValueReductionOperation<std::complex<float>>>() {
617 return [](mlir::MLIRContext *context) -> mlir::Type {
618 mlir::Type cplx = mlir::ComplexType::get(getModel<float>()(context));
619 auto refTy = fir::ReferenceType::get(cplx);
620 return mlir::FunctionType::get(context, {cplx, cplx}, refTy);
621 };
622}
623template <>
624constexpr TypeBuilderFunc
625getModel<Fortran::runtime::ValueReductionOperation<std::complex<double>>>() {
626 return [](mlir::MLIRContext *context) -> mlir::Type {
627 mlir::Type cplx = mlir::ComplexType::get(getModel<double>()(context));
628 auto refTy = fir::ReferenceType::get(cplx);
629 return mlir::FunctionType::get(context, {cplx, cplx}, refTy);
630 };
631}
632template <>
633constexpr TypeBuilderFunc
634getModel<Fortran::runtime::ReferenceReductionOperation<std::complex<float>>>() {
635 return [](mlir::MLIRContext *context) -> mlir::Type {
636 mlir::Type cplx = mlir::ComplexType::get(getModel<float>()(context));
637 auto refTy = fir::ReferenceType::get(cplx);
638 return mlir::FunctionType::get(context, {refTy, refTy}, refTy);
639 };
640}
641template <>
642constexpr TypeBuilderFunc getModel<
643 Fortran::runtime::ReferenceReductionOperation<std::complex<double>>>() {
644 return [](mlir::MLIRContext *context) -> mlir::Type {
645 mlir::Type cplx = mlir::ComplexType::get(getModel<double>()(context));
646 auto refTy = fir::ReferenceType::get(cplx);
647 return mlir::FunctionType::get(context, {refTy, refTy}, refTy);
648 };
649}
650
651REDUCTION_CHAR_OPERATION_MODEL(char)
652REDUCTION_CHAR_OPERATION_MODEL(char16_t)
653REDUCTION_CHAR_OPERATION_MODEL(char32_t)
654
655template <>
656constexpr TypeBuilderFunc
657getModel<Fortran::runtime::ReductionDerivedTypeOperation>() {
658 return [](mlir::MLIRContext *context) -> mlir::Type {
659 auto voidTy =
660 fir::LLVMPointerType::get(context, mlir::IntegerType::get(context, 8));
661 return mlir::FunctionType::get(context, {voidTy, voidTy, voidTy}, voidTy);
662 };
663}
664
665template <typename...>
667template <typename RT, typename... ATs>
668struct RuntimeTableKey<RT(ATs...)> {
669 static constexpr FuncTypeBuilderFunc getTypeModel() {
670 return [](mlir::MLIRContext *ctxt) {
671 TypeBuilderFunc ret = getModel<RT>();
672 std::array<TypeBuilderFunc, sizeof...(ATs)> args = {getModel<ATs>()...};
673 mlir::Type retTy = ret(ctxt);
674 llvm::SmallVector<mlir::Type, sizeof...(ATs)> argTys;
675 for (auto f : args)
676 argTys.push_back(f(ctxt));
677 if (mlir::isa<mlir::NoneType>(retTy))
678 return mlir::FunctionType::get(ctxt, argTys, {});
679 return mlir::FunctionType::get(ctxt, argTys, {retTy});
680 };
681 }
682};
683
684//===----------------------------------------------------------------------===//
685// Runtime table building (constexpr folded)
686//===----------------------------------------------------------------------===//
687
688template <char... Cs>
689using RuntimeIdentifier = std::integer_sequence<char, Cs...>;
690
691namespace details {
692template <typename T, T... As, T... Bs>
693static constexpr std::integer_sequence<T, As..., Bs...>
694concat(std::integer_sequence<T, As...>, std::integer_sequence<T, Bs...>) {
695 return {};
696}
697template <typename T, T... As, T... Bs, typename... Cs>
698static constexpr auto concat(std::integer_sequence<T, As...>,
699 std::integer_sequence<T, Bs...>, Cs...) {
700 return concat(std::integer_sequence<T, As..., Bs...>{}, Cs{}...);
701}
702template <typename T>
703static constexpr std::integer_sequence<T> concat(std::integer_sequence<T>) {
704 return {};
705}
706template <typename T, T a>
707static constexpr auto filterZero(std::integer_sequence<T, a>) {
708 if constexpr (a != 0) {
709 return std::integer_sequence<T, a>{};
710 } else {
711 return std::integer_sequence<T>{};
712 }
713}
714template <typename T, T... b>
715static constexpr auto filter(std::integer_sequence<T, b...>) {
716 if constexpr (sizeof...(b) > 0) {
717 return details::concat(filterZero(std::integer_sequence<T, b>{})...);
718 } else {
719 return std::integer_sequence<T>{};
720 }
721}
722} // namespace details
723
724template <typename...>
726template <typename KT, char... Cs>
727struct RuntimeTableEntry<RuntimeTableKey<KT>, RuntimeIdentifier<Cs...>> {
728 static constexpr FuncTypeBuilderFunc getTypeModel() {
730 }
731 static constexpr const char name[sizeof...(Cs) + 1] = {Cs..., '\0'};
732};
733
745#undef FirE
746#define FirE(L, I) (I < sizeof(L) / sizeof(*L) ? L[I] : 0)
747#define FirQuoteKey(X) #X
748#define ExpandAndQuoteKey(X) FirQuoteKey(X)
749#define FirMacroExpandKey(X) \
750 FirE(X, 0), FirE(X, 1), FirE(X, 2), FirE(X, 3), FirE(X, 4), FirE(X, 5), \
751 FirE(X, 6), FirE(X, 7), FirE(X, 8), FirE(X, 9), FirE(X, 10), \
752 FirE(X, 11), FirE(X, 12), FirE(X, 13), FirE(X, 14), FirE(X, 15), \
753 FirE(X, 16), FirE(X, 17), FirE(X, 18), FirE(X, 19), FirE(X, 20), \
754 FirE(X, 21), FirE(X, 22), FirE(X, 23), FirE(X, 24), FirE(X, 25), \
755 FirE(X, 26), FirE(X, 27), FirE(X, 28), FirE(X, 29), FirE(X, 30), \
756 FirE(X, 31), FirE(X, 32), FirE(X, 33), FirE(X, 34), FirE(X, 35), \
757 FirE(X, 36), FirE(X, 37), FirE(X, 38), FirE(X, 39), FirE(X, 40), \
758 FirE(X, 41), FirE(X, 42), FirE(X, 43), FirE(X, 44), FirE(X, 45), \
759 FirE(X, 46), FirE(X, 47), FirE(X, 48), FirE(X, 49)
760#define FirExpandKey(X) FirMacroExpandKey(FirQuoteKey(X))
761#define FirFullSeq(X) std::integer_sequence<char, FirExpandKey(X)>
762#define FirAsSequence(X) \
763 decltype(fir::runtime::details::filter(FirFullSeq(X){}))
764#define FirmkKey(X) \
765 fir::runtime::RuntimeTableEntry<fir::runtime::RuntimeTableKey<decltype(X)>, \
766 FirAsSequence(X)>
767#define mkRTKey(X) FirmkKey(RTNAME(X))
768#define EXPAND_AND_QUOTE_KEY(S) ExpandAndQuoteKey(RTNAME(S))
769
772template <typename RuntimeEntry>
773static mlir::func::FuncOp getRuntimeFunc(mlir::Location loc,
774 fir::FirOpBuilder &builder) {
775 using namespace Fortran::runtime;
776 auto name = RuntimeEntry::name;
777 auto func = builder.getNamedFunction(name);
778 if (func)
779 return func;
780 auto funTy = RuntimeEntry::getTypeModel()(builder.getContext());
781 func = builder.createFunction(loc, name, funTy);
782 func->setAttr(FIROpsDialect::getFirRuntimeAttrName(), builder.getUnitAttr());
783 return func;
784}
785
786namespace helper {
787template <int N, typename A>
788void createArguments(llvm::SmallVectorImpl<mlir::Value> &result,
789 fir::FirOpBuilder &builder, mlir::Location loc,
790 mlir::FunctionType fTy, A arg) {
791 result.emplace_back(builder.createConvert(loc, fTy.getInput(N), arg));
792}
793
794template <int N, typename A, typename... As>
795void createArguments(llvm::SmallVectorImpl<mlir::Value> &result,
796 fir::FirOpBuilder &builder, mlir::Location loc,
797 mlir::FunctionType fTy, A arg, As... args) {
798 result.emplace_back(builder.createConvert(loc, fTy.getInput(N), arg));
799 createArguments<N + 1>(result, builder, loc, fTy, args...);
800}
801} // namespace helper
802
804template <typename... As>
806createArguments(fir::FirOpBuilder &builder, mlir::Location loc,
807 mlir::FunctionType fTy, As... args) {
809 helper::createArguments<0>(result, builder, loc, fTy, args...);
810 return result;
811}
812
813} // namespace fir::runtime
814
815#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_RTBUILDER_H
Definition: uint128.h:29
Definition: FIRBuilder.h:55
mlir::Value createConvert(mlir::Location loc, mlir::Type toTy, mlir::Value val)
Lazy creation of fir.convert op.
Definition: FIRBuilder.cpp:511
mlir::func::FuncOp getNamedFunction(llvm::StringRef name)
Definition: FIRBuilder.h:332
mlir::func::FuncOp createFunction(mlir::Location loc, llvm::StringRef name, mlir::FunctionType ty)
Definition: FIRBuilder.h:371
Definition: OpenACC.h:20
Definition: RTBuilder.h:725
Definition: RTBuilder.h:666