[flang][fir] Update flang test tool support classes.

This updates the various classes that support the compliation of
Fortran. These classes are shared by the test tools.

Authors: Eric Schweitz, Sameeran Joshi, et.al.

Differential Revision: https://reviews.llvm.org/D97073
This commit is contained in:
Eric Schweitz 2021-02-19 11:05:41 -08:00
parent f8c1f3b14a
commit c68d2895a1
11 changed files with 466 additions and 127 deletions

View File

@ -0,0 +1,56 @@
//===-- Optimizer/Support/FIRContext.h --------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//
/// Setters and getters for associating context with an instance of a ModuleOp.
/// The context is typically set by the tool and needed in later stages to
/// determine how to correctly generate code.
//===----------------------------------------------------------------------===//
#ifndef FORTRAN_OPTIMIZER_SUPPORT_FIRCONTEXT_H
#define FORTRAN_OPTIMIZER_SUPPORT_FIRCONTEXT_H
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
namespace mlir {
class ModuleOp;
}
namespace fir {
class KindMapping;
struct NameUniquer;
/// Set the target triple for the module. `triple` must not be deallocated while
/// module `mod` is still live.
void setTargetTriple(mlir::ModuleOp mod, llvm::StringRef triple);
/// Get the Triple instance from the Module or return the default Triple.
llvm::Triple getTargetTriple(mlir::ModuleOp mod);
/// Set the kind mapping for the module. `kindMap` must not be deallocated while
/// module `mod` is still live.
void setKindMapping(mlir::ModuleOp mod, KindMapping &kindMap);
/// Get the KindMapping instance from the Module. If none was set, returns a
/// default.
KindMapping getKindMapping(mlir::ModuleOp mod);
/// Helper for determining the target from the host, etc. Tools may use this
/// function to provide a consistent interpretation of the `--target=<string>`
/// command-line option.
/// An empty string ("") or "default" will specify that the default triple
/// should be used. "native" will specify that the host machine be used to
/// construct the triple.
std::string determineTargetTriple(llvm::StringRef triple);
} // namespace fir
#endif // FORTRAN_OPTIMIZER_SUPPORT_FIRCONTEXT_H

View File

@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
#ifndef OPTIMIZER_SUPPORT_INTERNALNAMES_H
#define OPTIMIZER_SUPPORT_INTERNALNAMES_H
#ifndef FORTRAN_OPTIMIZER_SUPPORT_INTERNALNAMES_H
#define FORTRAN_OPTIMIZER_SUPPORT_INTERNALNAMES_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
@ -59,58 +59,58 @@ struct NameUniquer {
llvm::SmallVector<std::int64_t, 4> kinds;
};
NameUniquer() = default;
/// Unique a common block name
std::string doCommonBlock(llvm::StringRef name);
static std::string doCommonBlock(llvm::StringRef name);
/// Unique a block data unit name
std::string doBlockData(llvm::StringRef name);
static std::string doBlockData(llvm::StringRef name);
/// Unique a (global) constant name
std::string doConstant(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
llvm::StringRef name);
static std::string doConstant(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
llvm::StringRef name);
/// Unique a dispatch table name
std::string doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
llvm::StringRef name,
llvm::ArrayRef<std::int64_t> kinds);
static std::string doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
llvm::StringRef name,
llvm::ArrayRef<std::int64_t> kinds);
/// Unique a compiler generated name
std::string doGenerated(llvm::StringRef name);
static std::string doGenerated(llvm::StringRef name);
/// Unique an intrinsic type descriptor
std::string doIntrinsicTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
IntrinsicType type, std::int64_t kind);
static std::string
doIntrinsicTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
IntrinsicType type, std::int64_t kind);
/// Unique a procedure name
std::string doProcedure(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
llvm::StringRef name);
static std::string doProcedure(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
llvm::StringRef name);
/// Unique a derived type name
std::string doType(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host, llvm::StringRef name,
llvm::ArrayRef<std::int64_t> kinds);
static std::string doType(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
llvm::StringRef name,
llvm::ArrayRef<std::int64_t> kinds);
/// Unique a (derived) type descriptor name
std::string doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
llvm::StringRef name,
llvm::ArrayRef<std::int64_t> kinds);
std::string doTypeDescriptor(llvm::ArrayRef<std::string> modules,
llvm::Optional<std::string> host,
llvm::StringRef name,
llvm::ArrayRef<std::int64_t> kinds);
static std::string doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
llvm::StringRef name,
llvm::ArrayRef<std::int64_t> kinds);
static std::string doTypeDescriptor(llvm::ArrayRef<std::string> modules,
llvm::Optional<std::string> host,
llvm::StringRef name,
llvm::ArrayRef<std::int64_t> kinds);
/// Unique a (global) variable name. A variable with save attribute
/// defined inside a subprogram also needs to be handled here
std::string doVariable(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
llvm::StringRef name);
static std::string doVariable(llvm::ArrayRef<llvm::StringRef> modules,
llvm::Optional<llvm::StringRef> host,
llvm::StringRef name);
/// Entry point for the PROGRAM (called by the runtime)
/// Can be overridden with the `--main-entry-name=<name>` option.
@ -121,12 +121,17 @@ struct NameUniquer {
deconstruct(llvm::StringRef uniquedName);
private:
std::string intAsString(std::int64_t i);
std::string doKind(std::int64_t kind);
std::string doKinds(llvm::ArrayRef<std::int64_t> kinds);
std::string toLower(llvm::StringRef name);
static std::string intAsString(std::int64_t i);
static std::string doKind(std::int64_t kind);
static std::string doKinds(llvm::ArrayRef<std::int64_t> kinds);
static std::string toLower(llvm::StringRef name);
NameUniquer() = delete;
NameUniquer(const NameUniquer &) = delete;
NameUniquer(NameUniquer &&) = delete;
NameUniquer &operator=(const NameUniquer &) = delete;
};
} // namespace fir
#endif // OPTIMIZER_SUPPORT_INTERNALNAMES_H
#endif // FORTRAN_OPTIMIZER_SUPPORT_INTERNALNAMES_H

View File

@ -10,8 +10,8 @@
//
//===----------------------------------------------------------------------===//
#ifndef OPTIMIZER_SUPPORT_KINDMAPPING_H
#define OPTIMIZER_SUPPORT_KINDMAPPING_H
#ifndef FORTRAN_OPTIMIZER_SUPPORT_KINDMAPPING_H
#define FORTRAN_OPTIMIZER_SUPPORT_KINDMAPPING_H
#include "mlir/IR/OpDefinition.h"
#include "llvm/ADT/DenseMap.h"
@ -52,15 +52,24 @@ public:
using LLVMTypeID = llvm::Type::TypeID;
using MatchResult = mlir::ParseResult;
/// KindMapping constructors take an optional `defs` argument to specify the
/// KindMapping constructor with both the kind map and default kinds read from
/// command-line options.
explicit KindMapping(mlir::MLIRContext *context);
/// KindMapping constructor taking a `defs` argument to specify the default
/// kinds for intrinsic types. To set the default kinds, an ArrayRef of 6
/// KindTy must be passed. The kinds must be the given in the following order:
/// CHARACTER, COMPLEX, DOUBLE PRECISION, INTEGER, LOGICAL, and REAL. The
/// kind map is read from command-line options, if given.
explicit KindMapping(mlir::MLIRContext *context, llvm::ArrayRef<KindTy> defs);
/// KindMapping constructor taking an optional `defs` argument to specify the
/// default kinds for intrinsic types. To set the default kinds, an ArrayRef
/// of 6 KindTy must be passed. The kinds must be the given in the following
/// order: CHARACTER, COMPLEX, DOUBLE PRECISION, INTEGER, LOGICAL, and REAL.
/// If `defs` is not specified, default default kinds will be used.
explicit KindMapping(mlir::MLIRContext *context,
llvm::ArrayRef<KindTy> defs = llvm::None);
explicit KindMapping(mlir::MLIRContext *context, llvm::StringRef map,
llvm::ArrayRef<KindTy> defs = llvm::None);
explicit KindMapping(mlir::MLIRContext *context, llvm::StringRef map,
llvm::StringRef defs)
: KindMapping{context, map, toDefaultKinds(defs)} {}
/// Get the size in bits of !fir.char<kind>
Bitsize getCharacterBitsize(KindTy kind) const;
@ -85,6 +94,12 @@ public:
/// Get the float semantics of !fir.real<kind>
const llvm::fltSemantics &getFloatSemantics(KindTy kind) const;
/// Get the default kind map as a string.
static constexpr const char *getDefaultMap() { return ""; }
/// Convert the current kind map to a string.
std::string mapToString() const;
//===--------------------------------------------------------------------===//
// Default kinds of intrinsic types
//===--------------------------------------------------------------------===//
@ -96,6 +111,16 @@ public:
KindTy defaultLogicalKind() const;
KindTy defaultRealKind() const;
/// Get the default kinds as a string.
static constexpr const char *getDefaultKinds() { return "a1c4d8i4l4r4"; }
/// Convert the current default kinds to a string.
std::string defaultsToString() const;
/// Translate a default kinds string into a default kind vector. This vector
/// can be passed to the KindMapping ctor.
static std::vector<KindTy> toDefaultKinds(llvm::StringRef defs);
private:
MatchResult badMapString(const llvm::Twine &ptr);
MatchResult parse(llvm::StringRef kindMap);
@ -109,4 +134,4 @@ private:
} // namespace fir
#endif // OPTIMIZER_SUPPORT_KINDMAPPING_H
#endif // FORTRAN_OPTIMIZER_SUPPORT_KINDMAPPING_H

View File

@ -6,6 +6,7 @@ add_flang_library(FIROptimizer
Dialect/FIROps.cpp
Dialect/FIRType.cpp
Support/FIRContext.cpp
Support/InternalNames.cpp
Support/KindMapping.cpp

View File

@ -0,0 +1,62 @@
//===-- FIRContext.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
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Support/FIRContext.h"
#include "flang/Optimizer/Support/KindMapping.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "llvm/Support/Host.h"
static constexpr const char *tripleName = "fir.triple";
void fir::setTargetTriple(mlir::ModuleOp mod, llvm::StringRef triple) {
auto target = fir::determineTargetTriple(triple);
mod->setAttr(tripleName, mlir::StringAttr::get(mod.getContext(), target));
}
llvm::Triple fir::getTargetTriple(mlir::ModuleOp mod) {
if (auto target = mod->getAttrOfType<mlir::StringAttr>(tripleName))
return llvm::Triple(target.getValue());
return llvm::Triple(llvm::sys::getDefaultTargetTriple());
}
static constexpr const char *kindMapName = "fir.kindmap";
static constexpr const char *defKindName = "fir.defaultkind";
void fir::setKindMapping(mlir::ModuleOp mod, fir::KindMapping &kindMap) {
auto ctx = mod.getContext();
mod->setAttr(kindMapName, mlir::StringAttr::get(ctx, kindMap.mapToString()));
auto defs = kindMap.defaultsToString();
mod->setAttr(defKindName, mlir::StringAttr::get(ctx, defs));
}
fir::KindMapping fir::getKindMapping(mlir::ModuleOp mod) {
auto ctx = mod.getContext();
if (auto defs = mod->getAttrOfType<mlir::StringAttr>(defKindName)) {
auto defVals = fir::KindMapping::toDefaultKinds(defs.getValue());
if (auto maps = mod->getAttrOfType<mlir::StringAttr>(kindMapName))
return fir::KindMapping(ctx, maps.getValue(), defVals);
return fir::KindMapping(ctx, defVals);
}
return fir::KindMapping(ctx);
}
std::string fir::determineTargetTriple(llvm::StringRef triple) {
// Treat "" or "default" as stand-ins for the default machine.
if (triple.empty() || triple == "default")
return llvm::sys::getDefaultTargetTriple();
// Treat "native" as stand-in for the host machine.
if (triple == "native")
return llvm::sys::getProcessTriple();
// TODO: normalize the triple?
return triple.str();
}

View File

@ -5,6 +5,10 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Optimizer/Dialect/FIRType.h"

View File

@ -24,9 +24,27 @@ 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(""));
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(fir::KindMapping::getDefaultMap()));
static llvm::cl::opt<std::string>
clDefaultKinds("default-kinds",
llvm::cl::desc("string to set default kind values"),
llvm::cl::value_desc("default-kind-string"),
llvm::cl::init(fir::KindMapping::getDefaultKinds()));
// Keywords for the floating point types.
static constexpr const char *kwHalf = "Half";
static constexpr const char *kwBFloat = "BFloat";
static constexpr const char *kwFloat = "Float";
static constexpr const char *kwDouble = "Double";
static constexpr const char *kwX86FP80 = "X86_FP80";
static constexpr const char *kwFP128 = "FP128";
static constexpr const char *kwPPCFP128 = "PPC_FP128";
/// Integral types default to the kind value being the size of the value in
/// bytes. The default is to scale from bytes to bits.
@ -104,32 +122,50 @@ static const llvm::fltSemantics &getFloatSemanticsOfKind(KindTy kind,
}
}
static MatchResult parseCode(char &code, const char *&ptr) {
/// Parse an intrinsic type code. The codes are ('a', CHARACTER), ('c',
/// COMPLEX), ('i', INTEGER), ('l', LOGICAL), and ('r', REAL).
static MatchResult parseCode(char &code, const char *&ptr, const char *endPtr) {
if (ptr >= endPtr)
return mlir::failure();
if (*ptr != 'a' && *ptr != 'c' && *ptr != 'i' && *ptr != 'l' && *ptr != 'r')
return mlir::failure();
code = *ptr++;
return mlir::success();
}
/// Same as `parseCode` but adds the ('d', DOUBLE PRECISION) code.
static MatchResult parseDefCode(char &code, const char *&ptr,
const char *endPtr) {
if (ptr >= endPtr)
return mlir::failure();
if (*ptr == 'd') {
code = *ptr++;
return mlir::success();
}
return parseCode(code, ptr, endPtr);
}
template <char ch>
static MatchResult parseSingleChar(const char *&ptr) {
if (*ptr != ch)
static MatchResult parseSingleChar(const char *&ptr, const char *endPtr) {
if (ptr >= endPtr || *ptr != ch)
return mlir::failure();
++ptr;
return mlir::success();
}
static MatchResult parseColon(const char *&ptr) {
return parseSingleChar<':'>(ptr);
static MatchResult parseColon(const char *&ptr, const char *endPtr) {
return parseSingleChar<':'>(ptr, endPtr);
}
static MatchResult parseComma(const char *&ptr) {
return parseSingleChar<','>(ptr);
static MatchResult parseComma(const char *&ptr, const char *endPtr) {
return parseSingleChar<','>(ptr, endPtr);
}
static MatchResult parseInt(unsigned &result, const char *&ptr) {
/// Recognize and parse an unsigned integer.
static MatchResult parseInt(unsigned &result, const char *&ptr,
const char *endPtr) {
const char *beg = ptr;
while (*ptr >= '0' && *ptr <= '9')
while (ptr < endPtr && *ptr >= '0' && *ptr <= '9')
ptr++;
if (beg == ptr)
return mlir::failure();
@ -141,9 +177,9 @@ static MatchResult parseInt(unsigned &result, const char *&ptr) {
return mlir::success();
}
static mlir::LogicalResult matchString(const char *&ptr,
static mlir::LogicalResult matchString(const char *&ptr, const char *endPtr,
llvm::StringRef literal) {
llvm::StringRef s(ptr);
llvm::StringRef s(ptr, endPtr - ptr);
if (s.startswith(literal)) {
ptr += literal.size();
return mlir::success();
@ -151,32 +187,35 @@ static mlir::LogicalResult matchString(const char *&ptr,
return mlir::failure();
}
static MatchResult parseTypeID(LLVMTypeID &result, const char *&ptr) {
if (mlir::succeeded(matchString(ptr, "Half"))) {
/// Recognize and parse the various floating-point keywords. These follow the
/// LLVM naming convention.
static MatchResult parseTypeID(LLVMTypeID &result, const char *&ptr,
const char *endPtr) {
if (mlir::succeeded(matchString(ptr, endPtr, kwHalf))) {
result = LLVMTypeID::HalfTyID;
return mlir::success();
}
if (mlir::succeeded(matchString(ptr, "BFloat"))) {
if (mlir::succeeded(matchString(ptr, endPtr, kwBFloat))) {
result = LLVMTypeID::BFloatTyID;
return mlir::success();
}
if (mlir::succeeded(matchString(ptr, "Float"))) {
if (mlir::succeeded(matchString(ptr, endPtr, kwFloat))) {
result = LLVMTypeID::FloatTyID;
return mlir::success();
}
if (mlir::succeeded(matchString(ptr, "Double"))) {
if (mlir::succeeded(matchString(ptr, endPtr, kwDouble))) {
result = LLVMTypeID::DoubleTyID;
return mlir::success();
}
if (mlir::succeeded(matchString(ptr, "X86_FP80"))) {
if (mlir::succeeded(matchString(ptr, endPtr, kwX86FP80))) {
result = LLVMTypeID::X86_FP80TyID;
return mlir::success();
}
if (mlir::succeeded(matchString(ptr, "FP128"))) {
if (mlir::succeeded(matchString(ptr, endPtr, kwFP128))) {
result = LLVMTypeID::FP128TyID;
return mlir::success();
}
if (mlir::succeeded(matchString(ptr, "PPC_FP128"))) {
if (mlir::succeeded(matchString(ptr, endPtr, kwPPCFP128))) {
result = LLVMTypeID::PPC_FP128TyID;
return mlir::success();
}
@ -196,6 +235,9 @@ fir::KindMapping::KindMapping(mlir::MLIRContext *context,
llvm::ArrayRef<KindTy> defs)
: KindMapping{context, clKindMapping, defs} {}
fir::KindMapping::KindMapping(mlir::MLIRContext *context)
: KindMapping{context, clKindMapping, clDefaultKinds} {}
MatchResult fir::KindMapping::badMapString(const llvm::Twine &ptr) {
auto unknown = mlir::UnknownLoc::get(context);
mlir::emitError(unknown, ptr);
@ -206,28 +248,29 @@ MatchResult fir::KindMapping::parse(llvm::StringRef kindMap) {
if (kindMap.empty())
return mlir::success();
const char *srcPtr = kindMap.begin();
const char *endPtr = kindMap.end();
while (true) {
char code = '\0';
KindTy kind = 0;
if (parseCode(code, srcPtr) || parseInt(kind, srcPtr))
if (parseCode(code, srcPtr, endPtr) || parseInt(kind, srcPtr, endPtr))
return badMapString(srcPtr);
if (code == 'a' || code == 'i' || code == 'l') {
Bitsize bits = 0;
if (parseColon(srcPtr) || parseInt(bits, srcPtr))
if (parseColon(srcPtr, endPtr) || parseInt(bits, srcPtr, endPtr))
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))
if (parseColon(srcPtr, endPtr) || parseTypeID(id, srcPtr, endPtr))
return badMapString(srcPtr);
floatMap[std::pair<char, KindTy>{code, kind}] = id;
} else {
return badMapString(srcPtr);
}
if (parseComma(srcPtr))
if (parseComma(srcPtr, endPtr))
break;
}
if (*srcPtr)
if (srcPtr > endPtr)
return badMapString(srcPtr);
return mlir::success();
}
@ -263,6 +306,51 @@ fir::KindMapping::getFloatSemantics(KindTy kind) const {
return getFloatSemanticsOfKind<'r'>(kind, floatMap);
}
std::string fir::KindMapping::mapToString() const {
std::string result;
bool addComma = false;
for (auto [k, v] : intMap) {
if (addComma)
result.append(",");
else
addComma = true;
result += k.first + std::to_string(k.second) + ":" + std::to_string(v);
}
for (auto [k, v] : floatMap) {
if (addComma)
result.append(",");
else
addComma = true;
result.append(k.first + std::to_string(k.second) + ":");
switch (v) {
default:
llvm_unreachable("unhandled type-id");
case LLVMTypeID::HalfTyID:
result.append(kwHalf);
break;
case LLVMTypeID::BFloatTyID:
result.append(kwBFloat);
break;
case LLVMTypeID::FloatTyID:
result.append(kwFloat);
break;
case LLVMTypeID::DoubleTyID:
result.append(kwDouble);
break;
case LLVMTypeID::X86_FP80TyID:
result.append(kwX86FP80);
break;
case LLVMTypeID::FP128TyID:
result.append(kwFP128);
break;
case LLVMTypeID::PPC_FP128TyID:
result.append(kwPPCFP128);
break;
}
}
return result;
}
mlir::LogicalResult
fir::KindMapping::setDefaultKinds(llvm::ArrayRef<KindTy> defs) {
if (defs.empty()) {
@ -289,6 +377,52 @@ fir::KindMapping::setDefaultKinds(llvm::ArrayRef<KindTy> defs) {
return mlir::success();
}
std::string fir::KindMapping::defaultsToString() const {
return std::string("a") + std::to_string(defaultMap.find('a')->second) +
std::string("c") + std::to_string(defaultMap.find('c')->second) +
std::string("d") + std::to_string(defaultMap.find('d')->second) +
std::string("i") + std::to_string(defaultMap.find('i')->second) +
std::string("l") + std::to_string(defaultMap.find('l')->second) +
std::string("r") + std::to_string(defaultMap.find('r')->second);
}
/// Convert a default intrinsic code into the proper position in the array. The
/// default kinds have a precise ordering.
static int codeToIndex(char code) {
switch (code) {
case 'a':
return 0;
case 'c':
return 1;
case 'd':
return 2;
case 'i':
return 3;
case 'l':
return 4;
case 'r':
return 5;
}
llvm_unreachable("invalid default kind intrinsic code");
}
std::vector<KindTy> fir::KindMapping::toDefaultKinds(llvm::StringRef defs) {
std::vector<KindTy> result(6);
char code;
KindTy kind;
if (defs.empty())
defs = clDefaultKinds;
const char *srcPtr = defs.begin();
const char *endPtr = defs.end();
while (srcPtr < endPtr) {
if (parseDefCode(code, srcPtr, endPtr) || parseInt(kind, srcPtr, endPtr))
llvm::report_fatal_error("invalid default kind code");
result[codeToIndex(code)] = kind;
}
assert(srcPtr == endPtr);
return result;
}
KindTy fir::KindMapping::defaultCharacterKind() const {
auto iter = defaultMap.find('a');
assert(iter != defaultMap.end());

View File

@ -6,6 +6,7 @@ set(LIBS
)
add_flang_unittest(FlangOptimizerTests
FIRContextTest.cpp
InternalNamesTest.cpp
KindMappingTest.cpp
)

View File

@ -0,0 +1,57 @@
//===- FIRContextTest.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/FIRContext.h"
#include "flang/Optimizer/Support/KindMapping.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "llvm/Support/Host.h"
#include "gtest/gtest.h"
#include <string>
using namespace fir;
struct StringAttributesTests : public testing::Test {
public:
void SetUp() {
kindMap = new KindMapping(&context, kindMapInit, "r42a10c14d28i40l41");
mod = mlir::ModuleOp::create(mlir::UnknownLoc::get(&context));
}
void TearDown() { delete kindMap; }
mlir::MLIRContext context;
KindMapping *kindMap{};
std::string kindMapInit =
"i10:80,l3:24,a1:8,r54:Double,r62:X86_FP80,r11:PPC_FP128";
std::string target = "powerpc64le-unknown-linux-gnu";
mlir::ModuleOp mod;
};
TEST_F(StringAttributesTests, moduleStringAttrTest) {
setTargetTriple(mod, target);
setKindMapping(mod, *kindMap);
auto triple = getTargetTriple(mod);
EXPECT_EQ(triple.getArch(), llvm::Triple::ArchType::ppc64le);
EXPECT_EQ(triple.getOS(), llvm::Triple::OSType::Linux);
auto map = getKindMapping(mod);
EXPECT_EQ(map.defaultsToString(), "a10c14d28i40l41r42");
auto mapStr = map.mapToString();
EXPECT_EQ(mapStr.size(), kindMapInit.size());
EXPECT_TRUE(mapStr.find("a1:8") != std::string::npos);
EXPECT_TRUE(mapStr.find("l3:24") != std::string::npos);
EXPECT_TRUE(mapStr.find("i10:80") != std::string::npos);
EXPECT_TRUE(mapStr.find("r11:PPC_FP128") != std::string::npos);
EXPECT_TRUE(mapStr.find("r54:Double") != std::string::npos);
EXPECT_TRUE(mapStr.find("r62:X86_FP80") != std::string::npos);
}
// main() from gtest_main

View File

@ -47,9 +47,8 @@ void validateDeconstructedName(
}
TEST(InternalNamesTest, doBlockDataTest) {
NameUniquer obj;
std::string actual = obj.doBlockData("blockdatatest");
std::string actualBlank = obj.doBlockData("");
std::string actual = NameUniquer::doBlockData("blockdatatest");
std::string actualBlank = NameUniquer::doBlockData("");
std::string expectedMangledName = "_QLblockdatatest";
std::string expectedMangledNameBlank = "_QL";
ASSERT_EQ(actual, expectedMangledName);
@ -57,9 +56,8 @@ TEST(InternalNamesTest, doBlockDataTest) {
}
TEST(InternalNamesTest, doCommonBlockTest) {
NameUniquer obj;
std::string actual = obj.doCommonBlock("hello");
std::string actualBlank = obj.doCommonBlock("");
std::string actual = NameUniquer::doCommonBlock("hello");
std::string actualBlank = NameUniquer::doCommonBlock("");
std::string expectedMangledName = "_QBhello";
std::string expectedMangledNameBlank = "_QB";
ASSERT_EQ(actual, expectedMangledName);
@ -67,108 +65,105 @@ TEST(InternalNamesTest, doCommonBlockTest) {
}
TEST(InternalNamesTest, doGeneratedTest) {
NameUniquer obj;
std::string actual = obj.doGenerated("@MAIN");
std::string actual = NameUniquer::doGenerated("@MAIN");
std::string expectedMangledName = "_QQ@MAIN";
ASSERT_EQ(actual, expectedMangledName);
std::string actual1 = obj.doGenerated("@_ZNSt8ios_base4InitC1Ev");
std::string actual1 = NameUniquer::doGenerated("@_ZNSt8ios_base4InitC1Ev");
std::string expectedMangledName1 = "_QQ@_ZNSt8ios_base4InitC1Ev";
ASSERT_EQ(actual1, expectedMangledName1);
std::string actual2 = obj.doGenerated("_QQ@MAIN");
std::string actual2 = NameUniquer::doGenerated("_QQ@MAIN");
std::string expectedMangledName2 = "_QQ_QQ@MAIN";
ASSERT_EQ(actual2, expectedMangledName2);
}
TEST(InternalNamesTest, doConstantTest) {
NameUniquer obj;
std::string actual = obj.doConstant({"mod1", "mod2"}, {"foo"}, "Hello");
std::string actual =
NameUniquer::doConstant({"mod1", "mod2"}, {"foo"}, "Hello");
std::string expectedMangledName = "_QMmod1Smod2FfooEChello";
ASSERT_EQ(actual, expectedMangledName);
}
TEST(InternalNamesTest, doProcedureTest) {
NameUniquer obj;
std::string actual = obj.doProcedure({"mod1", "mod2"}, {}, "HeLLo");
std::string actual = NameUniquer::doProcedure({"mod1", "mod2"}, {}, "HeLLo");
std::string expectedMangledName = "_QMmod1Smod2Phello";
ASSERT_EQ(actual, expectedMangledName);
}
TEST(InternalNamesTest, doTypeTest) {
NameUniquer obj;
std::string actual = obj.doType({}, {}, "mytype", {4, -1});
std::string actual = NameUniquer::doType({}, {}, "mytype", {4, -1});
std::string expectedMangledName = "_QTmytypeK4KN1";
ASSERT_EQ(actual, expectedMangledName);
}
TEST(InternalNamesTest, doIntrinsicTypeDescriptorTest) {
using IntrinsicType = fir::NameUniquer::IntrinsicType;
NameUniquer obj;
std::string actual =
obj.doIntrinsicTypeDescriptor({}, {}, IntrinsicType::REAL, 42);
NameUniquer::doIntrinsicTypeDescriptor({}, {}, IntrinsicType::REAL, 42);
std::string expectedMangledName = "_QCrealK42";
ASSERT_EQ(actual, expectedMangledName);
actual = obj.doIntrinsicTypeDescriptor({}, {}, IntrinsicType::REAL, {});
actual =
NameUniquer::doIntrinsicTypeDescriptor({}, {}, IntrinsicType::REAL, {});
expectedMangledName = "_QCrealK0";
ASSERT_EQ(actual, expectedMangledName);
actual = obj.doIntrinsicTypeDescriptor({}, {}, IntrinsicType::INTEGER, 3);
actual =
NameUniquer::doIntrinsicTypeDescriptor({}, {}, IntrinsicType::INTEGER, 3);
expectedMangledName = "_QCintegerK3";
ASSERT_EQ(actual, expectedMangledName);
actual = obj.doIntrinsicTypeDescriptor({}, {}, IntrinsicType::LOGICAL, 2);
actual =
NameUniquer::doIntrinsicTypeDescriptor({}, {}, IntrinsicType::LOGICAL, 2);
expectedMangledName = "_QClogicalK2";
ASSERT_EQ(actual, expectedMangledName);
actual = obj.doIntrinsicTypeDescriptor({}, {}, IntrinsicType::CHARACTER, 4);
actual = NameUniquer::doIntrinsicTypeDescriptor(
{}, {}, IntrinsicType::CHARACTER, 4);
expectedMangledName = "_QCcharacterK4";
ASSERT_EQ(actual, expectedMangledName);
actual = obj.doIntrinsicTypeDescriptor({}, {}, IntrinsicType::COMPLEX, 4);
actual =
NameUniquer::doIntrinsicTypeDescriptor({}, {}, IntrinsicType::COMPLEX, 4);
expectedMangledName = "_QCcomplexK4";
ASSERT_EQ(actual, expectedMangledName);
}
TEST(InternalNamesTest, doDispatchTableTest) {
NameUniquer obj;
std::string actual = obj.doDispatchTable({}, {}, "MyTYPE", {2, 8, 18});
std::string actual =
NameUniquer::doDispatchTable({}, {}, "MyTYPE", {2, 8, 18});
std::string expectedMangledName = "_QDTmytypeK2K8K18";
ASSERT_EQ(actual, expectedMangledName);
}
TEST(InternalNamesTest, doTypeDescriptorTest) {
NameUniquer obj;
std::string actual = obj.doTypeDescriptor(
std::string actual = NameUniquer::doTypeDescriptor(
{StringRef("moD1")}, {StringRef("foo")}, "MyTYPE", {2, 8});
std::string expectedMangledName = "_QMmod1FfooCTmytypeK2K8";
ASSERT_EQ(actual, expectedMangledName);
}
TEST(InternalNamesTest, doVariableTest) {
NameUniquer obj;
std::string actual = obj.doVariable(
std::string actual = NameUniquer::doVariable(
{"mod1", "mod2"}, {""}, "intvar"); // Function is present and is blank.
std::string expectedMangledName = "_QMmod1Smod2FEintvar";
ASSERT_EQ(actual, expectedMangledName);
std::string actual2 = obj.doVariable(
std::string actual2 = NameUniquer::doVariable(
{"mod1", "mod2"}, {}, "intVariable"); // Function is not present.
std::string expectedMangledName2 = "_QMmod1Smod2Eintvariable";
ASSERT_EQ(actual2, expectedMangledName2);
}
TEST(InternalNamesTest, doProgramEntry) {
NameUniquer obj;
llvm::StringRef actual = obj.doProgramEntry();
llvm::StringRef actual = NameUniquer::doProgramEntry();
std::string expectedMangledName = "_QQmain";
ASSERT_EQ(actual.str(), expectedMangledName);
}
TEST(InternalNamesTest, deconstructTest) {
NameUniquer obj;
std::pair actual = obj.deconstruct("_QBhello");
std::pair actual = NameUniquer::deconstruct("_QBhello");
auto expectedNameKind = NameUniquer::NameKind::COMMON;
struct DeconstructedName expectedComponents {
{}, {}, "hello", {}
@ -178,39 +173,38 @@ TEST(InternalNamesTest, deconstructTest) {
TEST(InternalNamesTest, complexdeconstructTest) {
using NameKind = fir::NameUniquer::NameKind;
NameUniquer obj;
std::pair actual = obj.deconstruct("_QMmodSs1modSs2modFsubPfun");
std::pair actual = NameUniquer::deconstruct("_QMmodSs1modSs2modFsubPfun");
auto expectedNameKind = NameKind::PROCEDURE;
struct DeconstructedName expectedComponents = {
{"mod", "s1mod", "s2mod"}, {"sub"}, "fun", {}};
validateDeconstructedName(actual, expectedNameKind, expectedComponents);
actual = obj.deconstruct("_QPsub");
actual = NameUniquer::deconstruct("_QPsub");
expectedNameKind = NameKind::PROCEDURE;
expectedComponents = {{}, {}, "sub", {}};
validateDeconstructedName(actual, expectedNameKind, expectedComponents);
actual = obj.deconstruct("_QBvariables");
actual = NameUniquer::deconstruct("_QBvariables");
expectedNameKind = NameKind::COMMON;
expectedComponents = {{}, {}, "variables", {}};
validateDeconstructedName(actual, expectedNameKind, expectedComponents);
actual = obj.deconstruct("_QMmodEintvar");
actual = NameUniquer::deconstruct("_QMmodEintvar");
expectedNameKind = NameKind::VARIABLE;
expectedComponents = {{"mod"}, {}, "intvar", {}};
validateDeconstructedName(actual, expectedNameKind, expectedComponents);
actual = obj.deconstruct("_QMmodECpi");
actual = NameUniquer::deconstruct("_QMmodECpi");
expectedNameKind = NameKind::CONSTANT;
expectedComponents = {{"mod"}, {}, "pi", {}};
validateDeconstructedName(actual, expectedNameKind, expectedComponents);
actual = obj.deconstruct("_QTyourtypeK4KN6");
actual = NameUniquer::deconstruct("_QTyourtypeK4KN6");
expectedNameKind = NameKind::DERIVED_TYPE;
expectedComponents = {{}, {}, "yourtype", {4, -6}};
validateDeconstructedName(actual, expectedNameKind, expectedComponents);
actual = obj.deconstruct("_QDTt");
actual = NameUniquer::deconstruct("_QDTt");
expectedNameKind = NameKind::DISPATCH_TABLE;
expectedComponents = {{}, {}, "t", {}};
validateDeconstructedName(actual, expectedNameKind, expectedComponents);

View File

@ -176,19 +176,19 @@ TEST(KindMappingDeathTests, mapTest) {
}
TEST_F(KindDefaultsTests, getIntegerBitsizeTest) {
EXPECT_EQ(defaultDefaultKinds->defaultCharacterKind(), 1u);
EXPECT_EQ(defaultDefaultKinds->defaultComplexKind(), 4u);
EXPECT_EQ(defaultDefaultKinds->defaultDoubleKind(), 8u);
EXPECT_EQ(defaultDefaultKinds->defaultIntegerKind(), 4u);
EXPECT_EQ(defaultDefaultKinds->defaultLogicalKind(), 4u);
EXPECT_EQ(defaultDefaultKinds->defaultRealKind(), 4u);
EXPECT_EQ(defaultDefaultKinds->defaultCharacterKind(), 1u);
EXPECT_EQ(defaultDefaultKinds->defaultComplexKind(), 4u);
EXPECT_EQ(defaultDefaultKinds->defaultDoubleKind(), 8u);
EXPECT_EQ(defaultDefaultKinds->defaultIntegerKind(), 4u);
EXPECT_EQ(defaultDefaultKinds->defaultLogicalKind(), 4u);
EXPECT_EQ(defaultDefaultKinds->defaultRealKind(), 4u);
EXPECT_EQ(overrideDefaultKinds->defaultCharacterKind(), 20u);
EXPECT_EQ(overrideDefaultKinds->defaultComplexKind(), 121u);
EXPECT_EQ(overrideDefaultKinds->defaultDoubleKind(), 32u);
EXPECT_EQ(overrideDefaultKinds->defaultIntegerKind(), 133u);
EXPECT_EQ(overrideDefaultKinds->defaultLogicalKind(), 44u);
EXPECT_EQ(overrideDefaultKinds->defaultRealKind(), 145u);
EXPECT_EQ(overrideDefaultKinds->defaultCharacterKind(), 20u);
EXPECT_EQ(overrideDefaultKinds->defaultComplexKind(), 121u);
EXPECT_EQ(overrideDefaultKinds->defaultDoubleKind(), 32u);
EXPECT_EQ(overrideDefaultKinds->defaultIntegerKind(), 133u);
EXPECT_EQ(overrideDefaultKinds->defaultLogicalKind(), 44u);
EXPECT_EQ(overrideDefaultKinds->defaultRealKind(), 145u);
}
// main() from gtest_main