[flang-commits] [flang] 45503fc - [fir] Add FIRBuilder utility functions
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Tue Oct 19 05:19:55 PDT 2021
Author: Valentin Clement
Date: 2021-10-19T14:19:45+02:00
New Revision: 45503fc044499a5dc88be273a2d599f8ad5bccd3
URL: https://github.com/llvm/llvm-project/commit/45503fc044499a5dc88be273a2d599f8ad5bccd3
DIFF: https://github.com/llvm/llvm-project/commit/45503fc044499a5dc88be273a2d599f8ad5bccd3.diff
LOG: [fir] Add FIRBuilder utility functions
Extract some code from the big ptach D111337. This patch
contains some utility functions from the FIRBuidler.
List of utility functions added:
- getRegion
- getModule
- getKindMap
- getRefType
- getVarLenSeqTy
- getRealType
- createNullConstant
- createRealConstant
- createRealZeroConstant
- createGlobal
- createGlobalConstant
- createStringLitOp
- getNamedFunction
- getNamedGlobal
- createFunction
- addNamedFunction
- createBool
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: kiranchandramohan
Differential Revision: https://reviews.llvm.org/D112057
Co-authored-by: Jean Perier <jperier at nvidia.com>
Co-authored-by: Eric Schweitz <eschweitz at nvidia.com>
Added:
Modified:
flang/include/flang/Optimizer/Builder/FIRBuilder.h
flang/lib/Optimizer/Builder/FIRBuilder.cpp
flang/lib/Optimizer/Dialect/FIROps.cpp
flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
index 900a974819dc4..5984055b9ea51 100644
--- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
@@ -33,10 +33,27 @@ namespace fir {
class FirOpBuilder : public mlir::OpBuilder {
public:
explicit FirOpBuilder(mlir::Operation *op, const fir::KindMapping &kindMap)
- : OpBuilder{op} {}
+ : OpBuilder{op}, kindMap{kindMap} {}
explicit FirOpBuilder(mlir::OpBuilder &builder,
const fir::KindMapping &kindMap)
- : OpBuilder{builder} {}
+ : OpBuilder{builder}, kindMap{kindMap} {}
+
+ /// Get the current Region of the insertion point.
+ mlir::Region &getRegion() { return *getBlock()->getParent(); }
+
+ /// Get the current Module
+ mlir::ModuleOp getModule() {
+ return getRegion().getParentOfType<mlir::ModuleOp>();
+ }
+
+ /// Get a reference to the kind map.
+ const fir::KindMapping &getKindMap() { return kindMap; }
+
+ /// Safely create a reference type to the type `eleTy`.
+ mlir::Type getRefType(mlir::Type eleTy);
+
+ /// Create a sequence of `eleTy` with `rank` dimensions of unknown size.
+ mlir::Type getVarLenSeqTy(mlir::Type eleTy, unsigned rank = 1);
/// Get the integer type whose bit width corresponds to the width of pointer
/// types, or is bigger.
@@ -46,19 +63,133 @@ class FirOpBuilder : public mlir::OpBuilder {
return getI64Type();
}
+ /// Get the mlir real type that implements fortran REAL(kind).
+ mlir::Type getRealType(int kind);
+
+ /// Create a null constant memory reference of type \p ptrType.
+ /// If \p ptrType is not provided, !fir.ref<none> type will be used.
+ mlir::Value createNullConstant(mlir::Location loc, mlir::Type ptrType = {});
+
/// Create an integer constant of type \p type and value \p i.
mlir::Value createIntegerConstant(mlir::Location loc, mlir::Type integerType,
std::int64_t i);
- /// Lazy creation of fir.convert op.
- mlir::Value createConvert(mlir::Location loc, mlir::Type toTy,
- mlir::Value val);
+ /// Create a real constant from an integer value.
+ mlir::Value createRealConstant(mlir::Location loc, mlir::Type realType,
+ llvm::APFloat::integerPart val);
+
+ /// Create a real constant from an APFloat value.
+ mlir::Value createRealConstant(mlir::Location loc, mlir::Type realType,
+ const llvm::APFloat &val);
+
+ /// Create a real constant of type \p realType with a value zero.
+ mlir::Value createRealZeroConstant(mlir::Location loc, mlir::Type realType) {
+ return createRealConstant(loc, realType, 0u);
+ }
+
+ /// Create a global value.
+ fir::GlobalOp createGlobal(mlir::Location loc, mlir::Type type,
+ llvm::StringRef name,
+ mlir::StringAttr linkage = {},
+ mlir::Attribute value = {}, bool isConst = false);
+
+ fir::GlobalOp createGlobal(mlir::Location loc, mlir::Type type,
+ llvm::StringRef name, bool isConst,
+ std::function<void(FirOpBuilder &)> bodyBuilder,
+ mlir::StringAttr linkage = {});
+
+ /// Create a global constant (read-only) value.
+ fir::GlobalOp createGlobalConstant(mlir::Location loc, mlir::Type type,
+ llvm::StringRef name,
+ mlir::StringAttr linkage = {},
+ mlir::Attribute value = {}) {
+ return createGlobal(loc, type, name, linkage, value, /*isConst=*/true);
+ }
+
+ fir::GlobalOp
+ createGlobalConstant(mlir::Location loc, mlir::Type type,
+ llvm::StringRef name,
+ std::function<void(FirOpBuilder &)> bodyBuilder,
+ mlir::StringAttr linkage = {}) {
+ return createGlobal(loc, type, name, /*isConst=*/true, bodyBuilder,
+ linkage);
+ }
+
+ /// Convert a StringRef string into a fir::StringLitOp.
+ fir::StringLitOp createStringLitOp(mlir::Location loc,
+ llvm::StringRef string);
+
+ //===--------------------------------------------------------------------===//
+ // Linkage helpers (inline). The default linkage is external.
+ //===--------------------------------------------------------------------===//
+
+ mlir::StringAttr createCommonLinkage() { return getStringAttr("common"); }
+
+ mlir::StringAttr createInternalLinkage() { return getStringAttr("internal"); }
+
+ mlir::StringAttr createLinkOnceLinkage() { return getStringAttr("linkonce"); }
+
+ mlir::StringAttr createWeakLinkage() { return getStringAttr("weak"); }
/// Cast the input value to IndexType.
mlir::Value convertToIndexType(mlir::Location loc, mlir::Value val) {
return createConvert(loc, getIndexType(), val);
}
+ /// Get a function by name. If the function exists in the current module, it
+ /// is returned. Otherwise, a null FuncOp is returned.
+ mlir::FuncOp getNamedFunction(llvm::StringRef name) {
+ return getNamedFunction(getModule(), name);
+ }
+
+ static mlir::FuncOp getNamedFunction(mlir::ModuleOp module,
+ llvm::StringRef name);
+
+ fir::GlobalOp getNamedGlobal(llvm::StringRef name) {
+ return getNamedGlobal(getModule(), name);
+ }
+
+ static fir::GlobalOp getNamedGlobal(mlir::ModuleOp module,
+ llvm::StringRef name);
+
+ /// Lazy creation of fir.convert op.
+ mlir::Value createConvert(mlir::Location loc, mlir::Type toTy,
+ mlir::Value val);
+
+ /// Create a new FuncOp. If the function may have already been created, use
+ /// `addNamedFunction` instead.
+ mlir::FuncOp createFunction(mlir::Location loc, llvm::StringRef name,
+ mlir::FunctionType ty) {
+ return createFunction(loc, getModule(), name, ty);
+ }
+
+ static mlir::FuncOp createFunction(mlir::Location loc, mlir::ModuleOp module,
+ llvm::StringRef name,
+ mlir::FunctionType ty);
+
+ /// Determine if the named function is already in the module. Return the
+ /// instance if found, otherwise add a new named function to the module.
+ mlir::FuncOp addNamedFunction(mlir::Location loc, llvm::StringRef name,
+ mlir::FunctionType ty) {
+ if (auto func = getNamedFunction(name))
+ return func;
+ return createFunction(loc, name, ty);
+ }
+
+ static mlir::FuncOp addNamedFunction(mlir::Location loc,
+ mlir::ModuleOp module,
+ llvm::StringRef name,
+ mlir::FunctionType ty) {
+ if (auto func = getNamedFunction(module, name))
+ return func;
+ return createFunction(loc, module, name, ty);
+ }
+
+ /// Create constant i1 with value 1. if \p b is true or 0. otherwise
+ mlir::Value createBool(mlir::Location loc, bool b) {
+ return createIntegerConstant(loc, getIntegerType(1), b ? 1 : 0);
+ }
+
//===--------------------------------------------------------------------===//
// If-Then-Else generation helper
//===--------------------------------------------------------------------===//
@@ -126,8 +257,30 @@ class FirOpBuilder : public mlir::OpBuilder {
/// Generate code testing \p addr is a null address.
mlir::Value genIsNull(mlir::Location loc, mlir::Value addr);
+
+private:
+ const KindMapping &kindMap;
};
} // namespace fir
+namespace fir::factory {
+
+//===--------------------------------------------------------------------===//
+// String literal helper helpers
+//===--------------------------------------------------------------------===//
+
+/// Unique a compiler generated identifier. A short prefix should be provided
+/// to hint at the origin of the identifier.
+std::string uniqueCGIdent(llvm::StringRef prefix, llvm::StringRef name);
+
+//===----------------------------------------------------------------------===//
+// Location helpers
+//===----------------------------------------------------------------------===//
+
+/// Generate a constant of the given type with the location line number
+mlir::Value locationToLineNo(fir::FirOpBuilder &, mlir::Location, mlir::Type);
+
+} // namespace fir::factory
+
#endif // FORTRAN_OPTIMIZER_BUILDER_FIRBUILDER_H
diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index 6f98e6029916f..22e77d405f76e 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -7,6 +7,70 @@
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Dialect/FIROpsSupport.h"
+#include "flang/Optimizer/Support/FatalError.h"
+#include "flang/Optimizer/Support/InternalNames.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MD5.h"
+
+static llvm::cl::opt<std::size_t>
+ nameLengthHashSize("length-to-hash-string-literal",
+ llvm::cl::desc("string literals that exceed this length"
+ " will use a hash value as their symbol "
+ "name"),
+ llvm::cl::init(32));
+
+mlir::FuncOp fir::FirOpBuilder::createFunction(mlir::Location loc,
+ mlir::ModuleOp module,
+ llvm::StringRef name,
+ mlir::FunctionType ty) {
+ return fir::createFuncOp(loc, module, name, ty);
+}
+
+mlir::FuncOp fir::FirOpBuilder::getNamedFunction(mlir::ModuleOp modOp,
+ llvm::StringRef name) {
+ return modOp.lookupSymbol<mlir::FuncOp>(name);
+}
+
+fir::GlobalOp fir::FirOpBuilder::getNamedGlobal(mlir::ModuleOp modOp,
+ llvm::StringRef name) {
+ return modOp.lookupSymbol<fir::GlobalOp>(name);
+}
+
+mlir::Type fir::FirOpBuilder::getRefType(mlir::Type eleTy) {
+ assert(!eleTy.isa<fir::ReferenceType>() && "cannot be a reference type");
+ return fir::ReferenceType::get(eleTy);
+}
+
+mlir::Type fir::FirOpBuilder::getVarLenSeqTy(mlir::Type eleTy, unsigned rank) {
+ fir::SequenceType::Shape shape(rank, fir::SequenceType::getUnknownExtent());
+ return fir::SequenceType::get(shape, eleTy);
+}
+
+mlir::Type fir::FirOpBuilder::getRealType(int kind) {
+ switch (kindMap.getRealTypeID(kind)) {
+ case llvm::Type::TypeID::HalfTyID:
+ return mlir::FloatType::getF16(getContext());
+ case llvm::Type::TypeID::FloatTyID:
+ return mlir::FloatType::getF32(getContext());
+ case llvm::Type::TypeID::DoubleTyID:
+ return mlir::FloatType::getF64(getContext());
+ case llvm::Type::TypeID::X86_FP80TyID:
+ return mlir::FloatType::getF80(getContext());
+ case llvm::Type::TypeID::FP128TyID:
+ return mlir::FloatType::getF128(getContext());
+ default:
+ fir::emitFatalError(UnknownLoc::get(getContext()),
+ "unsupported type !fir.real<kind>");
+ }
+}
+
+mlir::Value fir::FirOpBuilder::createNullConstant(mlir::Location loc,
+ mlir::Type ptrType) {
+ auto ty = ptrType ? ptrType : getRefType(getNoneType());
+ return create<fir::ZeroOp>(loc, ty);
+}
mlir::Value fir::FirOpBuilder::createIntegerConstant(mlir::Location loc,
mlir::Type ty,
@@ -14,6 +78,74 @@ mlir::Value fir::FirOpBuilder::createIntegerConstant(mlir::Location loc,
return create<mlir::ConstantOp>(loc, ty, getIntegerAttr(ty, cst));
}
+mlir::Value
+fir::FirOpBuilder::createRealConstant(mlir::Location loc, mlir::Type fltTy,
+ llvm::APFloat::integerPart val) {
+ auto apf = [&]() -> llvm::APFloat {
+ if (auto ty = fltTy.dyn_cast<fir::RealType>())
+ return llvm::APFloat(kindMap.getFloatSemantics(ty.getFKind()), val);
+ if (fltTy.isF16())
+ return llvm::APFloat(llvm::APFloat::IEEEhalf(), val);
+ if (fltTy.isBF16())
+ return llvm::APFloat(llvm::APFloat::BFloat(), val);
+ if (fltTy.isF32())
+ return llvm::APFloat(llvm::APFloat::IEEEsingle(), val);
+ if (fltTy.isF64())
+ return llvm::APFloat(llvm::APFloat::IEEEdouble(), val);
+ if (fltTy.isF80())
+ return llvm::APFloat(llvm::APFloat::x87DoubleExtended(), val);
+ if (fltTy.isF128())
+ return llvm::APFloat(llvm::APFloat::IEEEquad(), val);
+ llvm_unreachable("unhandled MLIR floating-point type");
+ };
+ return createRealConstant(loc, fltTy, apf());
+}
+
+mlir::Value fir::FirOpBuilder::createRealConstant(mlir::Location loc,
+ mlir::Type fltTy,
+ const llvm::APFloat &value) {
+ if (fltTy.isa<mlir::FloatType>()) {
+ auto attr = getFloatAttr(fltTy, value);
+ return create<mlir::arith::ConstantOp>(loc, fltTy, attr);
+ }
+ llvm_unreachable("should use builtin floating-point type");
+}
+
+/// Create a global variable in the (read-only) data section. A global variable
+/// must have a unique name to identify and reference it.
+fir::GlobalOp
+fir::FirOpBuilder::createGlobal(mlir::Location loc, mlir::Type type,
+ llvm::StringRef name, mlir::StringAttr linkage,
+ mlir::Attribute value, bool isConst) {
+ auto module = getModule();
+ auto insertPt = saveInsertionPoint();
+ if (auto glob = module.lookupSymbol<fir::GlobalOp>(name))
+ return glob;
+ setInsertionPoint(module.getBody(), module.getBody()->end());
+ auto glob = create<fir::GlobalOp>(loc, name, isConst, type, value, linkage);
+ restoreInsertionPoint(insertPt);
+ return glob;
+}
+
+fir::GlobalOp fir::FirOpBuilder::createGlobal(
+ mlir::Location loc, mlir::Type type, llvm::StringRef name, bool isConst,
+ std::function<void(FirOpBuilder &)> bodyBuilder, mlir::StringAttr linkage) {
+ auto module = getModule();
+ auto insertPt = saveInsertionPoint();
+ if (auto glob = module.lookupSymbol<fir::GlobalOp>(name))
+ return glob;
+ setInsertionPoint(module.getBody(), module.getBody()->end());
+ auto glob = create<fir::GlobalOp>(loc, name, isConst, type, mlir::Attribute{},
+ linkage);
+ auto ®ion = glob.getRegion();
+ region.push_back(new mlir::Block);
+ auto &block = glob.getRegion().back();
+ setInsertionPointToStart(&block);
+ bodyBuilder(*this);
+ restoreInsertionPoint(insertPt);
+ return glob;
+}
+
mlir::Value fir::FirOpBuilder::createConvert(mlir::Location loc,
mlir::Type toTy, mlir::Value val) {
if (val.getType() != toTy) {
@@ -23,6 +155,19 @@ mlir::Value fir::FirOpBuilder::createConvert(mlir::Location loc,
return val;
}
+fir::StringLitOp fir::FirOpBuilder::createStringLitOp(mlir::Location loc,
+ llvm::StringRef data) {
+ auto type = fir::CharacterType::get(getContext(), 1, data.size());
+ auto strAttr = mlir::StringAttr::get(getContext(), data);
+ auto valTag = mlir::Identifier::get(fir::StringLitOp::value(), getContext());
+ mlir::NamedAttribute dataAttr(valTag, strAttr);
+ auto sizeTag = mlir::Identifier::get(fir::StringLitOp::size(), getContext());
+ mlir::NamedAttribute sizeAttr(sizeTag, getI64IntegerAttr(data.size()));
+ llvm::SmallVector<mlir::NamedAttribute> attrs{dataAttr, sizeAttr};
+ return create<fir::StringLitOp>(loc, llvm::ArrayRef<mlir::Type>{type},
+ llvm::None, attrs);
+}
+
static mlir::Value genNullPointerComparison(fir::FirOpBuilder &builder,
mlir::Location loc,
mlir::Value addr,
@@ -41,3 +186,31 @@ mlir::Value fir::FirOpBuilder::genIsNotNull(mlir::Location loc,
mlir::Value fir::FirOpBuilder::genIsNull(mlir::Location loc, mlir::Value addr) {
return genNullPointerComparison(*this, loc, addr, arith::CmpIPredicate::eq);
}
+
+std::string fir::factory::uniqueCGIdent(llvm::StringRef prefix,
+ llvm::StringRef name) {
+ // For "long" identifiers use a hash value
+ if (name.size() > nameLengthHashSize) {
+ llvm::MD5 hash;
+ hash.update(name);
+ llvm::MD5::MD5Result result;
+ hash.final(result);
+ llvm::SmallString<32> str;
+ llvm::MD5::stringifyResult(result, str);
+ std::string hashName = prefix.str();
+ hashName.append(".").append(str.c_str());
+ return fir::NameUniquer::doGenerated(hashName);
+ }
+ // "Short" identifiers use a reversible hex string
+ std::string nm = prefix.str();
+ return fir::NameUniquer::doGenerated(
+ nm.append(".").append(llvm::toHex(name)));
+}
+
+mlir::Value fir::factory::locationToLineNo(fir::FirOpBuilder &builder,
+ mlir::Location loc,
+ mlir::Type type) {
+ if (auto flc = loc.dyn_cast<mlir::FileLineColLoc>())
+ return builder.createIntegerConstant(loc, type, flc.getLine());
+ return builder.createIntegerConstant(loc, type, 0);
+}
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index d46785ab6f8e6..287cc6ad3321f 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -3176,7 +3176,7 @@ mlir::FuncOp fir::createFuncOp(mlir::Location loc, mlir::ModuleOp module,
if (auto f = module.lookupSymbol<mlir::FuncOp>(name))
return f;
mlir::OpBuilder modBuilder(module.getBodyRegion());
- modBuilder.setInsertionPoint(module.getBody()->getTerminator());
+ modBuilder.setInsertionPointToEnd(module.getBody());
auto result = modBuilder.create<mlir::FuncOp>(loc, name, type, attrs);
result.setVisibility(mlir::SymbolTable::Visibility::Private);
return result;
diff --git a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
index 07ae0bcd33862..06b45756b454b 100644
--- a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
+++ b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
@@ -16,8 +16,19 @@ struct FIRBuilderTest : public testing::Test {
void SetUp() override {
fir::KindMapping kindMap(&context);
mlir::OpBuilder builder(&context);
- firBuilder = std::make_unique<fir::FirOpBuilder>(builder, kindMap);
+ auto loc = builder.getUnknownLoc();
+
+ // Set up a Module with a dummy function operation inside.
+ // Set the insertion point in the function entry block.
+ mlir::ModuleOp mod = builder.create<mlir::ModuleOp>(loc);
+ mlir::FuncOp func = mlir::FuncOp::create(
+ loc, "func1", builder.getFunctionType(llvm::None, llvm::None));
+ auto *entryBlock = func.addEntryBlock();
+ mod.push_back(mod);
+ builder.setInsertionPointToStart(entryBlock);
+
fir::support::loadDialects(context);
+ firBuilder = std::make_unique<fir::FirOpBuilder>(mod, kindMap);
}
fir::FirOpBuilder &getBuilder() { return *firBuilder; }
@@ -34,6 +45,14 @@ static arith::CmpIOp createCondition(fir::FirOpBuilder &builder) {
loc, arith::CmpIPredicate::eq, zero1, zero2);
}
+static void checkIntegerConstant(mlir::Value value, mlir::Type ty, int64_t v) {
+ EXPECT_TRUE(mlir::isa<ConstantOp>(value.getDefiningOp()));
+ auto cstOp = dyn_cast<ConstantOp>(value.getDefiningOp());
+ EXPECT_EQ(ty, cstOp.getType());
+ auto valueAttr = cstOp.getValue().dyn_cast_or_null<IntegerAttr>();
+ EXPECT_EQ(v, valueAttr.getInt());
+}
+
//===----------------------------------------------------------------------===//
// IfBuilder tests
//===----------------------------------------------------------------------===//
@@ -99,3 +118,128 @@ TEST_F(FIRBuilderTest, genIsNull) {
auto cmpOp = dyn_cast<arith::CmpIOp>(res.getDefiningOp());
EXPECT_EQ(arith::CmpIPredicate::eq, cmpOp.predicate());
}
+
+TEST_F(FIRBuilderTest, createZeroConstant) {
+ auto builder = getBuilder();
+ auto loc = builder.getUnknownLoc();
+
+ auto cst = builder.createNullConstant(loc);
+ EXPECT_TRUE(mlir::isa<fir::ZeroOp>(cst.getDefiningOp()));
+ auto zeroOp = dyn_cast<fir::ZeroOp>(cst.getDefiningOp());
+ EXPECT_EQ(fir::ReferenceType::get(builder.getNoneType()),
+ zeroOp.getResult().getType());
+ auto idxTy = builder.getIndexType();
+
+ cst = builder.createNullConstant(loc, idxTy);
+ EXPECT_TRUE(mlir::isa<fir::ZeroOp>(cst.getDefiningOp()));
+ zeroOp = dyn_cast<fir::ZeroOp>(cst.getDefiningOp());
+ EXPECT_EQ(builder.getIndexType(), zeroOp.getResult().getType());
+}
+
+TEST_F(FIRBuilderTest, createRealZeroConstant) {
+ auto builder = getBuilder();
+ auto ctx = builder.getContext();
+ auto loc = builder.getUnknownLoc();
+ auto realTy = mlir::FloatType::getF64(ctx);
+ auto cst = builder.createRealZeroConstant(loc, realTy);
+ EXPECT_TRUE(mlir::isa<mlir::arith::ConstantOp>(cst.getDefiningOp()));
+ auto cstOp = dyn_cast<mlir::arith::ConstantOp>(cst.getDefiningOp());
+ EXPECT_EQ(realTy, cstOp.getType());
+ EXPECT_EQ(0u, cstOp.value().cast<FloatAttr>().getValue().convertToDouble());
+}
+
+TEST_F(FIRBuilderTest, createBool) {
+ auto builder = getBuilder();
+ auto loc = builder.getUnknownLoc();
+ auto b = builder.createBool(loc, false);
+ checkIntegerConstant(b, builder.getIntegerType(1), 0);
+}
+
+TEST_F(FIRBuilderTest, getVarLenSeqTy) {
+ auto builder = getBuilder();
+ auto ty = builder.getVarLenSeqTy(builder.getI64Type());
+ EXPECT_TRUE(ty.isa<fir::SequenceType>());
+ fir::SequenceType seqTy = ty.dyn_cast<fir::SequenceType>();
+ EXPECT_EQ(1u, seqTy.getDimension());
+ EXPECT_TRUE(fir::unwrapSequenceType(ty).isInteger(64));
+}
+
+TEST_F(FIRBuilderTest, getNamedFunction) {
+ auto builder = getBuilder();
+ auto func2 = builder.getNamedFunction("func2");
+ EXPECT_EQ(nullptr, func2);
+ auto loc = builder.getUnknownLoc();
+ func2 = builder.createFunction(
+ loc, "func2", builder.getFunctionType(llvm::None, llvm::None));
+ auto func2query = builder.getNamedFunction("func2");
+ EXPECT_EQ(func2, func2query);
+}
+
+TEST_F(FIRBuilderTest, createGlobal1) {
+ auto builder = getBuilder();
+ auto loc = builder.getUnknownLoc();
+ auto i64Type = IntegerType::get(builder.getContext(), 64);
+ auto global = builder.createGlobal(
+ loc, i64Type, "global1", builder.createInternalLinkage(), {}, true);
+ EXPECT_TRUE(mlir::isa<fir::GlobalOp>(global));
+ EXPECT_EQ("global1", global.sym_name());
+ EXPECT_TRUE(global.constant().hasValue());
+ EXPECT_EQ(i64Type, global.type());
+ EXPECT_TRUE(global.linkName().hasValue());
+ EXPECT_EQ(
+ builder.createInternalLinkage().getValue(), global.linkName().getValue());
+ EXPECT_FALSE(global.initVal().hasValue());
+
+ auto g1 = builder.getNamedGlobal("global1");
+ EXPECT_EQ(global, g1);
+ auto g2 = builder.getNamedGlobal("global7");
+ EXPECT_EQ(nullptr, g2);
+ auto g3 = builder.getNamedGlobal("");
+ EXPECT_EQ(nullptr, g3);
+}
+
+TEST_F(FIRBuilderTest, createGlobal2) {
+ auto builder = getBuilder();
+ auto loc = builder.getUnknownLoc();
+ auto i32Type = IntegerType::get(builder.getContext(), 32);
+ auto attr = builder.getIntegerAttr(i32Type, 16);
+ auto global = builder.createGlobal(
+ loc, i32Type, "global2", builder.createLinkOnceLinkage(), attr, false);
+ EXPECT_TRUE(mlir::isa<fir::GlobalOp>(global));
+ EXPECT_EQ("global2", global.sym_name());
+ EXPECT_FALSE(global.constant().hasValue());
+ EXPECT_EQ(i32Type, global.type());
+ EXPECT_TRUE(global.initVal().hasValue());
+ EXPECT_TRUE(global.initVal().getValue().isa<mlir::IntegerAttr>());
+ EXPECT_EQ(
+ 16, global.initVal().getValue().cast<mlir::IntegerAttr>().getValue());
+ EXPECT_TRUE(global.linkName().hasValue());
+ EXPECT_EQ(
+ builder.createLinkOnceLinkage().getValue(), global.linkName().getValue());
+}
+
+TEST_F(FIRBuilderTest, uniqueCFIdent) {
+ auto str1 = fir::factory::uniqueCGIdent("", "func1");
+ EXPECT_EQ("_QQ.66756E6331", str1);
+ str1 = fir::factory::uniqueCGIdent("", "");
+ EXPECT_EQ("_QQ.", str1);
+ str1 = fir::factory::uniqueCGIdent("pr", "func1");
+ EXPECT_EQ("_QQpr.66756E6331", str1);
+ str1 = fir::factory::uniqueCGIdent(
+ "", "longnamemorethan32characterneedshashing");
+ EXPECT_EQ("_QQ.c22a886b2f30ea8c064ef1178377fc31", str1);
+ str1 = fir::factory::uniqueCGIdent(
+ "pr", "longnamemorethan32characterneedshashing");
+ EXPECT_EQ("_QQpr.c22a886b2f30ea8c064ef1178377fc31", str1);
+}
+
+TEST_F(FIRBuilderTest, locationToLineNo) {
+ auto builder = getBuilder();
+ auto loc = mlir::FileLineColLoc::get(builder.getIdentifier("file1"), 10, 5);
+ mlir::Value line =
+ fir::factory::locationToLineNo(builder, loc, builder.getI64Type());
+ checkIntegerConstant(line, builder.getI64Type(), 10);
+ line = fir::factory::locationToLineNo(
+ builder, builder.getUnknownLoc(), builder.getI64Type());
+ checkIntegerConstant(line, builder.getI64Type(), 0);
+}
More information about the flang-commits
mailing list