1*54c56347SValentin Clement //===-- DescriptorModel.h -- model of descriptors for codegen ---*- C++ -*-===//
2*54c56347SValentin Clement //
3*54c56347SValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*54c56347SValentin Clement // See https://llvm.org/LICENSE.txt for license information.
5*54c56347SValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*54c56347SValentin Clement //
7*54c56347SValentin Clement //===----------------------------------------------------------------------===//
8*54c56347SValentin Clement // LLVM IR dialect models of C++ types.
9*54c56347SValentin Clement //
10*54c56347SValentin Clement // This supplies a set of model builders to decompose the C declaration of a
11*54c56347SValentin Clement // descriptor (as encoded in ISO_Fortran_binding.h and elsewhere) and
12*54c56347SValentin Clement // reconstruct that type in the LLVM IR dialect.
13*54c56347SValentin Clement //
14*54c56347SValentin Clement // TODO: It is understood that this is deeply incorrect as far as building a
15*54c56347SValentin Clement // portability layer for cross-compilation as these reflected types are those of
16*54c56347SValentin Clement // the build machine and not necessarily that of either the host or the target.
17*54c56347SValentin Clement // This assumption that build == host == target is actually pervasive across the
18*54c56347SValentin Clement // compiler (https://llvm.org/PR52418).
19*54c56347SValentin Clement //
20*54c56347SValentin Clement //===----------------------------------------------------------------------===//
21*54c56347SValentin Clement
22*54c56347SValentin Clement #ifndef OPTIMIZER_DESCRIPTOR_MODEL_H
23*54c56347SValentin Clement #define OPTIMIZER_DESCRIPTOR_MODEL_H
24*54c56347SValentin Clement
25*54c56347SValentin Clement #include "flang/ISO_Fortran_binding.h"
26*54c56347SValentin Clement #include "flang/Runtime/descriptor.h"
27*54c56347SValentin Clement #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
28*54c56347SValentin Clement #include "llvm/Support/ErrorHandling.h"
29*54c56347SValentin Clement #include <tuple>
30*54c56347SValentin Clement
31*54c56347SValentin Clement namespace fir {
32*54c56347SValentin Clement
33*54c56347SValentin Clement using TypeBuilderFunc = mlir::Type (*)(mlir::MLIRContext *);
34*54c56347SValentin Clement
35*54c56347SValentin Clement /// Get the LLVM IR dialect model for building a particular C++ type, `T`.
36*54c56347SValentin Clement template <typename T>
37*54c56347SValentin Clement TypeBuilderFunc getModel();
38*54c56347SValentin Clement
39*54c56347SValentin Clement template <>
40*54c56347SValentin Clement TypeBuilderFunc getModel<void *>() {
41*54c56347SValentin Clement return [](mlir::MLIRContext *context) -> mlir::Type {
42*54c56347SValentin Clement return mlir::LLVM::LLVMPointerType::get(mlir::IntegerType::get(context, 8));
43*54c56347SValentin Clement };
44*54c56347SValentin Clement }
45*54c56347SValentin Clement template <>
46*54c56347SValentin Clement TypeBuilderFunc getModel<unsigned>() {
47*54c56347SValentin Clement return [](mlir::MLIRContext *context) -> mlir::Type {
48*54c56347SValentin Clement return mlir::IntegerType::get(context, sizeof(unsigned) * 8);
49*54c56347SValentin Clement };
50*54c56347SValentin Clement }
51*54c56347SValentin Clement template <>
52*54c56347SValentin Clement TypeBuilderFunc getModel<int>() {
53*54c56347SValentin Clement return [](mlir::MLIRContext *context) -> mlir::Type {
54*54c56347SValentin Clement return mlir::IntegerType::get(context, sizeof(int) * 8);
55*54c56347SValentin Clement };
56*54c56347SValentin Clement }
57*54c56347SValentin Clement template <>
58*54c56347SValentin Clement TypeBuilderFunc getModel<unsigned long>() {
59*54c56347SValentin Clement return [](mlir::MLIRContext *context) -> mlir::Type {
60*54c56347SValentin Clement return mlir::IntegerType::get(context, sizeof(unsigned long) * 8);
61*54c56347SValentin Clement };
62*54c56347SValentin Clement }
63*54c56347SValentin Clement template <>
64*54c56347SValentin Clement TypeBuilderFunc getModel<unsigned long long>() {
65*54c56347SValentin Clement return [](mlir::MLIRContext *context) -> mlir::Type {
66*54c56347SValentin Clement return mlir::IntegerType::get(context, sizeof(unsigned long long) * 8);
67*54c56347SValentin Clement };
68*54c56347SValentin Clement }
69*54c56347SValentin Clement template <>
70*54c56347SValentin Clement TypeBuilderFunc getModel<long long>() {
71*54c56347SValentin Clement return [](mlir::MLIRContext *context) -> mlir::Type {
72*54c56347SValentin Clement return mlir::IntegerType::get(context, sizeof(long long) * 8);
73*54c56347SValentin Clement };
74*54c56347SValentin Clement }
75*54c56347SValentin Clement template <>
76*54c56347SValentin Clement TypeBuilderFunc getModel<Fortran::ISO::CFI_rank_t>() {
77*54c56347SValentin Clement return [](mlir::MLIRContext *context) -> mlir::Type {
78*54c56347SValentin Clement return mlir::IntegerType::get(context,
79*54c56347SValentin Clement sizeof(Fortran::ISO::CFI_rank_t) * 8);
80*54c56347SValentin Clement };
81*54c56347SValentin Clement }
82*54c56347SValentin Clement template <>
83*54c56347SValentin Clement TypeBuilderFunc getModel<Fortran::ISO::CFI_type_t>() {
84*54c56347SValentin Clement return [](mlir::MLIRContext *context) -> mlir::Type {
85*54c56347SValentin Clement return mlir::IntegerType::get(context,
86*54c56347SValentin Clement sizeof(Fortran::ISO::CFI_type_t) * 8);
87*54c56347SValentin Clement };
88*54c56347SValentin Clement }
89*54c56347SValentin Clement template <>
90*54c56347SValentin Clement TypeBuilderFunc getModel<long>() {
91*54c56347SValentin Clement return [](mlir::MLIRContext *context) -> mlir::Type {
92*54c56347SValentin Clement return mlir::IntegerType::get(context, sizeof(long) * 8);
93*54c56347SValentin Clement };
94*54c56347SValentin Clement }
95*54c56347SValentin Clement template <>
96*54c56347SValentin Clement TypeBuilderFunc getModel<Fortran::ISO::CFI_dim_t>() {
97*54c56347SValentin Clement return [](mlir::MLIRContext *context) -> mlir::Type {
98*54c56347SValentin Clement auto indexTy = getModel<Fortran::ISO::CFI_index_t>()(context);
99*54c56347SValentin Clement return mlir::LLVM::LLVMArrayType::get(indexTy, 3);
100*54c56347SValentin Clement };
101*54c56347SValentin Clement }
102*54c56347SValentin Clement template <>
103*54c56347SValentin Clement TypeBuilderFunc
104*54c56347SValentin Clement getModel<Fortran::ISO::cfi_internal::FlexibleArray<Fortran::ISO::CFI_dim_t>>() {
105*54c56347SValentin Clement return getModel<Fortran::ISO::CFI_dim_t>();
106*54c56347SValentin Clement }
107*54c56347SValentin Clement
108*54c56347SValentin Clement //===----------------------------------------------------------------------===//
109*54c56347SValentin Clement // Descriptor reflection
110*54c56347SValentin Clement //===----------------------------------------------------------------------===//
111*54c56347SValentin Clement
112*54c56347SValentin Clement /// Get the type model of the field number `Field` in an ISO CFI descriptor.
113*54c56347SValentin Clement template <int Field>
getDescFieldTypeModel()114*54c56347SValentin Clement static constexpr TypeBuilderFunc getDescFieldTypeModel() {
115*54c56347SValentin Clement Fortran::ISO::Fortran_2018::CFI_cdesc_t dummyDesc{};
116*54c56347SValentin Clement // check that the descriptor is exactly 8 fields as specified in CFI_cdesc_t
117*54c56347SValentin Clement // in flang/include/flang/ISO_Fortran_binding.h.
118*54c56347SValentin Clement auto [a, b, c, d, e, f, g, h] = dummyDesc;
119*54c56347SValentin Clement auto tup = std::tie(a, b, c, d, e, f, g, h);
120*54c56347SValentin Clement auto field = std::get<Field>(tup);
121*54c56347SValentin Clement return getModel<decltype(field)>();
122*54c56347SValentin Clement }
123*54c56347SValentin Clement
124*54c56347SValentin Clement /// An extended descriptor is defined by a class in runtime/descriptor.h. The
125*54c56347SValentin Clement /// three fields in the class are hard-coded here, unlike the reflection used on
126*54c56347SValentin Clement /// the ISO parts, which are a POD.
127*54c56347SValentin Clement template <int Field>
getExtendedDescFieldTypeModel()128*54c56347SValentin Clement static constexpr TypeBuilderFunc getExtendedDescFieldTypeModel() {
129*54c56347SValentin Clement if constexpr (Field == 8) {
130*54c56347SValentin Clement return getModel<void *>();
131*54c56347SValentin Clement } else if constexpr (Field == 9) {
132*54c56347SValentin Clement return getModel<Fortran::runtime::typeInfo::TypeParameterValue>();
133*54c56347SValentin Clement } else {
134*54c56347SValentin Clement llvm_unreachable("extended ISO descriptor only has 10 fields");
135*54c56347SValentin Clement }
136*54c56347SValentin Clement }
137*54c56347SValentin Clement
138*54c56347SValentin Clement } // namespace fir
139*54c56347SValentin Clement
140*54c56347SValentin Clement #endif // OPTIMIZER_DESCRIPTOR_MODEL_H
141