157f536a4SjeanPerier //===-- KindMapping.cpp ---------------------------------------------------===//
257f536a4SjeanPerier //
357f536a4SjeanPerier // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457f536a4SjeanPerier // See https://llvm.org/LICENSE.txt for license information.
557f536a4SjeanPerier // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
657f536a4SjeanPerier //
757f536a4SjeanPerier //===----------------------------------------------------------------------===//
84dc87d10SEric Schweitz //
94dc87d10SEric Schweitz // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
104dc87d10SEric Schweitz //
114dc87d10SEric Schweitz //===----------------------------------------------------------------------===//
1257f536a4SjeanPerier 
1357f536a4SjeanPerier #include "flang/Optimizer/Support/KindMapping.h"
1457f536a4SjeanPerier #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
1557f536a4SjeanPerier #include "llvm/Support/CommandLine.h"
1657f536a4SjeanPerier 
1757f536a4SjeanPerier /// Allow the user to set the FIR intrinsic type kind value to LLVM type
1857f536a4SjeanPerier /// mappings.  Note that these are not mappings from kind values to any
1957f536a4SjeanPerier /// other MLIR dialect, only to LLVM IR. The default values follow the f18
2057f536a4SjeanPerier /// front-end kind mappings.
2157f536a4SjeanPerier 
2257f536a4SjeanPerier using Bitsize = fir::KindMapping::Bitsize;
2357f536a4SjeanPerier using KindTy = fir::KindMapping::KindTy;
2457f536a4SjeanPerier using LLVMTypeID = fir::KindMapping::LLVMTypeID;
2557f536a4SjeanPerier using MatchResult = fir::KindMapping::MatchResult;
2657f536a4SjeanPerier 
27c68d2895SEric Schweitz static llvm::cl::opt<std::string>
28c68d2895SEric Schweitz     clKindMapping("kind-mapping",
29c68d2895SEric Schweitz                   llvm::cl::desc("kind mapping string to set kind precision"),
30c68d2895SEric Schweitz                   llvm::cl::value_desc("kind-mapping-string"),
31c68d2895SEric Schweitz                   llvm::cl::init(fir::KindMapping::getDefaultMap()));
32c68d2895SEric Schweitz 
33c68d2895SEric Schweitz static llvm::cl::opt<std::string>
34c68d2895SEric Schweitz     clDefaultKinds("default-kinds",
35c68d2895SEric Schweitz                    llvm::cl::desc("string to set default kind values"),
36c68d2895SEric Schweitz                    llvm::cl::value_desc("default-kind-string"),
37c68d2895SEric Schweitz                    llvm::cl::init(fir::KindMapping::getDefaultKinds()));
38c68d2895SEric Schweitz 
39c68d2895SEric Schweitz // Keywords for the floating point types.
40c68d2895SEric Schweitz 
41c68d2895SEric Schweitz static constexpr const char *kwHalf = "Half";
42c68d2895SEric Schweitz static constexpr const char *kwBFloat = "BFloat";
43c68d2895SEric Schweitz static constexpr const char *kwFloat = "Float";
44c68d2895SEric Schweitz static constexpr const char *kwDouble = "Double";
45c68d2895SEric Schweitz static constexpr const char *kwX86FP80 = "X86_FP80";
46c68d2895SEric Schweitz static constexpr const char *kwFP128 = "FP128";
47c68d2895SEric Schweitz static constexpr const char *kwPPCFP128 = "PPC_FP128";
4857f536a4SjeanPerier 
4957f536a4SjeanPerier /// Integral types default to the kind value being the size of the value in
5057f536a4SjeanPerier /// bytes. The default is to scale from bytes to bits.
defaultScalingKind(KindTy kind)5157f536a4SjeanPerier static Bitsize defaultScalingKind(KindTy kind) {
521e96c4b5SValentin Clement   const unsigned bitsInByte = 8;
531e96c4b5SValentin Clement   return kind * bitsInByte;
5457f536a4SjeanPerier }
5557f536a4SjeanPerier 
5657f536a4SjeanPerier /// Floating-point types default to the kind value being the size of the value
574dc87d10SEric Schweitz /// in bytes. The default is to translate kinds of 2, 3, 4, 8, 10, and 16 to a
5857f536a4SjeanPerier /// valid llvm::Type::TypeID value. Otherwise, the default is FloatTyID.
defaultRealKind(KindTy kind)5957f536a4SjeanPerier static LLVMTypeID defaultRealKind(KindTy kind) {
6057f536a4SjeanPerier   switch (kind) {
6157f536a4SjeanPerier   case 2:
6257f536a4SjeanPerier     return LLVMTypeID::HalfTyID;
634dc87d10SEric Schweitz   case 3:
644dc87d10SEric Schweitz     return LLVMTypeID::BFloatTyID;
6557f536a4SjeanPerier   case 4:
6657f536a4SjeanPerier     return LLVMTypeID::FloatTyID;
6757f536a4SjeanPerier   case 8:
6857f536a4SjeanPerier     return LLVMTypeID::DoubleTyID;
6957f536a4SjeanPerier   case 10:
7057f536a4SjeanPerier     return LLVMTypeID::X86_FP80TyID;
7157f536a4SjeanPerier   case 16:
7257f536a4SjeanPerier     return LLVMTypeID::FP128TyID;
7357f536a4SjeanPerier   default:
7457f536a4SjeanPerier     return LLVMTypeID::FloatTyID;
7557f536a4SjeanPerier   }
7657f536a4SjeanPerier }
7757f536a4SjeanPerier 
7857f536a4SjeanPerier // lookup the kind-value given the defaults, the mappings, and a KIND key
7957f536a4SjeanPerier template <typename RT, char KEY>
doLookup(std::function<RT (KindTy)> def,const llvm::DenseMap<std::pair<char,KindTy>,RT> & map,KindTy kind)8057f536a4SjeanPerier static RT doLookup(std::function<RT(KindTy)> def,
8157f536a4SjeanPerier                    const llvm::DenseMap<std::pair<char, KindTy>, RT> &map,
8257f536a4SjeanPerier                    KindTy kind) {
8357f536a4SjeanPerier   std::pair<char, KindTy> key{KEY, kind};
8457f536a4SjeanPerier   auto iter = map.find(key);
8557f536a4SjeanPerier   if (iter != map.end())
8657f536a4SjeanPerier     return iter->second;
8757f536a4SjeanPerier   return def(kind);
8857f536a4SjeanPerier }
8957f536a4SjeanPerier 
90*f29f86b6SShao-Ce SUN // do a lookup for INTEGER, LOGICAL, or CHARACTER
9157f536a4SjeanPerier template <char KEY, typename MAP>
getIntegerLikeBitsize(KindTy kind,const MAP & map)9257f536a4SjeanPerier static Bitsize getIntegerLikeBitsize(KindTy kind, const MAP &map) {
9357f536a4SjeanPerier   return doLookup<Bitsize, KEY>(defaultScalingKind, map, kind);
9457f536a4SjeanPerier }
9557f536a4SjeanPerier 
9657f536a4SjeanPerier // do a lookup for REAL or COMPLEX
9757f536a4SjeanPerier template <char KEY, typename MAP>
getFloatLikeTypeID(KindTy kind,const MAP & map)9857f536a4SjeanPerier static LLVMTypeID getFloatLikeTypeID(KindTy kind, const MAP &map) {
9957f536a4SjeanPerier   return doLookup<LLVMTypeID, KEY>(defaultRealKind, map, kind);
10057f536a4SjeanPerier }
10157f536a4SjeanPerier 
10257f536a4SjeanPerier template <char KEY, typename MAP>
getFloatSemanticsOfKind(KindTy kind,const MAP & map)10357f536a4SjeanPerier static const llvm::fltSemantics &getFloatSemanticsOfKind(KindTy kind,
10457f536a4SjeanPerier                                                          const MAP &map) {
10557f536a4SjeanPerier   switch (doLookup<LLVMTypeID, KEY>(defaultRealKind, map, kind)) {
10657f536a4SjeanPerier   case LLVMTypeID::HalfTyID:
10757f536a4SjeanPerier     return llvm::APFloat::IEEEhalf();
1084dc87d10SEric Schweitz   case LLVMTypeID::BFloatTyID:
1094dc87d10SEric Schweitz     return llvm::APFloat::BFloat();
11057f536a4SjeanPerier   case LLVMTypeID::FloatTyID:
11157f536a4SjeanPerier     return llvm::APFloat::IEEEsingle();
11257f536a4SjeanPerier   case LLVMTypeID::DoubleTyID:
11357f536a4SjeanPerier     return llvm::APFloat::IEEEdouble();
11457f536a4SjeanPerier   case LLVMTypeID::X86_FP80TyID:
11557f536a4SjeanPerier     return llvm::APFloat::x87DoubleExtended();
11657f536a4SjeanPerier   case LLVMTypeID::FP128TyID:
11757f536a4SjeanPerier     return llvm::APFloat::IEEEquad();
11857f536a4SjeanPerier   case LLVMTypeID::PPC_FP128TyID:
11957f536a4SjeanPerier     return llvm::APFloat::PPCDoubleDouble();
12057f536a4SjeanPerier   default:
12157f536a4SjeanPerier     llvm_unreachable("Invalid floating type");
12257f536a4SjeanPerier   }
12357f536a4SjeanPerier }
12457f536a4SjeanPerier 
125c68d2895SEric Schweitz /// Parse an intrinsic type code. The codes are ('a', CHARACTER), ('c',
126c68d2895SEric Schweitz /// COMPLEX), ('i', INTEGER), ('l', LOGICAL), and ('r', REAL).
parseCode(char & code,const char * & ptr,const char * endPtr)127c68d2895SEric Schweitz static MatchResult parseCode(char &code, const char *&ptr, const char *endPtr) {
128c68d2895SEric Schweitz   if (ptr >= endPtr)
129c68d2895SEric Schweitz     return mlir::failure();
13057f536a4SjeanPerier   if (*ptr != 'a' && *ptr != 'c' && *ptr != 'i' && *ptr != 'l' && *ptr != 'r')
13157f536a4SjeanPerier     return mlir::failure();
13257f536a4SjeanPerier   code = *ptr++;
13357f536a4SjeanPerier   return mlir::success();
13457f536a4SjeanPerier }
13557f536a4SjeanPerier 
136c68d2895SEric Schweitz /// Same as `parseCode` but adds the ('d', DOUBLE PRECISION) code.
parseDefCode(char & code,const char * & ptr,const char * endPtr)137c68d2895SEric Schweitz static MatchResult parseDefCode(char &code, const char *&ptr,
138c68d2895SEric Schweitz                                 const char *endPtr) {
139c68d2895SEric Schweitz   if (ptr >= endPtr)
140c68d2895SEric Schweitz     return mlir::failure();
141c68d2895SEric Schweitz   if (*ptr == 'd') {
142c68d2895SEric Schweitz     code = *ptr++;
143c68d2895SEric Schweitz     return mlir::success();
144c68d2895SEric Schweitz   }
145c68d2895SEric Schweitz   return parseCode(code, ptr, endPtr);
146c68d2895SEric Schweitz }
147c68d2895SEric Schweitz 
14857f536a4SjeanPerier template <char ch>
parseSingleChar(const char * & ptr,const char * endPtr)149c68d2895SEric Schweitz static MatchResult parseSingleChar(const char *&ptr, const char *endPtr) {
150c68d2895SEric Schweitz   if (ptr >= endPtr || *ptr != ch)
15157f536a4SjeanPerier     return mlir::failure();
15257f536a4SjeanPerier   ++ptr;
15357f536a4SjeanPerier   return mlir::success();
15457f536a4SjeanPerier }
15557f536a4SjeanPerier 
parseColon(const char * & ptr,const char * endPtr)156c68d2895SEric Schweitz static MatchResult parseColon(const char *&ptr, const char *endPtr) {
157c68d2895SEric Schweitz   return parseSingleChar<':'>(ptr, endPtr);
15857f536a4SjeanPerier }
15957f536a4SjeanPerier 
parseComma(const char * & ptr,const char * endPtr)160c68d2895SEric Schweitz static MatchResult parseComma(const char *&ptr, const char *endPtr) {
161c68d2895SEric Schweitz   return parseSingleChar<','>(ptr, endPtr);
16257f536a4SjeanPerier }
16357f536a4SjeanPerier 
164c68d2895SEric Schweitz /// Recognize and parse an unsigned integer.
parseInt(unsigned & result,const char * & ptr,const char * endPtr)165c68d2895SEric Schweitz static MatchResult parseInt(unsigned &result, const char *&ptr,
166c68d2895SEric Schweitz                             const char *endPtr) {
16757f536a4SjeanPerier   const char *beg = ptr;
168c68d2895SEric Schweitz   while (ptr < endPtr && *ptr >= '0' && *ptr <= '9')
16957f536a4SjeanPerier     ptr++;
17057f536a4SjeanPerier   if (beg == ptr)
17157f536a4SjeanPerier     return mlir::failure();
17257f536a4SjeanPerier   llvm::StringRef ref(beg, ptr - beg);
17357f536a4SjeanPerier   int temp;
17457f536a4SjeanPerier   if (ref.consumeInteger(10, temp))
17557f536a4SjeanPerier     return mlir::failure();
17657f536a4SjeanPerier   result = temp;
17757f536a4SjeanPerier   return mlir::success();
17857f536a4SjeanPerier }
17957f536a4SjeanPerier 
matchString(const char * & ptr,const char * endPtr,llvm::StringRef literal)180c68d2895SEric Schweitz static mlir::LogicalResult matchString(const char *&ptr, const char *endPtr,
18157f536a4SjeanPerier                                        llvm::StringRef literal) {
182c68d2895SEric Schweitz   llvm::StringRef s(ptr, endPtr - ptr);
18357f536a4SjeanPerier   if (s.startswith(literal)) {
18457f536a4SjeanPerier     ptr += literal.size();
18557f536a4SjeanPerier     return mlir::success();
18657f536a4SjeanPerier   }
18757f536a4SjeanPerier   return mlir::failure();
18857f536a4SjeanPerier }
18957f536a4SjeanPerier 
190c68d2895SEric Schweitz /// Recognize and parse the various floating-point keywords. These follow the
191c68d2895SEric Schweitz /// LLVM naming convention.
parseTypeID(LLVMTypeID & result,const char * & ptr,const char * endPtr)192c68d2895SEric Schweitz static MatchResult parseTypeID(LLVMTypeID &result, const char *&ptr,
193c68d2895SEric Schweitz                                const char *endPtr) {
194c68d2895SEric Schweitz   if (mlir::succeeded(matchString(ptr, endPtr, kwHalf))) {
19557f536a4SjeanPerier     result = LLVMTypeID::HalfTyID;
19657f536a4SjeanPerier     return mlir::success();
19757f536a4SjeanPerier   }
198c68d2895SEric Schweitz   if (mlir::succeeded(matchString(ptr, endPtr, kwBFloat))) {
1994dc87d10SEric Schweitz     result = LLVMTypeID::BFloatTyID;
2004dc87d10SEric Schweitz     return mlir::success();
2014dc87d10SEric Schweitz   }
202c68d2895SEric Schweitz   if (mlir::succeeded(matchString(ptr, endPtr, kwFloat))) {
20357f536a4SjeanPerier     result = LLVMTypeID::FloatTyID;
20457f536a4SjeanPerier     return mlir::success();
20557f536a4SjeanPerier   }
206c68d2895SEric Schweitz   if (mlir::succeeded(matchString(ptr, endPtr, kwDouble))) {
20757f536a4SjeanPerier     result = LLVMTypeID::DoubleTyID;
20857f536a4SjeanPerier     return mlir::success();
20957f536a4SjeanPerier   }
210c68d2895SEric Schweitz   if (mlir::succeeded(matchString(ptr, endPtr, kwX86FP80))) {
21157f536a4SjeanPerier     result = LLVMTypeID::X86_FP80TyID;
21257f536a4SjeanPerier     return mlir::success();
21357f536a4SjeanPerier   }
214c68d2895SEric Schweitz   if (mlir::succeeded(matchString(ptr, endPtr, kwFP128))) {
21557f536a4SjeanPerier     result = LLVMTypeID::FP128TyID;
21657f536a4SjeanPerier     return mlir::success();
21757f536a4SjeanPerier   }
218c68d2895SEric Schweitz   if (mlir::succeeded(matchString(ptr, endPtr, kwPPCFP128))) {
21957f536a4SjeanPerier     result = LLVMTypeID::PPC_FP128TyID;
22057f536a4SjeanPerier     return mlir::success();
22157f536a4SjeanPerier   }
22257f536a4SjeanPerier   return mlir::failure();
22357f536a4SjeanPerier }
22457f536a4SjeanPerier 
KindMapping(mlir::MLIRContext * context,llvm::StringRef map,llvm::ArrayRef<KindTy> defs)2254dc87d10SEric Schweitz fir::KindMapping::KindMapping(mlir::MLIRContext *context, llvm::StringRef map,
2264dc87d10SEric Schweitz                               llvm::ArrayRef<KindTy> defs)
22757f536a4SjeanPerier     : context{context} {
2284dc87d10SEric Schweitz   if (mlir::failed(setDefaultKinds(defs)))
2294dc87d10SEric Schweitz     llvm::report_fatal_error("bad default kinds");
2304dc87d10SEric Schweitz   if (mlir::failed(parse(map)))
2314dc87d10SEric Schweitz     llvm::report_fatal_error("could not parse kind map");
23257f536a4SjeanPerier }
23357f536a4SjeanPerier 
KindMapping(mlir::MLIRContext * context,llvm::ArrayRef<KindTy> defs)2344dc87d10SEric Schweitz fir::KindMapping::KindMapping(mlir::MLIRContext *context,
2354dc87d10SEric Schweitz                               llvm::ArrayRef<KindTy> defs)
2364dc87d10SEric Schweitz     : KindMapping{context, clKindMapping, defs} {}
23757f536a4SjeanPerier 
KindMapping(mlir::MLIRContext * context)238c68d2895SEric Schweitz fir::KindMapping::KindMapping(mlir::MLIRContext *context)
239c68d2895SEric Schweitz     : KindMapping{context, clKindMapping, clDefaultKinds} {}
240c68d2895SEric Schweitz 
badMapString(const llvm::Twine & ptr)24157f536a4SjeanPerier MatchResult fir::KindMapping::badMapString(const llvm::Twine &ptr) {
24257f536a4SjeanPerier   auto unknown = mlir::UnknownLoc::get(context);
24357f536a4SjeanPerier   mlir::emitError(unknown, ptr);
24457f536a4SjeanPerier   return mlir::failure();
24557f536a4SjeanPerier }
24657f536a4SjeanPerier 
parse(llvm::StringRef kindMap)24757f536a4SjeanPerier MatchResult fir::KindMapping::parse(llvm::StringRef kindMap) {
24857f536a4SjeanPerier   if (kindMap.empty())
24957f536a4SjeanPerier     return mlir::success();
25057f536a4SjeanPerier   const char *srcPtr = kindMap.begin();
251c68d2895SEric Schweitz   const char *endPtr = kindMap.end();
25257f536a4SjeanPerier   while (true) {
25357f536a4SjeanPerier     char code = '\0';
25457f536a4SjeanPerier     KindTy kind = 0;
255c68d2895SEric Schweitz     if (parseCode(code, srcPtr, endPtr) || parseInt(kind, srcPtr, endPtr))
25657f536a4SjeanPerier       return badMapString(srcPtr);
25757f536a4SjeanPerier     if (code == 'a' || code == 'i' || code == 'l') {
25857f536a4SjeanPerier       Bitsize bits = 0;
259c68d2895SEric Schweitz       if (parseColon(srcPtr, endPtr) || parseInt(bits, srcPtr, endPtr))
26057f536a4SjeanPerier         return badMapString(srcPtr);
26157f536a4SjeanPerier       intMap[std::pair<char, KindTy>{code, kind}] = bits;
26257f536a4SjeanPerier     } else if (code == 'r' || code == 'c') {
26357f536a4SjeanPerier       LLVMTypeID id{};
264c68d2895SEric Schweitz       if (parseColon(srcPtr, endPtr) || parseTypeID(id, srcPtr, endPtr))
26557f536a4SjeanPerier         return badMapString(srcPtr);
26657f536a4SjeanPerier       floatMap[std::pair<char, KindTy>{code, kind}] = id;
26757f536a4SjeanPerier     } else {
26857f536a4SjeanPerier       return badMapString(srcPtr);
26957f536a4SjeanPerier     }
270c68d2895SEric Schweitz     if (parseComma(srcPtr, endPtr))
27157f536a4SjeanPerier       break;
27257f536a4SjeanPerier   }
273c68d2895SEric Schweitz   if (srcPtr > endPtr)
27457f536a4SjeanPerier     return badMapString(srcPtr);
27557f536a4SjeanPerier   return mlir::success();
27657f536a4SjeanPerier }
27757f536a4SjeanPerier 
getCharacterBitsize(KindTy kind) const278c3477c51SEric Schweitz Bitsize fir::KindMapping::getCharacterBitsize(KindTy kind) const {
27957f536a4SjeanPerier   return getIntegerLikeBitsize<'a'>(kind, intMap);
28057f536a4SjeanPerier }
28157f536a4SjeanPerier 
getIntegerBitsize(KindTy kind) const282c3477c51SEric Schweitz Bitsize fir::KindMapping::getIntegerBitsize(KindTy kind) const {
28357f536a4SjeanPerier   return getIntegerLikeBitsize<'i'>(kind, intMap);
28457f536a4SjeanPerier }
28557f536a4SjeanPerier 
getLogicalBitsize(KindTy kind) const286c3477c51SEric Schweitz Bitsize fir::KindMapping::getLogicalBitsize(KindTy kind) const {
28757f536a4SjeanPerier   return getIntegerLikeBitsize<'l'>(kind, intMap);
28857f536a4SjeanPerier }
28957f536a4SjeanPerier 
getRealTypeID(KindTy kind) const290c3477c51SEric Schweitz LLVMTypeID fir::KindMapping::getRealTypeID(KindTy kind) const {
29157f536a4SjeanPerier   return getFloatLikeTypeID<'r'>(kind, floatMap);
29257f536a4SjeanPerier }
29357f536a4SjeanPerier 
getComplexTypeID(KindTy kind) const294c3477c51SEric Schweitz LLVMTypeID fir::KindMapping::getComplexTypeID(KindTy kind) const {
29557f536a4SjeanPerier   return getFloatLikeTypeID<'c'>(kind, floatMap);
29657f536a4SjeanPerier }
29757f536a4SjeanPerier 
getRealBitsize(KindTy kind) const298c3477c51SEric Schweitz Bitsize fir::KindMapping::getRealBitsize(KindTy kind) const {
299c3477c51SEric Schweitz   auto typeId = getFloatLikeTypeID<'r'>(kind, floatMap);
300c3477c51SEric Schweitz   llvm::LLVMContext llCtxt; // FIXME
301c3477c51SEric Schweitz   return llvm::Type::getPrimitiveType(llCtxt, typeId)->getPrimitiveSizeInBits();
302c3477c51SEric Schweitz }
303c3477c51SEric Schweitz 
304c3477c51SEric Schweitz const llvm::fltSemantics &
getFloatSemantics(KindTy kind) const305c3477c51SEric Schweitz fir::KindMapping::getFloatSemantics(KindTy kind) const {
30657f536a4SjeanPerier   return getFloatSemanticsOfKind<'r'>(kind, floatMap);
30757f536a4SjeanPerier }
3084dc87d10SEric Schweitz 
mapToString() const309c68d2895SEric Schweitz std::string fir::KindMapping::mapToString() const {
310c68d2895SEric Schweitz   std::string result;
311c68d2895SEric Schweitz   bool addComma = false;
312c68d2895SEric Schweitz   for (auto [k, v] : intMap) {
313c68d2895SEric Schweitz     if (addComma)
314c68d2895SEric Schweitz       result.append(",");
315c68d2895SEric Schweitz     else
316c68d2895SEric Schweitz       addComma = true;
317c68d2895SEric Schweitz     result += k.first + std::to_string(k.second) + ":" + std::to_string(v);
318c68d2895SEric Schweitz   }
319c68d2895SEric Schweitz   for (auto [k, v] : floatMap) {
320c68d2895SEric Schweitz     if (addComma)
321c68d2895SEric Schweitz       result.append(",");
322c68d2895SEric Schweitz     else
323c68d2895SEric Schweitz       addComma = true;
324c68d2895SEric Schweitz     result.append(k.first + std::to_string(k.second) + ":");
325c68d2895SEric Schweitz     switch (v) {
326c68d2895SEric Schweitz     default:
327c68d2895SEric Schweitz       llvm_unreachable("unhandled type-id");
328c68d2895SEric Schweitz     case LLVMTypeID::HalfTyID:
329c68d2895SEric Schweitz       result.append(kwHalf);
330c68d2895SEric Schweitz       break;
331c68d2895SEric Schweitz     case LLVMTypeID::BFloatTyID:
332c68d2895SEric Schweitz       result.append(kwBFloat);
333c68d2895SEric Schweitz       break;
334c68d2895SEric Schweitz     case LLVMTypeID::FloatTyID:
335c68d2895SEric Schweitz       result.append(kwFloat);
336c68d2895SEric Schweitz       break;
337c68d2895SEric Schweitz     case LLVMTypeID::DoubleTyID:
338c68d2895SEric Schweitz       result.append(kwDouble);
339c68d2895SEric Schweitz       break;
340c68d2895SEric Schweitz     case LLVMTypeID::X86_FP80TyID:
341c68d2895SEric Schweitz       result.append(kwX86FP80);
342c68d2895SEric Schweitz       break;
343c68d2895SEric Schweitz     case LLVMTypeID::FP128TyID:
344c68d2895SEric Schweitz       result.append(kwFP128);
345c68d2895SEric Schweitz       break;
346c68d2895SEric Schweitz     case LLVMTypeID::PPC_FP128TyID:
347c68d2895SEric Schweitz       result.append(kwPPCFP128);
348c68d2895SEric Schweitz       break;
349c68d2895SEric Schweitz     }
350c68d2895SEric Schweitz   }
351c68d2895SEric Schweitz   return result;
352c68d2895SEric Schweitz }
353c68d2895SEric Schweitz 
3544dc87d10SEric Schweitz mlir::LogicalResult
setDefaultKinds(llvm::ArrayRef<KindTy> defs)3554dc87d10SEric Schweitz fir::KindMapping::setDefaultKinds(llvm::ArrayRef<KindTy> defs) {
3564dc87d10SEric Schweitz   if (defs.empty()) {
3574dc87d10SEric Schweitz     // generic front-end defaults
3584dc87d10SEric Schweitz     const KindTy genericKind = 4;
3594dc87d10SEric Schweitz     defaultMap.insert({'a', 1});
3604dc87d10SEric Schweitz     defaultMap.insert({'c', genericKind});
3614dc87d10SEric Schweitz     defaultMap.insert({'d', 2 * genericKind});
3624dc87d10SEric Schweitz     defaultMap.insert({'i', genericKind});
3634dc87d10SEric Schweitz     defaultMap.insert({'l', genericKind});
3644dc87d10SEric Schweitz     defaultMap.insert({'r', genericKind});
3654dc87d10SEric Schweitz     return mlir::success();
3664dc87d10SEric Schweitz   }
3674dc87d10SEric Schweitz   if (defs.size() != 6)
3684dc87d10SEric Schweitz     return mlir::failure();
3694dc87d10SEric Schweitz 
3704dc87d10SEric Schweitz   // defaults determined after command-line processing
3714dc87d10SEric Schweitz   defaultMap.insert({'a', defs[0]});
3724dc87d10SEric Schweitz   defaultMap.insert({'c', defs[1]});
3734dc87d10SEric Schweitz   defaultMap.insert({'d', defs[2]});
3744dc87d10SEric Schweitz   defaultMap.insert({'i', defs[3]});
3754dc87d10SEric Schweitz   defaultMap.insert({'l', defs[4]});
3764dc87d10SEric Schweitz   defaultMap.insert({'r', defs[5]});
3774dc87d10SEric Schweitz   return mlir::success();
3784dc87d10SEric Schweitz }
3794dc87d10SEric Schweitz 
defaultsToString() const380c68d2895SEric Schweitz std::string fir::KindMapping::defaultsToString() const {
381c68d2895SEric Schweitz   return std::string("a") + std::to_string(defaultMap.find('a')->second) +
382c68d2895SEric Schweitz          std::string("c") + std::to_string(defaultMap.find('c')->second) +
383c68d2895SEric Schweitz          std::string("d") + std::to_string(defaultMap.find('d')->second) +
384c68d2895SEric Schweitz          std::string("i") + std::to_string(defaultMap.find('i')->second) +
385c68d2895SEric Schweitz          std::string("l") + std::to_string(defaultMap.find('l')->second) +
386c68d2895SEric Schweitz          std::string("r") + std::to_string(defaultMap.find('r')->second);
387c68d2895SEric Schweitz }
388c68d2895SEric Schweitz 
389c68d2895SEric Schweitz /// Convert a default intrinsic code into the proper position in the array. The
390c68d2895SEric Schweitz /// default kinds have a precise ordering.
codeToIndex(char code)391c68d2895SEric Schweitz static int codeToIndex(char code) {
392c68d2895SEric Schweitz   switch (code) {
393c68d2895SEric Schweitz   case 'a':
394c68d2895SEric Schweitz     return 0;
395c68d2895SEric Schweitz   case 'c':
396c68d2895SEric Schweitz     return 1;
397c68d2895SEric Schweitz   case 'd':
398c68d2895SEric Schweitz     return 2;
399c68d2895SEric Schweitz   case 'i':
400c68d2895SEric Schweitz     return 3;
401c68d2895SEric Schweitz   case 'l':
402c68d2895SEric Schweitz     return 4;
403c68d2895SEric Schweitz   case 'r':
404c68d2895SEric Schweitz     return 5;
405c68d2895SEric Schweitz   }
406c68d2895SEric Schweitz   llvm_unreachable("invalid default kind intrinsic code");
407c68d2895SEric Schweitz }
408c68d2895SEric Schweitz 
toDefaultKinds(llvm::StringRef defs)409c68d2895SEric Schweitz std::vector<KindTy> fir::KindMapping::toDefaultKinds(llvm::StringRef defs) {
410c68d2895SEric Schweitz   std::vector<KindTy> result(6);
411c68d2895SEric Schweitz   char code;
412c68d2895SEric Schweitz   KindTy kind;
413c68d2895SEric Schweitz   if (defs.empty())
414c68d2895SEric Schweitz     defs = clDefaultKinds;
415c68d2895SEric Schweitz   const char *srcPtr = defs.begin();
416c68d2895SEric Schweitz   const char *endPtr = defs.end();
417c68d2895SEric Schweitz   while (srcPtr < endPtr) {
418c68d2895SEric Schweitz     if (parseDefCode(code, srcPtr, endPtr) || parseInt(kind, srcPtr, endPtr))
419c68d2895SEric Schweitz       llvm::report_fatal_error("invalid default kind code");
420c68d2895SEric Schweitz     result[codeToIndex(code)] = kind;
421c68d2895SEric Schweitz   }
422c68d2895SEric Schweitz   assert(srcPtr == endPtr);
423c68d2895SEric Schweitz   return result;
424c68d2895SEric Schweitz }
425c68d2895SEric Schweitz 
defaultCharacterKind() const4264dc87d10SEric Schweitz KindTy fir::KindMapping::defaultCharacterKind() const {
4274dc87d10SEric Schweitz   auto iter = defaultMap.find('a');
4284dc87d10SEric Schweitz   assert(iter != defaultMap.end());
4294dc87d10SEric Schweitz   return iter->second;
4304dc87d10SEric Schweitz }
4314dc87d10SEric Schweitz 
defaultComplexKind() const4324dc87d10SEric Schweitz KindTy fir::KindMapping::defaultComplexKind() const {
4334dc87d10SEric Schweitz   auto iter = defaultMap.find('c');
4344dc87d10SEric Schweitz   assert(iter != defaultMap.end());
4354dc87d10SEric Schweitz   return iter->second;
4364dc87d10SEric Schweitz }
4374dc87d10SEric Schweitz 
defaultDoubleKind() const4384dc87d10SEric Schweitz KindTy fir::KindMapping::defaultDoubleKind() const {
4394dc87d10SEric Schweitz   auto iter = defaultMap.find('d');
4404dc87d10SEric Schweitz   assert(iter != defaultMap.end());
4414dc87d10SEric Schweitz   return iter->second;
4424dc87d10SEric Schweitz }
4434dc87d10SEric Schweitz 
defaultIntegerKind() const4444dc87d10SEric Schweitz KindTy fir::KindMapping::defaultIntegerKind() const {
4454dc87d10SEric Schweitz   auto iter = defaultMap.find('i');
4464dc87d10SEric Schweitz   assert(iter != defaultMap.end());
4474dc87d10SEric Schweitz   return iter->second;
4484dc87d10SEric Schweitz }
4494dc87d10SEric Schweitz 
defaultLogicalKind() const4504dc87d10SEric Schweitz KindTy fir::KindMapping::defaultLogicalKind() const {
4514dc87d10SEric Schweitz   auto iter = defaultMap.find('l');
4524dc87d10SEric Schweitz   assert(iter != defaultMap.end());
4534dc87d10SEric Schweitz   return iter->second;
4544dc87d10SEric Schweitz }
4554dc87d10SEric Schweitz 
defaultRealKind() const4564dc87d10SEric Schweitz KindTy fir::KindMapping::defaultRealKind() const {
4574dc87d10SEric Schweitz   auto iter = defaultMap.find('r');
4584dc87d10SEric Schweitz   assert(iter != defaultMap.end());
4594dc87d10SEric Schweitz   return iter->second;
4604dc87d10SEric Schweitz }
461