1 //===-- Lower/CharacterExpr.h -- lowering of characters ---------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef FORTRAN_LOWER_CHARACTEREXPR_H 10 #define FORTRAN_LOWER_CHARACTEREXPR_H 11 12 #include "flang/Lower/FIRBuilder.h" 13 #include "flang/Lower/Support/BoxValue.h" 14 15 namespace Fortran::lower { 16 17 /// Helper to facilitate lowering of CHARACTER in FIR. 18 class CharacterExprHelper { 19 public: 20 /// Constructor. CharacterExprHelper(FirOpBuilder & builder,mlir::Location loc)21 explicit CharacterExprHelper(FirOpBuilder &builder, mlir::Location loc) 22 : builder{builder}, loc{loc} {} 23 CharacterExprHelper(const CharacterExprHelper &) = delete; 24 25 /// Unless otherwise stated, all mlir::Value inputs of these pseudo-fir ops 26 /// must be of type: 27 /// - fir.boxchar<kind> (dynamic length character), 28 /// - fir.ref<fir.array<len x fir.char<kind>>> (character with compile time 29 /// constant length), 30 /// - fir.array<len x fir.char<kind>> (compile time constant character) 31 32 /// Copy the \p count first characters of \p src into \p dest. 33 /// \p count can have any integer type. 34 void createCopy(mlir::Value dest, mlir::Value src, mlir::Value count); 35 36 /// Set characters of \p str at position [\p lower, \p upper) to blanks. 37 /// \p lower and \upper bounds are zero based. 38 /// If \p upper <= \p lower, no padding is done. 39 /// \p upper and \p lower can have any integer type. 40 void createPadding(mlir::Value str, mlir::Value lower, mlir::Value upper); 41 42 /// Create str(lb:ub), lower bounds must always be specified, upper 43 /// bound is optional. 44 mlir::Value createSubstring(mlir::Value str, 45 llvm::ArrayRef<mlir::Value> bounds); 46 47 /// Return blank character of given \p type !fir.char<kind> 48 mlir::Value createBlankConstant(fir::CharacterType type); 49 50 /// Lower \p lhs = \p rhs where \p lhs and \p rhs are scalar characters. 51 /// It handles cases where \p lhs and \p rhs may overlap. 52 void createAssign(mlir::Value lhs, mlir::Value rhs); 53 54 /// Lower an assignment where the buffer and LEN parameter are known and do 55 /// not need to be unboxed. 56 void createAssign(mlir::Value lptr, mlir::Value llen, mlir::Value rptr, 57 mlir::Value rlen); 58 59 /// Create lhs // rhs in temp obtained with fir.alloca 60 mlir::Value createConcatenate(mlir::Value lhs, mlir::Value rhs); 61 62 /// LEN_TRIM intrinsic. 63 mlir::Value createLenTrim(mlir::Value str); 64 65 /// Embox \p addr and \p len and return fir.boxchar. 66 /// Take care of type conversions before emboxing. 67 /// \p len is converted to the integer type for character lengths if needed. 68 mlir::Value createEmboxChar(mlir::Value addr, mlir::Value len); 69 70 /// Unbox \p boxchar into (fir.ref<fir.char<kind>>, getLengthType()). 71 std::pair<mlir::Value, mlir::Value> createUnboxChar(mlir::Value boxChar); 72 73 /// Allocate a temp of fir::CharacterType type and length len. 74 /// Returns related fir.ref<fir.char<kind>>. 75 mlir::Value createCharacterTemp(mlir::Type type, mlir::Value len); 76 77 /// Allocate a temp of compile time constant length. 78 /// Returns related fir.ref<fir.array<len x fir.char<kind>>>. createCharacterTemp(mlir::Type type,int len)79 mlir::Value createCharacterTemp(mlir::Type type, int len) { 80 return createTemp(type, len); 81 } 82 83 /// Return buffer/length pair of character str, if str is a constant, 84 /// it is allocated into a temp, otherwise, its memory reference is 85 /// returned as the buffer. 86 /// The buffer type of str is of type: 87 /// - fir.ref<fir.array<len x fir.char<kind>>> if str has compile time 88 /// constant length. 89 /// - fir.ref<fir.char<kind>> if str has dynamic length. 90 std::pair<mlir::Value, mlir::Value> materializeCharacter(mlir::Value str); 91 92 /// Return true if \p type is a character literal type (is 93 /// fir.array<len x fir.char<kind>>).; 94 static bool isCharacterLiteral(mlir::Type type); 95 96 /// Return true if \p type is one of the following type 97 /// - fir.boxchar<kind> 98 /// - fir.ref<fir.array<len x fir.char<kind>>> 99 /// - fir.array<len x fir.char<kind>> 100 static bool isCharacter(mlir::Type type); 101 102 /// Extract the kind of a character type 103 static int getCharacterKind(mlir::Type type); 104 105 /// Return the integer type that must be used to manipulate 106 /// Character lengths. TODO: move this to FirOpBuilder? getLengthType()107 mlir::Type getLengthType() { return builder.getIndexType(); } 108 109 /// Create an extended value from: 110 /// - fir.boxchar<kind> 111 /// - fir.ref<fir.array<len x fir.char<kind>>> 112 /// - fir.array<len x fir.char<kind>> 113 /// - fir.char<kind> 114 /// - fir.ref<char<kind>> 115 /// If the no length is passed, it is attempted to be extracted from \p 116 /// character (or its type). This will crash if this is not possible. 117 /// The returned value is a CharBoxValue if \p character is a scalar, 118 /// otherwise it is a CharArrayBoxValue. 119 fir::ExtendedValue toExtendedValue(mlir::Value character, 120 mlir::Value len = {}); 121 122 private: 123 fir::CharBoxValue materializeValue(const fir::CharBoxValue &str); 124 fir::CharBoxValue toDataLengthPair(mlir::Value character); 125 mlir::Type getReferenceType(const fir::CharBoxValue &c) const; 126 mlir::Value createEmbox(const fir::CharBoxValue &str); 127 mlir::Value createLoadCharAt(const fir::CharBoxValue &str, mlir::Value index); 128 void createStoreCharAt(const fir::CharBoxValue &str, mlir::Value index, 129 mlir::Value c); 130 void createCopy(const fir::CharBoxValue &dest, const fir::CharBoxValue &src, 131 mlir::Value count); 132 void createPadding(const fir::CharBoxValue &str, mlir::Value lower, 133 mlir::Value upper); 134 fir::CharBoxValue createTemp(mlir::Type type, mlir::Value len); 135 void createLengthOneAssign(const fir::CharBoxValue &lhs, 136 const fir::CharBoxValue &rhs); 137 void createAssign(const fir::CharBoxValue &lhs, const fir::CharBoxValue &rhs); 138 fir::CharBoxValue createConcatenate(const fir::CharBoxValue &lhs, 139 const fir::CharBoxValue &rhs); 140 fir::CharBoxValue createSubstring(const fir::CharBoxValue &str, 141 llvm::ArrayRef<mlir::Value> bounds); 142 mlir::Value createLenTrim(const fir::CharBoxValue &str); 143 mlir::Value createTemp(mlir::Type type, int len); 144 mlir::Value createBlankConstantCode(fir::CharacterType type); 145 146 private: 147 FirOpBuilder &builder; 148 mlir::Location loc; 149 }; 150 151 } // namespace Fortran::lower 152 153 #endif // FORTRAN_LOWER_CHARACTEREXPR_H 154