251 lines
7.7 KiB
C++
251 lines
7.7 KiB
C++
//===-- KindMapping.cpp ---------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "flang/Optimizer/Support/KindMapping.h"
|
|
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
/// Allow the user to set the FIR intrinsic type kind value to LLVM type
|
|
/// mappings. Note that these are not mappings from kind values to any
|
|
/// other MLIR dialect, only to LLVM IR. The default values follow the f18
|
|
/// front-end kind mappings.
|
|
|
|
using Bitsize = fir::KindMapping::Bitsize;
|
|
using KindTy = fir::KindMapping::KindTy;
|
|
using LLVMTypeID = fir::KindMapping::LLVMTypeID;
|
|
using MatchResult = fir::KindMapping::MatchResult;
|
|
|
|
static llvm::cl::opt<std::string> clKindMapping(
|
|
"kind-mapping", llvm::cl::desc("kind mapping string to set kind precision"),
|
|
llvm::cl::value_desc("kind-mapping-string"), llvm::cl::init(""));
|
|
|
|
/// Integral types default to the kind value being the size of the value in
|
|
/// bytes. The default is to scale from bytes to bits.
|
|
static Bitsize defaultScalingKind(KindTy kind) {
|
|
const unsigned BITS_IN_BYTE = 8;
|
|
return kind * BITS_IN_BYTE;
|
|
}
|
|
|
|
/// Floating-point types default to the kind value being the size of the value
|
|
/// in bytes. The default is to translate kinds of 2, 4, 8, 10, and 16 to a
|
|
/// valid llvm::Type::TypeID value. Otherwise, the default is FloatTyID.
|
|
static LLVMTypeID defaultRealKind(KindTy kind) {
|
|
switch (kind) {
|
|
case 2:
|
|
return LLVMTypeID::HalfTyID;
|
|
case 4:
|
|
return LLVMTypeID::FloatTyID;
|
|
case 8:
|
|
return LLVMTypeID::DoubleTyID;
|
|
case 10:
|
|
return LLVMTypeID::X86_FP80TyID;
|
|
case 16:
|
|
return LLVMTypeID::FP128TyID;
|
|
default:
|
|
return LLVMTypeID::FloatTyID;
|
|
}
|
|
}
|
|
|
|
// lookup the kind-value given the defaults, the mappings, and a KIND key
|
|
template <typename RT, char KEY>
|
|
static RT doLookup(std::function<RT(KindTy)> def,
|
|
const llvm::DenseMap<std::pair<char, KindTy>, RT> &map,
|
|
KindTy kind) {
|
|
std::pair<char, KindTy> key{KEY, kind};
|
|
auto iter = map.find(key);
|
|
if (iter != map.end())
|
|
return iter->second;
|
|
return def(kind);
|
|
}
|
|
|
|
// do a lookup for INTERGER, LOGICAL, or CHARACTER
|
|
template <char KEY, typename MAP>
|
|
static Bitsize getIntegerLikeBitsize(KindTy kind, const MAP &map) {
|
|
return doLookup<Bitsize, KEY>(defaultScalingKind, map, kind);
|
|
}
|
|
|
|
// do a lookup for REAL or COMPLEX
|
|
template <char KEY, typename MAP>
|
|
static LLVMTypeID getFloatLikeTypeID(KindTy kind, const MAP &map) {
|
|
return doLookup<LLVMTypeID, KEY>(defaultRealKind, map, kind);
|
|
}
|
|
|
|
template <char KEY, typename MAP>
|
|
static const llvm::fltSemantics &getFloatSemanticsOfKind(KindTy kind,
|
|
const MAP &map) {
|
|
switch (doLookup<LLVMTypeID, KEY>(defaultRealKind, map, kind)) {
|
|
case LLVMTypeID::HalfTyID:
|
|
return llvm::APFloat::IEEEhalf();
|
|
case LLVMTypeID::FloatTyID:
|
|
return llvm::APFloat::IEEEsingle();
|
|
case LLVMTypeID::DoubleTyID:
|
|
return llvm::APFloat::IEEEdouble();
|
|
case LLVMTypeID::X86_FP80TyID:
|
|
return llvm::APFloat::x87DoubleExtended();
|
|
case LLVMTypeID::FP128TyID:
|
|
return llvm::APFloat::IEEEquad();
|
|
case LLVMTypeID::PPC_FP128TyID:
|
|
return llvm::APFloat::PPCDoubleDouble();
|
|
default:
|
|
llvm_unreachable("Invalid floating type");
|
|
}
|
|
}
|
|
|
|
static MatchResult parseCode(char &code, const char *&ptr) {
|
|
if (*ptr != 'a' && *ptr != 'c' && *ptr != 'i' && *ptr != 'l' && *ptr != 'r')
|
|
return mlir::failure();
|
|
code = *ptr++;
|
|
return mlir::success();
|
|
}
|
|
|
|
template <char ch>
|
|
static MatchResult parseSingleChar(const char *&ptr) {
|
|
if (*ptr != ch)
|
|
return mlir::failure();
|
|
++ptr;
|
|
return mlir::success();
|
|
}
|
|
|
|
static MatchResult parseColon(const char *&ptr) {
|
|
return parseSingleChar<':'>(ptr);
|
|
}
|
|
|
|
static MatchResult parseComma(const char *&ptr) {
|
|
return parseSingleChar<','>(ptr);
|
|
}
|
|
|
|
static MatchResult parseInt(unsigned &result, const char *&ptr) {
|
|
const char *beg = ptr;
|
|
while (*ptr >= '0' && *ptr <= '9')
|
|
ptr++;
|
|
if (beg == ptr)
|
|
return mlir::failure();
|
|
llvm::StringRef ref(beg, ptr - beg);
|
|
int temp;
|
|
if (ref.consumeInteger(10, temp))
|
|
return mlir::failure();
|
|
result = temp;
|
|
return mlir::success();
|
|
}
|
|
|
|
static mlir::LogicalResult matchString(const char *&ptr,
|
|
llvm::StringRef literal) {
|
|
llvm::StringRef s(ptr);
|
|
if (s.startswith(literal)) {
|
|
ptr += literal.size();
|
|
return mlir::success();
|
|
}
|
|
return mlir::failure();
|
|
}
|
|
|
|
static MatchResult parseTypeID(LLVMTypeID &result, const char *&ptr) {
|
|
if (mlir::succeeded(matchString(ptr, "Half"))) {
|
|
result = LLVMTypeID::HalfTyID;
|
|
return mlir::success();
|
|
}
|
|
if (mlir::succeeded(matchString(ptr, "Float"))) {
|
|
result = LLVMTypeID::FloatTyID;
|
|
return mlir::success();
|
|
}
|
|
if (mlir::succeeded(matchString(ptr, "Double"))) {
|
|
result = LLVMTypeID::DoubleTyID;
|
|
return mlir::success();
|
|
}
|
|
if (mlir::succeeded(matchString(ptr, "X86_FP80"))) {
|
|
result = LLVMTypeID::X86_FP80TyID;
|
|
return mlir::success();
|
|
}
|
|
if (mlir::succeeded(matchString(ptr, "FP128"))) {
|
|
result = LLVMTypeID::FP128TyID;
|
|
return mlir::success();
|
|
}
|
|
if (mlir::succeeded(matchString(ptr, "PPC_FP128"))) {
|
|
result = LLVMTypeID::PPC_FP128TyID;
|
|
return mlir::success();
|
|
}
|
|
return mlir::failure();
|
|
}
|
|
|
|
fir::KindMapping::KindMapping(mlir::MLIRContext *context, llvm::StringRef map)
|
|
: context{context} {
|
|
if (mlir::failed(parse(map))) {
|
|
intMap.clear();
|
|
floatMap.clear();
|
|
}
|
|
}
|
|
|
|
fir::KindMapping::KindMapping(mlir::MLIRContext *context)
|
|
: KindMapping{context, clKindMapping} {}
|
|
|
|
MatchResult fir::KindMapping::badMapString(const llvm::Twine &ptr) {
|
|
auto unknown = mlir::UnknownLoc::get(context);
|
|
mlir::emitError(unknown, ptr);
|
|
return mlir::failure();
|
|
}
|
|
|
|
MatchResult fir::KindMapping::parse(llvm::StringRef kindMap) {
|
|
if (kindMap.empty())
|
|
return mlir::success();
|
|
const char *srcPtr = kindMap.begin();
|
|
while (true) {
|
|
char code = '\0';
|
|
KindTy kind = 0;
|
|
if (parseCode(code, srcPtr) || parseInt(kind, srcPtr))
|
|
return badMapString(srcPtr);
|
|
if (code == 'a' || code == 'i' || code == 'l') {
|
|
Bitsize bits = 0;
|
|
if (parseColon(srcPtr) || parseInt(bits, srcPtr))
|
|
return badMapString(srcPtr);
|
|
intMap[std::pair<char, KindTy>{code, kind}] = bits;
|
|
} else if (code == 'r' || code == 'c') {
|
|
LLVMTypeID id{};
|
|
if (parseColon(srcPtr) || parseTypeID(id, srcPtr))
|
|
return badMapString(srcPtr);
|
|
floatMap[std::pair<char, KindTy>{code, kind}] = id;
|
|
} else {
|
|
return badMapString(srcPtr);
|
|
}
|
|
if (parseComma(srcPtr))
|
|
break;
|
|
}
|
|
if (*srcPtr)
|
|
return badMapString(srcPtr);
|
|
return mlir::success();
|
|
}
|
|
|
|
Bitsize fir::KindMapping::getCharacterBitsize(KindTy kind) const {
|
|
return getIntegerLikeBitsize<'a'>(kind, intMap);
|
|
}
|
|
|
|
Bitsize fir::KindMapping::getIntegerBitsize(KindTy kind) const {
|
|
return getIntegerLikeBitsize<'i'>(kind, intMap);
|
|
}
|
|
|
|
Bitsize fir::KindMapping::getLogicalBitsize(KindTy kind) const {
|
|
return getIntegerLikeBitsize<'l'>(kind, intMap);
|
|
}
|
|
|
|
LLVMTypeID fir::KindMapping::getRealTypeID(KindTy kind) const {
|
|
return getFloatLikeTypeID<'r'>(kind, floatMap);
|
|
}
|
|
|
|
LLVMTypeID fir::KindMapping::getComplexTypeID(KindTy kind) const {
|
|
return getFloatLikeTypeID<'c'>(kind, floatMap);
|
|
}
|
|
|
|
Bitsize fir::KindMapping::getRealBitsize(KindTy kind) const {
|
|
auto typeId = getFloatLikeTypeID<'r'>(kind, floatMap);
|
|
llvm::LLVMContext llCtxt; // FIXME
|
|
return llvm::Type::getPrimitiveType(llCtxt, typeId)->getPrimitiveSizeInBits();
|
|
}
|
|
|
|
const llvm::fltSemantics &
|
|
fir::KindMapping::getFloatSemantics(KindTy kind) const {
|
|
return getFloatSemanticsOfKind<'r'>(kind, floatMap);
|
|
}
|