• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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