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 | |