diff --git a/flang/include/flang/Optimizer/Dialect/FIRAttr.td b/flang/include/flang/Optimizer/Dialect/FIRAttr.td index aedb6769186e..60281dfa6371 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRAttr.td +++ b/flang/include/flang/Optimizer/Dialect/FIRAttr.td @@ -111,4 +111,17 @@ def fir_LowerBoundModifierAttribute : I32EnumAttr< let cppNamespace = "::fir"; } +def fir_LocationKind : I32EnumAttr<"LocationKind", "Flang location kind", + [ + I32EnumAttrCase<"Base", 0, "base">, + I32EnumAttrCase<"Inclusion", 1, "inclusion">, + ]> { + let genSpecializedAttr = 0; + let cppNamespace = "::fir"; +} +def fir_LocationKindAttr : EnumAttr; + +def LocationKindArrayAttr : ArrayOfAttr; + #endif // FIR_DIALECT_FIR_ATTRS diff --git a/flang/include/flang/Parser/provenance.h b/flang/include/flang/Parser/provenance.h index 3189e012cd49..a9224b727fd0 100644 --- a/flang/include/flang/Parser/provenance.h +++ b/flang/include/flang/Parser/provenance.h @@ -172,6 +172,8 @@ public: } void setShowColors(bool showColors) { showColors_ = showColors; } bool getShowColors() const { return showColors_; } + std::optional GetInclusionInfo( + const std::optional &) const; void EmitMessage(llvm::raw_ostream &, const std::optional &, const std::string &message, const std::string &prefix, llvm::raw_ostream::Colors color, bool echoSourceLine = false) const; diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index a4043744c638..3d5b2e2a2fe0 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -939,24 +939,59 @@ public: return mlir::UnknownLoc::get(&getMLIRContext()); } + static mlir::Location genLocation(Fortran::parser::SourcePosition pos, + mlir::MLIRContext &ctx) { + llvm::SmallString<256> path(*pos.path); + llvm::sys::fs::make_absolute(path); + llvm::sys::path::remove_dots(path); + return mlir::FileLineColLoc::get(&ctx, path.str(), pos.line, pos.column); + } + /// Generate a `Location` from the `CharBlock`. mlir::Location genLocation(const Fortran::parser::CharBlock &block) override final { + mlir::Location mainLocation = genUnknownLocation(); if (const Fortran::parser::AllCookedSources *cooked = bridge.getCookedSource()) { if (std::optional provenance = cooked->GetProvenanceRange(block)) { if (std::optional filePos = - cooked->allSources().GetSourcePosition(provenance->start())) { - llvm::SmallString<256> filePath(*filePos->path); - llvm::sys::fs::make_absolute(filePath); - llvm::sys::path::remove_dots(filePath); - return mlir::FileLineColLoc::get(&getMLIRContext(), filePath.str(), - filePos->line, filePos->column); + cooked->allSources().GetSourcePosition(provenance->start())) + mainLocation = genLocation(*filePos, getMLIRContext()); + + llvm::SmallVector locs; + locs.push_back(mainLocation); + + llvm::SmallVector locAttrs; + locAttrs.push_back(fir::LocationKindAttr::get(&getMLIRContext(), + fir::LocationKind::Base)); + + // Gather include location information if any. + Fortran::parser::ProvenanceRange *prov = &*provenance; + while (prov) { + if (std::optional include = + cooked->allSources().GetInclusionInfo(*prov)) { + if (std::optional incPos = + cooked->allSources().GetSourcePosition(include->start())) { + locs.push_back(genLocation(*incPos, getMLIRContext())); + locAttrs.push_back(fir::LocationKindAttr::get( + &getMLIRContext(), fir::LocationKind::Inclusion)); + } + prov = &*include; + } else { + prov = nullptr; + } + } + if (locs.size() > 1) { + assert(locs.size() == locAttrs.size() && + "expect as many attributes as locations"); + return mlir::FusedLocWith::get( + &getMLIRContext(), locs, + fir::LocationKindArrayAttr::get(&getMLIRContext(), locAttrs)); } } } - return genUnknownLocation(); + return mainLocation; } const Fortran::semantics::Scope &getCurrentScope() override final { diff --git a/flang/lib/Optimizer/Dialect/FIRAttr.cpp b/flang/lib/Optimizer/Dialect/FIRAttr.cpp index a0202a015922..443e94ae6606 100644 --- a/flang/lib/Optimizer/Dialect/FIRAttr.cpp +++ b/flang/lib/Optimizer/Dialect/FIRAttr.cpp @@ -298,5 +298,6 @@ void fir::printFirAttribute(FIROpsDialect *dialect, mlir::Attribute attr, void FIROpsDialect::registerAttributes() { addAttributes(); + SubclassAttr, UpperBoundAttr, LocationKindAttr, + LocationKindArrayAttr>(); } diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 685a8645fa2f..1ddbcc958633 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -76,8 +76,11 @@ static uint32_t getLineFromLoc(mlir::Location loc) { } bool debugInfoIsAlreadySet(mlir::Location loc) { - if (mlir::isa(loc)) + if (mlir::isa(loc)) { + if (loc->findInstanceOf>()) + return false; return true; + } return false; } diff --git a/flang/lib/Parser/provenance.cpp b/flang/lib/Parser/provenance.cpp index c67ddd22f096..e31038b09e40 100644 --- a/flang/lib/Parser/provenance.cpp +++ b/flang/lib/Parser/provenance.cpp @@ -246,6 +246,27 @@ static void EmitPrefix(llvm::raw_ostream &o, llvm::raw_ostream::Colors color, } } +std::optional AllSources::GetInclusionInfo( + const std::optional &range) const { + if (!range) + return std::nullopt; + const Origin &origin{MapToOrigin(range->start())}; + + return common::visit( + common::visitors{ + [&](const Inclusion &inc) -> std::optional { + if (IsValid(origin.replaces) && + range_.Contains(origin.replaces.start())) + return origin.replaces; + return std::nullopt; + }, + [&](const auto &) -> std::optional { + return std::nullopt; + }, + }, + origin.u); +} + void AllSources::EmitMessage(llvm::raw_ostream &o, const std::optional &range, const std::string &message, const std::string &prefix, llvm::raw_ostream::Colors color, diff --git a/flang/test/Lower/location.f90 b/flang/test/Lower/location.f90 new file mode 100644 index 000000000000..a6ece31bbebe --- /dev/null +++ b/flang/test/Lower/location.f90 @@ -0,0 +1,13 @@ +! RUN: bbc -emit-hlfir --mlir-print-debuginfo %s -o - | FileCheck %s + +program test +include 'location0.inc' + +end + +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "test"} { +! CHECK: fir.call @_FortranAioOutputAscii(%{{.*}}, %{{.*}}, %{{.*}}) fastmath : (!fir.ref, !fir.ref, i64) -> i1 loc(fused<#fir>["{{.*}}location1.inc":1:10, "{{.*}}location0.inc":1:1, "{{.*}}location.f90":4:1]) +! CHECK: return loc("{{.*}}location.f90":6:1) +! CHECK: } loc("{{.*}}location.f90":3:1) + + diff --git a/flang/test/Lower/location0.inc b/flang/test/Lower/location0.inc new file mode 100644 index 000000000000..d46282c73c51 --- /dev/null +++ b/flang/test/Lower/location0.inc @@ -0,0 +1 @@ +include 'location1.inc' diff --git a/flang/test/Lower/location1.inc b/flang/test/Lower/location1.inc new file mode 100644 index 000000000000..6a2671c61828 --- /dev/null +++ b/flang/test/Lower/location1.inc @@ -0,0 +1 @@ +print *, 'from location.inc'