[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 &region = 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