forked from OSchip/llvm-project
[flang] Upstreaming intrinsic call lowering.
This module implements the lowering of Fortran intrinsics to the corresponding calls in support libraries (the Fortran runtime, math libraries, etc.) This revision is a tad larger because there are a large number of Fortran intrinsics and this adds lowering for a fair number of them. Differential revision: https://reviews.llvm.org/D83355
This commit is contained in:
parent
15fa287b64
commit
24b62f28c5
|
@ -106,6 +106,19 @@ public:
|
|||
/// Character lengths. TODO: move this to FirOpBuilder?
|
||||
mlir::Type getLengthType() { return builder.getIndexType(); }
|
||||
|
||||
/// Create an extended value from:
|
||||
/// - fir.boxchar<kind>
|
||||
/// - fir.ref<fir.array<len x fir.char<kind>>>
|
||||
/// - fir.array<len x fir.char<kind>>
|
||||
/// - fir.char<kind>
|
||||
/// - fir.ref<char<kind>>
|
||||
/// If the no length is passed, it is attempted to be extracted from \p
|
||||
/// character (or its type). This will crash if this is not possible.
|
||||
/// The returned value is a CharBoxValue if \p character is a scalar,
|
||||
/// otherwise it is a CharArrayBoxValue.
|
||||
fir::ExtendedValue toExtendedValue(mlir::Value character,
|
||||
mlir::Value len = {});
|
||||
|
||||
private:
|
||||
fir::CharBoxValue materializeValue(const fir::CharBoxValue &str);
|
||||
fir::CharBoxValue toDataLengthPair(mlir::Value character);
|
||||
|
|
|
@ -27,39 +27,40 @@ namespace Fortran::lower {
|
|||
|
||||
/// Helper for building calls to intrinsic functions in the runtime support
|
||||
/// libraries.
|
||||
class IntrinsicCallOpsHelper {
|
||||
public:
|
||||
explicit IntrinsicCallOpsHelper(FirOpBuilder &builder, mlir::Location loc)
|
||||
: builder(builder), loc(loc) {}
|
||||
IntrinsicCallOpsHelper(const IntrinsicCallOpsHelper &) = delete;
|
||||
|
||||
/// Generate the FIR+MLIR operations for the generic intrinsic \p name
|
||||
/// with arguments \p args and expected result type \p resultType.
|
||||
/// Returned mlir::Value is the returned Fortran intrinsic value.
|
||||
fir::ExtendedValue genIntrinsicCall(llvm::StringRef name,
|
||||
mlir::Type resultType,
|
||||
llvm::ArrayRef<fir::ExtendedValue> args);
|
||||
/// Generate the FIR+MLIR operations for the generic intrinsic \p name
|
||||
/// with arguments \p args and expected result type \p resultType.
|
||||
/// Returned mlir::Value is the returned Fortran intrinsic value.
|
||||
fir::ExtendedValue genIntrinsicCall(FirOpBuilder &, mlir::Location,
|
||||
llvm::StringRef name, mlir::Type resultType,
|
||||
llvm::ArrayRef<fir::ExtendedValue> args);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Direct access to intrinsics that may be used by lowering outside
|
||||
// of intrinsic call lowering.
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Get SymbolRefAttr of runtime (or wrapper function containing inlined
|
||||
// implementation) of an unrestricted intrinsic (defined by its signature
|
||||
// and generic name)
|
||||
mlir::SymbolRefAttr
|
||||
getUnrestrictedIntrinsicSymbolRefAttr(FirOpBuilder &, mlir::Location,
|
||||
llvm::StringRef name,
|
||||
mlir::FunctionType signature);
|
||||
|
||||
/// Generate maximum. There must be at least one argument and all arguments
|
||||
/// must have the same type.
|
||||
mlir::Value genMax(llvm::ArrayRef<mlir::Value> args);
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Direct access to intrinsics that may be used by lowering outside
|
||||
// of intrinsic call lowering.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
/// Generate minimum. Same constraints as genMax.
|
||||
mlir::Value genMin(llvm::ArrayRef<mlir::Value> args);
|
||||
/// Generate maximum. There must be at least one argument and all arguments
|
||||
/// must have the same type.
|
||||
mlir::Value genMax(FirOpBuilder &, mlir::Location,
|
||||
llvm::ArrayRef<mlir::Value> args);
|
||||
|
||||
/// Generate power function x**y with given the expected
|
||||
/// result type.
|
||||
mlir::Value genPow(mlir::Type resultType, mlir::Value x, mlir::Value y);
|
||||
/// Generate minimum. Same constraints as genMax.
|
||||
mlir::Value genMin(FirOpBuilder &, mlir::Location,
|
||||
llvm::ArrayRef<mlir::Value> args);
|
||||
|
||||
private:
|
||||
FirOpBuilder &builder;
|
||||
mlir::Location loc;
|
||||
};
|
||||
/// Generate power function x**y with given the expected
|
||||
/// result type.
|
||||
mlir::Value genPow(FirOpBuilder &, mlir::Location, mlir::Type resultType,
|
||||
mlir::Value x, mlir::Value y);
|
||||
|
||||
} // namespace Fortran::lower
|
||||
|
||||
|
|
|
@ -5,19 +5,32 @@
|
|||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef FORTRAN_LOWER_MANGLER_H_
|
||||
#define FORTRAN_LOWER_MANGLER_H_
|
||||
#ifndef FORTRAN_LOWER_MANGLER_H
|
||||
#define FORTRAN_LOWER_MANGLER_H
|
||||
|
||||
#include "mlir/IR/StandardTypes.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <string>
|
||||
|
||||
namespace fir {
|
||||
struct NameUniquer;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
class StringRef;
|
||||
}
|
||||
/// Returns a name suitable to define mlir functions for Fortran intrinsic
|
||||
/// Procedure. These names are guaranteed to not conflict with user defined
|
||||
/// procedures. This is needed to implement Fortran generic intrinsics as
|
||||
/// several mlir functions specialized for the argument types.
|
||||
/// The result is guaranteed to be distinct for different mlir::FunctionType
|
||||
/// arguments. The mangling pattern is:
|
||||
/// fir.<generic name>.<result type>.<arg type>...
|
||||
/// e.g ACOS(COMPLEX(4)) is mangled as fir.acos.z4.z4
|
||||
std::string mangleIntrinsicProcedure(llvm::StringRef genericName,
|
||||
mlir::FunctionType);
|
||||
} // namespace fir
|
||||
|
||||
namespace Fortran {
|
||||
namespace common {
|
||||
|
@ -41,4 +54,4 @@ std::string demangleName(llvm::StringRef name);
|
|||
} // namespace lower
|
||||
} // namespace Fortran
|
||||
|
||||
#endif // FORTRAN_LOWER_MANGLER_H_
|
||||
#endif // FORTRAN_LOWER_MANGLER_H
|
||||
|
|
|
@ -242,7 +242,7 @@ public:
|
|||
static bool kindof(unsigned kind) { return kind == TypeKind::FIR_DIMS; }
|
||||
|
||||
/// returns -1 if the rank is unknown
|
||||
int getRank() const;
|
||||
unsigned getRank() const;
|
||||
};
|
||||
|
||||
/// The type of a field name. Implementations may defer the layout of a Fortran
|
||||
|
@ -437,6 +437,12 @@ inline bool isa_real(mlir::Type t) {
|
|||
return t.isa<fir::RealType>() || t.isa<mlir::FloatType>();
|
||||
}
|
||||
|
||||
/// Is `t` an integral type?
|
||||
inline bool isa_integer(mlir::Type t) {
|
||||
return t.isa<mlir::IndexType>() || t.isa<mlir::IntegerType>() ||
|
||||
t.isa<fir::IntType>();
|
||||
}
|
||||
|
||||
/// Is `t` a FIR or MLIR Complex type?
|
||||
inline bool isa_complex(mlir::Type t) {
|
||||
return t.isa<fir::CplxType>() || t.isa<mlir::ComplexType>();
|
||||
|
|
|
@ -9,6 +9,7 @@ add_flang_library(FortranLower
|
|||
ConvertType.cpp
|
||||
DoLoopHelper.cpp
|
||||
FIRBuilder.cpp
|
||||
IntrinsicCall.cpp
|
||||
IO.cpp
|
||||
Mangler.cpp
|
||||
OpenMP.cpp
|
||||
|
|
|
@ -21,8 +21,10 @@ static fir::CharacterType getCharacterType(mlir::Type type) {
|
|||
return boxType.getEleTy();
|
||||
if (auto refType = type.dyn_cast<fir::ReferenceType>())
|
||||
type = refType.getEleTy();
|
||||
if (auto seqType = type.dyn_cast<fir::SequenceType>())
|
||||
if (auto seqType = type.dyn_cast<fir::SequenceType>()) {
|
||||
assert(seqType.getShape().size() == 1 && "rank must be 1");
|
||||
type = seqType.getEleTy();
|
||||
}
|
||||
if (auto charType = type.dyn_cast<fir::CharacterType>())
|
||||
return charType;
|
||||
llvm_unreachable("Invalid character value type");
|
||||
|
@ -65,38 +67,66 @@ fir::CharBoxValue Fortran::lower::CharacterExprHelper::materializeValue(
|
|||
|
||||
fir::CharBoxValue
|
||||
Fortran::lower::CharacterExprHelper::toDataLengthPair(mlir::Value character) {
|
||||
// TODO: get rid of toDataLengthPair when adding support for arrays
|
||||
auto charBox = toExtendedValue(character).getCharBox();
|
||||
assert(charBox && "Array unsupported in character lowering helper");
|
||||
return *charBox;
|
||||
}
|
||||
|
||||
fir::ExtendedValue
|
||||
Fortran::lower::CharacterExprHelper::toExtendedValue(mlir::Value character,
|
||||
mlir::Value len) {
|
||||
auto lenType = getLengthType();
|
||||
auto type = character.getType();
|
||||
if (auto boxCharType = type.dyn_cast<fir::BoxCharType>()) {
|
||||
auto base = character;
|
||||
mlir::Value resultLen = len;
|
||||
llvm::SmallVector<mlir::Value, 2> extents;
|
||||
|
||||
if (auto refType = type.dyn_cast<fir::ReferenceType>())
|
||||
type = refType.getEleTy();
|
||||
|
||||
if (auto arrayType = type.dyn_cast<fir::SequenceType>()) {
|
||||
type = arrayType.getEleTy();
|
||||
auto shape = arrayType.getShape();
|
||||
auto cstLen = shape[0];
|
||||
if (!resultLen && cstLen != fir::SequenceType::getUnknownExtent())
|
||||
resultLen = builder.createIntegerConstant(loc, lenType, cstLen);
|
||||
// FIXME: only allow `?` in last dimension ?
|
||||
auto typeExtents =
|
||||
llvm::ArrayRef<fir::SequenceType::Extent>{shape}.drop_front();
|
||||
auto indexType = builder.getIndexType();
|
||||
for (auto extent : typeExtents) {
|
||||
if (extent == fir::SequenceType::getUnknownExtent())
|
||||
break;
|
||||
extents.emplace_back(
|
||||
builder.createIntegerConstant(loc, indexType, extent));
|
||||
}
|
||||
// Last extent might be missing in case of assumed-size. If more extents
|
||||
// could not be deduced from type, that's an error (a fir.box should
|
||||
// have been used in the interface).
|
||||
if (extents.size() + 1 < typeExtents.size())
|
||||
mlir::emitError(loc, "cannot retrieve array extents from type");
|
||||
} else if (type.isa<fir::CharacterType>()) {
|
||||
if (!resultLen)
|
||||
resultLen = builder.createIntegerConstant(loc, lenType, 1);
|
||||
} else if (auto boxCharType = type.dyn_cast<fir::BoxCharType>()) {
|
||||
auto refType = builder.getRefType(boxCharType.getEleTy());
|
||||
auto unboxed =
|
||||
builder.create<fir::UnboxCharOp>(loc, refType, lenType, character);
|
||||
return {unboxed.getResult(0), unboxed.getResult(1)};
|
||||
base = unboxed.getResult(0);
|
||||
if (!resultLen)
|
||||
resultLen = unboxed.getResult(1);
|
||||
} else if (type.isa<fir::BoxType>()) {
|
||||
mlir::emitError(loc, "descriptor or derived type not yet handled");
|
||||
} else {
|
||||
llvm_unreachable("Cannot translate mlir::Value to character ExtendedValue");
|
||||
}
|
||||
if (auto seqType = type.dyn_cast<fir::CharacterType>()) {
|
||||
// Materialize length for usage into character manipulations.
|
||||
auto len = builder.createIntegerConstant(loc, lenType, 1);
|
||||
return {character, len};
|
||||
}
|
||||
if (auto refType = type.dyn_cast<fir::ReferenceType>())
|
||||
type = refType.getEleTy();
|
||||
if (auto seqType = type.dyn_cast<fir::SequenceType>()) {
|
||||
assert(seqType.hasConstantShape() &&
|
||||
"ssa array value must have constant length");
|
||||
auto shape = seqType.getShape();
|
||||
assert(shape.size() == 1 && "only scalar character supported");
|
||||
// Materialize length for usage into character manipulations.
|
||||
auto len = builder.createIntegerConstant(loc, lenType, shape[0]);
|
||||
// FIXME: this seems to work for tests, but don't think it is correct
|
||||
if (auto load = dyn_cast<fir::LoadOp>(character.getDefiningOp()))
|
||||
return {load.memref(), len};
|
||||
return {character, len};
|
||||
}
|
||||
if (auto charTy = type.dyn_cast<fir::CharacterType>()) {
|
||||
auto len = builder.createIntegerConstant(loc, lenType, 1);
|
||||
return {character, len};
|
||||
}
|
||||
llvm::report_fatal_error("unexpected character type");
|
||||
|
||||
if (!resultLen)
|
||||
mlir::emitError(loc, "no dynamic length found for character");
|
||||
if (!extents.empty())
|
||||
return fir::CharArrayBoxValue{base, resultLen, extents};
|
||||
return fir::CharBoxValue{base, resultLen};
|
||||
}
|
||||
|
||||
/// Get fir.ref<fir.char<kind>> type.
|
||||
|
@ -115,17 +145,15 @@ Fortran::lower::CharacterExprHelper::createEmbox(const fir::CharBoxValue &box) {
|
|||
auto boxCharType = fir::BoxCharType::get(builder.getContext(), kind);
|
||||
auto refType = getReferenceType(str);
|
||||
// So far, fir.emboxChar fails lowering to llvm when it is given
|
||||
// fir.data<fir.array<len x fir.char<kind>>> types, so convert to
|
||||
// fir.data<fir.char<kind>> if needed.
|
||||
// fir.ref<fir.array<len x fir.char<kind>>> types, so convert to
|
||||
// fir.ref<fir.char<kind>> if needed.
|
||||
auto buff = str.getBuffer();
|
||||
if (refType != str.getBuffer().getType())
|
||||
buff = builder.createConvert(loc, refType, buff);
|
||||
buff = builder.createConvert(loc, refType, buff);
|
||||
// Convert in case the provided length is not of the integer type that must
|
||||
// be used in boxchar.
|
||||
auto lenType = getLengthType();
|
||||
auto len = str.getLen();
|
||||
if (str.getLen().getType() != lenType)
|
||||
len = builder.createConvert(loc, lenType, len);
|
||||
len = builder.createConvert(loc, lenType, len);
|
||||
return builder.create<fir::EmboxCharOp>(loc, boxCharType, buff, len);
|
||||
}
|
||||
|
||||
|
@ -182,16 +210,20 @@ Fortran::lower::CharacterExprHelper::createTemp(mlir::Type type,
|
|||
void Fortran::lower::CharacterExprHelper::createLengthOneAssign(
|
||||
const fir::CharBoxValue &lhs, const fir::CharBoxValue &rhs) {
|
||||
auto addr = lhs.getBuffer();
|
||||
auto refType = getReferenceType(lhs);
|
||||
addr = builder.createConvert(loc, refType, addr);
|
||||
|
||||
auto val = rhs.getBuffer();
|
||||
if (!needToMaterialize(rhs)) {
|
||||
mlir::Value rhsAddr = rhs.getBuffer();
|
||||
rhsAddr = builder.createConvert(loc, refType, rhsAddr);
|
||||
val = builder.create<fir::LoadOp>(loc, rhsAddr);
|
||||
// If rhs value resides in memory, load it.
|
||||
if (!needToMaterialize(rhs))
|
||||
val = builder.create<fir::LoadOp>(loc, val);
|
||||
auto valTy = val.getType();
|
||||
// Precondition is rhs is size 1, but it may be wrapped in a fir.array.
|
||||
if (auto seqTy = valTy.dyn_cast<fir::SequenceType>()) {
|
||||
auto zero = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
|
||||
valTy = seqTy.getEleTy();
|
||||
val = builder.create<fir::ExtractValueOp>(loc, valTy, val, zero);
|
||||
}
|
||||
|
||||
auto addrTy = fir::ReferenceType::get(valTy);
|
||||
addr = builder.createConvert(loc, addrTy, addr);
|
||||
assert(fir::dyn_cast_ptrEleTy(addr.getType()) == val.getType());
|
||||
builder.create<fir::StoreOp>(loc, val, addr);
|
||||
}
|
||||
|
||||
|
@ -211,8 +243,8 @@ void Fortran::lower::CharacterExprHelper::createAssign(
|
|||
// if needed.
|
||||
mlir::Value copyCount = lhs.getLen();
|
||||
if (!compileTimeSameLength)
|
||||
copyCount = Fortran::lower::IntrinsicCallOpsHelper{builder, loc}.genMin(
|
||||
{lhs.getLen(), rhs.getLen()});
|
||||
copyCount =
|
||||
Fortran::lower::genMin(builder, loc, {lhs.getLen(), rhs.getLen()});
|
||||
|
||||
fir::CharBoxValue safeRhs = rhs;
|
||||
if (needToMaterialize(rhs)) {
|
||||
|
@ -433,7 +465,8 @@ Fortran::lower::CharacterExprHelper::materializeCharacter(mlir::Value str) {
|
|||
|
||||
bool Fortran::lower::CharacterExprHelper::isCharacterLiteral(mlir::Type type) {
|
||||
if (auto seqType = type.dyn_cast<fir::SequenceType>())
|
||||
return seqType.getEleTy().isa<fir::CharacterType>();
|
||||
return (seqType.getShape().size() == 1) &&
|
||||
seqType.getEleTy().isa<fir::CharacterType>();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -442,9 +475,9 @@ bool Fortran::lower::CharacterExprHelper::isCharacter(mlir::Type type) {
|
|||
return true;
|
||||
if (auto refType = type.dyn_cast<fir::ReferenceType>())
|
||||
type = refType.getEleTy();
|
||||
if (auto seqType = type.dyn_cast<fir::SequenceType>()) {
|
||||
type = seqType.getEleTy();
|
||||
}
|
||||
if (auto seqType = type.dyn_cast<fir::SequenceType>())
|
||||
if (seqType.getShape().size() == 1)
|
||||
type = seqType.getEleTy();
|
||||
return type.isa<fir::CharacterType>();
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,11 +9,13 @@
|
|||
#include "flang/Lower/Mangler.h"
|
||||
#include "flang/Common/reference.h"
|
||||
#include "flang/Lower/Utils.h"
|
||||
#include "flang/Optimizer/Dialect/FIRType.h"
|
||||
#include "flang/Optimizer/Support/InternalNames.h"
|
||||
#include "flang/Semantics/tools.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
|
||||
// recursively build the vector of module scopes
|
||||
|
@ -118,3 +120,49 @@ std::string Fortran::lower::mangle::demangleName(llvm::StringRef name) {
|
|||
auto result = fir::NameUniquer::deconstruct(name);
|
||||
return result.second.name;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Intrinsic Procedure Mangling
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Helper to encode type into string for intrinsic procedure names.
|
||||
/// Note: mlir has Type::dump(ostream) methods but it may add "!" that is not
|
||||
/// suitable for function names.
|
||||
static std::string typeToString(mlir::Type t) {
|
||||
if (auto refT{t.dyn_cast<fir::ReferenceType>()})
|
||||
return "ref_" + typeToString(refT.getEleTy());
|
||||
if (auto i{t.dyn_cast<mlir::IntegerType>()}) {
|
||||
return "i" + std::to_string(i.getWidth());
|
||||
}
|
||||
if (auto cplx{t.dyn_cast<fir::CplxType>()}) {
|
||||
return "z" + std::to_string(cplx.getFKind());
|
||||
}
|
||||
if (auto real{t.dyn_cast<fir::RealType>()}) {
|
||||
return "r" + std::to_string(real.getFKind());
|
||||
}
|
||||
if (auto f{t.dyn_cast<mlir::FloatType>()}) {
|
||||
return "f" + std::to_string(f.getWidth());
|
||||
}
|
||||
if (auto logical{t.dyn_cast<fir::LogicalType>()}) {
|
||||
return "l" + std::to_string(logical.getFKind());
|
||||
}
|
||||
if (auto character{t.dyn_cast<fir::CharacterType>()}) {
|
||||
return "c" + std::to_string(character.getFKind());
|
||||
}
|
||||
if (auto boxCharacter{t.dyn_cast<fir::BoxCharType>()}) {
|
||||
return "bc" + std::to_string(boxCharacter.getEleTy().getFKind());
|
||||
}
|
||||
llvm_unreachable("no mangling for type");
|
||||
}
|
||||
|
||||
std::string fir::mangleIntrinsicProcedure(llvm::StringRef intrinsic,
|
||||
mlir::FunctionType funTy) {
|
||||
std::string name = "fir.";
|
||||
name.append(intrinsic.str()).append(".");
|
||||
assert(funTy.getNumResults() == 1 && "only function mangling supported");
|
||||
name.append(typeToString(funTy.getResult(0)));
|
||||
auto e = funTy.getNumInputs();
|
||||
for (decltype(e) i = 0; i < e; ++i)
|
||||
name.append(".").append(typeToString(funTy.getInput(i)));
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -178,8 +178,10 @@ SequenceType parseSequence(mlir::DialectAsmParser &parser, mlir::Location) {
|
|||
return SequenceType::get(shape, eleTy, map);
|
||||
}
|
||||
|
||||
static bool verifyIntegerType(mlir::Type ty) {
|
||||
return ty.isa<mlir::IntegerType>() || ty.isa<IntType>();
|
||||
/// Is `ty` a standard or FIR integer type?
|
||||
static bool isaIntegerType(mlir::Type ty) {
|
||||
// TODO: why aren't we using isa_integer? investigatation required.
|
||||
return ty.isa<mlir::IntegerType>() || ty.isa<fir::IntType>();
|
||||
}
|
||||
|
||||
bool verifyRecordMemberType(mlir::Type ty) {
|
||||
|
@ -205,7 +207,7 @@ RecordType verifyDerived(mlir::DialectAsmParser &parser, RecordType derivedTy,
|
|||
return {};
|
||||
}
|
||||
for (auto &p : lenPList)
|
||||
if (!verifyIntegerType(p.second)) {
|
||||
if (!isaIntegerType(p.second)) {
|
||||
parser.emitError(loc, "LEN parameter must be integral type");
|
||||
return {};
|
||||
}
|
||||
|
@ -384,24 +386,22 @@ struct DimsTypeStorage : public mlir::TypeStorage {
|
|||
|
||||
static unsigned hashKey(const KeyTy &key) { return llvm::hash_combine(key); }
|
||||
|
||||
bool operator==(const KeyTy &key) const {
|
||||
return key == static_cast<unsigned>(getRank());
|
||||
}
|
||||
bool operator==(const KeyTy &key) const { return key == getRank(); }
|
||||
|
||||
static DimsTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
|
||||
int rank) {
|
||||
unsigned rank) {
|
||||
auto *storage = allocator.allocate<DimsTypeStorage>();
|
||||
return new (storage) DimsTypeStorage{rank};
|
||||
}
|
||||
|
||||
int getRank() const { return rank; }
|
||||
unsigned getRank() const { return rank; }
|
||||
|
||||
protected:
|
||||
int rank;
|
||||
unsigned rank;
|
||||
|
||||
private:
|
||||
DimsTypeStorage() = delete;
|
||||
explicit DimsTypeStorage(int rank) : rank{rank} {}
|
||||
explicit DimsTypeStorage(unsigned rank) : rank{rank} {}
|
||||
};
|
||||
|
||||
/// The type of a derived type part reference
|
||||
|
@ -832,6 +832,9 @@ bool isa_std_type(mlir::Type t) {
|
|||
}
|
||||
|
||||
bool isa_fir_or_std_type(mlir::Type t) {
|
||||
if (auto funcType = t.dyn_cast<mlir::FunctionType>())
|
||||
return llvm::all_of(funcType.getInputs(), isa_fir_or_std_type) &&
|
||||
llvm::all_of(funcType.getResults(), isa_fir_or_std_type);
|
||||
return isa_fir_type(t) || isa_std_type(t);
|
||||
}
|
||||
|
||||
|
@ -874,7 +877,7 @@ DimsType fir::DimsType::get(mlir::MLIRContext *ctxt, unsigned rank) {
|
|||
return Base::get(ctxt, FIR_DIMS, rank);
|
||||
}
|
||||
|
||||
int fir::DimsType::getRank() const { return getImpl()->getRank(); }
|
||||
unsigned fir::DimsType::getRank() const { return getImpl()->getRank(); }
|
||||
|
||||
// Field
|
||||
|
||||
|
@ -999,10 +1002,7 @@ fir::ReferenceType::verifyConstructionInvariants(mlir::Location loc,
|
|||
// Pointer<T>
|
||||
|
||||
PointerType fir::PointerType::get(mlir::Type elementType) {
|
||||
if (!singleIndirectionLevel(elementType)) {
|
||||
llvm_unreachable("FIXME: invalid element type");
|
||||
return {};
|
||||
}
|
||||
assert(singleIndirectionLevel(elementType) && "invalid element type");
|
||||
return Base::get(elementType.getContext(), FIR_POINTER, elementType);
|
||||
}
|
||||
|
||||
|
@ -1030,10 +1030,7 @@ fir::PointerType::verifyConstructionInvariants(mlir::Location loc,
|
|||
// Heap<T>
|
||||
|
||||
HeapType fir::HeapType::get(mlir::Type elementType) {
|
||||
if (!singleIndirectionLevel(elementType)) {
|
||||
llvm_unreachable("FIXME: invalid element type");
|
||||
return {};
|
||||
}
|
||||
assert(singleIndirectionLevel(elementType) && "invalid element type");
|
||||
return Base::get(elementType.getContext(), FIR_HEAP, elementType);
|
||||
}
|
||||
|
||||
|
@ -1171,7 +1168,6 @@ mlir::Type fir::RecordType::getType(llvm::StringRef ident) {
|
|||
for (auto f : getTypeList())
|
||||
if (ident == f.first)
|
||||
return f.second;
|
||||
llvm_unreachable("query for field not present in record");
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -1216,9 +1212,9 @@ llvm::SmallPtrSet<detail::RecordTypeStorage const *, 4> recordTypeVisited;
|
|||
} // namespace
|
||||
|
||||
void fir::verifyIntegralType(mlir::Type type) {
|
||||
if (verifyIntegerType(type) || type.isa<mlir::IndexType>())
|
||||
if (isaIntegerType(type) || type.isa<mlir::IndexType>())
|
||||
return;
|
||||
llvm_unreachable("expected integral type");
|
||||
llvm::report_fatal_error("expected integral type");
|
||||
}
|
||||
|
||||
void fir::printFirType(FIROpsDialect *, mlir::Type ty,
|
||||
|
|
Loading…
Reference in New Issue