Skip to content

Commit aaa6fbb

Browse files
committed
[Flang] Implement LOWER argument for C_F_POINTER
This PR adds support for the optional LOWER argument for C_F_POINTER (Fortran 2023, 18.2.3.3)
1 parent 3b8adcf commit aaa6fbb

File tree

3 files changed

+62
-9
lines changed

3 files changed

+62
-9
lines changed

flang/docs/F202X.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@ Addressing some issues and omissions in intrinsic modules:
268268
* LOGICAL8/16/32/64 and REAL16
269269
* IEEE module facilities upgraded to match latest IEEE FP standard
270270
* C_F_STRPOINTER, F_C_STRING for NUL-terminated strings
271-
* C_F_POINTER(LOWER=)
272271

273272
#### Intrinsic Procedure Extensions
274273

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3073,10 +3073,11 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer(
30733073
ActualArguments &arguments, FoldingContext &context) const {
30743074
characteristics::Procedure::Attrs attrs;
30753075
attrs.set(characteristics::Procedure::Attr::Subroutine);
3076-
static const char *const keywords[]{"cptr", "fptr", "shape", nullptr};
3076+
static const char *const keywords[]{
3077+
"cptr", "fptr", "shape", "lower", nullptr};
30773078
characteristics::DummyArguments dummies;
3078-
if (CheckAndRearrangeArguments(arguments, context.messages(), keywords, 1)) {
3079-
CHECK(arguments.size() == 3);
3079+
if (CheckAndRearrangeArguments(arguments, context.messages(), keywords, 2)) {
3080+
CHECK(arguments.size() == 4);
30803081
if (const auto *expr{arguments[0].value().UnwrapExpr()}) {
30813082
// General semantic checks will catch an actual argument that's not
30823083
// scalar.
@@ -3169,11 +3170,30 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer(
31693170
}
31703171
}
31713172
}
3173+
if (arguments[3] && fptrRank == 0) {
3174+
context.messages().Say(arguments[3]->sourceLocation(),
3175+
"LOWER= argument to C_F_POINTER() may not appear when FPTR= is scalar"_err_en_US);
3176+
} else if (arguments[3]) {
3177+
if (const auto *argExpr{arguments[3].value().UnwrapExpr()}) {
3178+
if (argExpr->Rank() > 1) {
3179+
context.messages().Say(arguments[3]->sourceLocation(),
3180+
"LOWER= argument to C_F_POINTER() must be a rank-one array."_err_en_US);
3181+
} else if (argExpr->Rank() == 1) {
3182+
if (auto constShape{GetConstantShape(context, *argExpr)}) {
3183+
if (constShape->At(ConstantSubscripts{1}).ToInt64() != fptrRank) {
3184+
context.messages().Say(arguments[3]->sourceLocation(),
3185+
"LOWER= argument to C_F_POINTER() must have size equal to the rank of FPTR="_err_en_US);
3186+
}
3187+
}
3188+
}
3189+
}
3190+
}
31723191
}
31733192
}
31743193
if (dummies.size() == 2) {
3194+
// Handle SHAPE
31753195
DynamicType shapeType{TypeCategory::Integer, defaults_.sizeIntegerKind()};
3176-
if (arguments[2]) {
3196+
if (arguments.size() >=3 && arguments[2]) {
31773197
if (auto type{arguments[2]->GetType()}) {
31783198
if (type->category() == TypeCategory::Integer) {
31793199
shapeType = *type;
@@ -3185,6 +3205,22 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer(
31853205
shape.intent = common::Intent::In;
31863206
shape.attrs.set(characteristics::DummyDataObject::Attr::Optional);
31873207
dummies.emplace_back("shape"s, std::move(shape));
3208+
3209+
// Handle LOWER
3210+
DynamicType lowerType{TypeCategory::Integer, defaults_.sizeIntegerKind()};
3211+
if (arguments.size() >= 4 && arguments[3]) {
3212+
if (auto type{arguments[3]->GetType()}) {
3213+
if (type->category() == TypeCategory::Integer) {
3214+
lowerType = *type;
3215+
}
3216+
}
3217+
}
3218+
characteristics::DummyDataObject lower{
3219+
characteristics::TypeAndShape{lowerType, 1}};
3220+
lower.intent = common::Intent::In;
3221+
lower.attrs.set(characteristics::DummyDataObject::Attr::Optional);
3222+
dummies.emplace_back("lower"s, std::move(lower));
3223+
31883224
return SpecificCall{
31893225
SpecificIntrinsic{"__builtin_c_f_pointer"s,
31903226
characteristics::Procedure{std::move(dummies), attrs}},

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,8 @@ static constexpr IntrinsicHandler handlers[]{
369369
&I::genCFPointer,
370370
{{{"cptr", asValue},
371371
{"fptr", asInquired},
372-
{"shape", asAddr, handleDynamicOptional}}},
372+
{"shape", asAddr, handleDynamicOptional},
373+
{"lower", asAddr, handleDynamicOptional}}},
373374
/*isElemental=*/false},
374375
{"c_f_procpointer",
375376
&I::genCFProcPointer,
@@ -3403,7 +3404,7 @@ IntrinsicLibrary::genCDevLoc(mlir::Type resultType,
34033404

34043405
// C_F_POINTER
34053406
void IntrinsicLibrary::genCFPointer(llvm::ArrayRef<fir::ExtendedValue> args) {
3406-
assert(args.size() == 3);
3407+
assert(args.size() == 4);
34073408
// Handle CPTR argument
34083409
// Get the value of the C address or the result of a reference to C_LOC.
34093410
mlir::Value cPtr = fir::getBase(args[0]);
@@ -3418,9 +3419,12 @@ void IntrinsicLibrary::genCFPointer(llvm::ArrayRef<fir::ExtendedValue> args) {
34183419
mlir::Value addr =
34193420
builder.createConvert(loc, fPtr->getMemTy(), cPtrAddrVal);
34203421
mlir::SmallVector<mlir::Value> extents;
3422+
mlir::SmallVector<mlir::Value> lbounds;
34213423
if (box.hasRank()) {
34223424
assert(isStaticallyPresent(args[2]) &&
34233425
"FPTR argument must be an array if SHAPE argument exists");
3426+
3427+
// Handle and unpack SHAPE argument
34243428
mlir::Value shape = fir::getBase(args[2]);
34253429
int arrayRank = box.rank();
34263430
mlir::Type shapeElementType =
@@ -3433,17 +3437,31 @@ void IntrinsicLibrary::genCFPointer(llvm::ArrayRef<fir::ExtendedValue> args) {
34333437
mlir::Value load = builder.create<fir::LoadOp>(loc, var);
34343438
extents.push_back(builder.createConvert(loc, idxType, load));
34353439
}
3440+
3441+
// Handle and unpack LOWER argument if present
3442+
if (isStaticallyPresent(args[3])) {
3443+
mlir::Value lower = fir::getBase(args[3]);
3444+
mlir::Type lowerElementType =
3445+
fir::unwrapSequenceType(fir::unwrapPassByRefType(lower.getType()));
3446+
for (int i = 0; i < arrayRank; ++i) {
3447+
mlir::Value index = builder.createIntegerConstant(loc, idxType, i);
3448+
mlir::Value var = builder.create<fir::CoordinateOp>(
3449+
loc, builder.getRefType(lowerElementType), lower, index);
3450+
mlir::Value load = builder.create<fir::LoadOp>(loc, var);
3451+
lbounds.push_back(builder.createConvert(loc, idxType, load));
3452+
}
3453+
}
34363454
}
34373455
if (box.isCharacter()) {
34383456
mlir::Value len = box.nonDeferredLenParams()[0];
34393457
if (box.hasRank())
3440-
return fir::CharArrayBoxValue{addr, len, extents};
3458+
return fir::CharArrayBoxValue{addr, len, extents, lbounds};
34413459
return fir::CharBoxValue{addr, len};
34423460
}
34433461
if (box.isDerivedWithLenParameters())
34443462
TODO(loc, "get length parameters of derived type");
34453463
if (box.hasRank())
3446-
return fir::ArrayBoxValue{addr, extents};
3464+
return fir::ArrayBoxValue{addr, extents, lbounds};
34473465
return addr;
34483466
};
34493467

0 commit comments

Comments
 (0)