@@ -122,7 +122,7 @@ static fir::GlobalOp declareGlobal(Fortran::lower::AbstractConverter &converter,
122
122
// symbol is an object of a function pointer.
123
123
const Fortran::semantics::Symbol &ultimate = sym.GetUltimate ();
124
124
if (!ultimate.has <Fortran::semantics::ObjectEntityDetails>() &&
125
- !ultimate. has < Fortran::semantics::ProcEntityDetails>( ))
125
+ !Fortran::semantics::IsProcedurePointer (ultimate ))
126
126
mlir::emitError (loc, " lowering global declaration: symbol '" )
127
127
<< toStringRef (sym.name ()) << " ' has unexpected details\n " ;
128
128
return builder.createGlobal (loc, converter.genType (var), globalName, linkage,
@@ -378,6 +378,10 @@ static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter,
378
378
379
379
if (global && globalIsInitialized (global))
380
380
return global;
381
+
382
+ if (Fortran::semantics::IsProcedurePointer (sym))
383
+ TODO (loc, " procedure pointer globals" );
384
+
381
385
// If this is an array, check to see if we can use a dense attribute
382
386
// with a tensor mlir type. This optimization currently only supports
383
387
// rank-1 Fortran arrays of integer, real, or logical. The tensor
@@ -1187,11 +1191,10 @@ static mlir::Value genExtentValue(fir::FirOpBuilder &builder,
1187
1191
}
1188
1192
1189
1193
// / Lower specification expressions and attributes of variable \p var and
1190
- // / add it to the symbol map.
1191
- // / For global and aliases, the address must be pre-computed and provided
1192
- // / in \p preAlloc.
1193
- // / Dummy arguments must have already been mapped to mlir block arguments
1194
- // / their mapping may be updated here.
1194
+ // / add it to the symbol map. For a global or an alias, the address must be
1195
+ // / pre-computed and provided in \p preAlloc. A dummy argument for the current
1196
+ // / entry point has already been mapped to an mlir block argument in
1197
+ // / mapDummiesAndResults. Its mapping may be updated here.
1195
1198
void Fortran::lower::mapSymbolAttributes (
1196
1199
AbstractConverter &converter, const Fortran::lower::pft::Variable &var,
1197
1200
Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
@@ -1200,14 +1203,32 @@ void Fortran::lower::mapSymbolAttributes(
1200
1203
const Fortran::semantics::Symbol &sym = var.getSymbol ();
1201
1204
const mlir::Location loc = converter.genLocation (sym.name ());
1202
1205
mlir::IndexType idxTy = builder.getIndexType ();
1203
- const bool isDummy = Fortran::semantics::IsDummy (sym);
1206
+ const bool isDeclaredDummy = Fortran::semantics::IsDummy (sym);
1207
+ // An active dummy from the current entry point.
1208
+ const bool isDummy = isDeclaredDummy && symMap.lookupSymbol (sym).getAddr ();
1209
+ // An unused dummy from another entry point.
1210
+ const bool isUnusedEntryDummy = isDeclaredDummy && !isDummy;
1204
1211
const bool isResult = Fortran::semantics::IsFunctionResult (sym);
1205
1212
const bool replace = isDummy || isResult;
1206
1213
fir::factory::CharacterExprHelper charHelp{builder, loc};
1214
+
1215
+ if (Fortran::semantics::IsProcedure (sym)) {
1216
+ if (isUnusedEntryDummy) {
1217
+ // Additional discussion below.
1218
+ mlir::Type dummyProcType =
1219
+ Fortran::lower::getDummyProcedureType (sym, converter);
1220
+ mlir::Value undefOp = builder.create <fir::UndefOp>(loc, dummyProcType);
1221
+ symMap.addSymbol (sym, undefOp);
1222
+ }
1223
+ if (Fortran::semantics::IsPointer (sym))
1224
+ TODO (loc, " procedure pointers" );
1225
+ return ;
1226
+ }
1227
+
1207
1228
Fortran::lower::BoxAnalyzer ba;
1208
1229
ba.analyze (sym);
1209
1230
1210
- // First deal with pointers an allocatables, because their handling here
1231
+ // First deal with pointers and allocatables, because their handling here
1211
1232
// is the same regardless of their rank.
1212
1233
if (Fortran::semantics::IsAllocatableOrPointer (sym)) {
1213
1234
// Get address of fir.box describing the entity.
@@ -1263,6 +1284,42 @@ void Fortran::lower::mapSymbolAttributes(
1263
1284
}
1264
1285
}
1265
1286
1287
+ // A dummy from another entry point that is not declared in the current
1288
+ // entry point requires a skeleton definition. Most such "unused" dummies
1289
+ // will not survive into final generated code, but some will. It is illegal
1290
+ // to reference one at run time if it does. Such a dummy is mapped to a
1291
+ // value in one of three ways:
1292
+ //
1293
+ // - Generate a fir::UndefOp value. This is lightweight, easy to clean up,
1294
+ // and often valid, but it may fail for a dummy with dynamic bounds,
1295
+ // or a dummy used to define another dummy. Information to distinguish
1296
+ // valid cases is not generally available here, with the exception of
1297
+ // dummy procedures. See the first function exit above.
1298
+ //
1299
+ // - Allocate an uninitialized stack slot. This is an intermediate-weight
1300
+ // solution that is harder to clean up. It is often valid, but may fail
1301
+ // for an object with dynamic bounds. This option is "automatically"
1302
+ // used by default for cases that do not use one of the other options.
1303
+ //
1304
+ // - Allocate a heap box/descriptor, initialized to zero. This always
1305
+ // works, but is more heavyweight and harder to clean up. It is used
1306
+ // for dynamic objects via calls to genUnusedEntryPointBox.
1307
+
1308
+ auto genUnusedEntryPointBox = [&]() {
1309
+ if (isUnusedEntryDummy) {
1310
+ assert (!Fortran::semantics::IsAllocatableOrPointer (sym) &&
1311
+ " handled above" );
1312
+ // The box is read right away because lowering code does not expect
1313
+ // a non pointer/allocatable symbol to be mapped to a MutableBox.
1314
+ symMap.addSymbol (sym, fir::factory::genMutableBoxRead (
1315
+ builder, loc,
1316
+ fir::factory::createTempMutableBox (
1317
+ builder, loc, converter.genType (var))));
1318
+ return true ;
1319
+ }
1320
+ return false ;
1321
+ };
1322
+
1266
1323
// Helper to generate scalars for the symbol properties.
1267
1324
auto genValue = [&](const Fortran::lower::SomeExpr &expr) {
1268
1325
return genScalarValue (converter, loc, expr, symMap, stmtCtx);
@@ -1412,24 +1469,17 @@ void Fortran::lower::mapSymbolAttributes(
1412
1469
// ===--------------------------------------------------------------===//
1413
1470
1414
1471
[&](const Fortran::lower::details::ScalarDynamicChar &x) {
1472
+ if (genUnusedEntryPointBox ())
1473
+ return ;
1415
1474
// type is a CHARACTER, determine the LEN value
1416
1475
auto charLen = x.charLen ();
1417
1476
if (replace) {
1418
1477
Fortran::lower::SymbolBox symBox = symMap.lookupSymbol (sym);
1419
1478
mlir::Value boxAddr = symBox.getAddr ();
1420
1479
mlir::Value len;
1421
1480
mlir::Type addrTy = boxAddr.getType ();
1422
- if (addrTy.isa <fir::BoxCharType>() || addrTy.isa <fir::BoxType>()) {
1481
+ if (addrTy.isa <fir::BoxCharType>() || addrTy.isa <fir::BoxType>())
1423
1482
std::tie (boxAddr, len) = charHelp.createUnboxChar (symBox.getAddr ());
1424
- } else {
1425
- // dummy from an other entry case: we cannot get a dynamic length
1426
- // for it, it's illegal for the user program to use it. However,
1427
- // since we are lowering all function unit statements regardless
1428
- // of whether the execution will reach them or not, we need to
1429
- // fill a value for the length here.
1430
- len = builder.createIntegerConstant (
1431
- loc, builder.getCharacterLengthType (), 1 );
1432
- }
1433
1483
// Override LEN with an expression
1434
1484
if (charLen)
1435
1485
len = genExplicitCharLen (charLen);
@@ -1484,6 +1534,8 @@ void Fortran::lower::mapSymbolAttributes(
1484
1534
// ===--------------------------------------------------------------===//
1485
1535
1486
1536
[&](const Fortran::lower::details::DynamicArray &x) {
1537
+ if (genUnusedEntryPointBox ())
1538
+ return ;
1487
1539
// cast to the known constant parts from the declaration
1488
1540
mlir::Type varType = converter.genType (var);
1489
1541
mlir::Value addr = symMap.lookupSymbol (sym).getAddr ();
@@ -1587,6 +1639,8 @@ void Fortran::lower::mapSymbolAttributes(
1587
1639
// ===--------------------------------------------------------------===//
1588
1640
1589
1641
[&](const Fortran::lower::details::StaticArrayDynamicChar &x) {
1642
+ if (genUnusedEntryPointBox ())
1643
+ return ;
1590
1644
mlir::Value addr;
1591
1645
mlir::Value len;
1592
1646
[[maybe_unused]] bool mustBeDummy = false ;
@@ -1656,6 +1710,8 @@ void Fortran::lower::mapSymbolAttributes(
1656
1710
// ===--------------------------------------------------------------===//
1657
1711
1658
1712
[&](const Fortran::lower::details::DynamicArrayStaticChar &x) {
1713
+ if (genUnusedEntryPointBox ())
1714
+ return ;
1659
1715
mlir::Value addr;
1660
1716
mlir::Value len;
1661
1717
mlir::Value argBox;
@@ -1714,6 +1770,8 @@ void Fortran::lower::mapSymbolAttributes(
1714
1770
// ===--------------------------------------------------------------===//
1715
1771
1716
1772
[&](const Fortran::lower::details::DynamicArrayDynamicChar &x) {
1773
+ if (genUnusedEntryPointBox ())
1774
+ return ;
1717
1775
mlir::Value addr;
1718
1776
mlir::Value len;
1719
1777
mlir::Value argBox;
0 commit comments