xref: /llvm-project/flang/lib/Optimizer/Dialect/Support/KindMapping.cpp (revision db791b278a414fb6df1acc1799adcf11d8fb9169)
1b07ef9e7SRenaud-K //===-- KindMapping.cpp ---------------------------------------------------===//
2b07ef9e7SRenaud-K //
3b07ef9e7SRenaud-K // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b07ef9e7SRenaud-K // See https://llvm.org/LICENSE.txt for license information.
5b07ef9e7SRenaud-K // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b07ef9e7SRenaud-K //
7b07ef9e7SRenaud-K //===----------------------------------------------------------------------===//
8b07ef9e7SRenaud-K //
9b07ef9e7SRenaud-K // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10b07ef9e7SRenaud-K //
11b07ef9e7SRenaud-K //===----------------------------------------------------------------------===//
12b07ef9e7SRenaud-K 
13b07ef9e7SRenaud-K #include "flang/Optimizer/Dialect/Support/KindMapping.h"
14b07ef9e7SRenaud-K #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
15b07ef9e7SRenaud-K #include "llvm/Support/CommandLine.h"
16b07ef9e7SRenaud-K 
17b07ef9e7SRenaud-K /// Allow the user to set the FIR intrinsic type kind value to LLVM type
18b07ef9e7SRenaud-K /// mappings.  Note that these are not mappings from kind values to any
19b07ef9e7SRenaud-K /// other MLIR dialect, only to LLVM IR. The default values follow the f18
20b07ef9e7SRenaud-K /// front-end kind mappings.
21b07ef9e7SRenaud-K 
22b07ef9e7SRenaud-K using Bitsize = fir::KindMapping::Bitsize;
23b07ef9e7SRenaud-K using KindTy = fir::KindMapping::KindTy;
24b07ef9e7SRenaud-K using LLVMTypeID = fir::KindMapping::LLVMTypeID;
25b07ef9e7SRenaud-K using MatchResult = fir::KindMapping::MatchResult;
26b07ef9e7SRenaud-K 
27b07ef9e7SRenaud-K static llvm::cl::opt<std::string>
28b07ef9e7SRenaud-K     clKindMapping("kind-mapping",
29b07ef9e7SRenaud-K                   llvm::cl::desc("kind mapping string to set kind precision"),
30b07ef9e7SRenaud-K                   llvm::cl::value_desc("kind-mapping-string"),
31b07ef9e7SRenaud-K                   llvm::cl::init(fir::KindMapping::getDefaultMap()));
32b07ef9e7SRenaud-K 
33b07ef9e7SRenaud-K static llvm::cl::opt<std::string>
34b07ef9e7SRenaud-K     clDefaultKinds("default-kinds",
35b07ef9e7SRenaud-K                    llvm::cl::desc("string to set default kind values"),
36b07ef9e7SRenaud-K                    llvm::cl::value_desc("default-kind-string"),
37b07ef9e7SRenaud-K                    llvm::cl::init(fir::KindMapping::getDefaultKinds()));
38b07ef9e7SRenaud-K 
39b07ef9e7SRenaud-K // Keywords for the floating point types.
40b07ef9e7SRenaud-K 
41b07ef9e7SRenaud-K static constexpr const char *kwHalf = "Half";
42b07ef9e7SRenaud-K static constexpr const char *kwBFloat = "BFloat";
43b07ef9e7SRenaud-K static constexpr const char *kwFloat = "Float";
44b07ef9e7SRenaud-K static constexpr const char *kwDouble = "Double";
45b07ef9e7SRenaud-K static constexpr const char *kwX86FP80 = "X86_FP80";
46b07ef9e7SRenaud-K static constexpr const char *kwFP128 = "FP128";
47b07ef9e7SRenaud-K static constexpr const char *kwPPCFP128 = "PPC_FP128";
48b07ef9e7SRenaud-K 
49b07ef9e7SRenaud-K /// Integral types default to the kind value being the size of the value in
50b07ef9e7SRenaud-K /// bytes. The default is to scale from bytes to bits.
defaultScalingKind(KindTy kind)51b07ef9e7SRenaud-K static Bitsize defaultScalingKind(KindTy kind) {
52b07ef9e7SRenaud-K   const unsigned bitsInByte = 8;
53b07ef9e7SRenaud-K   return kind * bitsInByte;
54b07ef9e7SRenaud-K }
55b07ef9e7SRenaud-K 
56b07ef9e7SRenaud-K /// Floating-point types default to the kind value being the size of the value
57b07ef9e7SRenaud-K /// in bytes. The default is to translate kinds of 2, 3, 4, 8, 10, and 16 to a
58b07ef9e7SRenaud-K /// valid llvm::Type::TypeID value. Otherwise, the default is FloatTyID.
defaultRealKind(KindTy kind)59b07ef9e7SRenaud-K static LLVMTypeID defaultRealKind(KindTy kind) {
60b07ef9e7SRenaud-K   switch (kind) {
61b07ef9e7SRenaud-K   case 2:
62b07ef9e7SRenaud-K     return LLVMTypeID::HalfTyID;
63b07ef9e7SRenaud-K   case 3:
64b07ef9e7SRenaud-K     return LLVMTypeID::BFloatTyID;
65b07ef9e7SRenaud-K   case 4:
66b07ef9e7SRenaud-K     return LLVMTypeID::FloatTyID;
67b07ef9e7SRenaud-K   case 8:
68b07ef9e7SRenaud-K     return LLVMTypeID::DoubleTyID;
69b07ef9e7SRenaud-K   case 10:
70b07ef9e7SRenaud-K     return LLVMTypeID::X86_FP80TyID;
71b07ef9e7SRenaud-K   case 16:
72b07ef9e7SRenaud-K     return LLVMTypeID::FP128TyID;
73b07ef9e7SRenaud-K   default:
74b07ef9e7SRenaud-K     return LLVMTypeID::FloatTyID;
75b07ef9e7SRenaud-K   }
76b07ef9e7SRenaud-K }
77b07ef9e7SRenaud-K 
78b07ef9e7SRenaud-K // lookup the kind-value given the defaults, the mappings, and a KIND key
79b07ef9e7SRenaud-K template <typename RT, char KEY>
doLookup(std::function<RT (KindTy)> def,const llvm::DenseMap<std::pair<char,KindTy>,RT> & map,KindTy kind)80b07ef9e7SRenaud-K static RT doLookup(std::function<RT(KindTy)> def,
81b07ef9e7SRenaud-K                    const llvm::DenseMap<std::pair<char, KindTy>, RT> &map,
82b07ef9e7SRenaud-K                    KindTy kind) {
83b07ef9e7SRenaud-K   std::pair<char, KindTy> key{KEY, kind};
84b07ef9e7SRenaud-K   auto iter = map.find(key);
85b07ef9e7SRenaud-K   if (iter != map.end())
86b07ef9e7SRenaud-K     return iter->second;
87b07ef9e7SRenaud-K   return def(kind);
88b07ef9e7SRenaud-K }
89b07ef9e7SRenaud-K 
90b07ef9e7SRenaud-K // do a lookup for INTEGER, LOGICAL, or CHARACTER
91b07ef9e7SRenaud-K template <char KEY, typename MAP>
getIntegerLikeBitsize(KindTy kind,const MAP & map)92b07ef9e7SRenaud-K static Bitsize getIntegerLikeBitsize(KindTy kind, const MAP &map) {
93b07ef9e7SRenaud-K   return doLookup<Bitsize, KEY>(defaultScalingKind, map, kind);
94b07ef9e7SRenaud-K }
95b07ef9e7SRenaud-K 
96b07ef9e7SRenaud-K // do a lookup for REAL or COMPLEX
97b07ef9e7SRenaud-K template <char KEY, typename MAP>
getFloatLikeTypeID(KindTy kind,const MAP & map)98b07ef9e7SRenaud-K static LLVMTypeID getFloatLikeTypeID(KindTy kind, const MAP &map) {
99b07ef9e7SRenaud-K   return doLookup<LLVMTypeID, KEY>(defaultRealKind, map, kind);
100b07ef9e7SRenaud-K }
101b07ef9e7SRenaud-K 
102b07ef9e7SRenaud-K template <char KEY, typename MAP>
getFloatSemanticsOfKind(KindTy kind,const MAP & map)103b07ef9e7SRenaud-K static const llvm::fltSemantics &getFloatSemanticsOfKind(KindTy kind,
104b07ef9e7SRenaud-K                                                          const MAP &map) {
105b07ef9e7SRenaud-K   switch (doLookup<LLVMTypeID, KEY>(defaultRealKind, map, kind)) {
106b07ef9e7SRenaud-K   case LLVMTypeID::HalfTyID:
107b07ef9e7SRenaud-K     return llvm::APFloat::IEEEhalf();
108b07ef9e7SRenaud-K   case LLVMTypeID::BFloatTyID:
109b07ef9e7SRenaud-K     return llvm::APFloat::BFloat();
110b07ef9e7SRenaud-K   case LLVMTypeID::FloatTyID:
111b07ef9e7SRenaud-K     return llvm::APFloat::IEEEsingle();
112b07ef9e7SRenaud-K   case LLVMTypeID::DoubleTyID:
113b07ef9e7SRenaud-K     return llvm::APFloat::IEEEdouble();
114b07ef9e7SRenaud-K   case LLVMTypeID::X86_FP80TyID:
115b07ef9e7SRenaud-K     return llvm::APFloat::x87DoubleExtended();
116b07ef9e7SRenaud-K   case LLVMTypeID::FP128TyID:
117b07ef9e7SRenaud-K     return llvm::APFloat::IEEEquad();
118b07ef9e7SRenaud-K   case LLVMTypeID::PPC_FP128TyID:
119b07ef9e7SRenaud-K     return llvm::APFloat::PPCDoubleDouble();
120b07ef9e7SRenaud-K   default:
121b07ef9e7SRenaud-K     llvm_unreachable("Invalid floating type");
122b07ef9e7SRenaud-K   }
123b07ef9e7SRenaud-K }
124b07ef9e7SRenaud-K 
125b07ef9e7SRenaud-K /// Parse an intrinsic type code. The codes are ('a', CHARACTER), ('c',
126b07ef9e7SRenaud-K /// COMPLEX), ('i', INTEGER), ('l', LOGICAL), and ('r', REAL).
parseCode(char & code,const char * & ptr,const char * endPtr)127b07ef9e7SRenaud-K static MatchResult parseCode(char &code, const char *&ptr, const char *endPtr) {
128b07ef9e7SRenaud-K   if (ptr >= endPtr)
129b07ef9e7SRenaud-K     return mlir::failure();
130b07ef9e7SRenaud-K   if (*ptr != 'a' && *ptr != 'c' && *ptr != 'i' && *ptr != 'l' && *ptr != 'r')
131b07ef9e7SRenaud-K     return mlir::failure();
132b07ef9e7SRenaud-K   code = *ptr++;
133b07ef9e7SRenaud-K   return mlir::success();
134b07ef9e7SRenaud-K }
135b07ef9e7SRenaud-K 
136b07ef9e7SRenaud-K /// Same as `parseCode` but adds the ('d', DOUBLE PRECISION) code.
parseDefCode(char & code,const char * & ptr,const char * endPtr)137b07ef9e7SRenaud-K static MatchResult parseDefCode(char &code, const char *&ptr,
138b07ef9e7SRenaud-K                                 const char *endPtr) {
139b07ef9e7SRenaud-K   if (ptr >= endPtr)
140b07ef9e7SRenaud-K     return mlir::failure();
141b07ef9e7SRenaud-K   if (*ptr == 'd') {
142b07ef9e7SRenaud-K     code = *ptr++;
143b07ef9e7SRenaud-K     return mlir::success();
144b07ef9e7SRenaud-K   }
145b07ef9e7SRenaud-K   return parseCode(code, ptr, endPtr);
146b07ef9e7SRenaud-K }
147b07ef9e7SRenaud-K 
148b07ef9e7SRenaud-K template <char ch>
parseSingleChar(const char * & ptr,const char * endPtr)149b07ef9e7SRenaud-K static MatchResult parseSingleChar(const char *&ptr, const char *endPtr) {
150b07ef9e7SRenaud-K   if (ptr >= endPtr || *ptr != ch)
151b07ef9e7SRenaud-K     return mlir::failure();
152b07ef9e7SRenaud-K   ++ptr;
153b07ef9e7SRenaud-K   return mlir::success();
154b07ef9e7SRenaud-K }
155b07ef9e7SRenaud-K 
parseColon(const char * & ptr,const char * endPtr)156b07ef9e7SRenaud-K static MatchResult parseColon(const char *&ptr, const char *endPtr) {
157b07ef9e7SRenaud-K   return parseSingleChar<':'>(ptr, endPtr);
158b07ef9e7SRenaud-K }
159b07ef9e7SRenaud-K 
parseComma(const char * & ptr,const char * endPtr)160b07ef9e7SRenaud-K static MatchResult parseComma(const char *&ptr, const char *endPtr) {
161b07ef9e7SRenaud-K   return parseSingleChar<','>(ptr, endPtr);
162b07ef9e7SRenaud-K }
163b07ef9e7SRenaud-K 
164b07ef9e7SRenaud-K /// Recognize and parse an unsigned integer.
parseInt(unsigned & result,const char * & ptr,const char * endPtr)165b07ef9e7SRenaud-K static MatchResult parseInt(unsigned &result, const char *&ptr,
166b07ef9e7SRenaud-K                             const char *endPtr) {
167b07ef9e7SRenaud-K   const char *beg = ptr;
168b07ef9e7SRenaud-K   while (ptr < endPtr && *ptr >= '0' && *ptr <= '9')
169b07ef9e7SRenaud-K     ptr++;
170b07ef9e7SRenaud-K   if (beg == ptr)
171b07ef9e7SRenaud-K     return mlir::failure();
172b07ef9e7SRenaud-K   llvm::StringRef ref(beg, ptr - beg);
173b07ef9e7SRenaud-K   int temp;
174b07ef9e7SRenaud-K   if (ref.consumeInteger(10, temp))
175b07ef9e7SRenaud-K     return mlir::failure();
176b07ef9e7SRenaud-K   result = temp;
177b07ef9e7SRenaud-K   return mlir::success();
178b07ef9e7SRenaud-K }
179b07ef9e7SRenaud-K 
matchString(const char * & ptr,const char * endPtr,llvm::StringRef literal)180*db791b27SRamkumar Ramachandra static llvm::LogicalResult matchString(const char *&ptr, const char *endPtr,
181b07ef9e7SRenaud-K                                        llvm::StringRef literal) {
182b07ef9e7SRenaud-K   llvm::StringRef s(ptr, endPtr - ptr);
18311efcceaSKazu Hirata   if (s.starts_with(literal)) {
184b07ef9e7SRenaud-K     ptr += literal.size();
185b07ef9e7SRenaud-K     return mlir::success();
186b07ef9e7SRenaud-K   }
187b07ef9e7SRenaud-K   return mlir::failure();
188b07ef9e7SRenaud-K }
189b07ef9e7SRenaud-K 
190b07ef9e7SRenaud-K /// Recognize and parse the various floating-point keywords. These follow the
191b07ef9e7SRenaud-K /// LLVM naming convention.
parseTypeID(LLVMTypeID & result,const char * & ptr,const char * endPtr)192b07ef9e7SRenaud-K static MatchResult parseTypeID(LLVMTypeID &result, const char *&ptr,
193b07ef9e7SRenaud-K                                const char *endPtr) {
194b07ef9e7SRenaud-K   if (mlir::succeeded(matchString(ptr, endPtr, kwHalf))) {
195b07ef9e7SRenaud-K     result = LLVMTypeID::HalfTyID;
196b07ef9e7SRenaud-K     return mlir::success();
197b07ef9e7SRenaud-K   }
198b07ef9e7SRenaud-K   if (mlir::succeeded(matchString(ptr, endPtr, kwBFloat))) {
199b07ef9e7SRenaud-K     result = LLVMTypeID::BFloatTyID;
200b07ef9e7SRenaud-K     return mlir::success();
201b07ef9e7SRenaud-K   }
202b07ef9e7SRenaud-K   if (mlir::succeeded(matchString(ptr, endPtr, kwFloat))) {
203b07ef9e7SRenaud-K     result = LLVMTypeID::FloatTyID;
204b07ef9e7SRenaud-K     return mlir::success();
205b07ef9e7SRenaud-K   }
206b07ef9e7SRenaud-K   if (mlir::succeeded(matchString(ptr, endPtr, kwDouble))) {
207b07ef9e7SRenaud-K     result = LLVMTypeID::DoubleTyID;
208b07ef9e7SRenaud-K     return mlir::success();
209b07ef9e7SRenaud-K   }
210b07ef9e7SRenaud-K   if (mlir::succeeded(matchString(ptr, endPtr, kwX86FP80))) {
211b07ef9e7SRenaud-K     result = LLVMTypeID::X86_FP80TyID;
212b07ef9e7SRenaud-K     return mlir::success();
213b07ef9e7SRenaud-K   }
214b07ef9e7SRenaud-K   if (mlir::succeeded(matchString(ptr, endPtr, kwFP128))) {
215b07ef9e7SRenaud-K     result = LLVMTypeID::FP128TyID;
216b07ef9e7SRenaud-K     return mlir::success();
217b07ef9e7SRenaud-K   }
218b07ef9e7SRenaud-K   if (mlir::succeeded(matchString(ptr, endPtr, kwPPCFP128))) {
219b07ef9e7SRenaud-K     result = LLVMTypeID::PPC_FP128TyID;
220b07ef9e7SRenaud-K     return mlir::success();
221b07ef9e7SRenaud-K   }
222b07ef9e7SRenaud-K   return mlir::failure();
223b07ef9e7SRenaud-K }
224b07ef9e7SRenaud-K 
KindMapping(mlir::MLIRContext * context,llvm::StringRef map,llvm::ArrayRef<KindTy> defs)225b07ef9e7SRenaud-K fir::KindMapping::KindMapping(mlir::MLIRContext *context, llvm::StringRef map,
226b07ef9e7SRenaud-K                               llvm::ArrayRef<KindTy> defs)
227b07ef9e7SRenaud-K     : context{context} {
228b07ef9e7SRenaud-K   if (mlir::failed(setDefaultKinds(defs)))
229b07ef9e7SRenaud-K     llvm::report_fatal_error("bad default kinds");
230b07ef9e7SRenaud-K   if (mlir::failed(parse(map)))
231b07ef9e7SRenaud-K     llvm::report_fatal_error("could not parse kind map");
232b07ef9e7SRenaud-K }
233b07ef9e7SRenaud-K 
KindMapping(mlir::MLIRContext * context,llvm::ArrayRef<KindTy> defs)234b07ef9e7SRenaud-K fir::KindMapping::KindMapping(mlir::MLIRContext *context,
235b07ef9e7SRenaud-K                               llvm::ArrayRef<KindTy> defs)
236b07ef9e7SRenaud-K     : KindMapping{context, clKindMapping, defs} {}
237b07ef9e7SRenaud-K 
KindMapping(mlir::MLIRContext * context)238b07ef9e7SRenaud-K fir::KindMapping::KindMapping(mlir::MLIRContext *context)
239b07ef9e7SRenaud-K     : KindMapping{context, clKindMapping, clDefaultKinds} {}
240b07ef9e7SRenaud-K 
badMapString(const llvm::Twine & ptr)241b07ef9e7SRenaud-K MatchResult fir::KindMapping::badMapString(const llvm::Twine &ptr) {
242b07ef9e7SRenaud-K   auto unknown = mlir::UnknownLoc::get(context);
243b07ef9e7SRenaud-K   mlir::emitError(unknown, ptr);
244b07ef9e7SRenaud-K   return mlir::failure();
245b07ef9e7SRenaud-K }
246b07ef9e7SRenaud-K 
parse(llvm::StringRef kindMap)247b07ef9e7SRenaud-K MatchResult fir::KindMapping::parse(llvm::StringRef kindMap) {
248b07ef9e7SRenaud-K   if (kindMap.empty())
249b07ef9e7SRenaud-K     return mlir::success();
250b07ef9e7SRenaud-K   const char *srcPtr = kindMap.begin();
251b07ef9e7SRenaud-K   const char *endPtr = kindMap.end();
252b07ef9e7SRenaud-K   while (true) {
253b07ef9e7SRenaud-K     char code = '\0';
254b07ef9e7SRenaud-K     KindTy kind = 0;
255b07ef9e7SRenaud-K     if (parseCode(code, srcPtr, endPtr) || parseInt(kind, srcPtr, endPtr))
256b07ef9e7SRenaud-K       return badMapString(srcPtr);
257b07ef9e7SRenaud-K     if (code == 'a' || code == 'i' || code == 'l') {
258b07ef9e7SRenaud-K       Bitsize bits = 0;
259b07ef9e7SRenaud-K       if (parseColon(srcPtr, endPtr) || parseInt(bits, srcPtr, endPtr))
260b07ef9e7SRenaud-K         return badMapString(srcPtr);
261b07ef9e7SRenaud-K       intMap[std::pair<char, KindTy>{code, kind}] = bits;
262b07ef9e7SRenaud-K     } else if (code == 'r' || code == 'c') {
263b07ef9e7SRenaud-K       LLVMTypeID id{};
264b07ef9e7SRenaud-K       if (parseColon(srcPtr, endPtr) || parseTypeID(id, srcPtr, endPtr))
265b07ef9e7SRenaud-K         return badMapString(srcPtr);
266b07ef9e7SRenaud-K       floatMap[std::pair<char, KindTy>{code, kind}] = id;
267b07ef9e7SRenaud-K     } else {
268b07ef9e7SRenaud-K       return badMapString(srcPtr);
269b07ef9e7SRenaud-K     }
270b07ef9e7SRenaud-K     if (parseComma(srcPtr, endPtr))
271b07ef9e7SRenaud-K       break;
272b07ef9e7SRenaud-K   }
273b07ef9e7SRenaud-K   if (srcPtr > endPtr)
274b07ef9e7SRenaud-K     return badMapString(srcPtr);
275b07ef9e7SRenaud-K   return mlir::success();
276b07ef9e7SRenaud-K }
277b07ef9e7SRenaud-K 
getCharacterBitsize(KindTy kind) const278b07ef9e7SRenaud-K Bitsize fir::KindMapping::getCharacterBitsize(KindTy kind) const {
279b07ef9e7SRenaud-K   return getIntegerLikeBitsize<'a'>(kind, intMap);
280b07ef9e7SRenaud-K }
281b07ef9e7SRenaud-K 
getIntegerBitsize(KindTy kind) const282b07ef9e7SRenaud-K Bitsize fir::KindMapping::getIntegerBitsize(KindTy kind) const {
283b07ef9e7SRenaud-K   return getIntegerLikeBitsize<'i'>(kind, intMap);
284b07ef9e7SRenaud-K }
285b07ef9e7SRenaud-K 
getLogicalBitsize(KindTy kind) const286b07ef9e7SRenaud-K Bitsize fir::KindMapping::getLogicalBitsize(KindTy kind) const {
287b07ef9e7SRenaud-K   return getIntegerLikeBitsize<'l'>(kind, intMap);
288b07ef9e7SRenaud-K }
289b07ef9e7SRenaud-K 
getRealTypeID(KindTy kind) const290b07ef9e7SRenaud-K LLVMTypeID fir::KindMapping::getRealTypeID(KindTy kind) const {
291b07ef9e7SRenaud-K   return getFloatLikeTypeID<'r'>(kind, floatMap);
292b07ef9e7SRenaud-K }
293b07ef9e7SRenaud-K 
getComplexTypeID(KindTy kind) const294b07ef9e7SRenaud-K LLVMTypeID fir::KindMapping::getComplexTypeID(KindTy kind) const {
295b07ef9e7SRenaud-K   return getFloatLikeTypeID<'c'>(kind, floatMap);
296b07ef9e7SRenaud-K }
297b07ef9e7SRenaud-K 
getRealBitsize(KindTy kind) const298b07ef9e7SRenaud-K Bitsize fir::KindMapping::getRealBitsize(KindTy kind) const {
299b07ef9e7SRenaud-K   auto typeId = getFloatLikeTypeID<'r'>(kind, floatMap);
300b07ef9e7SRenaud-K   llvm::LLVMContext llCtxt; // FIXME
301b07ef9e7SRenaud-K   return llvm::Type::getPrimitiveType(llCtxt, typeId)->getPrimitiveSizeInBits();
302b07ef9e7SRenaud-K }
303b07ef9e7SRenaud-K 
304b07ef9e7SRenaud-K const llvm::fltSemantics &
getFloatSemantics(KindTy kind) const305b07ef9e7SRenaud-K fir::KindMapping::getFloatSemantics(KindTy kind) const {
306b07ef9e7SRenaud-K   return getFloatSemanticsOfKind<'r'>(kind, floatMap);
307b07ef9e7SRenaud-K }
308b07ef9e7SRenaud-K 
mapToString() const309b07ef9e7SRenaud-K std::string fir::KindMapping::mapToString() const {
310b07ef9e7SRenaud-K   std::string result;
311b07ef9e7SRenaud-K   bool addComma = false;
312b07ef9e7SRenaud-K   for (auto [k, v] : intMap) {
313b07ef9e7SRenaud-K     if (addComma)
314b07ef9e7SRenaud-K       result.append(",");
315b07ef9e7SRenaud-K     else
316b07ef9e7SRenaud-K       addComma = true;
317b07ef9e7SRenaud-K     result += k.first + std::to_string(k.second) + ":" + std::to_string(v);
318b07ef9e7SRenaud-K   }
319b07ef9e7SRenaud-K   for (auto [k, v] : floatMap) {
320b07ef9e7SRenaud-K     if (addComma)
321b07ef9e7SRenaud-K       result.append(",");
322b07ef9e7SRenaud-K     else
323b07ef9e7SRenaud-K       addComma = true;
324b07ef9e7SRenaud-K     result.append(k.first + std::to_string(k.second) + ":");
325b07ef9e7SRenaud-K     switch (v) {
326b07ef9e7SRenaud-K     default:
327b07ef9e7SRenaud-K       llvm_unreachable("unhandled type-id");
328b07ef9e7SRenaud-K     case LLVMTypeID::HalfTyID:
329b07ef9e7SRenaud-K       result.append(kwHalf);
330b07ef9e7SRenaud-K       break;
331b07ef9e7SRenaud-K     case LLVMTypeID::BFloatTyID:
332b07ef9e7SRenaud-K       result.append(kwBFloat);
333b07ef9e7SRenaud-K       break;
334b07ef9e7SRenaud-K     case LLVMTypeID::FloatTyID:
335b07ef9e7SRenaud-K       result.append(kwFloat);
336b07ef9e7SRenaud-K       break;
337b07ef9e7SRenaud-K     case LLVMTypeID::DoubleTyID:
338b07ef9e7SRenaud-K       result.append(kwDouble);
339b07ef9e7SRenaud-K       break;
340b07ef9e7SRenaud-K     case LLVMTypeID::X86_FP80TyID:
341b07ef9e7SRenaud-K       result.append(kwX86FP80);
342b07ef9e7SRenaud-K       break;
343b07ef9e7SRenaud-K     case LLVMTypeID::FP128TyID:
344b07ef9e7SRenaud-K       result.append(kwFP128);
345b07ef9e7SRenaud-K       break;
346b07ef9e7SRenaud-K     case LLVMTypeID::PPC_FP128TyID:
347b07ef9e7SRenaud-K       result.append(kwPPCFP128);
348b07ef9e7SRenaud-K       break;
349b07ef9e7SRenaud-K     }
350b07ef9e7SRenaud-K   }
351b07ef9e7SRenaud-K   return result;
352b07ef9e7SRenaud-K }
353b07ef9e7SRenaud-K 
354*db791b27SRamkumar Ramachandra llvm::LogicalResult
setDefaultKinds(llvm::ArrayRef<KindTy> defs)355b07ef9e7SRenaud-K fir::KindMapping::setDefaultKinds(llvm::ArrayRef<KindTy> defs) {
356b07ef9e7SRenaud-K   if (defs.empty()) {
357b07ef9e7SRenaud-K     // generic front-end defaults
358b07ef9e7SRenaud-K     const KindTy genericKind = 4;
359b07ef9e7SRenaud-K     defaultMap.insert({'a', 1});
360b07ef9e7SRenaud-K     defaultMap.insert({'c', genericKind});
361b07ef9e7SRenaud-K     defaultMap.insert({'d', 2 * genericKind});
362b07ef9e7SRenaud-K     defaultMap.insert({'i', genericKind});
363b07ef9e7SRenaud-K     defaultMap.insert({'l', genericKind});
364b07ef9e7SRenaud-K     defaultMap.insert({'r', genericKind});
365b07ef9e7SRenaud-K     return mlir::success();
366b07ef9e7SRenaud-K   }
367b07ef9e7SRenaud-K   if (defs.size() != 6)
368b07ef9e7SRenaud-K     return mlir::failure();
369b07ef9e7SRenaud-K 
370b07ef9e7SRenaud-K   // defaults determined after command-line processing
371b07ef9e7SRenaud-K   defaultMap.insert({'a', defs[0]});
372b07ef9e7SRenaud-K   defaultMap.insert({'c', defs[1]});
373b07ef9e7SRenaud-K   defaultMap.insert({'d', defs[2]});
374b07ef9e7SRenaud-K   defaultMap.insert({'i', defs[3]});
375b07ef9e7SRenaud-K   defaultMap.insert({'l', defs[4]});
376b07ef9e7SRenaud-K   defaultMap.insert({'r', defs[5]});
377b07ef9e7SRenaud-K   return mlir::success();
378b07ef9e7SRenaud-K }
379b07ef9e7SRenaud-K 
defaultsToString() const380b07ef9e7SRenaud-K std::string fir::KindMapping::defaultsToString() const {
381b07ef9e7SRenaud-K   return std::string("a") + std::to_string(defaultMap.find('a')->second) +
382b07ef9e7SRenaud-K          std::string("c") + std::to_string(defaultMap.find('c')->second) +
383b07ef9e7SRenaud-K          std::string("d") + std::to_string(defaultMap.find('d')->second) +
384b07ef9e7SRenaud-K          std::string("i") + std::to_string(defaultMap.find('i')->second) +
385b07ef9e7SRenaud-K          std::string("l") + std::to_string(defaultMap.find('l')->second) +
386b07ef9e7SRenaud-K          std::string("r") + std::to_string(defaultMap.find('r')->second);
387b07ef9e7SRenaud-K }
388b07ef9e7SRenaud-K 
389b07ef9e7SRenaud-K /// Convert a default intrinsic code into the proper position in the array. The
390b07ef9e7SRenaud-K /// default kinds have a precise ordering.
codeToIndex(char code)391b07ef9e7SRenaud-K static int codeToIndex(char code) {
392b07ef9e7SRenaud-K   switch (code) {
393b07ef9e7SRenaud-K   case 'a':
394b07ef9e7SRenaud-K     return 0;
395b07ef9e7SRenaud-K   case 'c':
396b07ef9e7SRenaud-K     return 1;
397b07ef9e7SRenaud-K   case 'd':
398b07ef9e7SRenaud-K     return 2;
399b07ef9e7SRenaud-K   case 'i':
400b07ef9e7SRenaud-K     return 3;
401b07ef9e7SRenaud-K   case 'l':
402b07ef9e7SRenaud-K     return 4;
403b07ef9e7SRenaud-K   case 'r':
404b07ef9e7SRenaud-K     return 5;
405b07ef9e7SRenaud-K   }
406b07ef9e7SRenaud-K   llvm_unreachable("invalid default kind intrinsic code");
407b07ef9e7SRenaud-K }
408b07ef9e7SRenaud-K 
toDefaultKinds(llvm::StringRef defs)409b07ef9e7SRenaud-K std::vector<KindTy> fir::KindMapping::toDefaultKinds(llvm::StringRef defs) {
410b07ef9e7SRenaud-K   std::vector<KindTy> result(6);
411b07ef9e7SRenaud-K   char code;
412b07ef9e7SRenaud-K   KindTy kind;
413b07ef9e7SRenaud-K   if (defs.empty())
414b07ef9e7SRenaud-K     defs = clDefaultKinds;
415b07ef9e7SRenaud-K   const char *srcPtr = defs.begin();
416b07ef9e7SRenaud-K   const char *endPtr = defs.end();
417b07ef9e7SRenaud-K   while (srcPtr < endPtr) {
418b07ef9e7SRenaud-K     if (parseDefCode(code, srcPtr, endPtr) || parseInt(kind, srcPtr, endPtr))
419b07ef9e7SRenaud-K       llvm::report_fatal_error("invalid default kind code");
420b07ef9e7SRenaud-K     result[codeToIndex(code)] = kind;
421b07ef9e7SRenaud-K   }
422b07ef9e7SRenaud-K   assert(srcPtr == endPtr);
423b07ef9e7SRenaud-K   return result;
424b07ef9e7SRenaud-K }
425b07ef9e7SRenaud-K 
defaultCharacterKind() const426b07ef9e7SRenaud-K KindTy fir::KindMapping::defaultCharacterKind() const {
427b07ef9e7SRenaud-K   auto iter = defaultMap.find('a');
428b07ef9e7SRenaud-K   assert(iter != defaultMap.end());
429b07ef9e7SRenaud-K   return iter->second;
430b07ef9e7SRenaud-K }
431b07ef9e7SRenaud-K 
defaultComplexKind() const432b07ef9e7SRenaud-K KindTy fir::KindMapping::defaultComplexKind() const {
433b07ef9e7SRenaud-K   auto iter = defaultMap.find('c');
434b07ef9e7SRenaud-K   assert(iter != defaultMap.end());
435b07ef9e7SRenaud-K   return iter->second;
436b07ef9e7SRenaud-K }
437b07ef9e7SRenaud-K 
defaultDoubleKind() const438b07ef9e7SRenaud-K KindTy fir::KindMapping::defaultDoubleKind() const {
439b07ef9e7SRenaud-K   auto iter = defaultMap.find('d');
440b07ef9e7SRenaud-K   assert(iter != defaultMap.end());
441b07ef9e7SRenaud-K   return iter->second;
442b07ef9e7SRenaud-K }
443b07ef9e7SRenaud-K 
defaultIntegerKind() const444b07ef9e7SRenaud-K KindTy fir::KindMapping::defaultIntegerKind() const {
445b07ef9e7SRenaud-K   auto iter = defaultMap.find('i');
446b07ef9e7SRenaud-K   assert(iter != defaultMap.end());
447b07ef9e7SRenaud-K   return iter->second;
448b07ef9e7SRenaud-K }
449b07ef9e7SRenaud-K 
defaultLogicalKind() const450b07ef9e7SRenaud-K KindTy fir::KindMapping::defaultLogicalKind() const {
451b07ef9e7SRenaud-K   auto iter = defaultMap.find('l');
452b07ef9e7SRenaud-K   assert(iter != defaultMap.end());
453b07ef9e7SRenaud-K   return iter->second;
454b07ef9e7SRenaud-K }
455b07ef9e7SRenaud-K 
defaultRealKind() const456b07ef9e7SRenaud-K KindTy fir::KindMapping::defaultRealKind() const {
457b07ef9e7SRenaud-K   auto iter = defaultMap.find('r');
458b07ef9e7SRenaud-K   assert(iter != defaultMap.end());
459b07ef9e7SRenaud-K   return iter->second;
460b07ef9e7SRenaud-K }
461