Skip to content

Commit

Permalink
[flang][NFC] share Constant<SomeDerived> lowering
Browse files Browse the repository at this point in the history
A previous patch (https://reviews.llvm.org/D136955) already refactored
intrinsic constant lowering to place in its own file and allow using it from
both the current lowering and the new lowering to HLFIR.

This patch does the same for derived types. The core function
"genStructComponentInInitializer" is moved from ConvertExpr.cpp and
renamed "genInlinedStructureCtorLitImpl" into ConvertConstant.cpp
without significant logic change.

Then, genScalarLit, genArrayLit (and genInlinedArrayLit/genOutlinedArrayLit)
are updated to support derived types.

The core aspect of derived type constant lowering that differs between
the current lowering and the HLFIR update is the way
addresses/initial target descriptors are built when part of a derived
type constant. This part happens in ConvertVariable.cpp (since the
address of a variable is taken in an initializer and is left TODO).

The mangling of derived type global literal constant is fixed: it did not embed
the derived type name and could cause "conflicts" between unrelated
derived types containing the same data. However, the hash remains
unstable between two compilation of the same file. This is not a
correctness issue and would require a lot of work to hash the derived
type constant data without hashing some irrelevant (but not out of bound)
data in the compile time data structure that holds derived type
constants (Constant<SomeDerived>). This may have to be revisited later.

Differential Revision: https://reviews.llvm.org/D140986
  • Loading branch information
jeanPerier committed Jan 5, 2023
1 parent 6aa02f9 commit 2d9b4a5
Show file tree
Hide file tree
Showing 11 changed files with 424 additions and 258 deletions.
55 changes: 35 additions & 20 deletions flang/include/flang/Lower/ConvertConstant.h
Expand Up @@ -23,31 +23,36 @@
#include "flang/Optimizer/Builder/FIRBuilder.h"

namespace Fortran::lower {
template <typename T>
class ConstantBuilder {};
class AbstractConverter;

/// Class to lower intrinsic evaluate::Constant to fir::ExtendedValue.
template <common::TypeCategory TC, int KIND>
class ConstantBuilder<evaluate::Type<TC, KIND>> {
/// Class to lower evaluate::Constant to fir::ExtendedValue.
template <typename T>
class ConstantBuilder {
public:
/// Lower \p constant into a fir::ExtendedValue.
/// If \p outlineBigConstantsInReadOnlyMemory is set, character and array
/// constants will be lowered into read only memory fir.global, and the
/// resulting fir::ExtendedValue will contain the address of the fir.global.
/// This option should not be set if the constant is being lowered while the
/// builder is already in a fir.global body because fir.global initialization
/// body cannot contain code manipulating memory (e.g. fir.load/fir.store...).
static fir::ExtendedValue
gen(fir::FirOpBuilder &builder, mlir::Location loc,
const evaluate::Constant<evaluate::Type<TC, KIND>> &constant,
bool outlineBigConstantsInReadOnlyMemory);
/// If \p outlineBigConstantsInReadOnlyMemory is set, character, derived
/// type, and array constants will be lowered into read only memory
/// fir.global, and the resulting fir::ExtendedValue will contain the address
/// of the fir.global. This option should not be set if the constant is being
/// lowered while the builder is already in a fir.global body because
/// fir.global initialization body cannot contain code manipulating memory
/// (e.g. fir.load/fir.store...).
static fir::ExtendedValue gen(Fortran::lower::AbstractConverter &converter,
mlir::Location loc,
const evaluate::Constant<T> &constant,
bool outlineBigConstantsInReadOnlyMemory);
};

template <common::TypeCategory TC, int KIND>
using IntrinsicConstantBuilder = ConstantBuilder<evaluate::Type<TC, KIND>>;

using namespace evaluate;
FOR_EACH_INTRINSIC_KIND(extern template class ConstantBuilder, )
FOR_EACH_SPECIFIC_TYPE(extern template class ConstantBuilder, )

template <typename T>
fir::ExtendedValue convertConstant(Fortran::lower::AbstractConverter &converter,
mlir::Location loc,
const evaluate::Constant<T> &constant,
bool outlineBigConstantsInReadOnlyMemory) {
return ConstantBuilder<T>::gen(converter, loc, constant,
outlineBigConstantsInReadOnlyMemory);
}

/// Create a fir.global array with a dense attribute containing the value of
/// \p initExpr.
Expand All @@ -61,6 +66,16 @@ fir::GlobalOp tryCreatingDenseGlobal(fir::FirOpBuilder &builder,
mlir::StringAttr linkage, bool isConst,
const Fortran::lower::SomeExpr &initExpr);

/// Lower a StructureConstructor that must be lowered in read only data although
/// it may not be wrapped into a Constant<T> (this may be the case for derived
/// type descriptor compiler generated data that is not fully compliant with
/// Fortran constant expression but can and must still be lowered into read only
/// memory).
fir::ExtendedValue
genInlinedStructureCtorLit(Fortran::lower::AbstractConverter &converter,
mlir::Location loc,
const Fortran::evaluate::StructureConstructor &ctor);

} // namespace Fortran::lower

#endif // FORTRAN_LOWER_CONVERTCONSTANT_H
2 changes: 2 additions & 0 deletions flang/include/flang/Lower/ConvertType.h
Expand Up @@ -86,6 +86,8 @@ mlir::Type translateVariableToFIRType(Fortran::lower::AbstractConverter &,
/// Translate a REAL of KIND to the mlir::Type.
mlir::Type convertReal(mlir::MLIRContext *ctxt, int KIND);

bool isDerivedTypeWithLenParameters(const semantics::Symbol &);

template <typename T>
class TypeBuilder {
public:
Expand Down
17 changes: 14 additions & 3 deletions flang/include/flang/Lower/Mangler.h
Expand Up @@ -14,6 +14,7 @@
#define FORTRAN_LOWER_MANGLER_H

#include "flang/Evaluate/expression.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "mlir/IR/BuiltinTypes.h"
#include "llvm/ADT/StringRef.h"
#include <string>
Expand Down Expand Up @@ -63,10 +64,12 @@ std::string
mangleArrayLiteral(const uint8_t *addr, size_t size,
const Fortran::evaluate::ConstantSubscripts &shape,
Fortran::common::TypeCategory cat, int kind = 0,
Fortran::common::ConstantSubscript charLen = -1);
Fortran::common::ConstantSubscript charLen = -1,
llvm::StringRef derivedName = {});

template <Fortran::common::TypeCategory TC, int KIND>
std::string mangleArrayLiteral(
mlir::Type,
const Fortran::evaluate::Constant<Fortran::evaluate::Type<TC, KIND>> &x) {
return mangleArrayLiteral(
reinterpret_cast<const uint8_t *>(x.values().data()),
Expand All @@ -75,20 +78,28 @@ std::string mangleArrayLiteral(

template <int KIND>
std::string
mangleArrayLiteral(const Fortran::evaluate::Constant<Fortran::evaluate::Type<
mangleArrayLiteral(mlir::Type,
const Fortran::evaluate::Constant<Fortran::evaluate::Type<
Fortran::common::TypeCategory::Character, KIND>> &x) {
return mangleArrayLiteral(
reinterpret_cast<const uint8_t *>(x.values().data()),
x.values().size() * sizeof(x.values()[0]), x.shape(),
Fortran::common::TypeCategory::Character, KIND, x.LEN());
}

// FIXME: derived type mangling is safe but not reproducible between two
// compilation of a same file because `values().data()` is a nontrivial compile
// time data structure containing pointers and vectors. In particular, this
// means that similar structure constructors are not "combined" into the same
// global constant by lowering.
inline std::string mangleArrayLiteral(
mlir::Type eleTy,
const Fortran::evaluate::Constant<Fortran::evaluate::SomeDerived> &x) {
return mangleArrayLiteral(
reinterpret_cast<const uint8_t *>(x.values().data()),
x.values().size() * sizeof(x.values()[0]), x.shape(),
Fortran::common::TypeCategory::Derived);
Fortran::common::TypeCategory::Derived, /*kind=*/0, /*charLen=*/-1,
eleTy.cast<fir::RecordType>().getName());
}

/// Return the compiler-generated name of a static namelist variable descriptor.
Expand Down

0 comments on commit 2d9b4a5

Please sign in to comment.