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