1 //===-- Optimizer/Support/KindMapping.h -- support kind mapping -*- 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 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef FORTRAN_OPTIMIZER_SUPPORT_KINDMAPPING_H
14 #define FORTRAN_OPTIMIZER_SUPPORT_KINDMAPPING_H
15 
16 #include "mlir/IR/OpDefinition.h"
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/IR/Type.h"
19 
20 namespace llvm {
21 struct fltSemantics;
22 } // namespace llvm
23 
24 namespace fir {
25 
26 /// The kind mapping is an encoded string that informs FIR how the Fortran KIND
27 /// values from the front-end should be converted to LLVM IR types.  This
28 /// encoding allows the mapping from front-end KIND values to backend LLVM IR
29 /// types to be customized by the front-end.
30 ///
31 /// The provided string uses the following syntax.
32 ///
33 ///   intrinsic-key `:` kind-value (`,` intrinsic-key `:` kind-value)*
34 ///
35 /// intrinsic-key is a single character for the intrinsic type.
36 ///   'i' : INTEGER   (size in bits)
37 ///   'l' : LOGICAL   (size in bits)
38 ///   'a' : CHARACTER (size in bits)
39 ///   'r' : REAL    (encoding value)
40 ///   'c' : COMPLEX (encoding value)
41 ///
42 /// kind-value is either an unsigned integer (for 'i', 'l', and 'a') or one of
43 /// 'Half', 'BFloat', 'Float', 'Double', 'X86_FP80', or 'FP128' (for 'r' and
44 /// 'c').
45 ///
46 /// If LLVM adds support for new floating-point types, the final list should be
47 /// extended.
48 class KindMapping {
49 public:
50   using KindTy = unsigned;
51   using Bitsize = unsigned;
52   using LLVMTypeID = llvm::Type::TypeID;
53   using MatchResult = mlir::ParseResult;
54 
55   /// KindMapping constructor with both the kind map and default kinds read from
56   /// command-line options.
57   explicit KindMapping(mlir::MLIRContext *context);
58   /// KindMapping constructor taking a `defs` argument to specify the default
59   /// kinds for intrinsic types. To set the default kinds, an ArrayRef of 6
60   /// KindTy must be passed. The kinds must be the given in the following order:
61   /// CHARACTER, COMPLEX, DOUBLE PRECISION, INTEGER, LOGICAL, and REAL.  The
62   /// kind map is read from command-line options, if given.
63   explicit KindMapping(mlir::MLIRContext *context, llvm::ArrayRef<KindTy> defs);
64   /// KindMapping constructor taking an optional `defs` argument to specify the
65   /// default kinds for intrinsic types. To set the default kinds, an ArrayRef
66   /// of 6 KindTy must be passed. The kinds must be the given in the following
67   /// order: CHARACTER, COMPLEX, DOUBLE PRECISION, INTEGER, LOGICAL, and REAL.
68   explicit KindMapping(mlir::MLIRContext *context, llvm::StringRef map,
69                        llvm::ArrayRef<KindTy> defs = llvm::None);
KindMapping(mlir::MLIRContext * context,llvm::StringRef map,llvm::StringRef defs)70   explicit KindMapping(mlir::MLIRContext *context, llvm::StringRef map,
71                        llvm::StringRef defs)
72       : KindMapping{context, map, toDefaultKinds(defs)} {}
73 
74   /// Get the size in bits of !fir.char<kind>
75   Bitsize getCharacterBitsize(KindTy kind) const;
76 
77   /// Get the size in bits of !fir.int<kind>
78   Bitsize getIntegerBitsize(KindTy kind) const;
79 
80   /// Get the size in bits of !fir.logical<kind>
81   Bitsize getLogicalBitsize(KindTy kind) const;
82 
83   /// Get the size in bits of !fir.real<kind>
84   Bitsize getRealBitsize(KindTy kind) const;
85 
86   /// Get the LLVM Type::TypeID of !fir.real<kind>
87   LLVMTypeID getRealTypeID(KindTy kind) const;
88 
89   /// Get the LLVM Type::TypeID of !fir.complex<kind>
90   LLVMTypeID getComplexTypeID(KindTy kind) const;
91 
getContext()92   mlir::MLIRContext *getContext() const { return context; }
93 
94   /// Get the float semantics of !fir.real<kind>
95   const llvm::fltSemantics &getFloatSemantics(KindTy kind) const;
96 
97   /// Get the default kind map as a string.
getDefaultMap()98   static constexpr const char *getDefaultMap() { return ""; }
99 
100   /// Convert the current kind map to a string.
101   std::string mapToString() const;
102 
103   //===--------------------------------------------------------------------===//
104   // Default kinds of intrinsic types
105   //===--------------------------------------------------------------------===//
106 
107   KindTy defaultCharacterKind() const;
108   KindTy defaultComplexKind() const;
109   KindTy defaultDoubleKind() const;
110   KindTy defaultIntegerKind() const;
111   KindTy defaultLogicalKind() const;
112   KindTy defaultRealKind() const;
113 
114   /// Get the default kinds as a string.
getDefaultKinds()115   static constexpr const char *getDefaultKinds() { return "a1c4d8i4l4r4"; }
116 
117   /// Convert the current default kinds to a string.
118   std::string defaultsToString() const;
119 
120   /// Translate a default kinds string into a default kind vector. This vector
121   /// can be passed to the KindMapping ctor.
122   static std::vector<KindTy> toDefaultKinds(llvm::StringRef defs);
123 
124 private:
125   MatchResult badMapString(const llvm::Twine &ptr);
126   MatchResult parse(llvm::StringRef kindMap);
127   mlir::LogicalResult setDefaultKinds(llvm::ArrayRef<KindTy> defs);
128 
129   mlir::MLIRContext *context;
130   llvm::DenseMap<std::pair<char, KindTy>, Bitsize> intMap;
131   llvm::DenseMap<std::pair<char, KindTy>, LLVMTypeID> floatMap;
132   llvm::DenseMap<char, KindTy> defaultMap;
133 };
134 
135 } // namespace fir
136 
137 #endif // FORTRAN_OPTIMIZER_SUPPORT_KINDMAPPING_H
138