[flang-commits] [flang] c68d289 - [flang][fir] Update flang test tool support classes.
Eric Schweitz via flang-commits
flang-commits at lists.llvm.org
Fri Feb 19 16:02:54 PST 2021
Author: Eric Schweitz
Date: 2021-02-19T16:02:39-08:00
New Revision: c68d2895a1f4019b387c69d1e5eec31b0eb5e7b0
URL: https://github.com/llvm/llvm-project/commit/c68d2895a1f4019b387c69d1e5eec31b0eb5e7b0
DIFF: https://github.com/llvm/llvm-project/commit/c68d2895a1f4019b387c69d1e5eec31b0eb5e7b0.diff
LOG: [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
Added:
flang/include/flang/Optimizer/Support/FIRContext.h
flang/lib/Optimizer/Support/FIRContext.cpp
flang/unittests/Optimizer/FIRContextTest.cpp
Modified:
flang/include/flang/Optimizer/Support/InternalNames.h
flang/include/flang/Optimizer/Support/KindMapping.h
flang/lib/Optimizer/CMakeLists.txt
flang/lib/Optimizer/Support/InternalNames.cpp
flang/lib/Optimizer/Support/KindMapping.cpp
flang/unittests/Optimizer/CMakeLists.txt
flang/unittests/Optimizer/InternalNamesTest.cpp
flang/unittests/Optimizer/KindMappingTest.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Support/FIRContext.h b/flang/include/flang/Optimizer/Support/FIRContext.h
new file mode 100644
index 0000000000000..7f236081e2710
--- /dev/null
+++ b/flang/include/flang/Optimizer/Support/FIRContext.h
@@ -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
diff --git a/flang/include/flang/Optimizer/Support/InternalNames.h b/flang/include/flang/Optimizer/Support/InternalNames.h
index b2d741c9e403d..fa98cc2a8e490 100644
--- a/flang/include/flang/Optimizer/Support/InternalNames.h
+++ b/flang/include/flang/Optimizer/Support/InternalNames.h
@@ -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
diff --git a/flang/include/flang/Optimizer/Support/KindMapping.h b/flang/include/flang/Optimizer/Support/KindMapping.h
index faef765841ab9..cdde38599782a 100644
--- a/flang/include/flang/Optimizer/Support/KindMapping.h
+++ b/flang/include/flang/Optimizer/Support/KindMapping.h
@@ -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 @@ class KindMapping {
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 @@ class KindMapping {
/// 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 @@ class KindMapping {
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 @@ class KindMapping {
} // namespace fir
-#endif // OPTIMIZER_SUPPORT_KINDMAPPING_H
+#endif // FORTRAN_OPTIMIZER_SUPPORT_KINDMAPPING_H
diff --git a/flang/lib/Optimizer/CMakeLists.txt b/flang/lib/Optimizer/CMakeLists.txt
index 9903f3a3d9450..9088d08f16c98 100644
--- a/flang/lib/Optimizer/CMakeLists.txt
+++ b/flang/lib/Optimizer/CMakeLists.txt
@@ -6,6 +6,7 @@ add_flang_library(FIROptimizer
Dialect/FIROps.cpp
Dialect/FIRType.cpp
+ Support/FIRContext.cpp
Support/InternalNames.cpp
Support/KindMapping.cpp
diff --git a/flang/lib/Optimizer/Support/FIRContext.cpp b/flang/lib/Optimizer/Support/FIRContext.cpp
new file mode 100644
index 0000000000000..b4910dff9f7df
--- /dev/null
+++ b/flang/lib/Optimizer/Support/FIRContext.cpp
@@ -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();
+}
diff --git a/flang/lib/Optimizer/Support/InternalNames.cpp b/flang/lib/Optimizer/Support/InternalNames.cpp
index 5b12787860abe..a7493d7494fee 100644
--- a/flang/lib/Optimizer/Support/InternalNames.cpp
+++ b/flang/lib/Optimizer/Support/InternalNames.cpp
@@ -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"
diff --git a/flang/lib/Optimizer/Support/KindMapping.cpp b/flang/lib/Optimizer/Support/KindMapping.cpp
index 6cb8d5e5c78eb..a8abcb24073a6 100644
--- a/flang/lib/Optimizer/Support/KindMapping.cpp
+++ b/flang/lib/Optimizer/Support/KindMapping.cpp
@@ -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());
diff --git a/flang/unittests/Optimizer/CMakeLists.txt b/flang/unittests/Optimizer/CMakeLists.txt
index a021ce0a00a27..3996c69b1a982 100644
--- a/flang/unittests/Optimizer/CMakeLists.txt
+++ b/flang/unittests/Optimizer/CMakeLists.txt
@@ -6,6 +6,7 @@ set(LIBS
)
add_flang_unittest(FlangOptimizerTests
+ FIRContextTest.cpp
InternalNamesTest.cpp
KindMappingTest.cpp
)
diff --git a/flang/unittests/Optimizer/FIRContextTest.cpp b/flang/unittests/Optimizer/FIRContextTest.cpp
new file mode 100644
index 0000000000000..5976f2c4979f3
--- /dev/null
+++ b/flang/unittests/Optimizer/FIRContextTest.cpp
@@ -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
diff --git a/flang/unittests/Optimizer/InternalNamesTest.cpp b/flang/unittests/Optimizer/InternalNamesTest.cpp
index 0f22fee47950c..831d7997e3f82 100644
--- a/flang/unittests/Optimizer/InternalNamesTest.cpp
+++ b/flang/unittests/Optimizer/InternalNamesTest.cpp
@@ -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 at MAIN";
ASSERT_EQ(actual, expectedMangledName);
- std::string actual1 = obj.doGenerated("@_ZNSt8ios_base4InitC1Ev");
+ std::string actual1 = NameUniquer::doGenerated("@_ZNSt8ios_base4InitC1Ev");
std::string expectedMangledName1 = "_QQ at _ZNSt8ios_base4InitC1Ev";
ASSERT_EQ(actual1, expectedMangledName1);
- std::string actual2 = obj.doGenerated("_QQ at MAIN");
+ std::string actual2 = NameUniquer::doGenerated("_QQ at MAIN");
std::string expectedMangledName2 = "_QQ_QQ at 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);
diff --git a/flang/unittests/Optimizer/KindMappingTest.cpp b/flang/unittests/Optimizer/KindMappingTest.cpp
index d99b8179f55ee..6a11d61817159 100644
--- a/flang/unittests/Optimizer/KindMappingTest.cpp
+++ b/flang/unittests/Optimizer/KindMappingTest.cpp
@@ -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(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(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);
}
// main() from gtest_main
More information about the flang-commits
mailing list