1 //===- CharacterTest.cpp -- Character runtime builder 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/Runtime/Character.h"
10 #include "RuntimeCallTestBase.h"
11 #include "gtest/gtest.h"
12 #include "flang/Optimizer/Builder/Character.h"
13 
14 TEST_F(RuntimeCallTest, genAdjustLTest) {
15   auto loc = firBuilder->getUnknownLoc();
16   mlir::Value result = firBuilder->create<fir::UndefOp>(loc, boxTy);
17   mlir::Value string = firBuilder->create<fir::UndefOp>(loc, boxTy);
18   fir::runtime::genAdjustL(*firBuilder, loc, result, string);
19   checkCallOpFromResultBox(result, "_FortranAAdjustl", 2);
20 }
21 
22 TEST_F(RuntimeCallTest, genAdjustRTest) {
23   auto loc = firBuilder->getUnknownLoc();
24   mlir::Value result = firBuilder->create<fir::UndefOp>(loc, boxTy);
25   mlir::Value string = firBuilder->create<fir::UndefOp>(loc, boxTy);
26   fir::runtime::genAdjustR(*firBuilder, loc, result, string);
27   checkCallOpFromResultBox(result, "_FortranAAdjustr", 2);
28 }
29 
30 void checkCharCompare1(
31     fir::FirOpBuilder &builder, mlir::Type type, llvm::StringRef fctName) {
32   auto loc = builder.getUnknownLoc();
33   mlir::Type i32Ty = IntegerType::get(builder.getContext(), 32);
34   mlir::Value lhsBuff = builder.create<fir::UndefOp>(loc, type);
35   mlir::Value lhsLen = builder.create<fir::UndefOp>(loc, i32Ty);
36   mlir::Value rhsBuff = builder.create<fir::UndefOp>(loc, type);
37   mlir::Value rhsLen = builder.create<fir::UndefOp>(loc, i32Ty);
38   mlir::Value res = fir::runtime::genCharCompare(builder, loc,
39       mlir::arith::CmpIPredicate::eq, lhsBuff, lhsLen, rhsBuff, rhsLen);
40   checkCallOpFromResultBox(lhsBuff, fctName, 4, /*addLocArgs=*/false);
41   EXPECT_TRUE(mlir::isa<mlir::arith::CmpIOp>(res.getDefiningOp()));
42 }
43 
44 void checkCharCompare1AllTypeForKind(
45     fir::FirOpBuilder &builder, llvm::StringRef fctName, unsigned kind) {
46   mlir::Type charTy = fir::CharacterType::get(builder.getContext(), kind, 10);
47   mlir::Type seqCharTy = fir::SequenceType::get(charTy, 10);
48   mlir::Type refCharTy = fir::ReferenceType::get(charTy);
49   mlir::Type boxCharTy = fir::BoxCharType::get(builder.getContext(), kind);
50   mlir::Type boxTy = fir::BoxType::get(charTy);
51   checkCharCompare1(builder, charTy, fctName);
52   checkCharCompare1(builder, seqCharTy, fctName);
53   checkCharCompare1(builder, refCharTy, fctName);
54   checkCharCompare1(builder, boxCharTy, fctName);
55   checkCharCompare1(builder, boxTy, fctName);
56 }
57 
58 TEST_F(RuntimeCallTest, genCharCompar1Test) {
59   checkCharCompare1AllTypeForKind(
60       *firBuilder, "_FortranACharacterCompareScalar1", 1);
61   checkCharCompare1AllTypeForKind(
62       *firBuilder, "_FortranACharacterCompareScalar2", 2);
63   checkCharCompare1AllTypeForKind(
64       *firBuilder, "_FortranACharacterCompareScalar4", 4);
65 }
66 
67 void checkCharCompare2(
68     fir::FirOpBuilder &builder, llvm::StringRef fctName, unsigned kind) {
69   auto loc = builder.getUnknownLoc();
70   fir::factory::CharacterExprHelper charHelper(builder, loc);
71   mlir::Type i32Ty = IntegerType::get(builder.getContext(), 32);
72   mlir::Type boxCharTy = fir::BoxCharType::get(builder.getContext(), kind);
73   mlir::Value lhsBuff = builder.create<fir::UndefOp>(loc, boxCharTy);
74   mlir::Value lhsLen = builder.create<fir::UndefOp>(loc, i32Ty);
75   mlir::Value rhsBuff = builder.create<fir::UndefOp>(loc, boxCharTy);
76   mlir::Value rhsLen = builder.create<fir::UndefOp>(loc, i32Ty);
77   fir::ExtendedValue lhs = charHelper.toExtendedValue(lhsBuff, lhsLen);
78   fir::ExtendedValue rhs = charHelper.toExtendedValue(rhsBuff, rhsLen);
79   mlir::Value res = fir::runtime::genCharCompare(
80       builder, loc, mlir::arith::CmpIPredicate::eq, lhs, rhs);
81   EXPECT_TRUE(mlir::isa<mlir::arith::CmpIOp>(res.getDefiningOp()));
82   auto cmpOp = mlir::dyn_cast<mlir::arith::CmpIOp>(res.getDefiningOp());
83   checkCallOp(cmpOp.getLhs().getDefiningOp(), fctName, 4, /*addLocArgs=*/false);
84   auto allocas = res.getParentBlock()->getOps<fir::AllocaOp>();
85   EXPECT_TRUE(llvm::empty(allocas));
86 }
87 
88 TEST_F(RuntimeCallTest, genCharCompare2Test) {
89   checkCharCompare2(*firBuilder, "_FortranACharacterCompareScalar1", 1);
90   checkCharCompare2(*firBuilder, "_FortranACharacterCompareScalar2", 2);
91   checkCharCompare2(*firBuilder, "_FortranACharacterCompareScalar4", 4);
92 }
93 
94 void checkGenIndex(
95     fir::FirOpBuilder &builder, llvm::StringRef fctName, unsigned kind) {
96   auto loc = builder.getUnknownLoc();
97   mlir::Type i32Ty = IntegerType::get(builder.getContext(), 32);
98   mlir::Value stringBase = builder.create<fir::UndefOp>(loc, i32Ty);
99   mlir::Value stringLen = builder.create<fir::UndefOp>(loc, i32Ty);
100   mlir::Value substringBase = builder.create<fir::UndefOp>(loc, i32Ty);
101   mlir::Value substringLen = builder.create<fir::UndefOp>(loc, i32Ty);
102   mlir::Value back = builder.create<fir::UndefOp>(loc, i32Ty);
103   mlir::Value res = fir::runtime::genIndex(builder, loc, kind, stringBase,
104       stringLen, substringBase, substringLen, back);
105   checkCallOp(res.getDefiningOp(), fctName, 5, /*addLocArgs=*/false);
106 }
107 
108 TEST_F(RuntimeCallTest, genIndexTest) {
109   checkGenIndex(*firBuilder, "_FortranAIndex1", 1);
110   checkGenIndex(*firBuilder, "_FortranAIndex2", 2);
111   checkGenIndex(*firBuilder, "_FortranAIndex4", 4);
112 }
113 
114 TEST_F(RuntimeCallTest, genIndexDescriptorTest) {
115   auto loc = firBuilder->getUnknownLoc();
116   mlir::Value resultBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
117   mlir::Value stringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
118   mlir::Value substringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
119   mlir::Value backOpt = firBuilder->create<fir::UndefOp>(loc, boxTy);
120   mlir::Value kind = firBuilder->create<fir::UndefOp>(loc, i32Ty);
121   fir::runtime::genIndexDescriptor(
122       *firBuilder, loc, resultBox, stringBox, substringBox, backOpt, kind);
123   checkCallOpFromResultBox(resultBox, "_FortranAIndex", 5);
124 }
125 
126 TEST_F(RuntimeCallTest, genRepeatTest) {
127   auto loc = firBuilder->getUnknownLoc();
128   mlir::Value resultBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
129   mlir::Value stringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
130   mlir::Value ncopies = firBuilder->create<fir::UndefOp>(loc, i32Ty);
131   fir::runtime::genRepeat(*firBuilder, loc, resultBox, stringBox, ncopies);
132   checkCallOpFromResultBox(resultBox, "_FortranARepeat", 3);
133 }
134 
135 TEST_F(RuntimeCallTest, genTrimTest) {
136   auto loc = firBuilder->getUnknownLoc();
137   mlir::Value resultBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
138   mlir::Value stringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
139   fir::runtime::genTrim(*firBuilder, loc, resultBox, stringBox);
140   checkCallOpFromResultBox(resultBox, "_FortranATrim", 2);
141 }
142 
143 TEST_F(RuntimeCallTest, genScanDescriptorTest) {
144   auto loc = firBuilder->getUnknownLoc();
145   mlir::Value resultBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
146   mlir::Value stringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
147   mlir::Value setBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
148   mlir::Value backBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
149   mlir::Value kind = firBuilder->create<fir::UndefOp>(loc, i32Ty);
150   fir::runtime::genScanDescriptor(
151       *firBuilder, loc, resultBox, stringBox, setBox, backBox, kind);
152   checkCallOpFromResultBox(resultBox, "_FortranAScan", 5);
153 }
154 
155 void checkGenScan(
156     fir::FirOpBuilder &builder, llvm::StringRef fctName, unsigned kind) {
157   auto loc = builder.getUnknownLoc();
158   mlir::Type charTy = fir::CharacterType::get(builder.getContext(), kind, 10);
159   mlir::Type boxTy = fir::BoxType::get(charTy);
160   mlir::Type i32Ty = IntegerType::get(builder.getContext(), 32);
161   mlir::Value stringBase = builder.create<fir::UndefOp>(loc, boxTy);
162   mlir::Value stringLen = builder.create<fir::UndefOp>(loc, i32Ty);
163   mlir::Value setBase = builder.create<fir::UndefOp>(loc, boxTy);
164   mlir::Value setLen = builder.create<fir::UndefOp>(loc, i32Ty);
165   mlir::Value back = builder.create<fir::UndefOp>(loc, i32Ty);
166   mlir::Value res = fir::runtime::genScan(
167       builder, loc, kind, stringBase, stringLen, setBase, setLen, back);
168   checkCallOp(res.getDefiningOp(), fctName, 5, /*addLocArgs=*/false);
169 }
170 
171 TEST_F(RuntimeCallTest, genScanTest) {
172   checkGenScan(*firBuilder, "_FortranAScan1", 1);
173   checkGenScan(*firBuilder, "_FortranAScan2", 2);
174   checkGenScan(*firBuilder, "_FortranAScan4", 4);
175 }
176 
177 TEST_F(RuntimeCallTest, genVerifyDescriptorTest) {
178   auto loc = firBuilder->getUnknownLoc();
179   mlir::Value resultBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
180   mlir::Value stringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
181   mlir::Value setBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
182   mlir::Value backBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
183   mlir::Value kind = firBuilder->create<fir::UndefOp>(loc, i32Ty);
184   fir::runtime::genVerifyDescriptor(
185       *firBuilder, loc, resultBox, stringBox, setBox, backBox, kind);
186   checkCallOpFromResultBox(resultBox, "_FortranAVerify", 5);
187 }
188 
189 void checkGenVerify(
190     fir::FirOpBuilder &builder, llvm::StringRef fctName, unsigned kind) {
191   auto loc = builder.getUnknownLoc();
192   mlir::Type charTy = fir::CharacterType::get(builder.getContext(), kind, 10);
193   mlir::Type boxTy = fir::BoxType::get(charTy);
194   mlir::Type i32Ty = IntegerType::get(builder.getContext(), 32);
195   mlir::Value stringBase = builder.create<fir::UndefOp>(loc, boxTy);
196   mlir::Value stringLen = builder.create<fir::UndefOp>(loc, i32Ty);
197   mlir::Value setBase = builder.create<fir::UndefOp>(loc, boxTy);
198   mlir::Value setLen = builder.create<fir::UndefOp>(loc, i32Ty);
199   mlir::Value back = builder.create<fir::UndefOp>(loc, i32Ty);
200   mlir::Value res = fir::runtime::genVerify(
201       builder, loc, kind, stringBase, stringLen, setBase, setLen, back);
202   checkCallOp(res.getDefiningOp(), fctName, 5, /*addLocArgs=*/false);
203 }
204 
205 TEST_F(RuntimeCallTest, genVerifyTest) {
206   checkGenVerify(*firBuilder, "_FortranAVerify1", 1);
207   checkGenVerify(*firBuilder, "_FortranAVerify2", 2);
208   checkGenVerify(*firBuilder, "_FortranAVerify4", 4);
209 }
210