Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions flang/include/flang/Lower/AbstractConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,12 @@ class AbstractConverter {
virtual bool
isRegisteredDummySymbol(Fortran::semantics::SymbolRef symRef) const = 0;

/// Get the source-level argument position (1-based) for a dummy symbol.
/// Returns 0 if the symbol is not a registered dummy or position is unknown.
/// Can only be used reliably during the instantiation of variables.
virtual unsigned
getDummyArgPosition(const Fortran::semantics::Symbol &sym) const = 0;

/// Returns the FunctionLikeUnit being lowered, if any.
virtual const Fortran::lower::pft::FunctionLikeUnit *
getCurrentFunctionUnit() const = 0;
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Optimizer/Builder/HLFIRTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
fir::FortranVariableFlagsAttr flags,
mlir::Value dummyScope = nullptr, mlir::Value storage = nullptr,
std::uint64_t storageOffset = 0,
cuf::DataAttributeAttr dataAttr = {});
cuf::DataAttributeAttr dataAttr = {}, unsigned dummyArgNo = 0);

/// Generate an hlfir.associate to build a variable from an expression value.
/// The type of the variable must be provided so that scalar logicals are
Expand Down
5 changes: 3 additions & 2 deletions flang/include/flang/Optimizer/Dialect/FIRCG/CGOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,13 @@ def fircg_XDeclareOp : fircg_Op<"ext_declare", [AttrSizedOperandSegments]> {

let arguments = (ins AnyRefOrBox:$memref, Variadic<AnyIntegerType>:$shape,
Variadic<AnyIntegerType>:$shift, Variadic<AnyIntegerType>:$typeparams,
Optional<fir_DummyScopeType>:$dummy_scope, Builtin_StringAttr:$uniq_name);
Optional<fir_DummyScopeType>:$dummy_scope, Builtin_StringAttr:$uniq_name,
OptionalAttr<UI32Attr>:$dummy_arg_no);
let results = (outs AnyRefOrBox);

let assemblyFormat = [{
$memref (`(` $shape^ `)`)? (`origin` $shift^)? (`typeparams` $typeparams^)?
(`dummy_scope` $dummy_scope^)?
(`dummy_scope` $dummy_scope^ (`arg` $dummy_arg_no^)?)?
attr-dict `:` functional-type(operands, results)
}];

Expand Down
5 changes: 3 additions & 2 deletions flang/include/flang/Optimizer/Dialect/FIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -3274,13 +3274,14 @@ def fir_DeclareOp
DefaultValuedAttr<UI64Attr, "0">:$storage_offset,
Builtin_StringAttr:$uniq_name,
OptionalAttr<fir_FortranVariableFlagsAttr>:$fortran_attrs,
OptionalAttr<cuf_DataAttributeAttr>:$data_attr);
OptionalAttr<cuf_DataAttributeAttr>:$data_attr,
OptionalAttr<UI32Attr>:$dummy_arg_no);

let results = (outs AnyRefOrBox);

let assemblyFormat = [{
$memref (`(` $shape^ `)`)? (`typeparams` $typeparams^)?
(`dummy_scope` $dummy_scope^)?
(`dummy_scope` $dummy_scope^ (`arg` $dummy_arg_no^)?)?
(`storage` `(` $storage^ `[` $storage_offset `]` `)`)?
attr-dict `:` functional-type(operands, results)
}];
Expand Down
7 changes: 4 additions & 3 deletions flang/include/flang/Optimizer/HLFIR/HLFIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ def hlfir_DeclareOp
Builtin_StringAttr:$uniq_name,
OptionalAttr<fir_FortranVariableFlagsAttr>:$fortran_attrs,
OptionalAttr<cuf_DataAttributeAttr>:$data_attr,
OptionalAttr<UnitAttr>:$skip_rebox);
OptionalAttr<UnitAttr>:$skip_rebox, OptionalAttr<UI32Attr>:$dummy_arg_no);

let results = (outs AnyFortranVariable, AnyRefOrBoxLike);

let assemblyFormat = [{
$memref (`(` $shape^ `)`)? (`typeparams` $typeparams^)?
(`dummy_scope` $dummy_scope^)?
(`dummy_scope` $dummy_scope^ (`arg` $dummy_arg_no^)?)?
(`storage` `(` $storage^ `[` $storage_offset `]` `)`)?
(`skip_rebox` $skip_rebox^)?
attr-dict `:` functional-type(operands, results)
Expand All @@ -122,7 +122,8 @@ def hlfir_DeclareOp
CArg<"mlir::Value", "{}">:$storage,
CArg<"std::uint64_t", "0">:$storage_offset,
CArg<"fir::FortranVariableFlagsAttr", "{}">:$fortran_attrs,
CArg<"cuf::DataAttributeAttr", "{}">:$data_attr)>];
CArg<"cuf::DataAttributeAttr", "{}">:$data_attr,
CArg<"unsigned", "0">:$dummy_arg_no)>];

let extraClassDeclaration = [{
/// Get the variable original base (same as input). It lacks
Expand Down
45 changes: 39 additions & 6 deletions flang/lib/Lower/Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
return registeredDummySymbols.contains(sym);
}

unsigned getDummyArgPosition(
const Fortran::semantics::Symbol &sym) const override final {
auto it = dummyArgPositions.find(&sym);
return (it != dummyArgPositions.end()) ? it->second : 0;
}

const Fortran::lower::pft::FunctionLikeUnit *
getCurrentFunctionUnit() const override final {
return currentFunctionUnit;
Expand Down Expand Up @@ -1413,11 +1419,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
/// definitive mapping. The specification expression have not been lowered
/// yet. The final mapping will be done using this pre-mapping in
/// Fortran::lower::mapSymbolAttributes.
/// \param argNo The 1-based source position of this argument (0 if
/// unknown/result)
bool mapBlockArgToDummyOrResult(const Fortran::semantics::SymbolRef sym,
mlir::Value val, bool isResult) {
mlir::Value val, bool isResult,
unsigned argNo = 0) {
localSymbols.addSymbol(sym, val);
if (!isResult)
registerDummySymbol(sym);
registerDummySymbol(sym, argNo);

return true;
}
Expand Down Expand Up @@ -5962,7 +5971,16 @@ class FirConverter : public Fortran::lower::AbstractConverter {
const Fortran::lower::CalleeInterface &callee) {
assert(builder && "require a builder object at this point");
using PassBy = Fortran::lower::CalleeInterface::PassEntityBy;

// Track the source-level argument position (1-based)
unsigned argPosition = 0;

auto mapPassedEntity = [&](const auto arg, bool isResult = false) {
// Count only actual source-level dummy arguments (not results or
// host assoc tuples)
if (!isResult && arg.entity.has_value())
argPosition++;

if (arg.passBy == PassBy::AddressAndLength) {
if (callee.characterize().IsBindC())
return;
Expand All @@ -5973,11 +5991,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
mlir::Value casted =
builder->createVolatileCast(loc, false, arg.firArgument);
mlir::Value box = charHelp.createEmboxChar(casted, arg.firLength);
mapBlockArgToDummyOrResult(arg.entity->get(), box, isResult);
mapBlockArgToDummyOrResult(arg.entity->get(), box, isResult,
isResult ? 0 : argPosition);
} else {
if (arg.entity.has_value()) {
mapBlockArgToDummyOrResult(arg.entity->get(), arg.firArgument,
isResult);
isResult, isResult ? 0 : argPosition);
} else {
assert(funit.parentHasTupleHostAssoc() && "expect tuple argument");
}
Expand Down Expand Up @@ -6835,13 +6854,22 @@ class FirConverter : public Fortran::lower::AbstractConverter {
}

/// Record the given symbol as a dummy argument of this function.
void registerDummySymbol(Fortran::semantics::SymbolRef symRef) {
/// \param symRef The symbol representing the dummy argument
/// \param argNo The 1-based position of this argument in the source (0 =
/// unknown)
void registerDummySymbol(Fortran::semantics::SymbolRef symRef,
unsigned argNo = 0) {
auto *sym = &*symRef;
registeredDummySymbols.insert(sym);
if (argNo > 0)
dummyArgPositions[sym] = argNo;
}

/// Reset all registered dummy symbols.
void resetRegisteredDummySymbols() { registeredDummySymbols.clear(); }
void resetRegisteredDummySymbols() {
registeredDummySymbols.clear();
dummyArgPositions.clear();
}

void setCurrentFunctionUnit(Fortran::lower::pft::FunctionLikeUnit *unit) {
currentFunctionUnit = unit;
Expand Down Expand Up @@ -6883,6 +6911,11 @@ class FirConverter : public Fortran::lower::AbstractConverter {
llvm::SmallPtrSet<const Fortran::semantics::Symbol *, 16>
registeredDummySymbols;

/// Map from dummy symbols to their 1-based argument positions.
/// Used to generate debug info with correct argument numbers.
llvm::DenseMap<const Fortran::semantics::Symbol *, unsigned>
dummyArgPositions;

/// A map of unique names for constant expressions.
/// The names are used for representing the constant expressions
/// with global constant initialized objects.
Expand Down
11 changes: 8 additions & 3 deletions flang/lib/Lower/ConvertVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1946,12 +1946,15 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
return;
}
mlir::Value dummyScope;
if (converter.isRegisteredDummySymbol(sym))
unsigned argNo = 0;
if (converter.isRegisteredDummySymbol(sym)) {
dummyScope = converter.dummyArgsScopeValue();
argNo = converter.getDummyArgPosition(sym);
}
auto [storage, storageOffset] = converter.getSymbolStorage(sym);
auto newBase = hlfir::DeclareOp::create(
builder, loc, base, name, shapeOrShift, lenParams, dummyScope, storage,
storageOffset, attributes, dataAttr);
storageOffset, attributes, dataAttr, argNo);
symMap.addVariableDefinition(sym, newBase, force);
return;
}
Expand Down Expand Up @@ -2004,15 +2007,17 @@ void Fortran::lower::genDeclareSymbol(
sym.GetUltimate());
auto name = converter.mangleName(sym);
mlir::Value dummyScope;
unsigned argNo = 0;
fir::ExtendedValue base = exv;
if (converter.isRegisteredDummySymbol(sym)) {
base = genPackArray(converter, sym, exv);
dummyScope = converter.dummyArgsScopeValue();
argNo = converter.getDummyArgPosition(sym);
}
auto [storage, storageOffset] = converter.getSymbolStorage(sym);
hlfir::EntityWithAttributes declare =
hlfir::genDeclare(loc, builder, base, name, attributes, dummyScope,
storage, storageOffset, dataAttr);
storage, storageOffset, dataAttr, argNo);
symMap.addVariableDefinition(sym, declare.getIfVariableInterface(), force);
return;
}
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Optimizer/Builder/FIRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,8 @@ mlir::Value fir::FirOpBuilder::genTempDeclareOp(
builder, loc, memref.getType(), memref, shape, typeParams,
/*dummy_scope=*/nullptr,
/*storage=*/nullptr,
/*storage_offset=*/0, nameAttr, fortranAttrs, cuf::DataAttributeAttr{});
/*storage_offset=*/0, nameAttr, fortranAttrs, cuf::DataAttributeAttr{},
/*dummy_arg_no=*/mlir::IntegerAttr{});
}

mlir::Value fir::FirOpBuilder::genStackSave(mlir::Location loc) {
Expand Down
4 changes: 2 additions & 2 deletions flang/lib/Optimizer/Builder/HLFIRTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ hlfir::genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
const fir::ExtendedValue &exv, llvm::StringRef name,
fir::FortranVariableFlagsAttr flags, mlir::Value dummyScope,
mlir::Value storage, std::uint64_t storageOffset,
cuf::DataAttributeAttr dataAttr) {
cuf::DataAttributeAttr dataAttr, unsigned dummyArgNo) {

mlir::Value base = fir::getBase(exv);
assert(fir::conformsWithPassByRef(base.getType()) &&
Expand Down Expand Up @@ -281,7 +281,7 @@ hlfir::genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
[](const auto &) {});
auto declareOp = hlfir::DeclareOp::create(
builder, loc, base, name, shapeOrShift, lenParams, dummyScope, storage,
storageOffset, flags, dataAttr);
storageOffset, flags, dataAttr, dummyArgNo);
return mlir::cast<fir::FortranVariableOpInterface>(declareOp.getOperation());
}

Expand Down
6 changes: 5 additions & 1 deletion flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,15 @@ class DeclareOpConversion : public mlir::OpRewritePattern<fir::DeclareOp> {
else
return mlir::failure();
}
// Extract dummy_arg_no attribute if present
mlir::IntegerAttr dummyArgNoAttr;
if (auto attr = declareOp->getAttrOfType<mlir::IntegerAttr>("dummy_arg_no"))
dummyArgNoAttr = attr;
// FIXME: Add FortranAttrs and CudaAttrs
auto xDeclOp = fir::cg::XDeclareOp::create(
rewriter, loc, declareOp.getType(), declareOp.getMemref(), shapeOpers,
shiftOpers, declareOp.getTypeparams(), declareOp.getDummyScope(),
declareOp.getUniqName());
declareOp.getUniqName(), dummyArgNoAttr);
LLVM_DEBUG(llvm::dbgs()
<< "rewriting " << declareOp << " to " << xDeclOp << '\n');
rewriter.replaceOp(declareOp, xDeclOp.getOperation()->getResults());
Expand Down
19 changes: 10 additions & 9 deletions flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,12 @@ updateDeclaredInputTypeWithVolatility(mlir::Type inputType, mlir::Value memref,
return std::make_pair(inputType, memref);
}

void hlfir::DeclareOp::build(mlir::OpBuilder &builder,
mlir::OperationState &result, mlir::Value memref,
llvm::StringRef uniq_name, mlir::Value shape,
mlir::ValueRange typeparams,
mlir::Value dummy_scope, mlir::Value storage,
std::uint64_t storage_offset,
fir::FortranVariableFlagsAttr fortran_attrs,
cuf::DataAttributeAttr data_attr) {
void hlfir::DeclareOp::build(
mlir::OpBuilder &builder, mlir::OperationState &result, mlir::Value memref,
llvm::StringRef uniq_name, mlir::Value shape, mlir::ValueRange typeparams,
mlir::Value dummy_scope, mlir::Value storage, std::uint64_t storage_offset,
fir::FortranVariableFlagsAttr fortran_attrs,
cuf::DataAttributeAttr data_attr, unsigned dummy_arg_no) {
auto nameAttr = builder.getStringAttr(uniq_name);
mlir::Type inputType = memref.getType();
bool hasExplicitLbs = hasExplicitLowerBounds(shape);
Expand All @@ -279,9 +277,12 @@ void hlfir::DeclareOp::build(mlir::OpBuilder &builder,
}
auto [hlfirVariableType, firVarType] =
getDeclareOutputTypes(inputType, hasExplicitLbs);
mlir::IntegerAttr argNoAttr;
if (dummy_arg_no > 0)
argNoAttr = builder.getUI32IntegerAttr(dummy_arg_no);
build(builder, result, {hlfirVariableType, firVarType}, memref, shape,
typeparams, dummy_scope, storage, storage_offset, nameAttr,
fortran_attrs, data_attr, /*skip_rebox=*/mlir::UnitAttr{});
fortran_attrs, data_attr, /*skip_rebox=*/mlir::UnitAttr{}, argNoAttr);
}

llvm::LogicalResult hlfir::DeclareOp::verify() {
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ class DeclareOpConversion : public mlir::OpRewritePattern<hlfir::DeclareOp> {
declareOp.getTypeparams(), declareOp.getDummyScope(),
/*storage=*/declareOp.getStorage(),
/*storage_offset=*/declareOp.getStorageOffset(),
declareOp.getUniqName(), fortranAttrs, dataAttr);
declareOp.getUniqName(), fortranAttrs, dataAttr,
declareOp.getDummyArgNoAttr());

// Propagate other attributes from hlfir.declare to fir.declare.
// OpenACC's acc.declare is one example. Right now, the propagation
Expand Down
19 changes: 3 additions & 16 deletions flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,24 +228,11 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp,
}
}

// FIXME: There may be cases where an argument is processed a bit before
// DeclareOp is generated. In that case, DeclareOp may point to an
// intermediate op and not to BlockArgument.
// Moreover, with MLIR inlining we cannot use the BlockArgument
// position to identify the original number of the dummy argument.
// If we want to keep running AddDebugInfoPass late, the dummy argument
// position in the argument list has to be expressed in FIR (e.g. as a
// constant attribute of [hl]fir.declare/fircg.ext_declare operation that has
// a dummy_scope operand).
// Get the dummy argument position from the explicit attribute.
unsigned argNo = 0;
if (declOp.getDummyScope()) {
if (auto arg = llvm::dyn_cast<mlir::BlockArgument>(declOp.getMemref())) {
// Check if it is the BlockArgument of the function's entry block.
if (auto funcLikeOp =
declOp->getParentOfType<mlir::FunctionOpInterface>())
if (arg.getOwner() == &funcLikeOp.front())
argNo = arg.getArgNumber() + 1;
}
if (auto argNoOpt = declOp.getDummyArgNo())
argNo = *argNoOpt;
}

auto tyAttr = typeGen.convertType(fir::unwrapRefType(declOp.getType()),
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Fir/dispatch.f90
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ program test_type_to_class

! CHECK-LABEL: func.func @_QMdispatch1Pdisplay_class(
! CHECK-SAME: %[[ARG:.*]]: [[CLASS:!fir.class<.*>>]]
! CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMdispatch1Fdisplay_classEp"} : (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>)
! CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMdispatch1Fdisplay_classEp"} : (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>)

! Check dynamic dispatch equal to `call p%display2()` with binding index = 2.
! CHECK: %[[BOXDESC:.*]] = fir.box_tdesc %[[ARG_DECL]]#0 : ([[CLASS]]) -> !fir.tdesc<none>
Expand Down
Loading
Loading