diff options
Diffstat (limited to 'source/compiler-core')
| -rw-r--r-- | source/compiler-core/slang-source-loc.cpp | 100 | ||||
| -rw-r--r-- | source/compiler-core/slang-source-loc.h | 20 |
2 files changed, 94 insertions, 26 deletions
diff --git a/source/compiler-core/slang-source-loc.cpp b/source/compiler-core/slang-source-loc.cpp index 8710cf91f..f9014e0d8 100644 --- a/source/compiler-core/slang-source-loc.cpp +++ b/source/compiler-core/slang-source-loc.cpp @@ -190,12 +190,41 @@ void SourceView::addDefaultLineDirective(SourceLoc directiveLoc) m_entries.add(entry); } -SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, SourceView* sourceView, SourceLoc loc, HandleSourceLoc& outLoc) +// Nominal-like types take into account line directives, and potentially source maps +static bool _isNominalLike(SourceLocType type) +{ + return type == SourceLocType::Nominal || type == SourceLocType::Emit; +} + +static bool _canFollowSourceMap(SourceFile* sourceFile, SourceLocType type) +{ + // If we don't have a source map we have nothing to follow + if (!sourceFile->getSourceMap()) + { + return false; + } + + // If it's obfuscated we can't follow if we are emitting + if (sourceFile->getSourceMapKind() == SourceMapKind::Obfuscated && + type == SourceLocType::Emit) + { + return false; + } + + return _isNominalLike(type); +} + +static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, SourceView* sourceView, SourceLoc loc, SourceLocType type, HandleSourceLoc& outLoc) { auto sourceFile = sourceView->getSourceFile(); + if (!_canFollowSourceMap(sourceFile, type)) + { + return SLANG_E_NOT_FOUND; + } + // Hold a list of sourceFiles visited so we can't end up in a loop of lookups - List<SourceFile*> sourceFiles; + ShortList<SourceFile*, 8> sourceFiles; sourceFiles.add(sourceFile); Index entryIndex = -1; @@ -240,8 +269,10 @@ SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, SourceView sourceFiles.add(foundSourceFile); // If it has a source map, we try and look up the current location in it's source map - if (auto foundSourceMap = foundSourceFile->getSourceMap()) + if (_canFollowSourceMap(foundSourceFile, type)) { + auto foundSourceMap = foundSourceFile->getSourceMap(); + const auto foundEntryIndex = foundSourceMap->get().findEntry(entry.sourceLine, entry.sourceColumn); // If we found the entry repeat the lookup @@ -273,18 +304,30 @@ SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, SourceView return SLANG_OK; } -HandleSourceLoc SourceView::getHandleLoc(SourceLoc loc, SourceLocType type) + +SlangResult SourceView::_findSourceMapLoc(SourceLoc loc, SourceLocType type, HandleSourceLoc& outLoc) { - // If it's nominal - if (type == SourceLocType::Nominal && m_sourceFile->getSourceMap()) + // We only do source map lookups with nominal + if (!_isNominalLike(type)) { - // TODO(JS): - // Ideally we'd do the lookup on the "current" source manager rather than the source manager on this - // view, which may be a parent to the current one. - auto lookupSourceManager = m_sourceFile->getSourceManager(); + return SLANG_E_NOT_FOUND; + } - HandleSourceLoc handleLoc; - if (SLANG_SUCCEEDED(_findLocWithSourceMap(lookupSourceManager, this, loc, handleLoc))) + // TODO(JS): + // Ideally we'd do the lookup on the "current" source manager rather than the source manager on this + // view, which may be a parent to the current one. + auto lookupSourceManager = m_sourceFile->getSourceManager(); + + HandleSourceLoc handleLoc; + SLANG_RETURN_ON_FAIL(_findLocWithSourceMap(lookupSourceManager, this, loc, type, outLoc)); + + return SLANG_OK; +} + +HandleSourceLoc SourceView::getHandleLoc(SourceLoc loc, SourceLocType type) +{ + { HandleSourceLoc handleLoc; + if (SLANG_SUCCEEDED(_findSourceMapLoc(loc, type, handleLoc))) { return handleLoc; } @@ -307,22 +350,21 @@ HandleSourceLoc SourceView::getHandleLoc(SourceLoc loc, SourceLocType type) HandleSourceLoc handleLoc; handleLoc.column = columnIndex + 1; handleLoc.line = lineIndex + 1; - - // Make up a default entry - StringSlicePool::Handle pathHandle = StringSlicePool::Handle(0); - - // Only bother looking up the entry information if we want a 'Normal' lookup - const int entryIndex = (type == SourceLocType::Nominal) ? findEntryIndex(loc) : -1; - if (entryIndex >= 0) + + // Only bother looking up the entry information if we want a 'Norminal'-like lookup + if (_isNominalLike(type)) { - const Entry& entry = m_entries[entryIndex]; - // Adjust the line - handleLoc.line += entry.m_lineAdjust; - // Get the pathHandle.. - pathHandle = entry.m_pathHandle; + const int entryIndex = findEntryIndex(loc); + if (entryIndex >= 0) + { + const Entry& entry = m_entries[entryIndex]; + // Adjust the line + handleLoc.line += entry.m_lineAdjust; + // Get the pathHandle.. + handleLoc.pathHandle = entry.m_pathHandle; + } } - handleLoc.pathHandle = pathHandle; return handleLoc; } @@ -371,6 +413,14 @@ PathInfo SourceView::getPathInfo(SourceLoc loc, SourceLocType type) return getViewPathInfo(); } + { + HandleSourceLoc handleLoc; + if (SLANG_SUCCEEDED(_findSourceMapLoc(loc, type, handleLoc))) + { + return _getPathInfoFromHandle(handleLoc.pathHandle); + } + } + const int entryIndex = findEntryIndex(loc); return _getPathInfoFromHandle((entryIndex >= 0) ? m_entries[entryIndex].m_pathHandle : StringSlicePool::Handle(0)); } diff --git a/source/compiler-core/slang-source-loc.h b/source/compiler-core/slang-source-loc.h index fafff7de6..5c78c4293 100644 --- a/source/compiler-core/slang-source-loc.h +++ b/source/compiler-core/slang-source-loc.h @@ -164,6 +164,16 @@ struct SourceRange SourceLoc end; }; +/// Source maps associated with files are could be of different uses. We use the SourceMapKind +/// to indicate the usage. +/// +/// If the source map is obfuscated reasonable/desirable to ignore them on emit (if we didn't we leak information, +/// and we don't emit into the locations in the obfuscated intermediate "file"). +enum class SourceMapKind +{ + Normal, ///< A regular source map + Obfuscated, ///< Obfuscated source map +}; // Pre-declare struct SourceManager; @@ -256,8 +266,11 @@ public: /// Get the source map associated with this file. If it's set when doing /// lookup for source locations, the source map will be used IBoxValue<SourceMap>* getSourceMap() const { return m_sourceMap; } + /// Get the source map kind + SourceMapKind getSourceMapKind() const { return m_sourceMapKind; } + /// Set a source map - void setSourceMap(IBoxValue<SourceMap>* sourceMap) { m_sourceMap = sourceMap; } + void setSourceMap(IBoxValue<SourceMap>* sourceMap, SourceMapKind sourceMapKind) { m_sourceMap = sourceMap; m_sourceMapKind = sourceMapKind; } /// Ctor SourceFile(SourceManager* sourceManager, const PathInfo& pathInfo, size_t contentSize); @@ -281,12 +294,15 @@ public: // If set then the locations in this file are really from locations from elsewhere, // where the SourceMap specifies that mapping ComPtr<IBoxValue<SourceMap>> m_sourceMap; + // What kind of source map it is (if there is one) + SourceMapKind m_sourceMapKind = SourceMapKind::Normal; }; enum class SourceLocType { Nominal, ///< The normal interpretation which takes into account #line directives and source maps Actual, ///< Ignores #line directives/source maps - and is the location as seen in the actual file + Emit, ///< Behaves the same as `Nominal` but ignores source maps. Used for Emit source locations. }; // A source location in a format a human might like to see @@ -395,6 +411,8 @@ class SourceView /// Get the pathInfo from a string handle. If it's 0, it will return the _getPathInfo PathInfo _getPathInfoFromHandle(StringSlicePool::Handle pathHandle) const; + SlangResult _findSourceMapLoc(SourceLoc loc, SourceLocType type, HandleSourceLoc& outLoc); + String m_viewPath; ///< Path to this view. If empty the path is the path to the SourceView SourceLoc m_initiatingSourceLoc; ///< An optional source loc that defines where this view was initiated from. SourceLoc(0) if not defined. |
