1 //===-- KindMapping.cpp ---------------------------------------------------===// 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 #include "flang/Optimizer/Support/KindMapping.h" 10 #include "mlir/Dialect/LLVMIR/LLVMDialect.h" 11 #include "llvm/Support/CommandLine.h" 12 13 /// Allow the user to set the FIR intrinsic type kind value to LLVM type 14 /// mappings. Note that these are not mappings from kind values to any 15 /// other MLIR dialect, only to LLVM IR. The default values follow the f18 16 /// front-end kind mappings. 17 18 using Bitsize = fir::KindMapping::Bitsize; 19 using KindTy = fir::KindMapping::KindTy; 20 using LLVMTypeID = fir::KindMapping::LLVMTypeID; 21 using MatchResult = fir::KindMapping::MatchResult; 22 23 static llvm::cl::opt<std::string> clKindMapping( 24 "kind-mapping", llvm::cl::desc("kind mapping string to set kind precision"), 25 llvm::cl::value_desc("kind-mapping-string"), llvm::cl::init("")); 26 27 /// Integral types default to the kind value being the size of the value in 28 /// bytes. The default is to scale from bytes to bits. 29 static Bitsize defaultScalingKind(KindTy kind) { 30 const unsigned BITS_IN_BYTE = 8; 31 return kind * BITS_IN_BYTE; 32 } 33 34 /// Floating-point types default to the kind value being the size of the value 35 /// in bytes. The default is to translate kinds of 2, 4, 8, 10, and 16 to a 36 /// valid llvm::Type::TypeID value. Otherwise, the default is FloatTyID. 37 static LLVMTypeID defaultRealKind(KindTy kind) { 38 switch (kind) { 39 case 2: 40 return LLVMTypeID::HalfTyID; 41 case 4: 42 return LLVMTypeID::FloatTyID; 43 case 8: 44 return LLVMTypeID::DoubleTyID; 45 case 10: 46 return LLVMTypeID::X86_FP80TyID; 47 case 16: 48 return LLVMTypeID::FP128TyID; 49 default: 50 return LLVMTypeID::FloatTyID; 51 } 52 } 53 54 // lookup the kind-value given the defaults, the mappings, and a KIND key 55 template <typename RT, char KEY> 56 static RT doLookup(std::function<RT(KindTy)> def, 57 const llvm::DenseMap<std::pair<char, KindTy>, RT> &map, 58 KindTy kind) { 59 std::pair<char, KindTy> key{KEY, kind}; 60 auto iter = map.find(key); 61 if (iter != map.end()) 62 return iter->second; 63 return def(kind); 64 } 65 66 // do a lookup for INTERGER, LOGICAL, or CHARACTER 67 template <char KEY, typename MAP> 68 static Bitsize getIntegerLikeBitsize(KindTy kind, const MAP &map) { 69 return doLookup<Bitsize, KEY>(defaultScalingKind, map, kind); 70 } 71 72 // do a lookup for REAL or COMPLEX 73 template <char KEY, typename MAP> 74 static LLVMTypeID getFloatLikeTypeID(KindTy kind, const MAP &map) { 75 return doLookup<LLVMTypeID, KEY>(defaultRealKind, map, kind); 76 } 77 78 template <char KEY, typename MAP> 79 static const llvm::fltSemantics &getFloatSemanticsOfKind(KindTy kind, 80 const MAP &map) { 81 switch (doLookup<LLVMTypeID, KEY>(defaultRealKind, map, kind)) { 82 case LLVMTypeID::HalfTyID: 83 return llvm::APFloat::IEEEhalf(); 84 case LLVMTypeID::FloatTyID: 85 return llvm::APFloat::IEEEsingle(); 86 case LLVMTypeID::DoubleTyID: 87 return llvm::APFloat::IEEEdouble(); 88 case LLVMTypeID::X86_FP80TyID: 89 return llvm::APFloat::x87DoubleExtended(); 90 case LLVMTypeID::FP128TyID: 91 return llvm::APFloat::IEEEquad(); 92 case LLVMTypeID::PPC_FP128TyID: 93 return llvm::APFloat::PPCDoubleDouble(); 94 default: 95 llvm_unreachable("Invalid floating type"); 96 } 97 } 98 99 static MatchResult parseCode(char &code, const char *&ptr) { 100 if (*ptr != 'a' && *ptr != 'c' && *ptr != 'i' && *ptr != 'l' && *ptr != 'r') 101 return mlir::failure(); 102 code = *ptr++; 103 return mlir::success(); 104 } 105 106 template <char ch> 107 static MatchResult parseSingleChar(const char *&ptr) { 108 if (*ptr != ch) 109 return mlir::failure(); 110 ++ptr; 111 return mlir::success(); 112 } 113 114 static MatchResult parseColon(const char *&ptr) { 115 return parseSingleChar<':'>(ptr); 116 } 117 118 static MatchResult parseComma(const char *&ptr) { 119 return parseSingleChar<','>(ptr); 120 } 121 122 static MatchResult parseInt(unsigned &result, const char *&ptr) { 123 const char *beg = ptr; 124 while (*ptr >= '0' && *ptr <= '9') 125 ptr++; 126 if (beg == ptr) 127 return mlir::failure(); 128 llvm::StringRef ref(beg, ptr - beg); 129 int temp; 130 if (ref.consumeInteger(10, temp)) 131 return mlir::failure(); 132 result = temp; 133 return mlir::success(); 134 } 135 136 static mlir::LogicalResult matchString(const char *&ptr, 137 llvm::StringRef literal) { 138 llvm::StringRef s(ptr); 139 if (s.startswith(literal)) { 140 ptr += literal.size(); 141 return mlir::success(); 142 } 143 return mlir::failure(); 144 } 145 146 static MatchResult parseTypeID(LLVMTypeID &result, const char *&ptr) { 147 if (mlir::succeeded(matchString(ptr, "Half"))) { 148 result = LLVMTypeID::HalfTyID; 149 return mlir::success(); 150 } 151 if (mlir::succeeded(matchString(ptr, "Float"))) { 152 result = LLVMTypeID::FloatTyID; 153 return mlir::success(); 154 } 155 if (mlir::succeeded(matchString(ptr, "Double"))) { 156 result = LLVMTypeID::DoubleTyID; 157 return mlir::success(); 158 } 159 if (mlir::succeeded(matchString(ptr, "X86_FP80"))) { 160 result = LLVMTypeID::X86_FP80TyID; 161 return mlir::success(); 162 } 163 if (mlir::succeeded(matchString(ptr, "FP128"))) { 164 result = LLVMTypeID::FP128TyID; 165 return mlir::success(); 166 } 167 if (mlir::succeeded(matchString(ptr, "PPC_FP128"))) { 168 result = LLVMTypeID::PPC_FP128TyID; 169 return mlir::success(); 170 } 171 return mlir::failure(); 172 } 173 174 fir::KindMapping::KindMapping(mlir::MLIRContext *context, llvm::StringRef map) 175 : context{context} { 176 if (mlir::failed(parse(map))) { 177 intMap.clear(); 178 floatMap.clear(); 179 } 180 } 181 182 fir::KindMapping::KindMapping(mlir::MLIRContext *context) 183 : KindMapping{context, clKindMapping} {} 184 185 MatchResult fir::KindMapping::badMapString(const llvm::Twine &ptr) { 186 auto unknown = mlir::UnknownLoc::get(context); 187 mlir::emitError(unknown, ptr); 188 return mlir::failure(); 189 } 190 191 MatchResult fir::KindMapping::parse(llvm::StringRef kindMap) { 192 if (kindMap.empty()) 193 return mlir::success(); 194 const char *srcPtr = kindMap.begin(); 195 while (true) { 196 char code = '\0'; 197 KindTy kind = 0; 198 if (parseCode(code, srcPtr) || parseInt(kind, srcPtr)) 199 return badMapString(srcPtr); 200 if (code == 'a' || code == 'i' || code == 'l') { 201 Bitsize bits = 0; 202 if (parseColon(srcPtr) || parseInt(bits, srcPtr)) 203 return badMapString(srcPtr); 204 intMap[std::pair<char, KindTy>{code, kind}] = bits; 205 } else if (code == 'r' || code == 'c') { 206 LLVMTypeID id{}; 207 if (parseColon(srcPtr) || parseTypeID(id, srcPtr)) 208 return badMapString(srcPtr); 209 floatMap[std::pair<char, KindTy>{code, kind}] = id; 210 } else { 211 return badMapString(srcPtr); 212 } 213 if (parseComma(srcPtr)) 214 break; 215 } 216 if (*srcPtr) 217 return badMapString(srcPtr); 218 return mlir::success(); 219 } 220 221 Bitsize fir::KindMapping::getCharacterBitsize(KindTy kind) const { 222 return getIntegerLikeBitsize<'a'>(kind, intMap); 223 } 224 225 Bitsize fir::KindMapping::getIntegerBitsize(KindTy kind) const { 226 return getIntegerLikeBitsize<'i'>(kind, intMap); 227 } 228 229 Bitsize fir::KindMapping::getLogicalBitsize(KindTy kind) const { 230 return getIntegerLikeBitsize<'l'>(kind, intMap); 231 } 232 233 LLVMTypeID fir::KindMapping::getRealTypeID(KindTy kind) const { 234 return getFloatLikeTypeID<'r'>(kind, floatMap); 235 } 236 237 LLVMTypeID fir::KindMapping::getComplexTypeID(KindTy kind) const { 238 return getFloatLikeTypeID<'c'>(kind, floatMap); 239 } 240 241 Bitsize fir::KindMapping::getRealBitsize(KindTy kind) const { 242 auto typeId = getFloatLikeTypeID<'r'>(kind, floatMap); 243 llvm::LLVMContext llCtxt; // FIXME 244 return llvm::Type::getPrimitiveType(llCtxt, typeId)->getPrimitiveSizeInBits(); 245 } 246 247 const llvm::fltSemantics & 248 fir::KindMapping::getFloatSemantics(KindTy kind) const { 249 return getFloatSemanticsOfKind<'r'>(kind, floatMap); 250 } 251