[flang-commits] [flang] 9343398 - [flang][NFC] Extract TypeConverter from header file
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Mon Apr 10 08:41:52 PDT 2023
Author: Valentin Clement
Date: 2023-04-10T08:41:07-07:00
New Revision: 9343398708db096e7a17c5019bb2e408e0e74615
URL: https://github.com/llvm/llvm-project/commit/9343398708db096e7a17c5019bb2e408e0e74615
DIFF: https://github.com/llvm/llvm-project/commit/9343398708db096e7a17c5019bb2e408e0e74615.diff
LOG: [flang][NFC] Extract TypeConverter from header file
Extract the type converter definitions into its own .cpp
file so the type converter can be used by passes.
Reviewed By: PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D147824
Added:
flang/lib/Optimizer/CodeGen/TypeConverter.cpp
Modified:
flang/lib/Optimizer/CodeGen/CMakeLists.txt
flang/lib/Optimizer/CodeGen/TypeConverter.h
Removed:
################################################################################
diff --git a/flang/lib/Optimizer/CodeGen/CMakeLists.txt b/flang/lib/Optimizer/CodeGen/CMakeLists.txt
index 711bb402b40bd..016544ef870a5 100644
--- a/flang/lib/Optimizer/CodeGen/CMakeLists.txt
+++ b/flang/lib/Optimizer/CodeGen/CMakeLists.txt
@@ -6,6 +6,7 @@ add_flang_library(FIRCodeGen
TBAABuilder.cpp
Target.cpp
TargetRewrite.cpp
+ TypeConverter.cpp
DEPENDS
FIRDialect
diff --git a/flang/lib/Optimizer/CodeGen/TypeConverter.cpp b/flang/lib/Optimizer/CodeGen/TypeConverter.cpp
new file mode 100644
index 0000000000000..e6d8f62e7ec57
--- /dev/null
+++ b/flang/lib/Optimizer/CodeGen/TypeConverter.cpp
@@ -0,0 +1,344 @@
+//===-- TypeConverter.cpp -- type conversion --------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "flang-type-conversion"
+
+#include "TypeConverter.h"
+#include "DescriptorModel.h"
+#include "TBAABuilder.h"
+#include "Target.h"
+#include "flang/Optimizer/Builder/Todo.h" // remove when TODO's are done
+#include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Optimizer/Dialect/Support/FIRContext.h"
+#include "flang/Optimizer/Dialect/Support/KindMapping.h"
+#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
+#include "llvm/Support/Debug.h"
+
+namespace fir {
+
+LLVMTypeConverter::LLVMTypeConverter(mlir::ModuleOp module, bool applyTBAA)
+ : mlir::LLVMTypeConverter(module.getContext(),
+ [&] {
+ mlir::LowerToLLVMOptions options(
+ module.getContext());
+ options.useOpaquePointers = false;
+ return options;
+ }()),
+ kindMapping(getKindMapping(module)),
+ specifics(CodeGenSpecifics::get(module.getContext(),
+ getTargetTriple(module),
+ getKindMapping(module))),
+ tbaaBuilder(module, applyTBAA) {
+ LLVM_DEBUG(llvm::dbgs() << "FIR type converter\n");
+
+ // Each conversion should return a value of type mlir::Type.
+ addConversion([&](BoxType box) { return convertBoxType(box); });
+ addConversion([&](BoxCharType boxchar) {
+ LLVM_DEBUG(llvm::dbgs() << "type convert: " << boxchar << '\n');
+ return convertType(specifics->boxcharMemoryType(boxchar.getEleTy()));
+ });
+ addConversion([&](BoxProcType boxproc) {
+ // TODO: Support for this type will be added later when the Fortran 2003
+ // procedure pointer feature is implemented.
+ return std::nullopt;
+ });
+ addConversion(
+ [&](fir::ClassType classTy) { return convertBoxType(classTy); });
+ addConversion(
+ [&](fir::CharacterType charTy) { return convertCharType(charTy); });
+ addConversion(
+ [&](fir::ComplexType cmplx) { return convertComplexType(cmplx); });
+ addConversion([&](fir::FieldType field) {
+ // Convert to i32 because of LLVM GEP indexing restriction.
+ return mlir::IntegerType::get(field.getContext(), 32);
+ });
+ addConversion([&](HeapType heap) { return convertPointerLike(heap); });
+ addConversion([&](fir::IntegerType intTy) {
+ return mlir::IntegerType::get(
+ &getContext(), kindMapping.getIntegerBitsize(intTy.getFKind()));
+ });
+ addConversion([&](fir::LenType field) {
+ // Get size of len paramter from the descriptor.
+ return getModel<Fortran::runtime::typeInfo::TypeParameterValue>()(
+ &getContext());
+ });
+ addConversion([&](fir::LogicalType boolTy) {
+ return mlir::IntegerType::get(
+ &getContext(), kindMapping.getLogicalBitsize(boolTy.getFKind()));
+ });
+ addConversion([&](fir::LLVMPointerType pointer) {
+ return convertPointerLike(pointer);
+ });
+ addConversion(
+ [&](fir::PointerType pointer) { return convertPointerLike(pointer); });
+ addConversion([&](fir::RecordType derived,
+ llvm::SmallVectorImpl<mlir::Type> &results,
+ llvm::ArrayRef<mlir::Type> callStack) {
+ return convertRecordType(derived, results, callStack);
+ });
+ addConversion(
+ [&](fir::RealType real) { return convertRealType(real.getFKind()); });
+ addConversion(
+ [&](fir::ReferenceType ref) { return convertPointerLike(ref); });
+ addConversion([&](fir::SequenceType sequence) {
+ return convertSequenceType(sequence);
+ });
+ addConversion([&](fir::TypeDescType tdesc) {
+ return convertTypeDescType(tdesc.getContext());
+ });
+ addConversion([&](fir::VectorType vecTy) {
+ return mlir::VectorType::get(llvm::ArrayRef<int64_t>(vecTy.getLen()),
+ convertType(vecTy.getEleTy()));
+ });
+ addConversion([&](mlir::TupleType tuple) {
+ LLVM_DEBUG(llvm::dbgs() << "type convert: " << tuple << '\n');
+ llvm::SmallVector<mlir::Type> members;
+ for (auto mem : tuple.getTypes()) {
+ // Prevent fir.box from degenerating to a pointer to a descriptor in the
+ // context of a tuple type.
+ if (auto box = mem.dyn_cast<fir::BaseBoxType>())
+ members.push_back(convertBoxTypeAsStruct(box));
+ else
+ members.push_back(convertType(mem).cast<mlir::Type>());
+ }
+ return mlir::LLVM::LLVMStructType::getLiteral(&getContext(), members,
+ /*isPacked=*/false);
+ });
+ addConversion([&](mlir::NoneType none) {
+ return mlir::LLVM::LLVMStructType::getLiteral(
+ none.getContext(), std::nullopt, /*isPacked=*/false);
+ });
+ // FIXME: https://reviews.llvm.org/D82831 introduced an automatic
+ // materialization of conversion around function calls that is not working
+ // well with fir lowering to llvm (incorrect llvm.mlir.cast are inserted).
+ // Workaround until better analysis: register a handler that does not insert
+ // any conversions.
+ addSourceMaterialization(
+ [&](mlir::OpBuilder &builder, mlir::Type resultType,
+ mlir::ValueRange inputs,
+ mlir::Location loc) -> std::optional<mlir::Value> {
+ if (inputs.size() != 1)
+ return std::nullopt;
+ return inputs[0];
+ });
+ // Similar FIXME workaround here (needed for compare.fir/select-type.fir
+ // as well as rebox-global.fir tests). This is needed to cope with the
+ // the fact that codegen does not lower some operation results to the LLVM
+ // type produced by this LLVMTypeConverter. For instance, inside FIR
+ // globals, fir.box are lowered to llvm.struct, while the fir.box type
+ // conversion translates it into an llvm.ptr<llvm.struct<>> because
+ // descriptors are manipulated in memory outside of global initializers
+ // where this is not possible. Hence, MLIR inserts
+ // builtin.unrealized_conversion_cast after the translation of operations
+ // producing fir.box in fir.global codegen. addSourceMaterialization and
+ // addTargetMaterialization allow ignoring these ops and removing them
+ // after codegen assuming the type discrepencies are intended (like for
+ // fir.box inside globals).
+ addTargetMaterialization(
+ [&](mlir::OpBuilder &builder, mlir::Type resultType,
+ mlir::ValueRange inputs,
+ mlir::Location loc) -> std::optional<mlir::Value> {
+ if (inputs.size() != 1)
+ return std::nullopt;
+ return inputs[0];
+ });
+}
+
+// i32 is used here because LLVM wants i32 constants when indexing into struct
+// types. Indexing into other aggregate types is more flexible.
+mlir::Type LLVMTypeConverter::offsetType() {
+ return mlir::IntegerType::get(&getContext(), 32);
+}
+
+// i64 can be used to index into aggregates like arrays
+mlir::Type LLVMTypeConverter::indexType() {
+ return mlir::IntegerType::get(&getContext(), 64);
+}
+
+// fir.type<name(p : TY'...){f : TY...}> --> llvm<"%name = { ty... }">
+std::optional<mlir::LogicalResult>
+LLVMTypeConverter::convertRecordType(fir::RecordType derived,
+ llvm::SmallVectorImpl<mlir::Type> &results,
+ llvm::ArrayRef<mlir::Type> callStack) {
+ auto name = derived.getName();
+ auto st = mlir::LLVM::LLVMStructType::getIdentified(&getContext(), name);
+ if (llvm::count(callStack, derived) > 1) {
+ results.push_back(st);
+ return mlir::success();
+ }
+ llvm::SmallVector<mlir::Type> members;
+ for (auto mem : derived.getTypeList()) {
+ // Prevent fir.box from degenerating to a pointer to a descriptor in the
+ // context of a record type.
+ if (auto box = mem.second.dyn_cast<fir::BaseBoxType>())
+ members.push_back(convertBoxTypeAsStruct(box));
+ else
+ members.push_back(convertType(mem.second).cast<mlir::Type>());
+ }
+ if (mlir::failed(st.setBody(members, /*isPacked=*/false)))
+ return mlir::failure();
+ results.push_back(st);
+ return mlir::success();
+}
+
+// Is an extended descriptor needed given the element type of a fir.box type ?
+// Extended descriptors are required for derived types.
+bool LLVMTypeConverter::requiresExtendedDesc(mlir::Type boxElementType) {
+ auto eleTy = fir::unwrapSequenceType(boxElementType);
+ return eleTy.isa<fir::RecordType>();
+}
+
+// This corresponds to the descriptor as defined in ISO_Fortran_binding.h and
+// the addendum defined in descriptor.h.
+mlir::Type LLVMTypeConverter::convertBoxType(BaseBoxType box, int rank) {
+ // (base_addr*, elem_len, version, rank, type, attribute, f18Addendum, [dim]
+ llvm::SmallVector<mlir::Type> dataDescFields;
+ mlir::Type ele = box.getEleTy();
+ // remove fir.heap/fir.ref/fir.ptr
+ if (auto removeIndirection = fir::dyn_cast_ptrEleTy(ele))
+ ele = removeIndirection;
+ auto eleTy = convertType(ele);
+ // base_addr*
+ if (ele.isa<SequenceType>() && eleTy.isa<mlir::LLVM::LLVMPointerType>())
+ dataDescFields.push_back(eleTy);
+ else
+ dataDescFields.push_back(mlir::LLVM::LLVMPointerType::get(eleTy));
+ // elem_len
+ dataDescFields.push_back(
+ getDescFieldTypeModel<kElemLenPosInBox>()(&getContext()));
+ // version
+ dataDescFields.push_back(
+ getDescFieldTypeModel<kVersionPosInBox>()(&getContext()));
+ // rank
+ dataDescFields.push_back(
+ getDescFieldTypeModel<kRankPosInBox>()(&getContext()));
+ // type
+ dataDescFields.push_back(
+ getDescFieldTypeModel<kTypePosInBox>()(&getContext()));
+ // attribute
+ dataDescFields.push_back(
+ getDescFieldTypeModel<kAttributePosInBox>()(&getContext()));
+ // f18Addendum
+ dataDescFields.push_back(
+ getDescFieldTypeModel<kF18AddendumPosInBox>()(&getContext()));
+ // [dims]
+ if (rank == unknownRank()) {
+ if (auto seqTy = ele.dyn_cast<SequenceType>())
+ rank = seqTy.getDimension();
+ else
+ rank = 0;
+ }
+ if (rank > 0) {
+ auto rowTy = getDescFieldTypeModel<kDimsPosInBox>()(&getContext());
+ dataDescFields.push_back(mlir::LLVM::LLVMArrayType::get(rowTy, rank));
+ }
+ // opt-type-ptr: i8* (see fir.tdesc)
+ if (requiresExtendedDesc(ele) || fir::isUnlimitedPolymorphicType(box)) {
+ dataDescFields.push_back(
+ getExtendedDescFieldTypeModel<kOptTypePtrPosInBox>()(&getContext()));
+ auto rowTy =
+ getExtendedDescFieldTypeModel<kOptRowTypePosInBox>()(&getContext());
+ dataDescFields.push_back(mlir::LLVM::LLVMArrayType::get(rowTy, 1));
+ if (auto recTy = fir::unwrapSequenceType(ele).dyn_cast<fir::RecordType>())
+ if (recTy.getNumLenParams() > 0) {
+ // The descriptor design needs to be clarified regarding the number of
+ // length parameters in the addendum. Since it can change for
+ // polymorphic allocatables, it seems all length parameters cannot
+ // always possibly be placed in the addendum.
+ TODO_NOLOC("extended descriptor derived with length parameters");
+ unsigned numLenParams = recTy.getNumLenParams();
+ dataDescFields.push_back(
+ mlir::LLVM::LLVMArrayType::get(rowTy, numLenParams));
+ }
+ }
+ // TODO: send the box type and the converted LLVM structure layout
+ // to tbaaBuilder for proper creation of TBAATypeDescriptorOp.
+ return mlir::LLVM::LLVMPointerType::get(
+ mlir::LLVM::LLVMStructType::getLiteral(&getContext(), dataDescFields,
+ /*isPacked=*/false));
+}
+
+/// Convert fir.box type to the corresponding llvm struct type instead of a
+/// pointer to this struct type.
+mlir::Type LLVMTypeConverter::convertBoxTypeAsStruct(BaseBoxType box) {
+ return convertBoxType(box)
+ .cast<mlir::LLVM::LLVMPointerType>()
+ .getElementType();
+}
+
+// fir.boxproc<any> --> llvm<"{ any*, i8* }">
+mlir::Type LLVMTypeConverter::convertBoxProcType(BoxProcType boxproc) {
+ auto funcTy = convertType(boxproc.getEleTy());
+ auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(
+ mlir::IntegerType::get(&getContext(), 8));
+ llvm::SmallVector<mlir::Type, 2> tuple = {funcTy, i8PtrTy};
+ return mlir::LLVM::LLVMStructType::getLiteral(&getContext(), tuple,
+ /*isPacked=*/false);
+}
+
+unsigned LLVMTypeConverter::characterBitsize(fir::CharacterType charTy) {
+ return kindMapping.getCharacterBitsize(charTy.getFKind());
+}
+
+// fir.char<k,?> --> llvm<"ix"> where ix is scaled by kind mapping
+// fir.char<k,n> --> llvm.array<n x "ix">
+mlir::Type LLVMTypeConverter::convertCharType(fir::CharacterType charTy) {
+ auto iTy = mlir::IntegerType::get(&getContext(), characterBitsize(charTy));
+ if (charTy.getLen() == fir::CharacterType::unknownLen())
+ return iTy;
+ return mlir::LLVM::LLVMArrayType::get(iTy, charTy.getLen());
+}
+
+// convert a front-end kind value to either a std or LLVM IR dialect type
+// fir.real<n> --> llvm.anyfloat where anyfloat is a kind mapping
+mlir::Type LLVMTypeConverter::convertRealType(fir::KindTy kind) {
+ return fir::fromRealTypeID(&getContext(), kindMapping.getRealTypeID(kind),
+ kind);
+}
+
+// fir.array<c ... :any> --> llvm<"[...[c x any]]">
+mlir::Type LLVMTypeConverter::convertSequenceType(SequenceType seq) {
+ auto baseTy = convertType(seq.getEleTy());
+ if (characterWithDynamicLen(seq.getEleTy()))
+ return mlir::LLVM::LLVMPointerType::get(baseTy);
+ auto shape = seq.getShape();
+ auto constRows = seq.getConstantRows();
+ if (constRows) {
+ decltype(constRows) i = constRows;
+ for (auto e : shape) {
+ baseTy = mlir::LLVM::LLVMArrayType::get(baseTy, e);
+ if (--i == 0)
+ break;
+ }
+ if (!seq.hasDynamicExtents())
+ return baseTy;
+ }
+ return mlir::LLVM::LLVMPointerType::get(baseTy);
+}
+
+// fir.tdesc<any> --> llvm<"i8*">
+// TODO: For now use a void*, however pointer identity is not sufficient for
+// the f18 object v. class distinction (F2003).
+mlir::Type LLVMTypeConverter::convertTypeDescType(mlir::MLIRContext *ctx) {
+ return mlir::LLVM::LLVMPointerType::get(
+ mlir::IntegerType::get(&getContext(), 8));
+}
+
+// Relay TBAA tag attachment to TBAABuilder.
+void LLVMTypeConverter::attachTBAATag(mlir::LLVM::AliasAnalysisOpInterface op,
+ mlir::Type baseFIRType,
+ mlir::Type accessFIRType,
+ mlir::LLVM::GEPOp gep) {
+ tbaaBuilder.attachTBAATag(op, baseFIRType, accessFIRType, gep);
+}
+
+} // namespace fir
diff --git a/flang/lib/Optimizer/CodeGen/TypeConverter.h b/flang/lib/Optimizer/CodeGen/TypeConverter.h
index 36c02b8ff71c8..d2bcfd14162e7 100644
--- a/flang/lib/Optimizer/CodeGen/TypeConverter.h
+++ b/flang/lib/Optimizer/CodeGen/TypeConverter.h
@@ -13,7 +13,6 @@
#ifndef FORTRAN_OPTIMIZER_CODEGEN_TYPECONVERTER_H
#define FORTRAN_OPTIMIZER_CODEGEN_TYPECONVERTER_H
-#include "DescriptorModel.h"
#include "TBAABuilder.h"
#include "Target.h"
#include "flang/Optimizer/Builder/Todo.h" // remove when TODO's are done
@@ -46,173 +45,24 @@ namespace fir {
/// This converts FIR types to LLVM types (for now)
class LLVMTypeConverter : public mlir::LLVMTypeConverter {
public:
- LLVMTypeConverter(mlir::ModuleOp module, bool applyTBAA)
- : mlir::LLVMTypeConverter(module.getContext(),
- [&] {
- mlir::LowerToLLVMOptions options(
- module.getContext());
- options.useOpaquePointers = false;
- return options;
- }()),
- kindMapping(getKindMapping(module)),
- specifics(CodeGenSpecifics::get(module.getContext(),
- getTargetTriple(module),
- getKindMapping(module))),
- tbaaBuilder(module, applyTBAA) {
- LLVM_DEBUG(llvm::dbgs() << "FIR type converter\n");
-
- // Each conversion should return a value of type mlir::Type.
- addConversion([&](BoxType box) { return convertBoxType(box); });
- addConversion([&](BoxCharType boxchar) {
- LLVM_DEBUG(llvm::dbgs() << "type convert: " << boxchar << '\n');
- return convertType(specifics->boxcharMemoryType(boxchar.getEleTy()));
- });
- addConversion([&](BoxProcType boxproc) {
- // TODO: Support for this type will be added later when the Fortran 2003
- // procedure pointer feature is implemented.
- return std::nullopt;
- });
- addConversion(
- [&](fir::ClassType classTy) { return convertBoxType(classTy); });
- addConversion(
- [&](fir::CharacterType charTy) { return convertCharType(charTy); });
- addConversion(
- [&](fir::ComplexType cmplx) { return convertComplexType(cmplx); });
- addConversion([&](fir::FieldType field) {
- // Convert to i32 because of LLVM GEP indexing restriction.
- return mlir::IntegerType::get(field.getContext(), 32);
- });
- addConversion([&](HeapType heap) { return convertPointerLike(heap); });
- addConversion([&](fir::IntegerType intTy) {
- return mlir::IntegerType::get(
- &getContext(), kindMapping.getIntegerBitsize(intTy.getFKind()));
- });
- addConversion([&](fir::LenType field) {
- // Get size of len paramter from the descriptor.
- return getModel<Fortran::runtime::typeInfo::TypeParameterValue>()(
- &getContext());
- });
- addConversion([&](fir::LogicalType boolTy) {
- return mlir::IntegerType::get(
- &getContext(), kindMapping.getLogicalBitsize(boolTy.getFKind()));
- });
- addConversion([&](fir::LLVMPointerType pointer) {
- return convertPointerLike(pointer);
- });
- addConversion(
- [&](fir::PointerType pointer) { return convertPointerLike(pointer); });
- addConversion([&](fir::RecordType derived,
- llvm::SmallVectorImpl<mlir::Type> &results,
- llvm::ArrayRef<mlir::Type> callStack) {
- return convertRecordType(derived, results, callStack);
- });
- addConversion(
- [&](fir::RealType real) { return convertRealType(real.getFKind()); });
- addConversion(
- [&](fir::ReferenceType ref) { return convertPointerLike(ref); });
- addConversion([&](fir::SequenceType sequence) {
- return convertSequenceType(sequence);
- });
- addConversion([&](fir::TypeDescType tdesc) {
- return convertTypeDescType(tdesc.getContext());
- });
- addConversion([&](fir::VectorType vecTy) {
- return mlir::VectorType::get(llvm::ArrayRef<int64_t>(vecTy.getLen()),
- convertType(vecTy.getEleTy()));
- });
- addConversion([&](mlir::TupleType tuple) {
- LLVM_DEBUG(llvm::dbgs() << "type convert: " << tuple << '\n');
- llvm::SmallVector<mlir::Type> members;
- for (auto mem : tuple.getTypes()) {
- // Prevent fir.box from degenerating to a pointer to a descriptor in the
- // context of a tuple type.
- if (auto box = mem.dyn_cast<fir::BaseBoxType>())
- members.push_back(convertBoxTypeAsStruct(box));
- else
- members.push_back(convertType(mem).cast<mlir::Type>());
- }
- return mlir::LLVM::LLVMStructType::getLiteral(&getContext(), members,
- /*isPacked=*/false);
- });
- addConversion([&](mlir::NoneType none) {
- return mlir::LLVM::LLVMStructType::getLiteral(
- none.getContext(), std::nullopt, /*isPacked=*/false);
- });
- // FIXME: https://reviews.llvm.org/D82831 introduced an automatic
- // materialization of conversion around function calls that is not working
- // well with fir lowering to llvm (incorrect llvm.mlir.cast are inserted).
- // Workaround until better analysis: register a handler that does not insert
- // any conversions.
- addSourceMaterialization(
- [&](mlir::OpBuilder &builder, mlir::Type resultType,
- mlir::ValueRange inputs,
- mlir::Location loc) -> std::optional<mlir::Value> {
- if (inputs.size() != 1)
- return std::nullopt;
- return inputs[0];
- });
- // Similar FIXME workaround here (needed for compare.fir/select-type.fir
- // as well as rebox-global.fir tests). This is needed to cope with the
- // the fact that codegen does not lower some operation results to the LLVM
- // type produced by this LLVMTypeConverter. For instance, inside FIR
- // globals, fir.box are lowered to llvm.struct, while the fir.box type
- // conversion translates it into an llvm.ptr<llvm.struct<>> because
- // descriptors are manipulated in memory outside of global initializers
- // where this is not possible. Hence, MLIR inserts
- // builtin.unrealized_conversion_cast after the translation of operations
- // producing fir.box in fir.global codegen. addSourceMaterialization and
- // addTargetMaterialization allow ignoring these ops and removing them
- // after codegen assuming the type discrepencies are intended (like for
- // fir.box inside globals).
- addTargetMaterialization(
- [&](mlir::OpBuilder &builder, mlir::Type resultType,
- mlir::ValueRange inputs,
- mlir::Location loc) -> std::optional<mlir::Value> {
- if (inputs.size() != 1)
- return std::nullopt;
- return inputs[0];
- });
- }
+ LLVMTypeConverter(mlir::ModuleOp module, bool applyTBAA);
// i32 is used here because LLVM wants i32 constants when indexing into struct
// types. Indexing into other aggregate types is more flexible.
- mlir::Type offsetType() { return mlir::IntegerType::get(&getContext(), 32); }
+ mlir::Type offsetType();
// i64 can be used to index into aggregates like arrays
- mlir::Type indexType() { return mlir::IntegerType::get(&getContext(), 64); }
+ mlir::Type indexType();
// fir.type<name(p : TY'...){f : TY...}> --> llvm<"%name = { ty... }">
std::optional<mlir::LogicalResult>
convertRecordType(fir::RecordType derived,
llvm::SmallVectorImpl<mlir::Type> &results,
- llvm::ArrayRef<mlir::Type> callStack) {
- auto name = derived.getName();
- auto st = mlir::LLVM::LLVMStructType::getIdentified(&getContext(), name);
- if (llvm::count(callStack, derived) > 1) {
- results.push_back(st);
- return mlir::success();
- }
- llvm::SmallVector<mlir::Type> members;
- for (auto mem : derived.getTypeList()) {
- // Prevent fir.box from degenerating to a pointer to a descriptor in the
- // context of a record type.
- if (auto box = mem.second.dyn_cast<fir::BaseBoxType>())
- members.push_back(convertBoxTypeAsStruct(box));
- else
- members.push_back(convertType(mem.second).cast<mlir::Type>());
- }
- if (mlir::failed(st.setBody(members, /*isPacked=*/false)))
- return mlir::failure();
- results.push_back(st);
- return mlir::success();
- }
+ llvm::ArrayRef<mlir::Type> callStack);
// Is an extended descriptor needed given the element type of a fir.box type ?
// Extended descriptors are required for derived types.
- bool requiresExtendedDesc(mlir::Type boxElementType) {
- auto eleTy = fir::unwrapSequenceType(boxElementType);
- return eleTy.isa<fir::RecordType>();
- }
+ bool requiresExtendedDesc(mlir::Type boxElementType);
// Magic value to indicate we do not know the rank of an entity, either
// because it is assumed rank or because we have not determined it yet.
@@ -220,104 +70,20 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
// This corresponds to the descriptor as defined in ISO_Fortran_binding.h and
// the addendum defined in descriptor.h.
- mlir::Type convertBoxType(BaseBoxType box, int rank = unknownRank()) {
- // (base_addr*, elem_len, version, rank, type, attribute, f18Addendum, [dim]
- llvm::SmallVector<mlir::Type> dataDescFields;
- mlir::Type ele = box.getEleTy();
- // remove fir.heap/fir.ref/fir.ptr
- if (auto removeIndirection = fir::dyn_cast_ptrEleTy(ele))
- ele = removeIndirection;
- auto eleTy = convertType(ele);
- // base_addr*
- if (ele.isa<SequenceType>() && eleTy.isa<mlir::LLVM::LLVMPointerType>())
- dataDescFields.push_back(eleTy);
- else
- dataDescFields.push_back(mlir::LLVM::LLVMPointerType::get(eleTy));
- // elem_len
- dataDescFields.push_back(
- getDescFieldTypeModel<kElemLenPosInBox>()(&getContext()));
- // version
- dataDescFields.push_back(
- getDescFieldTypeModel<kVersionPosInBox>()(&getContext()));
- // rank
- dataDescFields.push_back(
- getDescFieldTypeModel<kRankPosInBox>()(&getContext()));
- // type
- dataDescFields.push_back(
- getDescFieldTypeModel<kTypePosInBox>()(&getContext()));
- // attribute
- dataDescFields.push_back(
- getDescFieldTypeModel<kAttributePosInBox>()(&getContext()));
- // f18Addendum
- dataDescFields.push_back(
- getDescFieldTypeModel<kF18AddendumPosInBox>()(&getContext()));
- // [dims]
- if (rank == unknownRank()) {
- if (auto seqTy = ele.dyn_cast<SequenceType>())
- rank = seqTy.getDimension();
- else
- rank = 0;
- }
- if (rank > 0) {
- auto rowTy = getDescFieldTypeModel<kDimsPosInBox>()(&getContext());
- dataDescFields.push_back(mlir::LLVM::LLVMArrayType::get(rowTy, rank));
- }
- // opt-type-ptr: i8* (see fir.tdesc)
- if (requiresExtendedDesc(ele) || fir::isUnlimitedPolymorphicType(box)) {
- dataDescFields.push_back(
- getExtendedDescFieldTypeModel<kOptTypePtrPosInBox>()(&getContext()));
- auto rowTy =
- getExtendedDescFieldTypeModel<kOptRowTypePosInBox>()(&getContext());
- dataDescFields.push_back(mlir::LLVM::LLVMArrayType::get(rowTy, 1));
- if (auto recTy = fir::unwrapSequenceType(ele).dyn_cast<fir::RecordType>())
- if (recTy.getNumLenParams() > 0) {
- // The descriptor design needs to be clarified regarding the number of
- // length parameters in the addendum. Since it can change for
- // polymorphic allocatables, it seems all length parameters cannot
- // always possibly be placed in the addendum.
- TODO_NOLOC("extended descriptor derived with length parameters");
- unsigned numLenParams = recTy.getNumLenParams();
- dataDescFields.push_back(
- mlir::LLVM::LLVMArrayType::get(rowTy, numLenParams));
- }
- }
- // TODO: send the box type and the converted LLVM structure layout
- // to tbaaBuilder for proper creation of TBAATypeDescriptorOp.
- return mlir::LLVM::LLVMPointerType::get(
- mlir::LLVM::LLVMStructType::getLiteral(&getContext(), dataDescFields,
- /*isPacked=*/false));
- }
+ mlir::Type convertBoxType(BaseBoxType box, int rank = unknownRank());
/// Convert fir.box type to the corresponding llvm struct type instead of a
/// pointer to this struct type.
- mlir::Type convertBoxTypeAsStruct(BaseBoxType box) {
- return convertBoxType(box)
- .cast<mlir::LLVM::LLVMPointerType>()
- .getElementType();
- }
+ mlir::Type convertBoxTypeAsStruct(BaseBoxType box);
// fir.boxproc<any> --> llvm<"{ any*, i8* }">
- mlir::Type convertBoxProcType(BoxProcType boxproc) {
- auto funcTy = convertType(boxproc.getEleTy());
- auto i8PtrTy = mlir::LLVM::LLVMPointerType::get(
- mlir::IntegerType::get(&getContext(), 8));
- llvm::SmallVector<mlir::Type, 2> tuple = {funcTy, i8PtrTy};
- return mlir::LLVM::LLVMStructType::getLiteral(&getContext(), tuple,
- /*isPacked=*/false);
- }
+ mlir::Type convertBoxProcType(BoxProcType boxproc);
- unsigned characterBitsize(fir::CharacterType charTy) {
- return kindMapping.getCharacterBitsize(charTy.getFKind());
- }
+ unsigned characterBitsize(fir::CharacterType charTy);
// fir.char<k,?> --> llvm<"ix"> where ix is scaled by kind mapping
// fir.char<k,n> --> llvm.array<n x "ix">
- mlir::Type convertCharType(fir::CharacterType charTy) {
- auto iTy = mlir::IntegerType::get(&getContext(), characterBitsize(charTy));
- if (charTy.getLen() == fir::CharacterType::unknownLen())
- return iTy;
- return mlir::LLVM::LLVMArrayType::get(iTy, charTy.getLen());
- }
+ mlir::Type convertCharType(fir::CharacterType charTy);
// Use the target specifics to figure out how to map complex to LLVM IR. The
// use of complex values in function signatures is handled before conversion
@@ -360,47 +126,22 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
// convert a front-end kind value to either a std or LLVM IR dialect type
// fir.real<n> --> llvm.anyfloat where anyfloat is a kind mapping
- mlir::Type convertRealType(fir::KindTy kind) {
- return fir::fromRealTypeID(&getContext(), kindMapping.getRealTypeID(kind),
- kind);
- }
+ mlir::Type convertRealType(fir::KindTy kind);
// fir.array<c ... :any> --> llvm<"[...[c x any]]">
- mlir::Type convertSequenceType(SequenceType seq) {
- auto baseTy = convertType(seq.getEleTy());
- if (characterWithDynamicLen(seq.getEleTy()))
- return mlir::LLVM::LLVMPointerType::get(baseTy);
- auto shape = seq.getShape();
- auto constRows = seq.getConstantRows();
- if (constRows) {
- decltype(constRows) i = constRows;
- for (auto e : shape) {
- baseTy = mlir::LLVM::LLVMArrayType::get(baseTy, e);
- if (--i == 0)
- break;
- }
- if (!seq.hasDynamicExtents())
- return baseTy;
- }
- return mlir::LLVM::LLVMPointerType::get(baseTy);
- }
+ mlir::Type convertSequenceType(SequenceType seq);
// fir.tdesc<any> --> llvm<"i8*">
// TODO: For now use a void*, however pointer identity is not sufficient for
// the f18 object v. class distinction (F2003).
- mlir::Type convertTypeDescType(mlir::MLIRContext *ctx) {
- return mlir::LLVM::LLVMPointerType::get(
- mlir::IntegerType::get(&getContext(), 8));
- }
+ mlir::Type convertTypeDescType(mlir::MLIRContext *ctx);
KindMapping &getKindMap() { return kindMapping; }
// Relay TBAA tag attachment to TBAABuilder.
void attachTBAATag(mlir::LLVM::AliasAnalysisOpInterface op,
mlir::Type baseFIRType, mlir::Type accessFIRType,
- mlir::LLVM::GEPOp gep) {
- tbaaBuilder.attachTBAATag(op, baseFIRType, accessFIRType, gep);
- }
+ mlir::LLVM::GEPOp gep);
private:
KindMapping kindMapping;
More information about the flang-commits
mailing list