From 0a494d0623a7ed6042d9f27bb4df81d59af1e935 Mon Sep 17 00:00:00 2001 From: Valentin Clement Date: Mon, 31 Jan 2022 18:29:06 +0100 Subject: [PATCH] [flang][NFC] Remove obsolete Character helper During the upstreaming process from fir-dev some new builder have been introduced in the `flang/Optimizer/Builder/Character.h` and `flang/include/Builder/Runtime/Character.h` files. This patch removes the obsolete Charachter helpers still present in the lowering directories. This patch is part of the upstreaming effort from fir-dev branch. Reviewed By: kiranchandramohan Differential Revision: https://reviews.llvm.org/D118594 --- flang/include/flang/Lower/CharacterExpr.h | 153 --------- flang/include/flang/Lower/CharacterRuntime.h | 36 --- flang/lib/Lower/CMakeLists.txt | 2 - flang/lib/Lower/CharacterExpr.cpp | 464 --------------------------- flang/lib/Lower/CharacterRuntime.cpp | 127 -------- 5 files changed, 782 deletions(-) delete mode 100644 flang/include/flang/Lower/CharacterExpr.h delete mode 100644 flang/include/flang/Lower/CharacterRuntime.h delete mode 100644 flang/lib/Lower/CharacterExpr.cpp delete mode 100644 flang/lib/Lower/CharacterRuntime.cpp diff --git a/flang/include/flang/Lower/CharacterExpr.h b/flang/include/flang/Lower/CharacterExpr.h deleted file mode 100644 index cb8ec95..0000000 --- a/flang/include/flang/Lower/CharacterExpr.h +++ /dev/null @@ -1,153 +0,0 @@ -//===-- Lower/CharacterExpr.h -- lowering of characters ---------*- 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 -// -//===----------------------------------------------------------------------===// - -#ifndef FORTRAN_LOWER_CHARACTEREXPR_H -#define FORTRAN_LOWER_CHARACTEREXPR_H - -#include "flang/Optimizer/Builder/BoxValue.h" -#include "flang/Optimizer/Builder/FIRBuilder.h" - -namespace Fortran::lower { - -/// Helper to facilitate lowering of CHARACTER in FIR. -class CharacterExprHelper { -public: - /// Constructor. - explicit CharacterExprHelper(fir::FirOpBuilder &builder, mlir::Location loc) - : builder{builder}, loc{loc} {} - CharacterExprHelper(const CharacterExprHelper &) = delete; - - /// Unless otherwise stated, all mlir::Value inputs of these pseudo-fir ops - /// must be of type: - /// - fir.boxchar (dynamic length character), - /// - fir.ref>> (character with compile time - /// constant length), - /// - fir.array> (compile time constant character) - - /// Copy the \p count first characters of \p src into \p dest. - /// \p count can have any integer type. - void createCopy(mlir::Value dest, mlir::Value src, mlir::Value count); - - /// Set characters of \p str at position [\p lower, \p upper) to blanks. - /// \p lower and \upper bounds are zero based. - /// If \p upper <= \p lower, no padding is done. - /// \p upper and \p lower can have any integer type. - void createPadding(mlir::Value str, mlir::Value lower, mlir::Value upper); - - /// Create str(lb:ub), lower bounds must always be specified, upper - /// bound is optional. - mlir::Value createSubstring(mlir::Value str, - llvm::ArrayRef bounds); - - /// Return blank character of given \p type !fir.char - mlir::Value createBlankConstant(fir::CharacterType type); - - /// Lower \p lhs = \p rhs where \p lhs and \p rhs are scalar characters. - /// It handles cases where \p lhs and \p rhs may overlap. - void createAssign(mlir::Value lhs, mlir::Value rhs); - - /// Lower an assignment where the buffer and LEN parameter are known and do - /// not need to be unboxed. - void createAssign(mlir::Value lptr, mlir::Value llen, mlir::Value rptr, - mlir::Value rlen); - - /// Create lhs // rhs in temp obtained with fir.alloca - mlir::Value createConcatenate(mlir::Value lhs, mlir::Value rhs); - - /// LEN_TRIM intrinsic. - mlir::Value createLenTrim(mlir::Value str); - - /// Embox \p addr and \p len and return fir.boxchar. - /// Take care of type conversions before emboxing. - /// \p len is converted to the integer type for character lengths if needed. - mlir::Value createEmboxChar(mlir::Value addr, mlir::Value len); - - /// Unbox \p boxchar into (fir.ref>, getLengthType()). - std::pair createUnboxChar(mlir::Value boxChar); - - /// Allocate a temp of fir::CharacterType type and length len. - /// Returns related fir.ref>. - mlir::Value createCharacterTemp(mlir::Type type, mlir::Value len); - - /// Allocate a temp of compile time constant length. - /// Returns related fir.ref>>. - mlir::Value createCharacterTemp(mlir::Type type, int len) { - return createTemp(type, len); - } - - /// Return buffer/length pair of character str, if str is a constant, - /// it is allocated into a temp, otherwise, its memory reference is - /// returned as the buffer. - /// The buffer type of str is of type: - /// - fir.ref>> if str has compile time - /// constant length. - /// - fir.ref> if str has dynamic length. - std::pair materializeCharacter(mlir::Value str); - - /// Return true if \p type is a character literal type (is - /// fir.array>).; - static bool isCharacterLiteral(mlir::Type type); - - /// Return true if \p type is one of the following type - /// - fir.boxchar - /// - fir.ref>> - /// - fir.array> - static bool isCharacter(mlir::Type type); - - /// Extract the kind of a character type - static int getCharacterKind(mlir::Type type); - - /// Return the integer type that must be used to manipulate - /// Character lengths. TODO: move this to FirOpBuilder? - mlir::Type getLengthType() { return builder.getIndexType(); } - - /// Create an extended value from: - /// - fir.boxchar - /// - fir.ref>> - /// - fir.array> - /// - fir.char - /// - fir.ref> - /// 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); - mlir::Type getReferenceType(const fir::CharBoxValue &c) const; - mlir::Value createEmbox(const fir::CharBoxValue &str); - mlir::Value createLoadCharAt(const fir::CharBoxValue &str, mlir::Value index); - void createStoreCharAt(const fir::CharBoxValue &str, mlir::Value index, - mlir::Value c); - void createCopy(const fir::CharBoxValue &dest, const fir::CharBoxValue &src, - mlir::Value count); - void createPadding(const fir::CharBoxValue &str, mlir::Value lower, - mlir::Value upper); - fir::CharBoxValue createTemp(mlir::Type type, mlir::Value len); - void createLengthOneAssign(const fir::CharBoxValue &lhs, - const fir::CharBoxValue &rhs); - void createAssign(const fir::CharBoxValue &lhs, const fir::CharBoxValue &rhs); - fir::CharBoxValue createConcatenate(const fir::CharBoxValue &lhs, - const fir::CharBoxValue &rhs); - fir::CharBoxValue createSubstring(const fir::CharBoxValue &str, - llvm::ArrayRef bounds); - mlir::Value createLenTrim(const fir::CharBoxValue &str); - mlir::Value createTemp(mlir::Type type, int len); - mlir::Value createBlankConstantCode(fir::CharacterType type); - -private: - fir::FirOpBuilder &builder; - mlir::Location loc; -}; - -} // namespace Fortran::lower - -#endif // FORTRAN_LOWER_CHARACTEREXPR_H diff --git a/flang/include/flang/Lower/CharacterRuntime.h b/flang/include/flang/Lower/CharacterRuntime.h deleted file mode 100644 index 0411c90..0000000 --- a/flang/include/flang/Lower/CharacterRuntime.h +++ /dev/null @@ -1,36 +0,0 @@ -//===-- Lower/CharacterRuntime.h -- lower CHARACTER operations --*- 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 -// -//===----------------------------------------------------------------------===// - -#ifndef FORTRAN_LOWER_CHARACTERRUNTIME_H -#define FORTRAN_LOWER_CHARACTERRUNTIME_H - -#include "mlir/Dialect/StandardOps/IR/Ops.h" - -namespace Fortran { -namespace lower { -class AbstractConverter; - -/// Generate call to a character comparison for two ssa-values of type -/// `boxchar`. -mlir::Value genBoxCharCompare(AbstractConverter &converter, mlir::Location loc, - mlir::arith::CmpIPredicate cmp, mlir::Value lhs, - mlir::Value rhs); - -/// Generate call to a character comparison op for two unboxed variables. There -/// are 4 arguments, 2 for the lhs and 2 for the rhs. Each CHARACTER must pass a -/// reference to its buffer (`ref>`) and its LEN type parameter (some -/// integral type). -mlir::Value genRawCharCompare(AbstractConverter &converter, mlir::Location loc, - mlir::arith::CmpIPredicate cmp, - mlir::Value lhsBuff, mlir::Value lhsLen, - mlir::Value rhsBuff, mlir::Value rhsLen); - -} // namespace lower -} // namespace Fortran - -#endif // FORTRAN_LOWER_CHARACTERRUNTIME_H diff --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt index 3e53b8c..9981f5d 100644 --- a/flang/lib/Lower/CMakeLists.txt +++ b/flang/lib/Lower/CMakeLists.txt @@ -3,8 +3,6 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) add_flang_library(FortranLower Bridge.cpp CallInterface.cpp - CharacterExpr.cpp - CharacterRuntime.cpp Coarray.cpp ConvertType.cpp Mangler.cpp diff --git a/flang/lib/Lower/CharacterExpr.cpp b/flang/lib/Lower/CharacterExpr.cpp deleted file mode 100644 index c262375..0000000 --- a/flang/lib/Lower/CharacterExpr.cpp +++ /dev/null @@ -1,464 +0,0 @@ -//===-- CharacterExpr.cpp -------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "flang/Lower/CharacterExpr.h" -#include "flang/Lower/ConvertType.h" -#include "flang/Optimizer/Builder/DoLoopHelper.h" -#include "flang/Optimizer/Builder/FIRBuilder.h" - -//===----------------------------------------------------------------------===// -// CharacterExprHelper implementation -//===----------------------------------------------------------------------===// - -/// Get fir.char type with the same kind as inside str. -static fir::CharacterType getCharacterType(mlir::Type type) { - if (auto boxType = type.dyn_cast()) - return boxType.getEleTy(); - if (auto refType = type.dyn_cast()) - type = refType.getEleTy(); - if (auto seqType = type.dyn_cast()) { - assert(seqType.getShape().size() == 1 && "rank must be 1"); - type = seqType.getEleTy(); - } - if (auto charType = type.dyn_cast()) - return charType; - llvm_unreachable("Invalid character value type"); -} - -static fir::CharacterType getCharacterType(const fir::CharBoxValue &box) { - return getCharacterType(box.getBuffer().getType()); -} - -static bool needToMaterialize(const fir::CharBoxValue &box) { - return box.getBuffer().getType().isa() || - box.getBuffer().getType().isa(); -} - -static std::optional -getCompileTimeLength(const fir::CharBoxValue &box) { - // FIXME: should this just return box.getLen() ?? - auto type = box.getBuffer().getType(); - if (type.isa()) - return 1; - if (auto refType = type.dyn_cast()) - type = refType.getEleTy(); - if (auto seqType = type.dyn_cast()) { - auto shape = seqType.getShape(); - assert(shape.size() == 1 && "only scalar character supported"); - if (shape[0] != fir::SequenceType::getUnknownExtent()) - return shape[0]; - } - return {}; -} - -fir::CharBoxValue Fortran::lower::CharacterExprHelper::materializeValue( - const fir::CharBoxValue &str) { - if (!needToMaterialize(str)) - return str; - auto variable = builder.create(loc, str.getBuffer().getType()); - builder.create(loc, str.getBuffer(), variable); - return {variable, str.getLen()}; -} - -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(); - auto base = character; - mlir::Value resultLen = len; - llvm::SmallVector extents; - - if (auto refType = type.dyn_cast()) - type = refType.getEleTy(); - - if (auto arrayType = type.dyn_cast()) { - 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{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()) { - if (!resultLen) - resultLen = builder.createIntegerConstant(loc, lenType, 1); - } else if (auto boxCharType = type.dyn_cast()) { - auto refType = builder.getRefType(boxCharType.getEleTy()); - auto unboxed = - builder.create(loc, refType, lenType, character); - base = unboxed.getResult(0); - if (!resultLen) - resultLen = unboxed.getResult(1); - } else if (type.isa()) { - mlir::emitError(loc, "descriptor or derived type not yet handled"); - } else { - llvm_unreachable("Cannot translate mlir::Value to character ExtendedValue"); - } - - 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> type. -mlir::Type Fortran::lower::CharacterExprHelper::getReferenceType( - const fir::CharBoxValue &box) const { - return builder.getRefType(getCharacterType(box)); -} - -mlir::Value -Fortran::lower::CharacterExprHelper::createEmbox(const fir::CharBoxValue &box) { - // BoxChar require a reference. - auto str = box; - if (needToMaterialize(box)) - str = materializeValue(box); - auto kind = getCharacterType(str).getFKind(); - 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.ref>> types, so convert to - // fir.ref> if needed. - auto buff = str.getBuffer(); - 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(); - len = builder.createConvert(loc, lenType, len); - return builder.create(loc, boxCharType, buff, len); -} - -mlir::Value Fortran::lower::CharacterExprHelper::createLoadCharAt( - const fir::CharBoxValue &str, mlir::Value index) { - // In case this is addressing a length one character scalar simply return - // the single character. - if (str.getBuffer().getType().isa()) - return str.getBuffer(); - auto addr = builder.create(loc, getReferenceType(str), - str.getBuffer(), index); - return builder.create(loc, addr); -} - -void Fortran::lower::CharacterExprHelper::createStoreCharAt( - const fir::CharBoxValue &str, mlir::Value index, mlir::Value c) { - assert(!needToMaterialize(str) && "not in memory"); - auto addr = builder.create(loc, getReferenceType(str), - str.getBuffer(), index); - builder.create(loc, c, addr); -} - -void Fortran::lower::CharacterExprHelper::createCopy( - const fir::CharBoxValue &dest, const fir::CharBoxValue &src, - mlir::Value count) { - fir::factory::DoLoopHelper{builder, loc}.createLoop( - count, [&](fir::FirOpBuilder &, mlir::Value index) { - auto charVal = createLoadCharAt(src, index); - createStoreCharAt(dest, index, charVal); - }); -} - -void Fortran::lower::CharacterExprHelper::createPadding( - const fir::CharBoxValue &str, mlir::Value lower, mlir::Value upper) { - auto blank = createBlankConstant(getCharacterType(str)); - // Always create the loop, if upper < lower, no iteration will be - // executed. - fir::factory::DoLoopHelper{builder, loc}.createLoop( - lower, upper, [&](fir::FirOpBuilder &, mlir::Value index) { - createStoreCharAt(str, index, blank); - }); -} - -fir::CharBoxValue -Fortran::lower::CharacterExprHelper::createTemp(mlir::Type type, - mlir::Value len) { - assert(type.isa() && "expected fir character type"); - llvm::SmallVector sizes{len}; - auto ref = builder.allocateLocal(loc, type, "", ".chrtmp", - /*shape=*/llvm::None, sizes); - return {ref, len}; -} - -// Simple length one character assignment without loops. -void Fortran::lower::CharacterExprHelper::createLengthOneAssign( - const fir::CharBoxValue &lhs, const fir::CharBoxValue &rhs) { - auto addr = lhs.getBuffer(); - auto val = rhs.getBuffer(); - // If rhs value resides in memory, load it. - if (!needToMaterialize(rhs)) - val = builder.create(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()) { - auto zero = builder.getIntegerAttr(builder.getIndexType(), 0); - valTy = seqTy.getEleTy(); - val = builder.create(loc, valTy, val, - builder.getArrayAttr(zero)); - } - auto addrTy = fir::ReferenceType::get(valTy); - addr = builder.createConvert(loc, addrTy, addr); - assert(fir::dyn_cast_ptrEleTy(addr.getType()) == val.getType()); - builder.create(loc, val, addr); -} - -void Fortran::lower::CharacterExprHelper::createAssign( - const fir::CharBoxValue &lhs, const fir::CharBoxValue &rhs) { - auto rhsCstLen = getCompileTimeLength(rhs); - auto lhsCstLen = getCompileTimeLength(lhs); - bool compileTimeSameLength = - lhsCstLen && rhsCstLen && *lhsCstLen == *rhsCstLen; - - if (compileTimeSameLength && *lhsCstLen == 1) { - createLengthOneAssign(lhs, rhs); - return; - } - - // Copy the minimum of the lhs and rhs lengths and pad the lhs remainder - // if needed. - mlir::Value copyCount = lhs.getLen(); - if (!compileTimeSameLength) { - auto cmp = builder.create(loc, arith::CmpIPredicate::slt, - lhs.getLen(), rhs.getLen()); - copyCount = - builder.create(loc, cmp, lhs.getLen(), rhs.getLen()); - } - - fir::CharBoxValue safeRhs = rhs; - if (needToMaterialize(rhs)) { - // TODO: revisit now that character constant handling changed. - // Need to materialize the constant to get its elements. - // (No equivalent of fir.coordinate_of for array value). - safeRhs = materializeValue(rhs); - } else { - // If rhs is in memory, always assumes rhs might overlap with lhs - // in a way that require a temp for the copy. That can be optimize later. - // Only create a temp of copyCount size because we do not need more from - // rhs. - auto temp = createTemp(getCharacterType(rhs), copyCount); - createCopy(temp, rhs, copyCount); - safeRhs = temp; - } - - // Actual copy - createCopy(lhs, safeRhs, copyCount); - - // Pad if needed. - if (!compileTimeSameLength) { - auto one = builder.createIntegerConstant(loc, lhs.getLen().getType(), 1); - auto maxPadding = - builder.create(loc, lhs.getLen(), one); - createPadding(lhs, copyCount, maxPadding); - } -} - -fir::CharBoxValue Fortran::lower::CharacterExprHelper::createConcatenate( - const fir::CharBoxValue &lhs, const fir::CharBoxValue &rhs) { - mlir::Value len = - builder.create(loc, lhs.getLen(), rhs.getLen()); - auto temp = createTemp(getCharacterType(rhs), len); - createCopy(temp, lhs, lhs.getLen()); - auto one = builder.createIntegerConstant(loc, len.getType(), 1); - auto upperBound = builder.create(loc, len, one); - auto lhsLen = - builder.createConvert(loc, builder.getIndexType(), lhs.getLen()); - fir::factory::DoLoopHelper{builder, loc}.createLoop( - lhs.getLen(), upperBound, one, - [&](fir::FirOpBuilder &bldr, mlir::Value index) { - auto rhsIndex = bldr.create(loc, index, lhsLen); - auto charVal = createLoadCharAt(rhs, rhsIndex); - createStoreCharAt(temp, index, charVal); - }); - return temp; -} - -fir::CharBoxValue Fortran::lower::CharacterExprHelper::createSubstring( - const fir::CharBoxValue &box, llvm::ArrayRef bounds) { - // Constant need to be materialize in memory to use fir.coordinate_of. - auto str = box; - if (needToMaterialize(box)) - str = materializeValue(box); - - auto nbounds{bounds.size()}; - if (nbounds < 1 || nbounds > 2) { - mlir::emitError(loc, "Incorrect number of bounds in substring"); - return {mlir::Value{}, mlir::Value{}}; - } - mlir::SmallVector castBounds; - // Convert bounds to length type to do safe arithmetic on it. - for (auto bound : bounds) - castBounds.push_back(builder.createConvert(loc, getLengthType(), bound)); - auto lowerBound = castBounds[0]; - // FIR CoordinateOp is zero based but Fortran substring are one based. - auto one = builder.createIntegerConstant(loc, lowerBound.getType(), 1); - auto offset = - builder.create(loc, lowerBound, one).getResult(); - auto idxType = builder.getIndexType(); - if (offset.getType() != idxType) - offset = builder.createConvert(loc, idxType, offset); - auto substringRef = builder.create( - loc, getReferenceType(str), str.getBuffer(), offset); - - // Compute the length. - mlir::Value substringLen{}; - if (nbounds < 2) { - substringLen = - builder.create(loc, str.getLen(), castBounds[0]); - } else { - substringLen = - builder.create(loc, castBounds[1], castBounds[0]); - } - substringLen = builder.create(loc, substringLen, one); - - // Set length to zero if bounds were reversed (Fortran 2018 9.4.1) - auto zero = builder.createIntegerConstant(loc, substringLen.getType(), 0); - auto cdt = builder.create( - loc, mlir::arith::CmpIPredicate::slt, substringLen, zero); - substringLen = builder.create(loc, cdt, zero, substringLen); - - return {substringRef, substringLen}; -} - -mlir::Value Fortran::lower::CharacterExprHelper::createLenTrim( - const fir::CharBoxValue &str) { - return {}; -} - -mlir::Value Fortran::lower::CharacterExprHelper::createTemp(mlir::Type type, - int len) { - assert(type.isa() && "expected fir character type"); - assert(len >= 0 && "expected positive length"); - fir::SequenceType::Shape shape{len}; - auto seqType = fir::SequenceType::get(shape, type); - return builder.create(loc, seqType); -} - -// Returns integer with code for blank. The integer has the same -// size as the character. Blank has ascii space code for all kinds. -mlir::Value Fortran::lower::CharacterExprHelper::createBlankConstantCode( - fir::CharacterType type) { - auto bits = builder.getKindMap().getCharacterBitsize(type.getFKind()); - auto intType = builder.getIntegerType(bits); - return builder.createIntegerConstant(loc, intType, ' '); -} - -mlir::Value Fortran::lower::CharacterExprHelper::createBlankConstant( - fir::CharacterType type) { - return builder.createConvert(loc, type, createBlankConstantCode(type)); -} - -void Fortran::lower::CharacterExprHelper::createCopy(mlir::Value dest, - mlir::Value src, - mlir::Value count) { - createCopy(toDataLengthPair(dest), toDataLengthPair(src), count); -} - -void Fortran::lower::CharacterExprHelper::createPadding(mlir::Value str, - mlir::Value lower, - mlir::Value upper) { - createPadding(toDataLengthPair(str), lower, upper); -} - -mlir::Value Fortran::lower::CharacterExprHelper::createSubstring( - mlir::Value str, llvm::ArrayRef bounds) { - return createEmbox(createSubstring(toDataLengthPair(str), bounds)); -} - -void Fortran::lower::CharacterExprHelper::createAssign(mlir::Value lhs, - mlir::Value rhs) { - createAssign(toDataLengthPair(lhs), toDataLengthPair(rhs)); -} - -mlir::Value -Fortran::lower::CharacterExprHelper::createLenTrim(mlir::Value str) { - return createLenTrim(toDataLengthPair(str)); -} - -void Fortran::lower::CharacterExprHelper::createAssign(mlir::Value lptr, - mlir::Value llen, - mlir::Value rptr, - mlir::Value rlen) { - createAssign(fir::CharBoxValue{lptr, llen}, fir::CharBoxValue{rptr, rlen}); -} - -mlir::Value -Fortran::lower::CharacterExprHelper::createConcatenate(mlir::Value lhs, - mlir::Value rhs) { - return createEmbox( - createConcatenate(toDataLengthPair(lhs), toDataLengthPair(rhs))); -} - -mlir::Value -Fortran::lower::CharacterExprHelper::createEmboxChar(mlir::Value addr, - mlir::Value len) { - return createEmbox(fir::CharBoxValue{addr, len}); -} - -std::pair -Fortran::lower::CharacterExprHelper::createUnboxChar(mlir::Value boxChar) { - auto box = toDataLengthPair(boxChar); - return {box.getBuffer(), box.getLen()}; -} - -mlir::Value -Fortran::lower::CharacterExprHelper::createCharacterTemp(mlir::Type type, - mlir::Value len) { - return createEmbox(createTemp(type, len)); -} - -std::pair -Fortran::lower::CharacterExprHelper::materializeCharacter(mlir::Value str) { - auto box = toDataLengthPair(str); - if (needToMaterialize(box)) - box = materializeValue(box); - return {box.getBuffer(), box.getLen()}; -} - -bool Fortran::lower::CharacterExprHelper::isCharacterLiteral(mlir::Type type) { - if (auto seqType = type.dyn_cast()) - return (seqType.getShape().size() == 1) && - seqType.getEleTy().isa(); - return false; -} - -bool Fortran::lower::CharacterExprHelper::isCharacter(mlir::Type type) { - if (type.isa()) - return true; - if (auto refType = type.dyn_cast()) - type = refType.getEleTy(); - if (auto seqType = type.dyn_cast()) - if (seqType.getShape().size() == 1) - type = seqType.getEleTy(); - return type.isa(); -} - -int Fortran::lower::CharacterExprHelper::getCharacterKind(mlir::Type type) { - return getCharacterType(type).getFKind(); -} diff --git a/flang/lib/Lower/CharacterRuntime.cpp b/flang/lib/Lower/CharacterRuntime.cpp deleted file mode 100644 index 23b0b6f..0000000 --- a/flang/lib/Lower/CharacterRuntime.cpp +++ /dev/null @@ -1,127 +0,0 @@ -//===-- CharacterRuntime.cpp -- runtime for CHARACTER type entities -------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "flang/Lower/CharacterRuntime.h" -#include "RTBuilder.h" -#include "flang/Lower/Bridge.h" -#include "flang/Lower/CharacterExpr.h" -#include "flang/Optimizer/Builder/FIRBuilder.h" -#include "flang/Runtime/character.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" - -using namespace Fortran::runtime; - -#define NAMIFY_HELPER(X) #X -#define NAMIFY(X) NAMIFY_HELPER(IONAME(X)) -#define mkRTKey(X) mkKey(RTNAME(X)) - -namespace Fortran::lower { -/// Static table of CHARACTER runtime calls -/// -/// This logical map contains the name and type builder function for each -/// runtime function listed in the tuple. This table is fully constructed at -/// compile-time. Use the `mkRTKey` macro to access the table. -static constexpr std::tuple< - mkRTKey(CharacterCompareScalar), mkRTKey(CharacterCompareScalar1), - mkRTKey(CharacterCompareScalar2), mkRTKey(CharacterCompareScalar4), - mkRTKey(CharacterCompare)> - newCharRTTable; -} // namespace Fortran::lower - -using namespace Fortran::lower; - -/// Helper function to retrieve the name of the IO function given the key `A` -template -static constexpr const char *getName() { - return std::get(newCharRTTable).name; -} - -/// Helper function to retrieve the type model signature builder of the IO -/// function as defined by the key `A` -template -static constexpr FuncTypeBuilderFunc getTypeModel() { - return std::get(newCharRTTable).getTypeModel(); -} - -inline int64_t getLength(mlir::Type argTy) { - return argTy.cast().getShape()[0]; -} - -/// Get (or generate) the MLIR FuncOp for a given runtime function. -template -static mlir::FuncOp getRuntimeFunc(mlir::Location loc, - fir::FirOpBuilder &builder) { - auto name = getName(); - auto func = builder.getNamedFunction(name); - if (func) - return func; - auto funTy = getTypeModel()(builder.getContext()); - func = builder.createFunction(loc, name, funTy); - func->setAttr("fir.runtime", builder.getUnitAttr()); - return func; -} - -/// Helper function to recover the KIND from the FIR type. -static int discoverKind(mlir::Type ty) { - if (auto charTy = ty.dyn_cast()) - return charTy.getFKind(); - if (auto eleTy = fir::dyn_cast_ptrEleTy(ty)) - return discoverKind(eleTy); - if (auto arrTy = ty.dyn_cast()) - return discoverKind(arrTy.getEleTy()); - if (auto boxTy = ty.dyn_cast()) - return discoverKind(boxTy.getEleTy()); - if (auto boxTy = ty.dyn_cast()) - return discoverKind(boxTy.getEleTy()); - llvm_unreachable("unexpected character type"); -} - -//===----------------------------------------------------------------------===// -// Lower character operations -//===----------------------------------------------------------------------===// - -mlir::Value Fortran::lower::genRawCharCompare( - Fortran::lower::AbstractConverter &converter, mlir::Location loc, - mlir::arith::CmpIPredicate cmp, mlir::Value lhsBuff, mlir::Value lhsLen, - mlir::Value rhsBuff, mlir::Value rhsLen) { - auto &builder = converter.getFirOpBuilder(); - mlir::FuncOp beginFunc; - switch (discoverKind(lhsBuff.getType())) { - case 1: - beginFunc = getRuntimeFunc(loc, builder); - break; - case 2: - beginFunc = getRuntimeFunc(loc, builder); - break; - case 4: - beginFunc = getRuntimeFunc(loc, builder); - break; - default: - llvm_unreachable("runtime does not support CHARACTER KIND"); - } - auto fTy = beginFunc.getType(); - auto lptr = builder.createConvert(loc, fTy.getInput(0), lhsBuff); - auto llen = builder.createConvert(loc, fTy.getInput(2), lhsLen); - auto rptr = builder.createConvert(loc, fTy.getInput(1), rhsBuff); - auto rlen = builder.createConvert(loc, fTy.getInput(3), rhsLen); - llvm::SmallVector args = {lptr, rptr, llen, rlen}; - auto tri = builder.create(loc, beginFunc, args).getResult(0); - auto zero = builder.createIntegerConstant(loc, tri.getType(), 0); - return builder.create(loc, cmp, tri, zero); -} - -mlir::Value Fortran::lower::genBoxCharCompare( - Fortran::lower::AbstractConverter &converter, mlir::Location loc, - mlir::arith::CmpIPredicate cmp, mlir::Value lhs, mlir::Value rhs) { - auto &builder = converter.getFirOpBuilder(); - Fortran::lower::CharacterExprHelper helper{builder, loc}; - auto lhsPair = helper.materializeCharacter(lhs); - auto rhsPair = helper.materializeCharacter(rhs); - return genRawCharCompare(converter, loc, cmp, lhsPair.first, lhsPair.second, - rhsPair.first, rhsPair.second); -} -- 2.7.4