1 //===- FIRBuilderTest.cpp -- FIRBuilder unit tests ------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "flang/Optimizer/Builder/FIRBuilder.h"
10 #include "gtest/gtest.h"
11 #include "flang/Optimizer/Builder/BoxValue.h"
12 #include "flang/Optimizer/Support/InitFIR.h"
13 #include "flang/Optimizer/Support/KindMapping.h"
14 
15 using namespace mlir;
16 
17 struct FIRBuilderTest : public testing::Test {
18 public:
SetUpFIRBuilderTest19   void SetUp() override {
20     fir::support::loadDialects(context);
21 
22     llvm::ArrayRef<fir::KindTy> defs;
23     fir::KindMapping kindMap(&context, defs);
24     mlir::OpBuilder builder(&context);
25     auto loc = builder.getUnknownLoc();
26 
27     // Set up a Module with a dummy function operation inside.
28     // Set the insertion point in the function entry block.
29     mlir::ModuleOp mod = builder.create<mlir::ModuleOp>(loc);
30     mlir::func::FuncOp func = mlir::func::FuncOp::create(
31         loc, "func1", builder.getFunctionType(llvm::None, llvm::None));
32     auto *entryBlock = func.addEntryBlock();
33     mod.push_back(mod);
34     builder.setInsertionPointToStart(entryBlock);
35 
36     firBuilder = std::make_unique<fir::FirOpBuilder>(mod, kindMap);
37   }
38 
getBuilderFIRBuilderTest39   fir::FirOpBuilder &getBuilder() { return *firBuilder; }
40 
41   mlir::MLIRContext context;
42   std::unique_ptr<fir::FirOpBuilder> firBuilder;
43 };
44 
createCondition(fir::FirOpBuilder & builder)45 static arith::CmpIOp createCondition(fir::FirOpBuilder &builder) {
46   auto loc = builder.getUnknownLoc();
47   auto zero1 = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
48   auto zero2 = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
49   return builder.create<arith::CmpIOp>(
50       loc, arith::CmpIPredicate::eq, zero1, zero2);
51 }
52 
checkIntegerConstant(mlir::Value value,mlir::Type ty,int64_t v)53 static void checkIntegerConstant(mlir::Value value, mlir::Type ty, int64_t v) {
54   EXPECT_TRUE(mlir::isa<mlir::arith::ConstantOp>(value.getDefiningOp()));
55   auto cstOp = dyn_cast<mlir::arith::ConstantOp>(value.getDefiningOp());
56   EXPECT_EQ(ty, cstOp.getType());
57   auto valueAttr = cstOp.getValue().dyn_cast_or_null<IntegerAttr>();
58   EXPECT_EQ(v, valueAttr.getInt());
59 }
60 
61 //===----------------------------------------------------------------------===//
62 // IfBuilder tests
63 //===----------------------------------------------------------------------===//
64 
TEST_F(FIRBuilderTest,genIfThen)65 TEST_F(FIRBuilderTest, genIfThen) {
66   auto builder = getBuilder();
67   auto loc = builder.getUnknownLoc();
68   auto cdt = createCondition(builder);
69   auto ifBuilder = builder.genIfThen(loc, cdt);
70   EXPECT_FALSE(ifBuilder.getIfOp().getThenRegion().empty());
71   EXPECT_TRUE(ifBuilder.getIfOp().getElseRegion().empty());
72 }
73 
TEST_F(FIRBuilderTest,genIfThenElse)74 TEST_F(FIRBuilderTest, genIfThenElse) {
75   auto builder = getBuilder();
76   auto loc = builder.getUnknownLoc();
77   auto cdt = createCondition(builder);
78   auto ifBuilder = builder.genIfThenElse(loc, cdt);
79   EXPECT_FALSE(ifBuilder.getIfOp().getThenRegion().empty());
80   EXPECT_FALSE(ifBuilder.getIfOp().getElseRegion().empty());
81 }
82 
TEST_F(FIRBuilderTest,genIfWithThen)83 TEST_F(FIRBuilderTest, genIfWithThen) {
84   auto builder = getBuilder();
85   auto loc = builder.getUnknownLoc();
86   auto cdt = createCondition(builder);
87   auto ifBuilder = builder.genIfOp(loc, {}, cdt, false);
88   EXPECT_FALSE(ifBuilder.getIfOp().getThenRegion().empty());
89   EXPECT_TRUE(ifBuilder.getIfOp().getElseRegion().empty());
90 }
91 
TEST_F(FIRBuilderTest,genIfWithThenAndElse)92 TEST_F(FIRBuilderTest, genIfWithThenAndElse) {
93   auto builder = getBuilder();
94   auto loc = builder.getUnknownLoc();
95   auto cdt = createCondition(builder);
96   auto ifBuilder = builder.genIfOp(loc, {}, cdt, true);
97   EXPECT_FALSE(ifBuilder.getIfOp().getThenRegion().empty());
98   EXPECT_FALSE(ifBuilder.getIfOp().getElseRegion().empty());
99 }
100 
101 //===----------------------------------------------------------------------===//
102 // Helper functions tests
103 //===----------------------------------------------------------------------===//
104 
TEST_F(FIRBuilderTest,genIsNotNullAddr)105 TEST_F(FIRBuilderTest, genIsNotNullAddr) {
106   auto builder = getBuilder();
107   auto loc = builder.getUnknownLoc();
108   auto dummyValue =
109       builder.createIntegerConstant(loc, builder.getIndexType(), 0);
110   auto res = builder.genIsNotNullAddr(loc, dummyValue);
111   EXPECT_TRUE(mlir::isa<arith::CmpIOp>(res.getDefiningOp()));
112   auto cmpOp = dyn_cast<arith::CmpIOp>(res.getDefiningOp());
113   EXPECT_EQ(arith::CmpIPredicate::ne, cmpOp.getPredicate());
114 }
115 
TEST_F(FIRBuilderTest,genIsNullAddr)116 TEST_F(FIRBuilderTest, genIsNullAddr) {
117   auto builder = getBuilder();
118   auto loc = builder.getUnknownLoc();
119   auto dummyValue =
120       builder.createIntegerConstant(loc, builder.getIndexType(), 0);
121   auto res = builder.genIsNullAddr(loc, dummyValue);
122   EXPECT_TRUE(mlir::isa<arith::CmpIOp>(res.getDefiningOp()));
123   auto cmpOp = dyn_cast<arith::CmpIOp>(res.getDefiningOp());
124   EXPECT_EQ(arith::CmpIPredicate::eq, cmpOp.getPredicate());
125 }
126 
TEST_F(FIRBuilderTest,createZeroConstant)127 TEST_F(FIRBuilderTest, createZeroConstant) {
128   auto builder = getBuilder();
129   auto loc = builder.getUnknownLoc();
130 
131   auto cst = builder.createNullConstant(loc);
132   EXPECT_TRUE(mlir::isa<fir::ZeroOp>(cst.getDefiningOp()));
133   auto zeroOp = dyn_cast<fir::ZeroOp>(cst.getDefiningOp());
134   EXPECT_EQ(fir::ReferenceType::get(builder.getNoneType()),
135       zeroOp.getResult().getType());
136   auto idxTy = builder.getIndexType();
137 
138   cst = builder.createNullConstant(loc, idxTy);
139   EXPECT_TRUE(mlir::isa<fir::ZeroOp>(cst.getDefiningOp()));
140   zeroOp = dyn_cast<fir::ZeroOp>(cst.getDefiningOp());
141   EXPECT_EQ(builder.getIndexType(), zeroOp.getResult().getType());
142 }
143 
TEST_F(FIRBuilderTest,createRealZeroConstant)144 TEST_F(FIRBuilderTest, createRealZeroConstant) {
145   auto builder = getBuilder();
146   auto ctx = builder.getContext();
147   auto loc = builder.getUnknownLoc();
148   auto realTy = mlir::FloatType::getF64(ctx);
149   auto cst = builder.createRealZeroConstant(loc, realTy);
150   EXPECT_TRUE(mlir::isa<arith::ConstantOp>(cst.getDefiningOp()));
151   auto cstOp = dyn_cast<arith::ConstantOp>(cst.getDefiningOp());
152   EXPECT_EQ(realTy, cstOp.getType());
153   EXPECT_EQ(
154       0u, cstOp.getValue().cast<FloatAttr>().getValue().convertToDouble());
155 }
156 
TEST_F(FIRBuilderTest,createBool)157 TEST_F(FIRBuilderTest, createBool) {
158   auto builder = getBuilder();
159   auto loc = builder.getUnknownLoc();
160   auto b = builder.createBool(loc, false);
161   checkIntegerConstant(b, builder.getIntegerType(1), 0);
162 }
163 
TEST_F(FIRBuilderTest,getVarLenSeqTy)164 TEST_F(FIRBuilderTest, getVarLenSeqTy) {
165   auto builder = getBuilder();
166   auto ty = builder.getVarLenSeqTy(builder.getI64Type());
167   EXPECT_TRUE(ty.isa<fir::SequenceType>());
168   fir::SequenceType seqTy = ty.dyn_cast<fir::SequenceType>();
169   EXPECT_EQ(1u, seqTy.getDimension());
170   EXPECT_TRUE(fir::unwrapSequenceType(ty).isInteger(64));
171 }
172 
TEST_F(FIRBuilderTest,getNamedFunction)173 TEST_F(FIRBuilderTest, getNamedFunction) {
174   auto builder = getBuilder();
175   auto func2 = builder.getNamedFunction("func2");
176   EXPECT_EQ(nullptr, func2);
177   auto loc = builder.getUnknownLoc();
178   func2 = builder.createFunction(
179       loc, "func2", builder.getFunctionType(llvm::None, llvm::None));
180   auto func2query = builder.getNamedFunction("func2");
181   EXPECT_EQ(func2, func2query);
182 }
183 
TEST_F(FIRBuilderTest,createGlobal1)184 TEST_F(FIRBuilderTest, createGlobal1) {
185   auto builder = getBuilder();
186   auto loc = builder.getUnknownLoc();
187   auto i64Type = IntegerType::get(builder.getContext(), 64);
188   auto global = builder.createGlobal(
189       loc, i64Type, "global1", builder.createInternalLinkage(), {}, true);
190   EXPECT_TRUE(mlir::isa<fir::GlobalOp>(global));
191   EXPECT_EQ("global1", global.getSymName());
192   EXPECT_TRUE(global.getConstant().has_value());
193   EXPECT_EQ(i64Type, global.getType());
194   EXPECT_TRUE(global.getLinkName().has_value());
195   EXPECT_EQ(
196       builder.createInternalLinkage().getValue(), global.getLinkName().value());
197   EXPECT_FALSE(global.getInitVal().has_value());
198 
199   auto g1 = builder.getNamedGlobal("global1");
200   EXPECT_EQ(global, g1);
201   auto g2 = builder.getNamedGlobal("global7");
202   EXPECT_EQ(nullptr, g2);
203   auto g3 = builder.getNamedGlobal("");
204   EXPECT_EQ(nullptr, g3);
205 }
206 
TEST_F(FIRBuilderTest,createGlobal2)207 TEST_F(FIRBuilderTest, createGlobal2) {
208   auto builder = getBuilder();
209   auto loc = builder.getUnknownLoc();
210   auto i32Type = IntegerType::get(builder.getContext(), 32);
211   auto attr = builder.getIntegerAttr(i32Type, 16);
212   auto global = builder.createGlobal(
213       loc, i32Type, "global2", builder.createLinkOnceLinkage(), attr, false);
214   EXPECT_TRUE(mlir::isa<fir::GlobalOp>(global));
215   EXPECT_EQ("global2", global.getSymName());
216   EXPECT_FALSE(global.getConstant().has_value());
217   EXPECT_EQ(i32Type, global.getType());
218   EXPECT_TRUE(global.getInitVal().has_value());
219   EXPECT_TRUE(global.getInitVal().value().isa<mlir::IntegerAttr>());
220   EXPECT_EQ(
221       16, global.getInitVal().value().cast<mlir::IntegerAttr>().getValue());
222   EXPECT_TRUE(global.getLinkName().has_value());
223   EXPECT_EQ(
224       builder.createLinkOnceLinkage().getValue(), global.getLinkName().value());
225 }
226 
TEST_F(FIRBuilderTest,uniqueCFIdent)227 TEST_F(FIRBuilderTest, uniqueCFIdent) {
228   auto str1 = fir::factory::uniqueCGIdent("", "func1");
229   EXPECT_EQ("_QQ.66756E6331", str1);
230   str1 = fir::factory::uniqueCGIdent("", "");
231   EXPECT_EQ("_QQ.", str1);
232   str1 = fir::factory::uniqueCGIdent("pr", "func1");
233   EXPECT_EQ("_QQpr.66756E6331", str1);
234   str1 = fir::factory::uniqueCGIdent(
235       "", "longnamemorethan32characterneedshashing");
236   EXPECT_EQ("_QQ.c22a886b2f30ea8c064ef1178377fc31", str1);
237   str1 = fir::factory::uniqueCGIdent(
238       "pr", "longnamemorethan32characterneedshashing");
239   EXPECT_EQ("_QQpr.c22a886b2f30ea8c064ef1178377fc31", str1);
240 }
241 
TEST_F(FIRBuilderTest,locationToLineNo)242 TEST_F(FIRBuilderTest, locationToLineNo) {
243   auto builder = getBuilder();
244   auto loc = mlir::FileLineColLoc::get(builder.getStringAttr("file1"), 10, 5);
245   mlir::Value line =
246       fir::factory::locationToLineNo(builder, loc, builder.getI64Type());
247   checkIntegerConstant(line, builder.getI64Type(), 10);
248   line = fir::factory::locationToLineNo(
249       builder, builder.getUnknownLoc(), builder.getI64Type());
250   checkIntegerConstant(line, builder.getI64Type(), 0);
251 }
252 
TEST_F(FIRBuilderTest,hasDynamicSize)253 TEST_F(FIRBuilderTest, hasDynamicSize) {
254   auto builder = getBuilder();
255   auto type = fir::CharacterType::get(builder.getContext(), 1, 16);
256   EXPECT_FALSE(fir::hasDynamicSize(type));
257   EXPECT_TRUE(fir::SequenceType::getUnknownExtent());
258   auto seqTy = builder.getVarLenSeqTy(builder.getI64Type(), 10);
259   EXPECT_TRUE(fir::hasDynamicSize(seqTy));
260   EXPECT_FALSE(fir::hasDynamicSize(builder.getI64Type()));
261 }
262 
TEST_F(FIRBuilderTest,locationToFilename)263 TEST_F(FIRBuilderTest, locationToFilename) {
264   auto builder = getBuilder();
265   auto loc =
266       mlir::FileLineColLoc::get(builder.getStringAttr("file1.f90"), 10, 5);
267   mlir::Value locToFile = fir::factory::locationToFilename(builder, loc);
268   auto addrOp = dyn_cast<fir::AddrOfOp>(locToFile.getDefiningOp());
269   auto symbol = addrOp.getSymbol().getRootReference().getValue();
270   auto global = builder.getNamedGlobal(symbol);
271   auto stringLitOps = global.getRegion().front().getOps<fir::StringLitOp>();
272   EXPECT_TRUE(llvm::hasSingleElement(stringLitOps));
273   for (auto stringLit : stringLitOps) {
274     EXPECT_EQ(10, stringLit.getSize().cast<mlir::IntegerAttr>().getValue());
275     EXPECT_TRUE(stringLit.getValue().isa<StringAttr>());
276     EXPECT_EQ(0,
277         strcmp("file1.f90\0",
278             stringLit.getValue()
279                 .dyn_cast<StringAttr>()
280                 .getValue()
281                 .str()
282                 .c_str()));
283   }
284 }
285 
TEST_F(FIRBuilderTest,createStringLitOp)286 TEST_F(FIRBuilderTest, createStringLitOp) {
287   auto builder = getBuilder();
288   llvm::StringRef data("mystringlitdata");
289   auto loc = builder.getUnknownLoc();
290   auto op = builder.createStringLitOp(loc, data);
291   EXPECT_EQ(15, op.getSize().cast<mlir::IntegerAttr>().getValue());
292   EXPECT_TRUE(op.getValue().isa<StringAttr>());
293   EXPECT_EQ(data, op.getValue().dyn_cast<StringAttr>().getValue());
294 }
295 
TEST_F(FIRBuilderTest,createStringLiteral)296 TEST_F(FIRBuilderTest, createStringLiteral) {
297   auto builder = getBuilder();
298   auto loc = builder.getUnknownLoc();
299   llvm::StringRef strValue("onestringliteral");
300   auto strLit = fir::factory::createStringLiteral(builder, loc, strValue);
301   EXPECT_EQ(0u, strLit.rank());
302   EXPECT_TRUE(strLit.getCharBox() != nullptr);
303   auto *charBox = strLit.getCharBox();
304   EXPECT_FALSE(fir::isArray(*charBox));
305   checkIntegerConstant(charBox->getLen(), builder.getCharacterLengthType(), 16);
306   auto generalGetLen = fir::getLen(strLit);
307   checkIntegerConstant(generalGetLen, builder.getCharacterLengthType(), 16);
308   auto addr = charBox->getBuffer();
309   EXPECT_TRUE(mlir::isa<fir::AddrOfOp>(addr.getDefiningOp()));
310   auto addrOp = dyn_cast<fir::AddrOfOp>(addr.getDefiningOp());
311   auto symbol = addrOp.getSymbol().getRootReference().getValue();
312   auto global = builder.getNamedGlobal(symbol);
313   EXPECT_EQ(
314       builder.createLinkOnceLinkage().getValue(), global.getLinkName().value());
315   EXPECT_EQ(fir::CharacterType::get(builder.getContext(), 1, strValue.size()),
316       global.getType());
317 
318   auto stringLitOps = global.getRegion().front().getOps<fir::StringLitOp>();
319   EXPECT_TRUE(llvm::hasSingleElement(stringLitOps));
320   for (auto stringLit : stringLitOps) {
321     EXPECT_EQ(16, stringLit.getSize().cast<mlir::IntegerAttr>().getValue());
322     EXPECT_TRUE(stringLit.getValue().isa<StringAttr>());
323     EXPECT_EQ(strValue, stringLit.getValue().dyn_cast<StringAttr>().getValue());
324   }
325 }
326 
TEST_F(FIRBuilderTest,allocateLocal)327 TEST_F(FIRBuilderTest, allocateLocal) {
328   auto builder = getBuilder();
329   auto loc = builder.getUnknownLoc();
330   llvm::StringRef varName = "var1";
331   auto var = builder.allocateLocal(
332       loc, builder.getI64Type(), "", varName, {}, {}, false);
333   EXPECT_TRUE(mlir::isa<fir::AllocaOp>(var.getDefiningOp()));
334   auto allocaOp = dyn_cast<fir::AllocaOp>(var.getDefiningOp());
335   EXPECT_EQ(builder.getI64Type(), allocaOp.getInType());
336   EXPECT_TRUE(allocaOp.getBindcName().has_value());
337   EXPECT_EQ(varName, allocaOp.getBindcName().value());
338   EXPECT_FALSE(allocaOp.getUniqName().has_value());
339   EXPECT_FALSE(allocaOp.getPinned());
340   EXPECT_EQ(0u, allocaOp.getTypeparams().size());
341   EXPECT_EQ(0u, allocaOp.getShape().size());
342 }
343 
checkShapeOp(mlir::Value shape,mlir::Value c10,mlir::Value c100)344 static void checkShapeOp(mlir::Value shape, mlir::Value c10, mlir::Value c100) {
345   EXPECT_TRUE(mlir::isa<fir::ShapeOp>(shape.getDefiningOp()));
346   fir::ShapeOp op = dyn_cast<fir::ShapeOp>(shape.getDefiningOp());
347   auto shapeTy = op.getType().dyn_cast<fir::ShapeType>();
348   EXPECT_EQ(2u, shapeTy.getRank());
349   EXPECT_EQ(2u, op.getExtents().size());
350   EXPECT_EQ(c10, op.getExtents()[0]);
351   EXPECT_EQ(c100, op.getExtents()[1]);
352 }
353 
TEST_F(FIRBuilderTest,genShapeWithExtents)354 TEST_F(FIRBuilderTest, genShapeWithExtents) {
355   auto builder = getBuilder();
356   auto loc = builder.getUnknownLoc();
357   auto c10 = builder.createIntegerConstant(loc, builder.getI64Type(), 10);
358   auto c100 = builder.createIntegerConstant(loc, builder.getI64Type(), 100);
359   llvm::SmallVector<mlir::Value> extents = {c10, c100};
360   auto shape = builder.genShape(loc, extents);
361   checkShapeOp(shape, c10, c100);
362 }
363 
TEST_F(FIRBuilderTest,genShapeWithExtentsAndShapeShift)364 TEST_F(FIRBuilderTest, genShapeWithExtentsAndShapeShift) {
365   auto builder = getBuilder();
366   auto loc = builder.getUnknownLoc();
367   auto c10 = builder.createIntegerConstant(loc, builder.getI64Type(), 10);
368   auto c100 = builder.createIntegerConstant(loc, builder.getI64Type(), 100);
369   auto c1 = builder.createIntegerConstant(loc, builder.getI64Type(), 100);
370   llvm::SmallVector<mlir::Value> shifts = {c1, c1};
371   llvm::SmallVector<mlir::Value> extents = {c10, c100};
372   auto shape = builder.genShape(loc, shifts, extents);
373   EXPECT_TRUE(mlir::isa<fir::ShapeShiftOp>(shape.getDefiningOp()));
374   fir::ShapeShiftOp op = dyn_cast<fir::ShapeShiftOp>(shape.getDefiningOp());
375   auto shapeTy = op.getType().dyn_cast<fir::ShapeShiftType>();
376   EXPECT_EQ(2u, shapeTy.getRank());
377   EXPECT_EQ(2u, op.getExtents().size());
378   EXPECT_EQ(2u, op.getOrigins().size());
379 }
380 
TEST_F(FIRBuilderTest,genShapeWithAbstractArrayBox)381 TEST_F(FIRBuilderTest, genShapeWithAbstractArrayBox) {
382   auto builder = getBuilder();
383   auto loc = builder.getUnknownLoc();
384   auto c10 = builder.createIntegerConstant(loc, builder.getI64Type(), 10);
385   auto c100 = builder.createIntegerConstant(loc, builder.getI64Type(), 100);
386   llvm::SmallVector<mlir::Value> extents = {c10, c100};
387   fir::AbstractArrayBox aab(extents, {});
388   EXPECT_TRUE(aab.lboundsAllOne());
389   auto shape = builder.genShape(loc, aab);
390   checkShapeOp(shape, c10, c100);
391 }
392 
TEST_F(FIRBuilderTest,readCharLen)393 TEST_F(FIRBuilderTest, readCharLen) {
394   auto builder = getBuilder();
395   auto loc = builder.getUnknownLoc();
396   llvm::StringRef strValue("length");
397   auto strLit = fir::factory::createStringLiteral(builder, loc, strValue);
398   auto len = fir::factory::readCharLen(builder, loc, strLit);
399   EXPECT_EQ(strLit.getCharBox()->getLen(), len);
400 }
401 
TEST_F(FIRBuilderTest,getExtents)402 TEST_F(FIRBuilderTest, getExtents) {
403   auto builder = getBuilder();
404   auto loc = builder.getUnknownLoc();
405   llvm::StringRef strValue("length");
406   auto strLit = fir::factory::createStringLiteral(builder, loc, strValue);
407   auto ext = fir::factory::getExtents(loc, builder, strLit);
408   EXPECT_EQ(0u, ext.size());
409   auto c10 = builder.createIntegerConstant(loc, builder.getI64Type(), 10);
410   auto c100 = builder.createIntegerConstant(loc, builder.getI64Type(), 100);
411   llvm::SmallVector<mlir::Value> extents = {c10, c100};
412   fir::SequenceType::Shape shape(2, fir::SequenceType::getUnknownExtent());
413   auto arrayTy = fir::SequenceType::get(shape, builder.getI64Type());
414   mlir::Value array = builder.create<fir::UndefOp>(loc, arrayTy);
415   fir::ArrayBoxValue aab(array, extents, {});
416   fir::ExtendedValue ex(aab);
417   auto readExtents = fir::factory::getExtents(loc, builder, ex);
418   EXPECT_EQ(2u, readExtents.size());
419 }
420 
TEST_F(FIRBuilderTest,createZeroValue)421 TEST_F(FIRBuilderTest, createZeroValue) {
422   auto builder = getBuilder();
423   auto loc = builder.getUnknownLoc();
424 
425   mlir::Type i64Ty = mlir::IntegerType::get(builder.getContext(), 64);
426   mlir::Value zeroInt = fir::factory::createZeroValue(builder, loc, i64Ty);
427   EXPECT_TRUE(zeroInt.getType() == i64Ty);
428   auto cst =
429       mlir::dyn_cast_or_null<mlir::arith::ConstantOp>(zeroInt.getDefiningOp());
430   EXPECT_TRUE(cst);
431   auto intAttr = cst.getValue().dyn_cast<mlir::IntegerAttr>();
432   EXPECT_TRUE(intAttr && intAttr.getInt() == 0);
433 
434   mlir::Type f32Ty = mlir::FloatType::getF32(builder.getContext());
435   mlir::Value zeroFloat = fir::factory::createZeroValue(builder, loc, f32Ty);
436   EXPECT_TRUE(zeroFloat.getType() == f32Ty);
437   auto cst2 = mlir::dyn_cast_or_null<mlir::arith::ConstantOp>(
438       zeroFloat.getDefiningOp());
439   EXPECT_TRUE(cst2);
440   auto floatAttr = cst2.getValue().dyn_cast<mlir::FloatAttr>();
441   EXPECT_TRUE(floatAttr && floatAttr.getValueAsDouble() == 0.);
442 
443   mlir::Type boolTy = mlir::IntegerType::get(builder.getContext(), 1);
444   mlir::Value flaseBool = fir::factory::createZeroValue(builder, loc, boolTy);
445   EXPECT_TRUE(flaseBool.getType() == boolTy);
446   auto cst3 = mlir::dyn_cast_or_null<mlir::arith::ConstantOp>(
447       flaseBool.getDefiningOp());
448   EXPECT_TRUE(cst3);
449   auto intAttr2 = cst.getValue().dyn_cast<mlir::IntegerAttr>();
450   EXPECT_TRUE(intAttr2 && intAttr2.getInt() == 0);
451 }
452 
TEST_F(FIRBuilderTest,getBaseTypeOf)453 TEST_F(FIRBuilderTest, getBaseTypeOf) {
454   auto builder = getBuilder();
455   auto loc = builder.getUnknownLoc();
456 
457   auto makeExv = [&](mlir::Type elementType, mlir::Type arrayType)
458       -> std::tuple<llvm::SmallVector<fir::ExtendedValue, 4>,
459           llvm::SmallVector<fir::ExtendedValue, 4>> {
460     auto ptrTyArray = fir::PointerType::get(arrayType);
461     auto ptrTyScalar = fir::PointerType::get(elementType);
462     auto ptrBoxTyArray = fir::BoxType::get(ptrTyArray);
463     auto ptrBoxTyScalar = fir::BoxType::get(ptrTyScalar);
464     auto boxRefTyArray = fir::ReferenceType::get(ptrBoxTyArray);
465     auto boxRefTyScalar = fir::ReferenceType::get(ptrBoxTyScalar);
466     auto boxTyArray = fir::BoxType::get(arrayType);
467     auto boxTyScalar = fir::BoxType::get(elementType);
468 
469     auto ptrValArray = builder.create<fir::UndefOp>(loc, ptrTyArray);
470     auto ptrValScalar = builder.create<fir::UndefOp>(loc, ptrTyScalar);
471     auto boxRefValArray = builder.create<fir::UndefOp>(loc, boxRefTyArray);
472     auto boxRefValScalar = builder.create<fir::UndefOp>(loc, boxRefTyScalar);
473     auto boxValArray = builder.create<fir::UndefOp>(loc, boxTyArray);
474     auto boxValScalar = builder.create<fir::UndefOp>(loc, boxTyScalar);
475 
476     llvm::SmallVector<fir::ExtendedValue, 4> scalars;
477     scalars.emplace_back(fir::UnboxedValue(ptrValScalar));
478     scalars.emplace_back(fir::BoxValue(boxValScalar));
479     scalars.emplace_back(
480         fir::MutableBoxValue(boxRefValScalar, mlir::ValueRange(), {}));
481 
482     llvm::SmallVector<fir::ExtendedValue, 4> arrays;
483     auto extent = builder.create<fir::UndefOp>(loc, builder.getIndexType());
484     llvm::SmallVector<mlir::Value> extents(
485         arrayType.dyn_cast<fir::SequenceType>().getDimension(),
486         extent.getResult());
487     arrays.emplace_back(fir::ArrayBoxValue(ptrValArray, extents));
488     arrays.emplace_back(fir::BoxValue(boxValArray));
489     arrays.emplace_back(
490         fir::MutableBoxValue(boxRefValArray, mlir::ValueRange(), {}));
491     return {scalars, arrays};
492   };
493 
494   auto f32Ty = mlir::FloatType::getF32(builder.getContext());
495   mlir::Type f32SeqTy = builder.getVarLenSeqTy(f32Ty);
496   auto [f32Scalars, f32Arrays] = makeExv(f32Ty, f32SeqTy);
497   for (const auto &scalar : f32Scalars) {
498     EXPECT_EQ(fir::getBaseTypeOf(scalar), f32Ty);
499     EXPECT_EQ(fir::getElementTypeOf(scalar), f32Ty);
500     EXPECT_FALSE(fir::isDerivedWithLenParameters(scalar));
501   }
502   for (const auto &array : f32Arrays) {
503     EXPECT_EQ(fir::getBaseTypeOf(array), f32SeqTy);
504     EXPECT_EQ(fir::getElementTypeOf(array), f32Ty);
505     EXPECT_FALSE(fir::isDerivedWithLenParameters(array));
506   }
507 
508   auto derivedWithLengthTy =
509       fir::RecordType::get(builder.getContext(), "derived_test");
510 
511   llvm::SmallVector<std::pair<std::string, mlir::Type>> parameters;
512   llvm::SmallVector<std::pair<std::string, mlir::Type>> components;
513   parameters.emplace_back("p1", builder.getI64Type());
514   components.emplace_back("c1", f32Ty);
515   derivedWithLengthTy.finalize(parameters, components);
516   mlir::Type derivedWithLengthSeqTy =
517       builder.getVarLenSeqTy(derivedWithLengthTy);
518   auto [derivedWithLengthScalars, derivedWithLengthArrays] =
519       makeExv(derivedWithLengthTy, derivedWithLengthSeqTy);
520   for (const auto &scalar : derivedWithLengthScalars) {
521     EXPECT_EQ(fir::getBaseTypeOf(scalar), derivedWithLengthTy);
522     EXPECT_EQ(fir::getElementTypeOf(scalar), derivedWithLengthTy);
523     EXPECT_TRUE(fir::isDerivedWithLenParameters(scalar));
524   }
525   for (const auto &array : derivedWithLengthArrays) {
526     EXPECT_EQ(fir::getBaseTypeOf(array), derivedWithLengthSeqTy);
527     EXPECT_EQ(fir::getElementTypeOf(array), derivedWithLengthTy);
528     EXPECT_TRUE(fir::isDerivedWithLenParameters(array));
529   }
530 }
531