xref: /llvm-project/flang/unittests/Optimizer/FortranVariableTest.cpp (revision f023da12d12635f5fba436e825cbfc999e28e623)
1 //===- FortranVariableTest.cpp --------------------------------------------===//
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 "gtest/gtest.h"
10 #include "flang/Optimizer/Dialect/FIROps.h"
11 #include "flang/Optimizer/Support/InitFIR.h"
12 
13 struct FortranVariableTest : public testing::Test {
14 public:
15   void SetUp() {
16     fir::support::loadDialects(context);
17     builder = std::make_unique<mlir::OpBuilder>(&context);
18     mlir::Location loc = builder->getUnknownLoc();
19 
20     // Set up a Module with a dummy function operation inside.
21     // Set the insertion point in the function entry block.
22     moduleOp = builder->create<mlir::ModuleOp>(loc);
23     builder->setInsertionPointToStart(moduleOp->getBody());
24     mlir::func::FuncOp func =
25         builder->create<mlir::func::FuncOp>(loc, "fortran_variable_tests",
26             builder->getFunctionType(std::nullopt, std::nullopt));
27     auto *entryBlock = func.addEntryBlock();
28     builder->setInsertionPointToStart(entryBlock);
29   }
30 
31   mlir::Location getLoc() { return builder->getUnknownLoc(); }
32   mlir::Value createConstant(std::int64_t cst) {
33     mlir::Type indexType = builder->getIndexType();
34     return builder->create<mlir::arith::ConstantOp>(
35         getLoc(), indexType, builder->getIntegerAttr(indexType, cst));
36   }
37 
38   mlir::Value createShape(llvm::ArrayRef<mlir::Value> extents) {
39     return builder->create<fir::ShapeOp>(getLoc(), extents);
40   }
41   mlir::MLIRContext context;
42   std::unique_ptr<mlir::OpBuilder> builder;
43   mlir::OwningOpRef<mlir::ModuleOp> moduleOp;
44 };
45 
46 TEST_F(FortranVariableTest, SimpleScalar) {
47   mlir::Location loc = getLoc();
48   mlir::Type eleType = mlir::Float32Type::get(&context);
49   mlir::Value addr = builder->create<fir::AllocaOp>(loc, eleType);
50   auto name = mlir::StringAttr::get(&context, "x");
51   auto declare = builder->create<fir::DeclareOp>(loc, addr.getType(), addr,
52       /*shape=*/mlir::Value{}, /*typeParams=*/std::nullopt,
53       /*dummy_scope=*/nullptr, name,
54       /*fortran_attrs=*/fir::FortranVariableFlagsAttr{},
55       /*data_attr=*/cuf::DataAttributeAttr{});
56 
57   fir::FortranVariableOpInterface fortranVariable = declare;
58   EXPECT_FALSE(fortranVariable.isArray());
59   EXPECT_FALSE(fortranVariable.isCharacter());
60   EXPECT_FALSE(fortranVariable.isPointer());
61   EXPECT_FALSE(fortranVariable.isAllocatable());
62   EXPECT_FALSE(fortranVariable.hasExplicitCharLen());
63   EXPECT_EQ(fortranVariable.getElementType(), eleType);
64   EXPECT_EQ(fortranVariable.getElementOrSequenceType(),
65       fortranVariable.getElementType());
66   EXPECT_NE(fortranVariable.getBase(), addr);
67   EXPECT_EQ(fortranVariable.getBase().getType(), addr.getType());
68 }
69 
70 TEST_F(FortranVariableTest, CharacterScalar) {
71   mlir::Location loc = getLoc();
72   mlir::Type eleType = fir::CharacterType::getUnknownLen(&context, 4);
73   mlir::Value len = createConstant(42);
74   llvm::SmallVector<mlir::Value> typeParams{len};
75   mlir::Value addr = builder->create<fir::AllocaOp>(
76       loc, eleType, /*pinned=*/false, typeParams);
77   auto name = mlir::StringAttr::get(&context, "x");
78   auto declare = builder->create<fir::DeclareOp>(loc, addr.getType(), addr,
79       /*shape=*/mlir::Value{}, typeParams, /*dummy_scope=*/nullptr, name,
80       /*fortran_attrs=*/fir::FortranVariableFlagsAttr{},
81       /*data_attr=*/cuf::DataAttributeAttr{});
82 
83   fir::FortranVariableOpInterface fortranVariable = declare;
84   EXPECT_FALSE(fortranVariable.isArray());
85   EXPECT_TRUE(fortranVariable.isCharacter());
86   EXPECT_FALSE(fortranVariable.isPointer());
87   EXPECT_FALSE(fortranVariable.isAllocatable());
88   EXPECT_TRUE(fortranVariable.hasExplicitCharLen());
89   EXPECT_EQ(fortranVariable.getElementType(), eleType);
90   EXPECT_EQ(fortranVariable.getElementOrSequenceType(),
91       fortranVariable.getElementType());
92   EXPECT_NE(fortranVariable.getBase(), addr);
93   EXPECT_EQ(fortranVariable.getBase().getType(), addr.getType());
94   EXPECT_EQ(fortranVariable.getExplicitCharLen(), len);
95 }
96 
97 TEST_F(FortranVariableTest, SimpleArray) {
98   mlir::Location loc = getLoc();
99   mlir::Type eleType = mlir::Float32Type::get(&context);
100   llvm::SmallVector<mlir::Value> extents{
101       createConstant(10), createConstant(20), createConstant(30)};
102   fir::SequenceType::Shape typeShape(
103       extents.size(), fir::SequenceType::getUnknownExtent());
104   mlir::Type seqTy = fir::SequenceType::get(typeShape, eleType);
105   mlir::Value addr = builder->create<fir::AllocaOp>(
106       loc, seqTy, /*pinned=*/false, /*typeParams=*/std::nullopt, extents);
107   mlir::Value shape = createShape(extents);
108   auto name = mlir::StringAttr::get(&context, "x");
109   auto declare = builder->create<fir::DeclareOp>(loc, addr.getType(), addr,
110       shape, /*typeParams*/ std::nullopt, /*dummy_scope=*/nullptr, name,
111       /*fortran_attrs=*/fir::FortranVariableFlagsAttr{},
112       /*data_attr=*/cuf::DataAttributeAttr{});
113 
114   fir::FortranVariableOpInterface fortranVariable = declare;
115   EXPECT_TRUE(fortranVariable.isArray());
116   EXPECT_FALSE(fortranVariable.isCharacter());
117   EXPECT_FALSE(fortranVariable.isPointer());
118   EXPECT_FALSE(fortranVariable.isAllocatable());
119   EXPECT_FALSE(fortranVariable.hasExplicitCharLen());
120   EXPECT_EQ(fortranVariable.getElementType(), eleType);
121   EXPECT_EQ(fortranVariable.getElementOrSequenceType(), seqTy);
122   EXPECT_NE(fortranVariable.getBase(), addr);
123   EXPECT_EQ(fortranVariable.getBase().getType(), addr.getType());
124 }
125 
126 TEST_F(FortranVariableTest, CharacterArray) {
127   mlir::Location loc = getLoc();
128   mlir::Type eleType = fir::CharacterType::getUnknownLen(&context, 4);
129   mlir::Value len = createConstant(42);
130   llvm::SmallVector<mlir::Value> typeParams{len};
131   llvm::SmallVector<mlir::Value> extents{
132       createConstant(10), createConstant(20), createConstant(30)};
133   fir::SequenceType::Shape typeShape(
134       extents.size(), fir::SequenceType::getUnknownExtent());
135   mlir::Type seqTy = fir::SequenceType::get(typeShape, eleType);
136   mlir::Value addr = builder->create<fir::AllocaOp>(
137       loc, seqTy, /*pinned=*/false, typeParams, extents);
138   mlir::Value shape = createShape(extents);
139   auto name = mlir::StringAttr::get(&context, "x");
140   auto declare = builder->create<fir::DeclareOp>(loc, addr.getType(), addr,
141       shape, typeParams, /*dummy_scope=*/nullptr, name,
142       /*fortran_attrs=*/fir::FortranVariableFlagsAttr{},
143       /*data_attr=*/cuf::DataAttributeAttr{});
144 
145   fir::FortranVariableOpInterface fortranVariable = declare;
146   EXPECT_TRUE(fortranVariable.isArray());
147   EXPECT_TRUE(fortranVariable.isCharacter());
148   EXPECT_FALSE(fortranVariable.isPointer());
149   EXPECT_FALSE(fortranVariable.isAllocatable());
150   EXPECT_TRUE(fortranVariable.hasExplicitCharLen());
151   EXPECT_EQ(fortranVariable.getElementType(), eleType);
152   EXPECT_EQ(fortranVariable.getElementOrSequenceType(), seqTy);
153   EXPECT_NE(fortranVariable.getBase(), addr);
154   EXPECT_EQ(fortranVariable.getBase().getType(), addr.getType());
155   EXPECT_EQ(fortranVariable.getExplicitCharLen(), len);
156 }
157