141 lines
4.9 KiB
C++
141 lines
4.9 KiB
C++
//===-- DescriptorModel.h -- model of descriptors for codegen ---*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// LLVM IR dialect models of C++ types.
|
|
//
|
|
// This supplies a set of model builders to decompose the C declaration of a
|
|
// descriptor (as encoded in ISO_Fortran_binding.h and elsewhere) and
|
|
// reconstruct that type in the LLVM IR dialect.
|
|
//
|
|
// TODO: It is understood that this is deeply incorrect as far as building a
|
|
// portability layer for cross-compilation as these reflected types are those of
|
|
// the build machine and not necessarily that of either the host or the target.
|
|
// This assumption that build == host == target is actually pervasive across the
|
|
// compiler (https://llvm.org/PR52418).
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef OPTIMIZER_DESCRIPTOR_MODEL_H
|
|
#define OPTIMIZER_DESCRIPTOR_MODEL_H
|
|
|
|
#include "flang/ISO_Fortran_binding.h"
|
|
#include "flang/Runtime/descriptor.h"
|
|
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include <tuple>
|
|
|
|
namespace fir {
|
|
|
|
using TypeBuilderFunc = mlir::Type (*)(mlir::MLIRContext *);
|
|
|
|
/// Get the LLVM IR dialect model for building a particular C++ type, `T`.
|
|
template <typename T>
|
|
TypeBuilderFunc getModel();
|
|
|
|
template <>
|
|
TypeBuilderFunc getModel<void *>() {
|
|
return [](mlir::MLIRContext *context) -> mlir::Type {
|
|
return mlir::LLVM::LLVMPointerType::get(mlir::IntegerType::get(context, 8));
|
|
};
|
|
}
|
|
template <>
|
|
TypeBuilderFunc getModel<unsigned>() {
|
|
return [](mlir::MLIRContext *context) -> mlir::Type {
|
|
return mlir::IntegerType::get(context, sizeof(unsigned) * 8);
|
|
};
|
|
}
|
|
template <>
|
|
TypeBuilderFunc getModel<int>() {
|
|
return [](mlir::MLIRContext *context) -> mlir::Type {
|
|
return mlir::IntegerType::get(context, sizeof(int) * 8);
|
|
};
|
|
}
|
|
template <>
|
|
TypeBuilderFunc getModel<unsigned long>() {
|
|
return [](mlir::MLIRContext *context) -> mlir::Type {
|
|
return mlir::IntegerType::get(context, sizeof(unsigned long) * 8);
|
|
};
|
|
}
|
|
template <>
|
|
TypeBuilderFunc getModel<unsigned long long>() {
|
|
return [](mlir::MLIRContext *context) -> mlir::Type {
|
|
return mlir::IntegerType::get(context, sizeof(unsigned long long) * 8);
|
|
};
|
|
}
|
|
template <>
|
|
TypeBuilderFunc getModel<long long>() {
|
|
return [](mlir::MLIRContext *context) -> mlir::Type {
|
|
return mlir::IntegerType::get(context, sizeof(long long) * 8);
|
|
};
|
|
}
|
|
template <>
|
|
TypeBuilderFunc getModel<Fortran::ISO::CFI_rank_t>() {
|
|
return [](mlir::MLIRContext *context) -> mlir::Type {
|
|
return mlir::IntegerType::get(context,
|
|
sizeof(Fortran::ISO::CFI_rank_t) * 8);
|
|
};
|
|
}
|
|
template <>
|
|
TypeBuilderFunc getModel<Fortran::ISO::CFI_type_t>() {
|
|
return [](mlir::MLIRContext *context) -> mlir::Type {
|
|
return mlir::IntegerType::get(context,
|
|
sizeof(Fortran::ISO::CFI_type_t) * 8);
|
|
};
|
|
}
|
|
template <>
|
|
TypeBuilderFunc getModel<long>() {
|
|
return [](mlir::MLIRContext *context) -> mlir::Type {
|
|
return mlir::IntegerType::get(context, sizeof(long) * 8);
|
|
};
|
|
}
|
|
template <>
|
|
TypeBuilderFunc getModel<Fortran::ISO::CFI_dim_t>() {
|
|
return [](mlir::MLIRContext *context) -> mlir::Type {
|
|
auto indexTy = getModel<Fortran::ISO::CFI_index_t>()(context);
|
|
return mlir::LLVM::LLVMArrayType::get(indexTy, 3);
|
|
};
|
|
}
|
|
template <>
|
|
TypeBuilderFunc
|
|
getModel<Fortran::ISO::cfi_internal::FlexibleArray<Fortran::ISO::CFI_dim_t>>() {
|
|
return getModel<Fortran::ISO::CFI_dim_t>();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Descriptor reflection
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Get the type model of the field number `Field` in an ISO CFI descriptor.
|
|
template <int Field>
|
|
static constexpr TypeBuilderFunc getDescFieldTypeModel() {
|
|
Fortran::ISO::Fortran_2018::CFI_cdesc_t dummyDesc{};
|
|
// check that the descriptor is exactly 8 fields as specified in CFI_cdesc_t
|
|
// in flang/include/flang/ISO_Fortran_binding.h.
|
|
auto [a, b, c, d, e, f, g, h] = dummyDesc;
|
|
auto tup = std::tie(a, b, c, d, e, f, g, h);
|
|
auto field = std::get<Field>(tup);
|
|
return getModel<decltype(field)>();
|
|
}
|
|
|
|
/// An extended descriptor is defined by a class in runtime/descriptor.h. The
|
|
/// three fields in the class are hard-coded here, unlike the reflection used on
|
|
/// the ISO parts, which are a POD.
|
|
template <int Field>
|
|
static constexpr TypeBuilderFunc getExtendedDescFieldTypeModel() {
|
|
if constexpr (Field == 8) {
|
|
return getModel<void *>();
|
|
} else if constexpr (Field == 9) {
|
|
return getModel<Fortran::runtime::typeInfo::TypeParameterValue>();
|
|
} else {
|
|
llvm_unreachable("extended ISO descriptor only has 10 fields");
|
|
}
|
|
}
|
|
|
|
} // namespace fir
|
|
|
|
#endif // OPTIMIZER_DESCRIPTOR_MODEL_H
|